filens-preview 0.3.0 → 0.3.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/README.md +13 -7
- package/dist/all-in-one/THIRD-PARTY-NOTICES.txt +870 -0
- package/dist/all-in-one/filens.js +5069 -114897
- package/dist/index.d.ts +2 -0
- package/dist/split/THIRD-PARTY-NOTICES.txt +870 -0
- package/dist/split/chunks/archive-haip2eOP.js +1 -0
- package/dist/split/chunks/browser-video-session-C_14e_mG.js +1 -0
- package/dist/split/chunks/cad-5oTkbaDV.js +7 -0
- package/dist/split/chunks/core-EjELrtsP.js +17 -0
- package/dist/split/chunks/diagram-BRcdlitF.js +1 -0
- package/dist/split/chunks/docx-I39iDYpR.js +1 -0
- package/dist/split/chunks/ebook-BRfadCGl.js +5 -0
- package/dist/split/chunks/index-C4jdVbDq.js +1 -0
- package/dist/split/chunks/index-DkF8PBGR.js +1 -0
- package/dist/split/chunks/iwork-DXq9Adf7.js +4 -0
- package/dist/split/chunks/media-runtime-B6322raw.js +1 -0
- package/dist/split/chunks/mindmap-CyR3TRfx.js +1 -0
- package/dist/split/chunks/model3d-BEt6INTt.js +55 -0
- package/dist/split/chunks/mp4box.all-Bw_Tlr0T-D0URDfA1.js +1 -0
- package/dist/split/chunks/panorama-ChsqnvWC.js +973 -0
- package/dist/split/chunks/pdf-Dzzffz3p.js +12 -0
- package/dist/split/chunks/vendor-C1aIdQ-w.js +4115 -0
- package/dist/split/chunks/xlsx-CITQo0Od.js +3 -0
- package/dist/split/converter-image.wasm +0 -0
- package/dist/split/filens.js +2 -5012
- package/package.json +1 -1
- package/dist/split/chunks/archive-B4jVwD9o.js +0 -921
- package/dist/split/chunks/cad-DMg-lGJX.js +0 -2405
- package/dist/split/chunks/core--zVW212C.js +0 -14627
- package/dist/split/chunks/diagram-CDwCA6LZ.js +0 -654
- package/dist/split/chunks/docx-CuQfFJqr.js +0 -299
- package/dist/split/chunks/ebook-CLlJ8KX3.js +0 -623
- package/dist/split/chunks/iwork-dNVC0X8j.js +0 -772
- package/dist/split/chunks/media-runtime-gcsBQMuo.js +0 -48
- package/dist/split/chunks/mindmap-g0-VoK-K.js +0 -560
- package/dist/split/chunks/model3d-1G1CC52V.js +0 -5093
- package/dist/split/chunks/panorama-D7GVivtM.js +0 -5972
- package/dist/split/chunks/pdf-CecYOWld.js +0 -17898
- package/dist/split/chunks/vendor-DPFNKNkh.js +0 -59575
- package/dist/split/chunks/xlsx-Co26yo-R.js +0 -818
|
@@ -0,0 +1,973 @@
|
|
|
1
|
+
var To=Object.defineProperty;var Ro=(t,e,i)=>e in t?To(t,e,{enumerable:true,configurable:true,writable:true,value:i}):t[e]=i;var L=(t,e,i)=>Ro(t,typeof e!="symbol"?e+"":e,i);import{x as Tn,c as Po,b as Ao,y as Lo,z as _o}from"./core-EjELrtsP.js";import{ac as Uo,S as Ki,ad as Mt,ae as Ta,af as Ra,ag as Pa,ah as Zi,j as ea,ai as Co,aj as Aa,ak as Rn,m as Eo,o as Io,a9 as zo,al as Yr,w as Bo}from"./vendor-C1aIdQ-w.js";function Se(t){if(t!=null&&t.aborted)throw Pn()}function Pn(){return Object.assign(new Error("The conversion was aborted."),{name:"AbortError"})}function ut(t,e){return e?new Promise((i,n)=>{const r=()=>n(Pn());t.then(o=>{e.removeEventListener("abort",r),i(o)},o=>{e.removeEventListener("abort",r),n(o)}),e.aborted?r():e.addEventListener("abort",r,{once:true})}):t}function La(t){let e;return()=>{if(!e){const i=Promise.resolve().then(t);e=i,i.catch(()=>{e===i&&(e=void 0)})}return e}}function jo(t){return/^(?:https?:|blob:|\/|\.{1,2}\/)/i.test(t)}function No(t){return t.trimStart().toLowerCase().startsWith("data:")}function Oo(t){const e=atob(t),i=new Uint8Array(e.length);for(let n=0;n<i.length;n++)i[n]=e.charCodeAt(n);return i}function Vo(t){var c;const e=t.trimStart(),i=e.indexOf(",");if(i<0)throw new Error("Conversion data URL is missing its payload separator.");const n=e.slice(0,i),r=e.slice(i+1),o=(c=n.match(/^data:([^;,]+)/i))==null?void 0:c[1];if(/;base64$/i.test(n))return{bytes:Oo(r),contentType:o};const s=new TextEncoder().encode(r);let a=0;for(let l=0;l<s.length;l++){if(s[l]===37){const u=Qr(s[l+1]),f=Qr(s[l+2]);if(u>=0&&f>=0){s[a++]=u<<4|f,l+=2;continue}}s[a++]=s[l]}return{bytes:s.subarray(0,a),contentType:o}}function Qr(t){if(t>=48&&t<=57)return t-48;const e=t|32;return e>=97&&e<=102?e-87:-1}async function An(t,e=globalThis.fetch,i,n=1/0){var o;const r=s=>{if(s>n)throw new Error("Conversion source exceeds the preview byte limit.")};if(Wo(t)){r(t.size);const s=new Uint8Array(await ut(t.arrayBuffer(),i));return r(s.length),s}if(t instanceof ArrayBuffer)return r(t.byteLength),new Uint8Array(t);if(ArrayBuffer.isView(t))return r(t.byteLength),new Uint8Array(t.buffer,t.byteOffset,t.byteLength);if(typeof t=="string"){if(No(t)){r(Math.max(0,t.length-t.indexOf(",")-1)/3);const a=Vo(t).bytes;return r(a.length),a}if(jo(t)){if(!e)throw new Error("A fetch implementation is required to load a conversion source URL.");const a=await ut(e(t,{signal:i}),i);if(Se(i),!a.ok)throw new Error(`Failed to fetch conversion source: ${a.status} ${a.statusText}`.trim());try{if(r(Number(a.headers.get("content-length"))),!Number.isFinite(n)||!a.body){const l=new Uint8Array(await ut(a.arrayBuffer(),i));return r(l.length),l}const c=a.body.getReader();try{const l=[];let u=0;for(;;){const{value:p,done:h}=await ut(c.read(),i);if(h)break;u+=p.length,r(u),l.push(p)}const f=new Uint8Array(u);let y=0;for(const p of l)f.set(p,y),y+=p.length;return f}finally{await c.cancel().catch(()=>{}),c.releaseLock()}}catch(c){throw await((o=a.body)==null?void 0:o.cancel().catch(()=>{})),c}}r(t.length);const s=new TextEncoder().encode(t);return r(s.length),s}throw new Error("Unsupported conversion source type.")}function Wo(t){return typeof t=="object"&&t!==null&&"arrayBuffer"in t&&typeof t.arrayBuffer=="function"}async function Go(t){var i;if(((i=t.headers.get("content-type"))==null?void 0:i.split(";",1)[0])!=="application/wasm+gzip")return t;if(typeof DecompressionStream<"u"&&t.body)return new Response(t.body.pipeThrough(new DecompressionStream("gzip")),{headers:{"content-type":"application/wasm"}});const e=Uo(new Uint8Array(await t.arrayBuffer()));return new Response(e,{headers:{"content-type":"application/wasm"}})}function wi(t){const e=La(()=>Ln(t.wasm,t.fetch));return async i=>{const n=i.signal;Se(n);const r=new Cn({args:i.args,files:i.files,captureStdio:i.captureStdio}),o=await ut(e(),n);Se(n);const s=await ut(WebAssembly.instantiate(o,{wasi_snapshot_preview1:r.imports}),n);Se(n),r.setInstance(s);let a=0;try{s.exports._start()}catch(c){if(c instanceof _n)a=c.code;else throw c}return{exitCode:a,...i.captureStdio?{stdout:r.readStdio(1),stderr:r.readStdio(2)}:{},files:Object.fromEntries((i.readFiles??[]).flatMap(c=>{const l=r.readFileIfPresent(c);return l?[[c,l]]:[]}))}}}async function Ln(t,e=globalThis.fetch){const i=typeof t=="function"?await t():await t;if(i instanceof WebAssembly.Module)return i;if(typeof i=="string"||qo(i)){if(!e)throw new Error("A fetch implementation is required to load converter WASM from a URL.");return Hr(await e(String(i)))}return typeof Response<"u"&&i instanceof Response?Hr(i):WebAssembly.compile(i)}function qo(t){return typeof URL<"u"&&t instanceof URL}async function Hr(t){var i;if(!t.ok)throw new Error(`Failed to fetch converter WASM: ${t.status} ${t.statusText}`.trim());const e=await Go(t);return typeof WebAssembly.compileStreaming=="function"&&((i=e.headers.get("content-type"))==null?void 0:i.split(";",1)[0])==="application/wasm"?WebAssembly.compileStreaming(e):WebAssembly.compile(await e.arrayBuffer())}class _n extends Error{constructor(e){super(`WASI exited with code ${e}`),this.code=e}}const Q=0,ge=8,Xo=20,Jr=28,hi=31,mi=44,Kr=54,ya=55,Un=2,wa=3,Fa=4,Zr=1,$o=2,Yo=4,Qo=8,en=1;class Cn{constructor(e){L(this,"imports",{args_get:(e2,i)=>this.argsGet(e2,i),args_sizes_get:(e2,i)=>this.argsSizesGet(e2,i),clock_time_get:(e2,i,n)=>this.clockTimeGet(n),environ_get:(e2,i)=>Q,environ_sizes_get:(e2,i)=>this.environSizesGet(e2,i),fd_close:e2=>this.fdClose(e2),fd_fdstat_get:(e2,i)=>this.fdFdstatGet(e2,i),fd_fdstat_set_flags:(e2,i)=>Q,fd_filestat_get:(e2,i)=>this.fdFilestatGet(e2,i),fd_pread:(e2,i,n,r,o)=>this.fdRead(e2,i,n,o,Number(r),false),fd_prestat_dir_name:(e2,i,n)=>this.fdPrestatDirName(e2,i,n),fd_prestat_get:(e2,i)=>this.fdPrestatGet(e2,i),fd_read:(e2,i,n,r)=>this.fdRead(e2,i,n,r),fd_seek:(e2,i,n,r)=>this.fdSeek(e2,i,n,r),fd_tell:(e2,i)=>this.fdTell(e2,i),fd_write:(e2,i,n,r)=>this.fdWrite(e2,i,n,r),path_create_directory:(e2,i,n)=>this.pathCreateDirectory(e2,i,n),path_filestat_get:(e2,i,n,r,o)=>this.pathFilestatGet(e2,n,r,o),path_open:(e2,i,n,r,o,s,a,c,l)=>this.pathOpen(e2,n,r,o,c,l),path_remove_directory:(e2,i,n)=>this.pathRemoveDirectory(e2,i,n),path_unlink_file:(e2,i,n)=>this.pathUnlinkFile(e2,i,n),poll_oneoff:(e2,i,n,r)=>this.pollOneoff(r),proc_exit:e2=>{throw new _n(e2)},random_get:(e2,i)=>this.randomGet(e2,i),sched_yield:()=>Q});L(this,"instance");L(this,"captureStdio");L(this,"stdio",{1:[],2:[]});L(this,"args");L(this,"files",new Map);L(this,"dirs",new Set(["/","/work"]));L(this,"fds",new Map([[0,{kind:"stdio",fd:0,position:0}],[1,{kind:"stdio",fd:1,position:0}],[2,{kind:"stdio",fd:2,position:0}],[3,{kind:"dir",path:"/work",position:0}]]));L(this,"nextFd",4);this.args=e.args,this.captureStdio=e.captureStdio??false;for(const[i,n]of Object.entries(e.files))this.writeInitialFile(i,n)}setInstance(e){this.instance=e}readStdio(e){return new TextDecoder().decode(new Uint8Array(this.stdio[e]))}readFile(e){const i=this.files.get(qt(e));if(!i)throw new Error(`WASM file was not written: ${e}`);const n=new Uint8Array(i.byteLength);return n.set(i),n}readFileIfPresent(e){return this.files.has(qt(e))?this.readFile(e):void 0}get memory(){var i;const e=(i=this.instance)==null?void 0:i.exports.memory;if(!(e instanceof WebAssembly.Memory))throw new Error("WASM instance did not export memory.");return e}get bytes(){return new Uint8Array(this.memory.buffer)}get view(){return new DataView(this.memory.buffer)}argsSizesGet(e,i){return this.view.setUint32(e,this.args.length,true),this.view.setUint32(i,Ho(this.args),true),Q}argsGet(e,i){return this.writeStringList(this.args,e,i)}environSizesGet(e,i){return this.view.setUint32(e,0,true),this.view.setUint32(i,0,true),Q}clockTimeGet(e){return this.view.setBigUint64(e,BigInt(Date.now())*1000000n,true),Q}fdClose(e){return e<=3||this.fds.delete(e)?Q:ge}fdFdstatGet(e,i){const n=this.fds.get(e);return n?(this.bytes.fill(0,i,i+24),this.bytes[i]=Jo(n),this.view.setBigUint64(i+8,0xffffffffffffffffn,true),this.view.setBigUint64(i+16,0xffffffffffffffffn,true),Q):ge}fdFilestatGet(e,i){var r;const n=this.fds.get(e);return n?n.kind==="file"?(this.writeFilestat(i,Fa,((r=this.files.get(n.path))==null?void 0:r.byteLength)??0),Q):n.kind==="dir"?(this.writeFilestat(i,wa,0),Q):(this.writeFilestat(i,Un,0),Q):ge}fdPrestatGet(e,i){const n=this.fds.get(e);return!n||n.kind!=="dir"||n.path!=="/work"?ge:(this.bytes.fill(0,i,i+8),this.view.setUint32(i+4,n.path.length,true),Q)}fdPrestatDirName(e,i,n){const r=this.fds.get(e);if(!r||r.kind!=="dir")return ge;const o=new TextEncoder().encode(r.path);return this.bytes.set(o.subarray(0,n),i),Q}fdRead(e,i,n,r,o,s=true){const a=this.fds.get(e);if(!a)return ge;if(a.kind!=="file")return this.view.setUint32(r,0,true),a.kind==="dir"?hi:Q;const c=this.files.get(a.path)??new Uint8Array;let l=o??a.position,u=0;for(const[f,y]of this.iovs(i,n)){const p=c.subarray(l,l+y);if(this.bytes.set(p,f),l+=p.byteLength,u+=p.byteLength,p.byteLength<y)break}return s&&o===void 0&&(a.position=l),this.view.setUint32(r,u,true),Q}fdSeek(e,i,n,r){var c;const o=this.fds.get(e);if(!o||o.kind!=="file")return(o==null?void 0:o.kind)==="dir"?hi:ge;if(n!==0&&n!==1&&n!==2)return Jr;const a=(n===0?0:n===1?o.position:n===2?((c=this.files.get(o.path))==null?void 0:c.byteLength)??0:-1)+Number(i);return!Number.isSafeInteger(a)||a<0?Jr:(o.position=a,this.view.setBigUint64(r,BigInt(a),true),Q)}fdTell(e,i){const n=this.fds.get(e);return!n||n.kind!=="file"?(n==null?void 0:n.kind)==="dir"?hi:ge:(this.view.setBigUint64(i,BigInt(n.position),true),Q)}fdWrite(e,i,n,r){const o=this.fds.get(e);if(!o)return ge;let s=0;if(o.kind==="stdio"){for(const[a,c]of this.iovs(i,n)){const l=this.captureStdio?this.stdio[o.fd]:void 0;if(l){const u=a+Math.min(c,Math.max(0,1048576-l.length)),f=this.bytes;for(let y=a;y<u;y++)l.push(f[y])}s+=c}return this.view.setUint32(r,s,true),Q}if(o.kind!=="file")return hi;for(const[a,c]of this.iovs(i,n)){const l=this.bytes.subarray(a,a+c);this.writeFileChunk(o,l),s+=c}return this.view.setUint32(r,s,true),Q}pathCreateDirectory(e,i,n){const r=this.readPath(e,i,n);return r?(this.ensureParentDir(r),this.files.has(r)?Kr:(this.dirs.add(r),Q)):ge}pathFilestatGet(e,i,n,r){var s;const o=this.readPath(e,i,n);return o?this.files.has(o)?(this.writeFilestat(r,Fa,((s=this.files.get(o))==null?void 0:s.byteLength)??0),Q):this.dirs.has(o)?(this.writeFilestat(r,wa,0),Q):mi:ge}pathOpen(e,i,n,r,o,s){var l;const a=this.readPath(e,i,n);if(!a)return ge;if(r&Zr&&r&Yo&&(this.files.has(a)||this.dirs.has(a)))return Xo;if(!!(r&$o))return this.dirs.has(a)?this.openDescriptor({kind:"dir",path:a,position:0},s):this.files.has(a)?Kr:mi;if(this.files.has(a))r&Qo&&this.files.set(a,new Uint8Array);else{if(!(r&Zr))return this.dirs.has(a)?hi:mi;this.ensureParentDir(a),this.files.set(a,new Uint8Array)}return this.openDescriptor({kind:"file",path:a,position:o&en?((l=this.files.get(a))==null?void 0:l.byteLength)??0:0,append:!!(o&en)},s)}pathRemoveDirectory(e,i,n){const r=this.readPath(e,i,n);if(!r)return ge;if(r==="/"||r==="/work")return ya;for(const o of this.dirs)if(o!==r&&ga(o)===r)return ya;for(const o of this.files.keys())if(ga(o)===r)return ya;return this.dirs.delete(r)?Q:mi}pathUnlinkFile(e,i,n){const r=this.readPath(e,i,n);return r?this.files.delete(r)?Q:mi:ge}pollOneoff(e){return this.view.setUint32(e,0,true),Q}randomGet(e,i){const n=this.bytes.subarray(e,e+i),r=globalThis.crypto;if(r!=null&&r.getRandomValues)r.getRandomValues(n);else for(let o=0;o<n.length;o+=1)n[o]=Math.floor(Math.random()*256);return Q}writeStringList(e,i,n){let r=n;for(let o=0;o<e.length;o+=1){const s=new TextEncoder().encode(e[o]);this.view.setUint32(i+o*4,r,true),this.bytes.set(s,r),this.bytes[r+s.byteLength]=0,r+=s.byteLength+1}return Q}iovs(e,i){const n=[];for(let r=0;r<i;r+=1){const o=e+r*8;n.push([this.view.getUint32(o,true),this.view.getUint32(o+4,true)])}return n}readPath(e,i,n){const r=this.fds.get(e);if(!r||r.kind!=="dir")return null;const o=new TextDecoder().decode(this.bytes.subarray(i,i+n));return Ko(r.path,o)}openDescriptor(e,i){const n=this.nextFd++;return this.fds.set(n,e),this.view.setUint32(i,n,true),Q}writeFilestat(e,i,n){this.bytes.fill(0,e,e+64),this.bytes[e+16]=i,this.view.setBigUint64(e+24,1n,true),this.view.setBigUint64(e+32,BigInt(n),true)}writeInitialFile(e,i){const n=qt(e);this.ensureParentDir(n);const r=new Uint8Array(i.byteLength);r.set(i),this.files.set(n,r)}ensureParentDir(e){const i=ga(e);i===e||this.dirs.has(i)||(this.ensureParentDir(i),this.dirs.add(i))}writeFileChunk(e,i){if(!i.byteLength)return;const n=this.files.get(e.path)??new Uint8Array,r=e.append?n.byteLength:e.position,o=Math.max(n.byteLength,r+i.byteLength);let s;if(o<=n.buffer.byteLength)s=new Uint8Array(n.buffer,0,o);else{const a=new Uint8Array(Math.max(o,n.buffer.byteLength*2));a.set(n),s=a.subarray(0,o)}s.set(i,r),this.files.set(e.path,s),e.position=r+i.byteLength}}function Ho(t){return t.reduce((e,i)=>e+new TextEncoder().encode(i).byteLength+1,0)}function Jo(t){switch(t.kind){case"dir":return wa;case"file":return Fa;default:return Un}}function Ko(t,e){return e.startsWith("/")?qt(e):qt(`${t}/${e}`)}function qt(t){const e=[];for(const i of t.replace(/\\/g,"/").split("/"))if(!(!i||i===".")){if(i===".."){e.pop();continue}e.push(i)}return`/${e.join("/")}`}function ga(t){const e=qt(t);if(e==="/")return"/";const i=e.lastIndexOf("/");return i<=0?"/":e.slice(0,i)}const Zo=[{sourceFormat:"dng",targetFormat:"jpg"},{sourceFormat:"cr2",targetFormat:"jpg"},{sourceFormat:"cr3",targetFormat:"jpg"},{sourceFormat:"nef",targetFormat:"jpg"},{sourceFormat:"nrw",targetFormat:"jpg"},{sourceFormat:"arw",targetFormat:"jpg"},{sourceFormat:"sr2",targetFormat:"jpg"},{sourceFormat:"srf",targetFormat:"jpg"},{sourceFormat:"orf",targetFormat:"jpg"},{sourceFormat:"rw2",targetFormat:"jpg"},{sourceFormat:"rwl",targetFormat:"jpg"},{sourceFormat:"raf",targetFormat:"jpg"},{sourceFormat:"kdc",targetFormat:"jpg"},{sourceFormat:"x3f",targetFormat:"jpg"},{sourceFormat:"pef",targetFormat:"jpg"},{sourceFormat:"srw",targetFormat:"jpg"},{sourceFormat:"erf",targetFormat:"jpg"},{sourceFormat:"mef",targetFormat:"jpg"},{sourceFormat:"mos",targetFormat:"jpg"},{sourceFormat:"mrw",targetFormat:"jpg"},{sourceFormat:"3fr",targetFormat:"jpg"},{sourceFormat:"iiq",targetFormat:"jpg"},{sourceFormat:"icns",targetFormat:"png"}],es=new Set(Tn.map(t=>dt(t.sourceFormat))),ts=new Set(Tn.map(t=>`${dt(t.sourceFormat)}->${dt(t.targetFormat)}`)),is=new Set(Zo.map(t=>`${dt(t.sourceFormat)}->${dt(t.targetFormat)}`));class Qi extends Error{constructor(e){super(e.errorMessage||e.errorCode||"WASM conversion failed."),this.result=e,this.name="WasmConversionError"}}function Hc(t){const e=wi(t),i=t.officeWasm?wi({wasm:t.officeWasm,fetch:t.fetch}):void 0,n=t.imageWasm?La(()=>Ln(t.imageWasm,t.fetch)):void 0,r=t.imageWasm?wi({wasm:n,fetch:t.fetch}):void 0,o=n?as(n):void 0;return{async convert(s,a){Se(a.signal);const c=dt(s.sourceFormat),l=dt(s.targetFormat),u=rs(c,l),f=`/work/input.${c}`,y=`/work/output.${l}`,p="/work/options.json",h="/work/result.json",d=await An(s.source,t.fetch,a.signal);Se(a.signal);const m=JSON.stringify({...s.password?{password:s.password}:{},...s.locale?{locale:s.locale}:{}}),g=!!(r&&is.has(u));if(g&&l==="jpg"&&o){const D=await o(d,a.signal);if(Se(a.signal),D)return D}const b=g?r:e,x=(D,F)=>D({args:[g?"converter-image":"converter-core","--input",f,"--output",y,"--source",c,"--target",l,"--options",p,"--result",h],files:{[f]:F,[p]:new TextEncoder().encode(m)},readFiles:[h,y],signal:a.signal});let v=await x(b,d),w=$i(v.files[h]);if(!w.ok&&w.errorCode==="engine_unavailable"&&w.requiredModule==="office"&&i){const D=await x(i,d);tn($i(D.files[h]),D.exitCode),v=await x(e,D.files[y]),w=$i(v.files[h])}return Se(a.signal),tn(w,v.exitCode),{source:v.files[y],format:dt(w.targetFormat||l),contentType:w.contentType,warnings:w.warnings}}}}function tn(t,e){if(!t.ok)throw new Qi(t);if(e!==0)throw new Qi({...t,ok:false,errorCode:t.errorCode||"conversion_failed",errorMessage:t.errorMessage||`converter WASM exited with code ${e}`})}function as(t){const e=La(async()=>{const i=await t(),n=new Set(WebAssembly.Module.exports(i).map(s=>s.name));if(!["filens_image_alloc","filens_image_free","filens_image_preview","memory"].every(s=>n.has(s)))return null;const r=new Cn({args:["converter-image"],files:{}}),o=await WebAssembly.instantiate(i,{wasi_snapshot_preview1:r.imports});return r.setInstance(o),o.exports});return async(i,n)=>{const r=await ut(e(),n);if(Se(n),!r||i.length===0)return null;let o=0,s=0,a=0;try{if(o=r.filens_image_alloc(i.length)>>>0,!o)throw new Error("Image core could not allocate its input buffer.");new Uint8Array(r.memory.buffer).set(i,o);const c=r.filens_image_preview(o,i.length);if(s=Number(c&0xffffffffn),a=Number(c>>32n),!s||a<4||s+a>r.memory.buffer.byteLength)throw new Error("Image core returned an invalid preview buffer.");const l=new Uint8Array(r.memory.buffer,s,a),u=new DataView(l.buffer,l.byteOffset,4).getUint32(0,true);if(u>l.length-4)throw new Error("Image core returned invalid preview metadata.");const f=$i(l.subarray(4,4+u));if(!f.ok)throw new Qi(f);return{source:l.slice(4+u),format:"jpg",contentType:f.contentType,warnings:f.warnings}}finally{s&&a&&r.filens_image_free(s,a),o&&r.filens_image_free(o,i.length)}}}function rs(t,e){const i=`${t}->${e}`;if(ts.has(i))return i;const n=es.has(t)?`unsupported conversion pair: ${t} -> ${e}`:`unsupported source format: ${t}`;throw new Qi({ok:false,sourceFormat:t,targetFormat:e,warnings:[],errorCode:"unsupported_format",errorMessage:n,metrics:{}})}function $i(t){const e=new TextDecoder().decode(t),i=JSON.parse(e);return{...i,warnings:Array.isArray(i.warnings)?i.warnings.map(String):[]}}function dt(t){return t.trim().replace(/^\./,"").toLowerCase()}const an=64*1024*1024;function Jc(){return{async convert(t,e){const i=t.sourceFormat.replace(/^\./,"").toLowerCase(),n=t.targetFormat.replace(/^\./,"").toLowerCase();if(!(["heic","heif"].includes(i)&&n==="png"))throw new Error(`Unsupported media conversion: ${i} -> ${n}.`);if(Se(e.signal),(t.source instanceof Blob?t.source.size:typeof t.source=="string"?0:t.source.byteLength)>an)throw new Error("HEIF input exceeds the 64 MiB preview limit.");const r=ArrayBuffer.isView(t.source)?t.source.slice():t.source instanceof ArrayBuffer?t.source.slice(0):t.source,o=await An(r,globalThis.fetch,e.signal,an);Se(e.signal);const s=await ut(import("./media-runtime-B6322raw.js"),e.signal);return Se(e.signal),s.convertMedia(o,i,e.signal)}}}function H(t){if(t!=null&&t.aborted)throw new DOMException("Panorama preview was aborted.","AbortError")}function le(t,e,i){return new Promise((n,r)=>{const o=()=>r(new DOMException("Panorama preview was aborted.","AbortError"));e.aborted?o():e.addEventListener("abort",o,{once:true}),t.then(s=>{e.removeEventListener("abort",o),e.aborted?i==null||i(s):n(s)},s=>{e.removeEventListener("abort",o),e.aborted||r(s)})})}function ns(t,e){const i=n=>(H(e),le(n(),e));return{open:(n,r)=>i(()=>t.open(n,{...r,signal:e})),...t.decodeImage?{decodeImage:()=>i(()=>t.decodeImage(e))}:{},readSample:(n,r,o)=>i(()=>t.readSample(n,r,o??e)),readImuWindow:(n,r,o)=>i(()=>t.readImuWindow(n,r,o??e)),computeSeam:(n,r)=>i(()=>t.computeSeam(n,r??e)),seek:n=>(H(e),t.seek(n)),getManifest:()=>(H(e),t.getManifest()),close:()=>{e.aborted||t.close()},abort:()=>{e.aborted||t.abort()}}}const rn=8,Mi=64<<20,os=128<<20,nn=120,ss=8<<20;class B extends Error{constructor(e,i){super(i),this.code=e,this.name="PanoramaProcessorError"}}function cs(t){const e=t.fetch??globalThis.fetch,i=wi({wasm:t.wasm,fetch:e}),n=t.imageWasm?wi({wasm:t.imageWasm,fetch:e}):void 0,r=l=>{const u=new AbortController,f=pi(u.signal,l);return{controller:u,...f,companionTrackIds:new Map}};let o=r();const s=l=>{const{reader:u,companionProcessor:f}=l;l.reader=void 0,l.manifest=void 0,l.companionProcessor=void 0,l.companionTrackIds.clear(),l.controller.abort(),l.release(),u==null||u.close(),f==null||f.close()},a=()=>{const l=o;o=r(),s(l)},c=async(l,u,f,y)=>{var x;ie(y);const p=l.companionTrackIds.get(u);if(p!==void 0&&l.companionProcessor){const v=await l.companionProcessor.readSample(p,f,y);return ie(y),{...v,trackId:u}}const{reader:h,manifest:d}=l;if(!h||!d)throw new B("invalid_manifest","Open a panorama source before reading samples.");const m=d.tracks.find(v=>v.id===u)??(((x=d.metadataTrack)==null?void 0:x.id)===u?d.metadataTrack:void 0),g=m==null?void 0:m.samples[f];if(!m||!g)throw new RangeError(`Unknown panorama sample ${u}:${f}.`);const b=await h.read(g.offset,g.size,y);return{...g,trackId:u,timescale:m.timescale,data:b}};return{async open(l,u){var h;const f=r(u.signal),y=o;o=f,s(y);const p=f.signal;try{ie(p);const d=await le(wt.open(l,e,p),p,k=>k.close());ie(p),f.reader=d;let m;const g=new Map,b=u.format==="insp"?1<<20:65536,x=u.format==="insp"?65536:1<<20,v=[{offset:0,length:Math.min(b,d.size)},{offset:Math.max(0,d.size-x),length:Math.min(x,d.size)}];await sn(d,g,v,p);let w;if(u.sidecar){const k=await wt.open(u.sidecar,e,p);try{if(k.size>8<<20)throw new B("resource_limit","Panorama sidecar exceeds 8 MiB.");w=await k.read(0,k.size,p)}finally{k.close()}}for(let k=0;k<rn;k+=1){ie(p);const D=[...g.values()].map((A,C)=>({offset:A.offset,path:`/work/range-${C}.bin`})),F={"/work/options.json":new TextEncoder().encode(JSON.stringify({logicalSize:d.size,ranges:D,...w?{sidecarPath:"/work/sidecar.pb"}:{}}))};w&&(F["/work/sidecar.pb"]=w),[...g.values()].forEach((A,C)=>{F[`/work/range-${C}.bin`]=A.bytes});const S="/work/result.json",R=await i({args:["converter-core","--operation","inspect-panorama","--source",u.format,"--options","/work/options.json","--result",S],files:F,readFiles:[S],signal:p});ie(p);const _=R.files[S];if(!_)throw new B("invalid_manifest","Panorama inspector did not return a result.");const T=JSON.parse(new TextDecoder().decode(_));if(T.ok&&T.payload){if(m=us(T.payload),u.companion){f.companionProcessor=cs(t);const A=await f.companionProcessor.open(u.companion,{format:u.format,sidecar:u.sidecar,signal:p});ie(p);const C=new Set(m.tracks.map(J=>J.id)),j=new Map,G=A.tracks.map(J=>{let Z=J.id;for(;C.has(Z);)Z+=1e6;return C.add(Z),f.companionTrackIds.set(Z,J.id),j.set(J.id,Z),{...J,id:Z}}),q=A.lenses.map(J=>({...J,sourceTrackId:J.sourceTrackId===void 0?void 0:j.get(J.sourceTrackId)})),te=[...m.tracks,...G],ne=hs(fs(m.lenses,q),te),ue=[...m.warnings,...A.warnings];m={...m,cameraModel:m.cameraModel||A.cameraModel,firmware:m.firmware||A.firmware,textureOrigin:m.textureOrigin||A.textureOrigin,projection:m.projection.kind==="unknown"?A.projection:m.projection,calibrationSource:m.calibrationSource==="unavailable"?A.calibrationSource:m.calibrationSource,confidence:m.confidence==="low"?A.confidence:m.confidence,tracks:te,lenses:ne,warnings:ne.length>=2?ue.filter(J=>!J.includes("matching companion file")&&!J.startsWith("INSV calibration was not found")):ue}}return f.manifest=m,m}if(T.errorCode!=="need_ranges"||!((h=T.requiredRanges)!=null&&h.length))throw va(T.errorCode,T.errorMessage);await sn(d,g,T.requiredRanges,p)}throw new B("resource_limit",`Panorama inspection exceeded ${rn} range iterations.`)}catch(d){throw o===f&&(o=r()),s(f),d}},async decodeImage(l){var p;const u=o,f=pi(u.signal,l),y=f.signal;try{ie(y);const h=u.reader,d=u.manifest;if(!h||(d==null?void 0:d.format)!=="dng")throw new B("invalid_manifest","Open a DNG before developing its RAW preview.");if(!n)throw new B("codec_unsupported","Calibrated DNG preview requires converter-image.wasm (imageWasm).");if(h.size>256*1024*1024)throw new B("resource_limit","RAW preview input exceeds 256 MiB.");const m=new Uint8Array(h.size);for(let w=0;w<m.length;w+=Mi){const k=Math.min(Mi,m.length-w),D=await h.read(w,k,y);if(ie(y),D.length!==k)throw new B("range_unavailable","DNG source returned an incomplete byte range.");m.set(D,w)}const g="/work/result.json",b="/work/preview.jpg",x=await n({args:["converter-image","--source","dng","--target","jpg","--input","/work/input.dng","--output",b,"--options","/work/options.json","--result",g],files:{"/work/input.dng":m,"/work/options.json":new TextEncoder().encode(JSON.stringify({preserveSensorGeometry:true}))},readFiles:[g,b],signal:y});ie(y);const v=JSON.parse(new TextDecoder().decode(x.files[g]??new Uint8Array));if(!v.ok||x.exitCode!==0||!((p=x.files[b])!=null&&p.length))throw new B("codec_unsupported",v.errorMessage||"WASM could not develop the DNG sensor preview.");return x.files[b]}finally{f.release()}},async readSample(l,u,f){const y=o,p=pi(y.signal,f);try{return await c(y,l,u,p.signal)}finally{p.release()}},async readImuWindow(l,u,f){var h;const y=o,p=pi(y.signal,f);try{ie(p.signal);const d=y.manifest;if(!(d!=null&&d.metadataTrack))return[];if(!Number.isSafeInteger(l)||!Number.isSafeInteger(u)||l<0||u<0||u>nn)throw new B("resource_limit",`Panorama metadata windows are limited to ${nn} samples.`);const m=d.metadataTrack,g=m.samples.slice(l,l+u);if(g.reduce((S,R)=>S+R.size,0)>ss)throw new B("resource_limit","Panorama metadata window exceeds 8 MiB.");const x={},v=[];for(let S=0;S<g.length;S+=1){const R=await c(y,m.id,l+S,p.signal),_=`/work/metadata-${S}.bin`;x[_]=R.data,v.push({path:_,pts:R.pts,timescale:R.timescale})}const w="/work/result.json";ie(p.signal),x["/work/options.json"]=new TextEncoder().encode(JSON.stringify({vendor:d.vendor,samples:v}));const k=await i({args:["converter-core","--operation","decode-panorama-metadata","--options","/work/options.json","--result",w],files:x,readFiles:[w],signal:p.signal});ie(p.signal);const D=k.files[w];if(!D)throw new B("invalid_manifest","Panorama metadata decoder did not return a result.");const F=JSON.parse(new TextDecoder().decode(D));if(!F.ok||!Array.isArray((h=F.payload)==null?void 0:h.samples))throw va(F.errorCode,F.errorMessage);return F.payload.samples}finally{p.release()}},seek(l){const u=o.manifest;return u?Object.fromEntries(u.tracks.map(f=>[f.id,ds(f,l)])):{}},async computeSeam(l,u){const f=pi(o.signal,u);try{ie(f.signal);const y="/work/result.json",p=await i({args:["converter-core","--operation","panorama-seam","--options","/work/options.json","--result",y],files:{"/work/options.json":new TextEncoder().encode(JSON.stringify({width:l.width,height:l.height,costs:Array.from(l.costs),previous:l.previous?Array.from(l.previous):[],temporalWeight:l.temporalWeight??2,maxStep:l.maxStep??1}))},readFiles:[y],signal:f.signal});ie(f.signal);const h=p.files[y];if(!h)throw new B("invalid_manifest","Panorama seam solver did not return a result.");const d=JSON.parse(new TextDecoder().decode(h));if(!d.ok||!d.payload)throw va(d.errorCode,d.errorMessage);const m=d.payload;if(!Array.isArray(m.seam)||!Number.isFinite(m.cost))throw new B("invalid_manifest","Panorama seam solver returned an invalid path.");return m}finally{f.release()}},close:a,abort:()=>o.controller.abort(),getManifest:()=>o.manifest}}function En(t){return{codec:ms(t),codedWidth:t.width,codedHeight:t.height,description:In(t.decoderConfig),optimizeForLatency:true}}function ls(t){return new EncodedVideoChunk({type:t.key?"key":"delta",timestamp:Math.round(t.pts*1e6/t.timescale),duration:Math.round(t.duration*1e6/t.timescale),data:t.data})}function us(t){var r;if(!t||!Array.isArray(t.tracks)||!Array.isArray(t.lenses))throw new B("invalid_manifest","Panorama inspector returned an invalid manifest.");const e=(r=t.lenses[0])==null?void 0:r.projection,i=typeof t.projection=="string"?e&&typeof e=="object"?e:{kind:t.projection}:{kind:"unknown"},n=t.lenses.map(o=>({...o,projection:o.projection&&typeof o.projection=="object"?o.projection:i}));return{...t,projection:i,lenses:n}}function ds(t,e){const i=Math.max(0,e)*t.timescale;let n=0;for(let r=0;r<t.samples.length;r+=1){const o=t.samples[r];if(o.pts>i)break;o.key&&(n=r)}return n}function fs(t,e){const i=t.slice(0,2),n=new Set(i.map(on));for(const r of e){if(i.length===2)break;const o=on(r);n.has(o)||(i.push(r),n.add(o))}return i}function hs(t,e){return e.length<t.length?t:t.map((i,n)=>i.sourceTrackId===void 0?{...i,sourceTrackId:e[n].id}:i)}function on(t){const e={...t};return delete e.sourceTrackId,delete e.sourceRect,JSON.stringify(e)}function ms(t){const e=In(t.decoderConfig);if((t.codec==="avc1"||t.codec==="avc3")&&e.length>=4)return`${t.codec}.${[...e.slice(1,4)].map(i=>i.toString(16).padStart(2,"0")).join("")}`;if((t.codec==="hvc1"||t.codec==="hev1")&&e.length>=13){const i=["","A","B","C"][e[1]>>6],n=e[1]&32?"H":"L",r=e[1]&31;let o=new DataView(e.buffer,e.byteOffset+2,4).getUint32(0),s=0;for(let u=0;u<32;u+=1)s=s<<1|o&1,o>>>=1;const a=(s>>>0).toString(16),c=[...e.slice(6,12)];for(;c.at(-1)===0;)c.pop();const l=c.length?`.${c.map(u=>u.toString(16)).join(".")}`:"";return`${t.codec}.${i}${r}.${a}.${n}${e[12]}${l}`}return t.codec}function In(t){return t?Uint8Array.from(t.match(/.{1,2}/g)??[],e=>Number.parseInt(e,16)):new Uint8Array}async function sn(t,e,i,n){for(const r of i){const o=r.offset+r.length;if(!Number.isSafeInteger(r.offset)||!Number.isSafeInteger(r.length)||!Number.isSafeInteger(o)||r.offset<0||r.length<=0||r.length>Mi||o>t.size)throw new B("resource_limit","Panorama inspector requested an invalid source range.");const s=[...e.values()].sort((u,f)=>u.offset-f.offset),a=[];let c=r.offset;for(const u of s)if(u.offset>c&&a.push({offset:c,length:Math.min(u.offset,o)-c}),c=Math.max(c,u.offset+u.bytes.length),c>=o)break;if(c<o&&a.push({offset:c,length:o-c}),s.reduce((u,f)=>u+f.bytes.length,0)+a.reduce((u,f)=>u+f.length,0)>os)throw new B("resource_limit","Panorama inspection exceeded its 128 MiB range budget.");for(const u of a){const f=await t.read(u.offset,u.length,n);e.set(`${u.offset}:${u.length}`,{offset:u.offset,bytes:f})}}}class wt{constructor(e,i,n){this.size=e,this.readRange=i,this.cleanup=n}static async open(e,i,n){if(ie(n),e instanceof Blob)return new wt(e.size,async(u,f)=>new Uint8Array(await e.slice(u,u+f).arrayBuffer()));if(e instanceof ArrayBuffer||ArrayBuffer.isView(e)){const u=e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer,e.byteOffset,e.byteLength);return new wt(u.byteLength,async(f,y)=>u.slice(f,f+y))}if(!i)throw new B("range_unavailable","A fetch implementation is required for remote panorama sources.");const r=String(e),o=await yi(i(r,{headers:{Range:"bytes=0-0"},signal:n}),n,gi);ie(n);const s=o.headers.get("content-range");if(o.status===206){const u=s==null?void 0:s.match(/^bytes 0-0\/(\d+)$/i),f=Number(u==null?void 0:u[1]);if(gi(o),!Number.isSafeInteger(f)||f<=0)throw new B("range_unavailable","Remote panorama size is unavailable.");return new wt(f,async(y,p,h)=>{var m;const d=await yi(i(r,{headers:{Range:`bytes=${y}-${y+p-1}`},signal:h}),h,gi);if(ie(h),d.status!==206||((m=d.headers.get("content-range"))==null?void 0:m.toLowerCase())!==`bytes ${y}-${y+p-1}/${f}`)throw gi(d),new B("range_unavailable","Remote server returned an inconsistent panorama byte range.");return new Uint8Array(await yi(d.arrayBuffer(),h))})}const a=Number(o.headers.get("content-length"));if(!o.ok||!Number.isSafeInteger(a)||a<=0||a>Mi)throw gi(o),new B("range_unavailable","Remote server must support HTTP byte ranges for large panorama files.");const c=new Uint8Array(await yi(o.arrayBuffer(),n));ie(n);const l=o.headers.get("content-encoding");if(!c.length||c.length>Mi||(!l||l.toLowerCase()==="identity")&&c.length!==a)throw new B("range_unavailable","Remote panorama body does not match its declared length or size limit.");return new wt(c.byteLength,async(u,f)=>c.slice(u,u+f))}async read(e,i,n){if(ie(n),!Number.isSafeInteger(e)||!Number.isSafeInteger(i)||e<0||i<0||i>this.size-e)throw new B("range_unavailable","Panorama source range is out of bounds.");if(!i)return new Uint8Array;const r=await yi(this.readRange(e,i,n),n);if(ie(n),r.length!==i)throw new B("range_unavailable","Panorama source returned an incomplete byte range.");return r}close(){var e;(e=this.cleanup)==null||e.call(this)}}function va(t,e){const i={range_unavailable:"range_unavailable",resource_limit:"resource_limit",sidecar_missing:"sidecar_missing",firmware_unknown:"firmware_unknown",invalid_panorama_options:"invalid_manifest",invalid_panorama_metadata:"invalid_manifest",unsupported_container:"invalid_manifest",unsupported_projection:"calibration_missing"};return new B(i[t??""]??"calibration_missing",e||t||"Panorama inspection failed.")}function pi(t,...e){const i=[...new Set([t,...e.filter(s=>!!s)])],n=[],r=()=>{n.splice(0).forEach(s=>s())};if(i.length===1)return{signal:i[0],release:r};if(typeof AbortSignal.any=="function")return{signal:AbortSignal.any(i),release:r};const o=new AbortController;for(const s of i){const a=()=>{o.abort(s.reason),r()};if(s.aborted){a();break}s.addEventListener("abort",a,{once:true}),n.push(()=>s.removeEventListener("abort",a))}return{signal:o.signal,release:r}}function yi(t,e,i){return e?le(t,e,i):t}function gi(t){var e;try{(e=t.body)==null||e.cancel().catch(()=>{})}catch{}}function ie(t){if(t!=null&&t.aborted)throw t.reason instanceof Error?t.reason:new DOMException("The panorama operation was aborted.","AbortError")}async function ps(t,e,i){var y,p,h,d;if(e.projection.kind!=="mei-extended"||!ta(e))throw new B("calibration_missing","This INSP does not contain two supported calibrated panorama lenses.");const n=e.width??Number(((y=i.image)==null?void 0:y.naturalWidth)??((p=i.image)==null?void 0:p.width)),r=e.height??Number(((h=i.image)==null?void 0:h.naturalHeight)??((d=i.image)==null?void 0:d.height));if(!(n>0)||!(r>0))throw new B("invalid_manifest","The calibrated INSP image dimensions are unavailable.");const o={id:0,codec:"jpeg",decoderConfig:"",width:n,height:r,timescale:1,samples:[]},s=e.lenses.slice(0,2).map(m=>({track:o,rect:m.sourceRect??{x:0,y:0,width:1,height:1}}));if(!s.every(m=>zn(m.rect)))throw new B("invalid_manifest","The calibrated INSP lenses are not bound to valid image regions.");i.flipY=Ua(e.textureOrigin),i.colorSpace=Ki,i.minFilter=Mt,i.generateMipmaps=false,i.needsUpdate=true;const a=new Ta(new Uint8Array(128*64).fill(128),128,64,Ra,Pa);a.needsUpdate=true,a.minFilter=Mt;const c=ys(e,s,i,a);Ca(c,e.lenses);const l=new Zi(500,96,64);l.scale(-1,1,1);const u=new ea(l,c),f=new jn(t,e,s,c,a);return await f.acceptImage(i.image),{mesh:u,update:()=>{},play:()=>{},pause:()=>{},seek:()=>{},close:()=>{f.close(),a.dispose(),l.dispose(),c.dispose()},duration:0,currentTime:0,paused:true,streamSyncMs:0,get dynamicSeam(){return f.active},stabilizationAvailable:false,stabilizationMode:"off",error:void 0,setStabilization:()=>"off"}}function ys(t,e,i,n){const r=t.lenses.slice(0,2);return new Aa({uniforms:{lens0:{value:i},lens1:{value:i},intrinsics0:{value:Yt(r[0])},intrinsics1:{value:Yt(r[1])},size0:{value:$t(r[0],e[0])},size1:{value:$t(r[1],e[1])},sourceRect0:{value:Xt(e[0],t.textureOrigin)},sourceRect1:{value:Xt(e[1],t.textureOrigin)},distortion0:{value:Ze(r[0])},distortion1:{value:Ze(r[1])},quaternion0:{value:ft(r[0])},quaternion1:{value:ft(r[1])},radialScale0:{value:St(r[0])},radialScale1:{value:St(r[1])},projectionKind:{value:1},xi0:{value:r[0].xi||0},xi1:{value:r[1].xi||0},tangential0:{value:ve(r[0].tangential)},tangential1:{value:ve(r[1].tangential)},thinPrism0:{value:Dt(r[0].thinPrism)},thinPrism1:{value:Dt(r[1].thinPrism)},sensorTilt0:{value:ve(r[0].sensorTilt)},sensorTilt1:{value:ve(r[1].sensorTilt)},seamMask:{value:n},useDynamicSeam:{value:0},exposureGain0:{value:[1,1,1]},exposureGain1:{value:[1,1,1]},stabilizationQuaternion:{value:[1,0,0,0]}},vertexShader:`
|
|
2
|
+
varying vec2 panoramaUv;
|
|
3
|
+
void main() {
|
|
4
|
+
panoramaUv = uv;
|
|
5
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
6
|
+
}
|
|
7
|
+
`,fragmentShader:`
|
|
8
|
+
precision highp float;
|
|
9
|
+
varying vec2 panoramaUv;
|
|
10
|
+
uniform sampler2D lens0;
|
|
11
|
+
uniform sampler2D lens1;
|
|
12
|
+
uniform vec4 intrinsics0;
|
|
13
|
+
uniform vec4 intrinsics1;
|
|
14
|
+
uniform vec2 size0;
|
|
15
|
+
uniform vec2 size1;
|
|
16
|
+
uniform vec4 sourceRect0;
|
|
17
|
+
uniform vec4 sourceRect1;
|
|
18
|
+
uniform vec4 distortion0;
|
|
19
|
+
uniform vec4 distortion1;
|
|
20
|
+
uniform vec4 quaternion0;
|
|
21
|
+
uniform vec4 quaternion1;
|
|
22
|
+
uniform float radialScale0;
|
|
23
|
+
uniform float radialScale1;
|
|
24
|
+
uniform int projectionKind;
|
|
25
|
+
uniform float xi0;
|
|
26
|
+
uniform float xi1;
|
|
27
|
+
uniform vec2 tangential0;
|
|
28
|
+
uniform vec2 tangential1;
|
|
29
|
+
uniform vec4 thinPrism0;
|
|
30
|
+
uniform vec4 thinPrism1;
|
|
31
|
+
uniform vec2 sensorTilt0;
|
|
32
|
+
uniform vec2 sensorTilt1;
|
|
33
|
+
uniform sampler2D seamMask;
|
|
34
|
+
uniform int useDynamicSeam;
|
|
35
|
+
uniform vec3 exposureGain0;
|
|
36
|
+
uniform vec3 exposureGain1;
|
|
37
|
+
uniform vec4 stabilizationQuaternion;
|
|
38
|
+
|
|
39
|
+
vec3 rotateQuaternion(vec4 q, vec3 v) {
|
|
40
|
+
vec3 u = q.yzw;
|
|
41
|
+
return 2.0 * dot(u, v) * u + (q.x * q.x - dot(u, u)) * v + 2.0 * q.x * cross(u, v);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
vec2 applySensorTilt(vec2 point, vec2 tilt) {
|
|
45
|
+
float cx = cos(tilt.x), sx = sin(tilt.x);
|
|
46
|
+
float cy = cos(tilt.y), sy = sin(tilt.y);
|
|
47
|
+
float rx = cy*point.x + sy*sx*point.y - sy*cx;
|
|
48
|
+
float ry = cx*point.y + sx;
|
|
49
|
+
float rz = sy*point.x - cy*sx*point.y + cy*cx;
|
|
50
|
+
float safeRz = abs(rz) > 0.000001 ? rz : (rz < 0.0 ? -0.000001 : 0.000001);
|
|
51
|
+
return vec2(cx*(cy*rx + sy*rz), cy*cx*ry - sx*rz) / safeRz;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
vec4 projectLens(vec3 body, vec4 intrinsics, vec2 imageSize, vec4 sourceRect, vec4 distortion, vec4 quaternion, float xi, vec2 tangential, vec4 thinPrism, vec2 sensorTilt, sampler2D image) {
|
|
55
|
+
vec3 direction = rotateQuaternion(normalize(vec4(quaternion.x, -quaternion.yzw)), body);
|
|
56
|
+
float denominator = direction.z + xi;
|
|
57
|
+
vec2 normalized = direction.xy / max(denominator, 0.000001);
|
|
58
|
+
float r2 = dot(normalized, normalized);
|
|
59
|
+
if (denominator <= 0.000001 || r2 > 16.0) return vec4(0.0);
|
|
60
|
+
float r4 = r2 * r2;
|
|
61
|
+
float radialFactor = 1.0 + distortion.x*r2 + distortion.y*r4 + distortion.z*r2*r4 + distortion.w*r4*r4;
|
|
62
|
+
float x = normalized.x;
|
|
63
|
+
float y = normalized.y;
|
|
64
|
+
vec2 distorted = vec2(
|
|
65
|
+
x*radialFactor + 2.0*tangential.x*x*y + tangential.y*(r2 + 2.0*x*x) + thinPrism.x*r2 + thinPrism.y*r4,
|
|
66
|
+
y*radialFactor + tangential.x*(r2 + 2.0*y*y) + 2.0*tangential.y*x*y + thinPrism.z*r2 + thinPrism.w*r4
|
|
67
|
+
);
|
|
68
|
+
vec2 pixel = intrinsics.zw + intrinsics.xy * applySensorTilt(distorted, sensorTilt);
|
|
69
|
+
vec2 uv = sourceRect.xy + ((pixel + vec2(0.5)) / imageSize) * sourceRect.zw;
|
|
70
|
+
float edgeRadius = 0.475 * min(imageSize.x, imageSize.y);
|
|
71
|
+
float coverageDepth = max(edgeRadius - distance(pixel, intrinsics.zw), 0.0);
|
|
72
|
+
float valid = float(direction.z + xi > 0.000001 && coverageDepth > 0.0)
|
|
73
|
+
* float(all(greaterThanEqual(pixel, vec2(0.0))) && all(lessThanEqual(pixel, imageSize - vec2(1.0))));
|
|
74
|
+
return vec4(texture2D(image, uv).rgb, valid * max(coverageDepth, 0.0001));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
vec2 panoramaUvForDirection(vec3 direction) {
|
|
78
|
+
float longitude = atan(direction.x, direction.z);
|
|
79
|
+
float latitude = asin(clamp(-direction.y, -1.0, 1.0));
|
|
80
|
+
return vec2(fract(longitude / 6.28318530718 + 0.5), latitude / 3.14159265359 + 0.5);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
void main() {
|
|
84
|
+
float longitude = panoramaUv.x * 6.28318530718 - 3.14159265359;
|
|
85
|
+
float latitude = (panoramaUv.y - 0.5) * 3.14159265359;
|
|
86
|
+
float cosLatitude = cos(latitude);
|
|
87
|
+
vec3 body = vec3(cosLatitude * sin(longitude), -sin(latitude), cosLatitude * cos(longitude));
|
|
88
|
+
body = rotateQuaternion(normalize(stabilizationQuaternion), body);
|
|
89
|
+
vec2 bodyPanoramaUv = panoramaUvForDirection(body);
|
|
90
|
+
vec4 a = projectLens(body, intrinsics0, size0, sourceRect0, distortion0, quaternion0, xi0, tangential0, thinPrism0, sensorTilt0, lens0);
|
|
91
|
+
vec4 b = projectLens(body, intrinsics1, size1, sourceRect1, distortion1, quaternion1, xi1, tangential1, thinPrism1, sensorTilt1, lens1);
|
|
92
|
+
if (a.a <= 0.0 && b.a <= 0.0) {
|
|
93
|
+
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
|
94
|
+
} else if (a.a <= 0.0 || b.a <= 0.0) {
|
|
95
|
+
gl_FragColor = vec4((a.a > 0.0 ? a.rgb * exposureGain0 : b.rgb * exposureGain1), 1.0);
|
|
96
|
+
} else {
|
|
97
|
+
float frontPreference = 1.0 - smoothstep(radians(75.0), radians(105.0), abs(bodyPanoramaUv.x * 6.28318530718 - 3.14159265359));
|
|
98
|
+
float aWeight = a.a * frontPreference;
|
|
99
|
+
float bWeight = b.a * (1.0 - frontPreference);
|
|
100
|
+
float lens1Weight = useDynamicSeam == 1
|
|
101
|
+
? texture2D(seamMask, bodyPanoramaUv).r
|
|
102
|
+
: bWeight / max(aWeight + bWeight, 0.0001);
|
|
103
|
+
gl_FragColor = vec4(mix(a.rgb * exposureGain0, b.rgb * exposureGain1, lens1Weight), 1.0);
|
|
104
|
+
}
|
|
105
|
+
#include <colorspace_fragment>
|
|
106
|
+
}
|
|
107
|
+
`})}async function gs(t,e){if(!["dji-fisheye-lut","mei-extended"].includes(e.projection.kind)||e.lenses.length<2)throw new B("calibration_missing","This source does not contain two supported calibrated panorama lenses.");if(!ta(e))throw new B("calibration_missing","The two panorama lenses do not contain complete, distinct calibration.");if(typeof VideoDecoder>"u"||typeof EncodedVideoChunk>"u")throw new B("codec_unsupported","This browser does not expose WebCodecs video decoding.");const i=ia(e);if(!i)throw new B("invalid_manifest","The panorama lenses are not bound to valid source tracks and frame regions.");const n=[...new Map(i.map(m=>[m.track.id,m.track])).values()];if(n.some(m=>m.timescale<=0||!m.samples.length))throw new B("invalid_manifest","The calibrated panorama tracks do not contain a playable sample timeline.");const r=n.map(En);if((await Promise.all(r.map(m=>VideoDecoder.isConfigSupported(m)))).some(m=>!m.supported))throw new B("codec_unsupported",`This browser cannot decode the ${[...new Set(n.map(m=>m.codec.toUpperCase()))].join("/")} panorama tracks.`);const s=n.map(()=>new Co);s.forEach(m=>{m.flipY=Ua(e.textureOrigin),m.colorSpace=Ki,m.minFilter=Mt});const a=new Ta(new Uint8Array(128*64).fill(128),128,64,Ra,Pa);a.needsUpdate=true,a.minFilter=Mt;const c=e.lenses.slice(0,2),l=i.map(m=>s[n.indexOf(m.track)]),u=new Aa({uniforms:{lens0:{value:l[0]},lens1:{value:l[1]},intrinsics0:{value:Yt(c[0])},intrinsics1:{value:Yt(c[1])},size0:{value:$t(c[0],i[0])},size1:{value:$t(c[1],i[1])},sourceRect0:{value:Xt(i[0],e.textureOrigin)},sourceRect1:{value:Xt(i[1],e.textureOrigin)},distortion0:{value:Ze(c[0])},distortion1:{value:Ze(c[1])},quaternion0:{value:ft(c[0])},quaternion1:{value:ft(c[1])},radialScale0:{value:St(c[0])},radialScale1:{value:St(c[1])},projectionKind:{value:e.projection.kind==="mei-extended"?1:0},xi0:{value:c[0].xi||0},xi1:{value:c[1].xi||0},tangential0:{value:ve(c[0].tangential)},tangential1:{value:ve(c[1].tangential)},thinPrism0:{value:Dt(c[0].thinPrism)},thinPrism1:{value:Dt(c[1].thinPrism)},sensorTilt0:{value:ve(c[0].sensorTilt)},sensorTilt1:{value:ve(c[1].sensorTilt)},seamMask:{value:a},useDynamicSeam:{value:0},exposureGain0:{value:[1,1,1]},exposureGain1:{value:[1,1,1]},stabilizationQuaternion:{value:[1,0,0,0]}},vertexShader:`
|
|
108
|
+
varying vec2 panoramaUv;
|
|
109
|
+
void main() {
|
|
110
|
+
panoramaUv = uv;
|
|
111
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
112
|
+
}
|
|
113
|
+
`,fragmentShader:`
|
|
114
|
+
precision highp float;
|
|
115
|
+
varying vec2 panoramaUv;
|
|
116
|
+
uniform sampler2D lens0;
|
|
117
|
+
uniform sampler2D lens1;
|
|
118
|
+
uniform vec4 intrinsics0;
|
|
119
|
+
uniform vec4 intrinsics1;
|
|
120
|
+
uniform vec2 size0;
|
|
121
|
+
uniform vec2 size1;
|
|
122
|
+
uniform vec4 sourceRect0;
|
|
123
|
+
uniform vec4 sourceRect1;
|
|
124
|
+
uniform vec4 distortion0;
|
|
125
|
+
uniform vec4 distortion1;
|
|
126
|
+
uniform vec4 quaternion0;
|
|
127
|
+
uniform vec4 quaternion1;
|
|
128
|
+
uniform float radialScale0;
|
|
129
|
+
uniform float radialScale1;
|
|
130
|
+
uniform int projectionKind;
|
|
131
|
+
uniform float xi0;
|
|
132
|
+
uniform float xi1;
|
|
133
|
+
uniform vec2 tangential0;
|
|
134
|
+
uniform vec2 tangential1;
|
|
135
|
+
uniform vec4 thinPrism0;
|
|
136
|
+
uniform vec4 thinPrism1;
|
|
137
|
+
uniform vec2 sensorTilt0;
|
|
138
|
+
uniform vec2 sensorTilt1;
|
|
139
|
+
uniform sampler2D seamMask;
|
|
140
|
+
uniform int useDynamicSeam;
|
|
141
|
+
uniform vec3 exposureGain0;
|
|
142
|
+
uniform vec3 exposureGain1;
|
|
143
|
+
uniform vec4 stabilizationQuaternion;
|
|
144
|
+
|
|
145
|
+
vec3 rotateQuaternion(vec4 q, vec3 v) {
|
|
146
|
+
vec3 u = q.yzw;
|
|
147
|
+
return 2.0 * dot(u, v) * u + (q.x * q.x - dot(u, u)) * v + 2.0 * q.x * cross(u, v);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
float radial(float theta, vec4 k, float scale, float fx) {
|
|
151
|
+
float limit = radians(85.0);
|
|
152
|
+
float t = min(theta, limit);
|
|
153
|
+
float t2 = t * t;
|
|
154
|
+
float polynomial = t * (1.0 + k.x*t2 + k.y*t2*t2 + k.z*t2*t2*t2 + k.w*t2*t2*t2*t2);
|
|
155
|
+
if (theta > limit) {
|
|
156
|
+
float derivative = 1.0 + 3.0*k.x*t2 + 5.0*k.y*t2*t2 + 7.0*k.z*t2*t2*t2 + 9.0*k.w*t2*t2*t2*t2;
|
|
157
|
+
polynomial += derivative * (theta - limit);
|
|
158
|
+
}
|
|
159
|
+
return scale * fx * polynomial;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
vec2 applySensorTilt(vec2 point, vec2 tilt) {
|
|
163
|
+
float cx = cos(tilt.x), sx = sin(tilt.x);
|
|
164
|
+
float cy = cos(tilt.y), sy = sin(tilt.y);
|
|
165
|
+
float rx = cy*point.x + sy*sx*point.y - sy*cx;
|
|
166
|
+
float ry = cx*point.y + sx;
|
|
167
|
+
float rz = sy*point.x - cy*sx*point.y + cy*cx;
|
|
168
|
+
float safeRz = abs(rz) > 0.000001 ? rz : (rz < 0.0 ? -0.000001 : 0.000001);
|
|
169
|
+
return vec2(cx*(cy*rx + sy*rz), cy*cx*ry - sx*rz) / safeRz;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
vec4 projectLens(vec3 body, vec4 intrinsics, vec2 imageSize, vec4 sourceRect, vec4 distortion, vec4 quaternion, float scale, float xi, vec2 tangential, vec4 thinPrism, vec2 sensorTilt, sampler2D image) {
|
|
173
|
+
vec4 lensQuaternion = projectionKind == 1 ? vec4(quaternion.x, -quaternion.yzw) : quaternion;
|
|
174
|
+
vec3 direction = rotateQuaternion(normalize(lensQuaternion), body);
|
|
175
|
+
float theta = acos(clamp(direction.z, -1.0, 1.0));
|
|
176
|
+
vec2 pixel;
|
|
177
|
+
if (projectionKind == 1) {
|
|
178
|
+
float denominator = direction.z + xi;
|
|
179
|
+
vec2 normalized = direction.xy / max(denominator, 0.000001);
|
|
180
|
+
float r2 = dot(normalized, normalized);
|
|
181
|
+
if (denominator <= 0.000001 || r2 > 16.0) return vec4(0.0);
|
|
182
|
+
float r4 = r2 * r2;
|
|
183
|
+
float radialFactor = 1.0 + distortion.x*r2 + distortion.y*r4 + distortion.z*r2*r4 + distortion.w*r4*r4;
|
|
184
|
+
float x = normalized.x;
|
|
185
|
+
float y = normalized.y;
|
|
186
|
+
vec2 distorted = vec2(
|
|
187
|
+
x*radialFactor + 2.0*tangential.x*x*y + tangential.y*(r2 + 2.0*x*x) + thinPrism.x*r2 + thinPrism.y*r4,
|
|
188
|
+
y*radialFactor + tangential.x*(r2 + 2.0*y*y) + 2.0*tangential.y*x*y + thinPrism.z*r2 + thinPrism.w*r4
|
|
189
|
+
);
|
|
190
|
+
pixel = intrinsics.zw + intrinsics.xy * applySensorTilt(distorted, sensorTilt);
|
|
191
|
+
} else {
|
|
192
|
+
float rho = max(length(direction.xy), 0.000001);
|
|
193
|
+
float radius = radial(theta, distortion, scale, intrinsics.x);
|
|
194
|
+
pixel = intrinsics.zw + radius * direction.xy / rho;
|
|
195
|
+
}
|
|
196
|
+
vec2 uv = sourceRect.xy + ((pixel + vec2(0.5)) / imageSize) * sourceRect.zw;
|
|
197
|
+
float validProjection = projectionKind == 1 ? float(direction.z + xi > 0.000001) : float(theta < radians(96.0));
|
|
198
|
+
float coverageDepth = 1.0;
|
|
199
|
+
if (projectionKind == 1) {
|
|
200
|
+
float edgeRadius = 0.475 * min(imageSize.x, imageSize.y);
|
|
201
|
+
coverageDepth = max(edgeRadius - distance(pixel, intrinsics.zw), 0.0);
|
|
202
|
+
validProjection *= float(coverageDepth > 0.0);
|
|
203
|
+
}
|
|
204
|
+
float valid = validProjection * float(all(greaterThanEqual(pixel, vec2(0.0))) && all(lessThanEqual(pixel, imageSize - vec2(1.0))));
|
|
205
|
+
float weight = projectionKind == 1
|
|
206
|
+
? valid * max(coverageDepth, 0.0001)
|
|
207
|
+
: valid * clamp((radians(95.0) - theta) / radians(10.0), 0.0, 1.0);
|
|
208
|
+
return vec4(texture2D(image, uv).rgb, weight);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
vec2 panoramaUvForDirection(vec3 direction) {
|
|
212
|
+
float longitude = projectionKind == 1 ? atan(direction.x, direction.z) : atan(-direction.y, direction.x);
|
|
213
|
+
float latitude = projectionKind == 1 ? asin(clamp(-direction.y, -1.0, 1.0)) : asin(clamp(direction.z, -1.0, 1.0));
|
|
214
|
+
return vec2(fract(longitude / 6.28318530718 + 0.5), latitude / 3.14159265359 + 0.5);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
void main() {
|
|
218
|
+
float longitude = panoramaUv.x * 6.28318530718 - 3.14159265359;
|
|
219
|
+
float latitude = (panoramaUv.y - 0.5) * 3.14159265359;
|
|
220
|
+
float cosLatitude = cos(latitude);
|
|
221
|
+
vec3 body = projectionKind == 1
|
|
222
|
+
? vec3(cosLatitude * sin(longitude), -sin(latitude), cosLatitude * cos(longitude))
|
|
223
|
+
: vec3(cosLatitude * sin(longitude + 1.57079632679), cosLatitude * cos(longitude + 1.57079632679), sin(latitude));
|
|
224
|
+
body = rotateQuaternion(normalize(stabilizationQuaternion), body);
|
|
225
|
+
vec2 bodyPanoramaUv = panoramaUvForDirection(body);
|
|
226
|
+
vec4 a = projectLens(body, intrinsics0, size0, sourceRect0, distortion0, quaternion0, radialScale0, xi0, tangential0, thinPrism0, sensorTilt0, lens0);
|
|
227
|
+
vec4 b = projectLens(body, intrinsics1, size1, sourceRect1, distortion1, quaternion1, radialScale1, xi1, tangential1, thinPrism1, sensorTilt1, lens1);
|
|
228
|
+
if (a.a <= 0.0 && b.a <= 0.0) {
|
|
229
|
+
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (a.a <= 0.0 || b.a <= 0.0) {
|
|
233
|
+
gl_FragColor = vec4((a.a > 0.0 ? a.rgb * exposureGain0 : b.rgb * exposureGain1), 1.0);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
float frontPreference = projectionKind == 1
|
|
237
|
+
? 1.0 - smoothstep(radians(75.0), radians(105.0), abs(bodyPanoramaUv.x * 6.28318530718 - 3.14159265359))
|
|
238
|
+
: 1.0;
|
|
239
|
+
float aWeight = projectionKind == 1 ? a.a * frontPreference : a.a;
|
|
240
|
+
float bWeight = projectionKind == 1 ? b.a * (1.0 - frontPreference) : b.a;
|
|
241
|
+
float total = aWeight + bWeight;
|
|
242
|
+
float lens1Weight = useDynamicSeam == 1 && a.a > 0.0 && b.a > 0.0
|
|
243
|
+
? texture2D(seamMask, bodyPanoramaUv).r
|
|
244
|
+
: bWeight / max(total, 0.0001);
|
|
245
|
+
gl_FragColor = vec4(mix(a.rgb * exposureGain0, b.rgb * exposureGain1, lens1Weight), 1.0);
|
|
246
|
+
}
|
|
247
|
+
`});Ca(u,e.lenses);const f=new Zi(500,96,64);f.scale(-1,1,1);const y=new ea(f,u),p=new jn(t,e,i,u,a),h=new ks(t,e,u),d=new Bn(t,n,s,r,(m,g)=>{h.apply(m.timestamp/1e6),p.accept(m,g)},m=>h.prepare(m),()=>{p.reset(),h.reset()});return d.start(),{mesh:y,update:()=>d.update(),play:()=>d.play(),pause:()=>d.pause(),seek:m=>d.seek(m),setPlaybackRate:m=>d.setPlaybackRate(m),close:()=>{d.close(),p.close(),s.forEach(m=>m.dispose()),a.dispose(),f.dispose(),u.dispose()},get streamSyncMs(){return d.streamSyncMs},get dynamicSeam(){return p.active},get duration(){return d.duration},get currentTime(){return d.currentTime},get paused(){return d.paused},get stabilizationAvailable(){return h.available},get stabilizationMode(){return h.mode},get error(){return d.error},setStabilization:m=>h.setMode(m)}}async function vs(t,e,i){if(!["dji-fisheye-lut","mei-extended"].includes(t.projection.kind)||t.lenses.length<2)throw new B("calibration_missing","This source does not contain two supported calibrated panorama lenses.");if(!ta(t))throw new B("calibration_missing","The two panorama lenses do not contain complete, distinct calibration.");const n=ia(t);if(!n)throw new B("invalid_manifest","The panorama lenses are not bound to valid source tracks and frame regions.");const r=[...new Map(n.map(d=>[d.track.id,d.track])).values()];if(r.some(d=>d.timescale<=0||!d.samples.length))throw new B("invalid_manifest","The calibrated panorama tracks do not contain a playable sample timeline.");const o=new Map;for(const d of n)o.has(d.track.id)||o.set(d.track.id,o.size===0||!i?e:i);const s=r.map(d=>xs(o.get(d.id)??e));try{await Promise.all(s.map(d=>ws(d)))}catch(d){throw s.forEach(m=>m.remove()),s.forEach(m=>cn(m)),new B("codec_unsupported",d instanceof Error?d.message:String(d))}const a=s.map(d=>{const m=new Rn(d);return m.flipY=Ua(t.textureOrigin),m.colorSpace=Ki,m.minFilter=Mt,m}),c=new Ta(new Uint8Array(128*64).fill(128),128,64,Ra,Pa);c.needsUpdate=true,c.minFilter=Mt;const l=t.lenses.slice(0,2),u=n.map(d=>a[r.indexOf(d.track)]),f=Fs(t,l,n,u,c);Ca(f,t.lenses);const y=new Zi(500,96,64);y.scale(-1,1,1);const p=new ea(y,f),h=new Ms(s,a);return h.play(),{mesh:p,update:()=>h.update(),play:()=>h.play(),pause:()=>h.pause(),seek:d=>h.seek(d),setPlaybackRate:d=>h.setPlaybackRate(d),close:()=>{h.close(),c.dispose(),a.forEach(d=>d.dispose()),y.dispose(),f.dispose(),s.forEach(d=>{d.remove(),cn(d)})},get duration(){return h.duration},get currentTime(){return h.currentTime},get paused(){return h.paused},streamSyncMs:0,dynamicSeam:false,stabilizationAvailable:false,stabilizationMode:"off",error:void 0,setStabilization:()=>"off"}}function xs(t){var i;const e=document.createElement("video");if(e.preload="auto",e.muted=true,e.loop=true,e.playsInline=true,e.crossOrigin="anonymous",e.setAttribute("aria-hidden","true"),e.style.display="none",typeof t=="string"||t instanceof URL)e.src=String(t);else{const n=t instanceof Blob?t:new Blob([bs(t)],{type:"video/mp4"}),r=URL.createObjectURL(n);Ma.set(e,r),e.src=r}return(i=document.body)==null||i.append(e),e.load(),e}function bs(t){if(t instanceof ArrayBuffer)return t;const e=new Uint8Array(t.buffer,t.byteOffset,t.byteLength),i=new Uint8Array(e.byteLength);return i.set(e),i.buffer}const Ma=new WeakMap;function ws(t){return t.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA?Promise.resolve():new Promise((e,i)=>{t.addEventListener("loadeddata",()=>e(),{once:true}),t.addEventListener("error",()=>i(new Error("The browser could not decode the calibrated INSV video track.")),{once:true})})}function cn(t){const e=Ma.get(t);e&&(URL.revokeObjectURL(e),Ma.delete(t))}function Fs(t,e,i,n,r){return new Aa({uniforms:{lens0:{value:n[0]},lens1:{value:n[1]},intrinsics0:{value:Yt(e[0])},intrinsics1:{value:Yt(e[1])},size0:{value:$t(e[0],i[0])},size1:{value:$t(e[1],i[1])},sourceRect0:{value:Xt(i[0],t.textureOrigin)},sourceRect1:{value:Xt(i[1],t.textureOrigin)},distortion0:{value:Ze(e[0])},distortion1:{value:Ze(e[1])},quaternion0:{value:ft(e[0])},quaternion1:{value:ft(e[1])},radialScale0:{value:St(e[0])},radialScale1:{value:St(e[1])},projectionKind:{value:t.projection.kind==="mei-extended"?1:0},xi0:{value:e[0].xi||0},xi1:{value:e[1].xi||0},tangential0:{value:ve(e[0].tangential)},tangential1:{value:ve(e[1].tangential)},thinPrism0:{value:Dt(e[0].thinPrism)},thinPrism1:{value:Dt(e[1].thinPrism)},sensorTilt0:{value:ve(e[0].sensorTilt)},sensorTilt1:{value:ve(e[1].sensorTilt)},seamMask:{value:r},useDynamicSeam:{value:0},exposureGain0:{value:[1,1,1]},exposureGain1:{value:[1,1,1]},stabilizationQuaternion:{value:[1,0,0,0]}},vertexShader:`
|
|
248
|
+
varying vec2 panoramaUv;
|
|
249
|
+
void main() {
|
|
250
|
+
panoramaUv = uv;
|
|
251
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
252
|
+
}
|
|
253
|
+
`,fragmentShader:`
|
|
254
|
+
precision highp float;
|
|
255
|
+
varying vec2 panoramaUv;
|
|
256
|
+
uniform sampler2D lens0;
|
|
257
|
+
uniform sampler2D lens1;
|
|
258
|
+
uniform vec4 intrinsics0;
|
|
259
|
+
uniform vec4 intrinsics1;
|
|
260
|
+
uniform vec2 size0;
|
|
261
|
+
uniform vec2 size1;
|
|
262
|
+
uniform vec4 sourceRect0;
|
|
263
|
+
uniform vec4 sourceRect1;
|
|
264
|
+
uniform vec4 distortion0;
|
|
265
|
+
uniform vec4 distortion1;
|
|
266
|
+
uniform vec4 quaternion0;
|
|
267
|
+
uniform vec4 quaternion1;
|
|
268
|
+
uniform float radialScale0;
|
|
269
|
+
uniform float radialScale1;
|
|
270
|
+
uniform int projectionKind;
|
|
271
|
+
uniform float xi0;
|
|
272
|
+
uniform float xi1;
|
|
273
|
+
uniform vec2 tangential0;
|
|
274
|
+
uniform vec2 tangential1;
|
|
275
|
+
uniform vec4 thinPrism0;
|
|
276
|
+
uniform vec4 thinPrism1;
|
|
277
|
+
uniform vec2 sensorTilt0;
|
|
278
|
+
uniform vec2 sensorTilt1;
|
|
279
|
+
uniform sampler2D seamMask;
|
|
280
|
+
uniform int useDynamicSeam;
|
|
281
|
+
uniform vec3 exposureGain0;
|
|
282
|
+
uniform vec3 exposureGain1;
|
|
283
|
+
uniform vec4 stabilizationQuaternion;
|
|
284
|
+
|
|
285
|
+
vec3 rotateQuaternion(vec4 q, vec3 v) {
|
|
286
|
+
vec3 u = q.yzw;
|
|
287
|
+
return 2.0 * dot(u, v) * u + (q.x * q.x - dot(u, u)) * v + 2.0 * q.x * cross(u, v);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
float radial(float theta, vec4 k, float scale, float fx) {
|
|
291
|
+
float limit = radians(85.0);
|
|
292
|
+
float t = min(theta, limit);
|
|
293
|
+
float t2 = t * t;
|
|
294
|
+
float polynomial = t * (1.0 + k.x*t2 + k.y*t2*t2 + k.z*t2*t2*t2 + k.w*t2*t2*t2*t2);
|
|
295
|
+
if (theta > limit) {
|
|
296
|
+
float derivative = 1.0 + 3.0*k.x*t2 + 5.0*k.y*t2*t2 + 7.0*k.z*t2*t2*t2 + 9.0*k.w*t2*t2*t2*t2;
|
|
297
|
+
polynomial += derivative * (theta - limit);
|
|
298
|
+
}
|
|
299
|
+
return scale * fx * polynomial;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
vec2 applySensorTilt(vec2 point, vec2 tilt) {
|
|
303
|
+
float cx = cos(tilt.x), sx = sin(tilt.x);
|
|
304
|
+
float cy = cos(tilt.y), sy = sin(tilt.y);
|
|
305
|
+
float rx = cy*point.x + sy*sx*point.y - sy*cx;
|
|
306
|
+
float ry = cx*point.y + sx;
|
|
307
|
+
float rz = sy*point.x - cy*sx*point.y + cy*cx;
|
|
308
|
+
float safeRz = abs(rz) > 0.000001 ? rz : (rz < 0.0 ? -0.000001 : 0.000001);
|
|
309
|
+
return vec2(cx*(cy*rx + sy*rz), cy*cx*ry - sx*rz) / safeRz;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
vec4 projectLens(vec3 body, vec4 intrinsics, vec2 imageSize, vec4 sourceRect, vec4 distortion, vec4 quaternion, float scale, float xi, vec2 tangential, vec4 thinPrism, vec2 sensorTilt, sampler2D image) {
|
|
313
|
+
vec4 lensQuaternion = projectionKind == 1 ? vec4(quaternion.x, -quaternion.yzw) : quaternion;
|
|
314
|
+
vec3 direction = rotateQuaternion(normalize(lensQuaternion), body);
|
|
315
|
+
float theta = acos(clamp(direction.z, -1.0, 1.0));
|
|
316
|
+
vec2 pixel;
|
|
317
|
+
if (projectionKind == 1) {
|
|
318
|
+
float denominator = direction.z + xi;
|
|
319
|
+
vec2 normalized = direction.xy / max(denominator, 0.000001);
|
|
320
|
+
float r2 = dot(normalized, normalized);
|
|
321
|
+
if (denominator <= 0.000001 || r2 > 16.0) return vec4(0.0);
|
|
322
|
+
float r4 = r2 * r2;
|
|
323
|
+
float radialFactor = 1.0 + distortion.x*r2 + distortion.y*r4 + distortion.z*r2*r4 + distortion.w*r4*r4;
|
|
324
|
+
float x = normalized.x;
|
|
325
|
+
float y = normalized.y;
|
|
326
|
+
vec2 distorted = vec2(
|
|
327
|
+
x*radialFactor + 2.0*tangential.x*x*y + tangential.y*(r2 + 2.0*x*x) + thinPrism.x*r2 + thinPrism.y*r4,
|
|
328
|
+
y*radialFactor + tangential.x*(r2 + 2.0*y*y) + 2.0*tangential.y*x*y + thinPrism.z*r2 + thinPrism.w*r4
|
|
329
|
+
);
|
|
330
|
+
pixel = intrinsics.zw + intrinsics.xy * applySensorTilt(distorted, sensorTilt);
|
|
331
|
+
} else {
|
|
332
|
+
float rho = max(length(direction.xy), 0.000001);
|
|
333
|
+
float radius = radial(theta, distortion, scale, intrinsics.x);
|
|
334
|
+
pixel = intrinsics.zw + radius * direction.xy / rho;
|
|
335
|
+
}
|
|
336
|
+
vec2 uv = sourceRect.xy + ((pixel + vec2(0.5)) / imageSize) * sourceRect.zw;
|
|
337
|
+
float validProjection = projectionKind == 1 ? float(direction.z + xi > 0.000001) : float(theta < radians(96.0));
|
|
338
|
+
float coverageDepth = 1.0;
|
|
339
|
+
if (projectionKind == 1) {
|
|
340
|
+
float edgeRadius = 0.475 * min(imageSize.x, imageSize.y);
|
|
341
|
+
coverageDepth = max(edgeRadius - distance(pixel, intrinsics.zw), 0.0);
|
|
342
|
+
validProjection *= float(coverageDepth > 0.0);
|
|
343
|
+
}
|
|
344
|
+
float valid = validProjection * float(all(greaterThanEqual(pixel, vec2(0.0))) && all(lessThanEqual(pixel, imageSize - vec2(1.0))));
|
|
345
|
+
float weight = projectionKind == 1
|
|
346
|
+
? valid * max(coverageDepth, 0.0001)
|
|
347
|
+
: valid * clamp((radians(95.0) - theta) / radians(10.0), 0.0, 1.0);
|
|
348
|
+
return vec4(texture2D(image, uv).rgb, weight);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
vec2 panoramaUvForDirection(vec3 direction) {
|
|
352
|
+
float longitude = projectionKind == 1 ? atan(direction.x, direction.z) : atan(-direction.y, direction.x);
|
|
353
|
+
float latitude = projectionKind == 1 ? asin(clamp(-direction.y, -1.0, 1.0)) : asin(clamp(direction.z, -1.0, 1.0));
|
|
354
|
+
return vec2(fract(longitude / 6.28318530718 + 0.5), latitude / 3.14159265359 + 0.5);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
void main() {
|
|
358
|
+
float longitude = panoramaUv.x * 6.28318530718 - 3.14159265359;
|
|
359
|
+
float latitude = (panoramaUv.y - 0.5) * 3.14159265359;
|
|
360
|
+
float cosLatitude = cos(latitude);
|
|
361
|
+
vec3 body = projectionKind == 1
|
|
362
|
+
? vec3(cosLatitude * sin(longitude), -sin(latitude), cosLatitude * cos(longitude))
|
|
363
|
+
: vec3(cosLatitude * sin(longitude + 1.57079632679), cosLatitude * cos(longitude + 1.57079632679), sin(latitude));
|
|
364
|
+
body = rotateQuaternion(normalize(stabilizationQuaternion), body);
|
|
365
|
+
vec2 bodyPanoramaUv = panoramaUvForDirection(body);
|
|
366
|
+
vec4 a = projectLens(body, intrinsics0, size0, sourceRect0, distortion0, quaternion0, radialScale0, xi0, tangential0, thinPrism0, sensorTilt0, lens0);
|
|
367
|
+
vec4 b = projectLens(body, intrinsics1, size1, sourceRect1, distortion1, quaternion1, radialScale1, xi1, tangential1, thinPrism1, sensorTilt1, lens1);
|
|
368
|
+
if (a.a <= 0.0 && b.a <= 0.0) { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); return; }
|
|
369
|
+
if (a.a <= 0.0 || b.a <= 0.0) { gl_FragColor = vec4((a.a > 0.0 ? a.rgb * exposureGain0 : b.rgb * exposureGain1), 1.0); return; }
|
|
370
|
+
float frontPreference = projectionKind == 1
|
|
371
|
+
? 1.0 - smoothstep(radians(75.0), radians(105.0), abs(bodyPanoramaUv.x * 6.28318530718 - 3.14159265359))
|
|
372
|
+
: 1.0;
|
|
373
|
+
float aWeight = projectionKind == 1 ? a.a * frontPreference : a.a;
|
|
374
|
+
float bWeight = projectionKind == 1 ? b.a * (1.0 - frontPreference) : b.a;
|
|
375
|
+
float total = aWeight + bWeight;
|
|
376
|
+
float lens1Weight = useDynamicSeam == 1 && a.a > 0.0 && b.a > 0.0 ? texture2D(seamMask, bodyPanoramaUv).r : bWeight / max(total, 0.0001);
|
|
377
|
+
gl_FragColor = vec4(mix(a.rgb * exposureGain0, b.rgb * exposureGain1, lens1Weight), 1.0);
|
|
378
|
+
}
|
|
379
|
+
`})}class Ms{constructor(e,i){L(this,"isClosed",false);this.videos=e,this.textures=i}get duration(){const e=this.videos.map(i=>i.duration).filter(Number.isFinite);return e.length?Math.min(...e):0}get currentTime(){var e;return((e=this.videos[0])==null?void 0:e.currentTime)||0}get paused(){var e;return((e=this.videos[0])==null?void 0:e.paused)??true}update(){if(!this.isClosed){if(this.videos.length>=2&&!this.paused){const e=this.currentTime;this.videos.slice(1).forEach(i=>{Math.abs(i.currentTime-e)>.05&&(i.currentTime=e)})}this.textures.forEach(e=>e.needsUpdate=true)}}play(){this.isClosed||this.videos.forEach(e=>{e.play().catch(()=>{})})}pause(){this.videos.forEach(e=>e.pause())}setPlaybackRate(e){this.isClosed||!Number.isFinite(e)||e<.5||e>2||this.videos.forEach(i=>{i.playbackRate=e})}seek(e){const i=Math.max(0,Math.min(Number.isFinite(e)?e:0,this.duration));this.videos.forEach(n=>{n.currentTime=i})}close(){this.isClosed||(this.isClosed=true,this.pause())}}function ta(t){const e=t.lenses.slice(0,2);if(e.length<2||!e.every(a=>Ss(a,t.projection.kind))||(t.cameraModel||"").replace(/^Insta360\s+/i,"").trim().toUpperCase()==="X5"&&(!["embedded","sidecar"].includes(t.calibrationSource)||!e.every(a=>a.distortionModel==="radtan_pro"?Ke(a.distortionCoeffs,13):Ke(a.thinPrism,4)&&Ke(a.sensorTilt,2))))return false;const n=Fi(e[0].extrinsicQuaternion),r=Fi(e[1].extrinsicQuaternion);if(Math.abs(n.reduce((a,c,l)=>a+c*r[l],0))>=.999)return false;const o=ln(e[0],t.projection.kind),s=ln(e[1],t.projection.kind);return o.reduce((a,c,l)=>a+c*s[l],0)<-.8}function ia(t){const e=t.lenses.slice(0,2);if(e.length<2)return;const i=e.map((n,r)=>{const o=n.sourceTrackId===void 0?t.tracks.length>=2?t.tracks[r]:void 0:t.tracks.find(a=>a.id===n.sourceTrackId),s=n.sourceRect??{x:0,y:0,width:1,height:1};return o&&zn(s)?{track:o,rect:s}:void 0});if(!(!i[0]||!i[1])&&!(i[0].track.id===i[1].track.id&&!e.every(n=>n.sourceRect)))return i}function Ds(t,e,i,n){return[i.rect.x+t*i.rect.width,i.rect.y+Is(e,n)*i.rect.height]}function Xt(t,e){const{x:i,y:n,width:r,height:o}=t.rect;return[i,e==="top-left"?n:1-n-o,r,o]}function zn(t){return[t.x,t.y,t.width,t.height].every(Number.isFinite)&&t.x>=0&&t.y>=0&&t.width>0&&t.height>0&&t.x+t.width<=1&&t.y+t.height<=1}function $t(t,e){return[t.width||e.track.width*e.rect.width,t.height||e.track.height*e.rect.height]}function ln(t,e){const i=ft(t);return Nn(e==="mei-extended"?i:_a(i),[0,0,1])}function Ss(t,e){const i=[t.width,t.height,t.fx,t.fy,t.cx,t.cy],n=t.extrinsicQuaternion;return!i.every(r=>typeof r=="number"&&Number.isFinite(r))||![t.width,t.height,t.fx,t.fy].every(r=>Number(r)>0)||Number(t.cx)<0||Number(t.cx)>=Number(t.width)||Number(t.cy)<0||Number(t.cy)>=Number(t.height)||(n==null?void 0:n.length)!==4||!n.every(Number.isFinite)||Math.hypot(...n)<.5?false:e==="dji-fisheye-lut"?Ke(t.distortion,4)&&Ke(t.radialLut1,14)&&Ke(t.radialLut2,14):t.distortionModel==="radtan_pro"&&!Ke(t.distortionCoeffs,13)?false:e==="mei-extended"&&Number.isFinite(t.xi)&&Number(t.xi)>0&&Ke(t.radial,4)&&Ke(t.tangential,2)}function Ke(t,e){return!!(t&&t.length>=e&&t.slice(0,e).every(i=>typeof i=="number"&&Number.isFinite(i)))}class Bn{constructor(e,i,n,r,o,s,a){L(this,"decoders");L(this,"queues");L(this,"indexes");L(this,"currentFrames");L(this,"startedAt",0);L(this,"clockTime",0);L(this,"clockRunning",false);L(this,"playbackRate",1);L(this,"feeding",false);L(this,"closed",false);L(this,"seekTargetUs",0);L(this,"isPaused",false);L(this,"pauseAfterSeek",false);L(this,"generation",0);L(this,"error");L(this,"duration");L(this,"seekEnd");L(this,"streamSyncMs",0);this.processor=e,this.tracks=i,this.textures=n,this.configs=r,this.onPair=o,this.prepareImu=s,this.onSeek=a,this.queues=i.map(()=>[]),this.indexes=i.map(()=>0),this.currentFrames=i.map(()=>{}),this.duration=Math.min(...i.map(Ys)),this.seekEnd=Math.min(...i.map(c=>c.samples.at(-1).pts/c.timescale)),this.decoders=[];try{r.forEach((c,l)=>{const u=new VideoDecoder({output:f=>{if(this.closed){f.close();return}this.queues[l].push(f);try{this.pairFrames()}catch(y){this.fail(y)}},error:f=>this.fail(f)});this.decoders.push(u),u.configure(c)})}catch(c){throw this.close(),c}}start(){this.startedAt=performance.now(),this.update()}update(){if(this.closed||this.isPaused||(this.pairFrames(),this.feeding||this.isPaused))return;if(this.duration>0&&this.currentTime>=this.duration){this.seek(0);return}this.feeding=true;const e=this.generation;this.feed(this.currentTime+(this.clockRunning?.25:0),e).catch(i=>this.fail(i)).finally(()=>{this.feeding=false})}get currentTime(){return Math.min(this.duration,this.clockTime+(this.isPaused||!this.clockRunning?0:(performance.now()-this.startedAt)/1e3*this.playbackRate))}get paused(){return this.isPaused}setPlaybackRate(e){this.closed||!Number.isFinite(e)||e<.5||e>2||(this.clockTime=this.currentTime,this.startedAt=performance.now(),this.playbackRate=e)}play(){this.closed||!this.isPaused||(this.startedAt=performance.now(),this.isPaused=false,this.update())}pause(){this.closed||this.isPaused||(this.clockTime=this.currentTime,this.isPaused=true)}seek(e){if(this.closed)return;const i=Math.max(0,Math.min(Number.isFinite(e)?e:0,this.seekEnd));this.pauseAfterSeek=this.isPaused,this.isPaused=false,this.clockTime=i,this.startedAt=performance.now(),this.clockRunning=false,this.seekTargetUs=i*1e6,this.generation+=1;const n=this.processor.seek(i);this.tracks.forEach((r,o)=>{this.indexes[o]=n[r.id]??0}),this.queues.flat().forEach(r=>r.close()),this.queues.forEach((r,o)=>{this.queues[o]=[]}),this.currentFrames.forEach((r,o)=>{r==null||r.close(),this.currentFrames[o]=void 0}),this.decoders.forEach((r,o)=>{r.reset(),r.configure(this.configs[o])}),this.onSeek(),this.update()}close(){this.closed||(this.closed=true,this.decoders.forEach(e=>{e.state!=="closed"&&e.close()}),this.queues.flat().forEach(e=>e.close()),this.currentFrames.forEach(e=>e==null?void 0:e.close()))}fail(e){this.error=e instanceof Error?e:new Error(String(e)),this.close()}async feed(e,i){if(await this.prepareImu(e),i!==this.generation)return;const n=!this.clockRunning;for(let r=0;r<this.tracks.length;r+=1){const o=this.tracks[r];let s=0;for(;this.indexes[r]<o.samples.length&&this.decoders[r].decodeQueueSize<4;){const a=this.indexes[r],c=o.samples[a];if(!n&&c.pts/o.timescale>e||n&&s>0)break;const l=await this.processor.readSample(o.id,a);if(this.closed||i!==this.generation)return;this.decoders[r].decode(ls(l)),this.indexes[r]+=1,s+=1}}}pairFrames(){if(!(this.closed||this.isPaused)){if(this.tracks.length===1){for(;this.queues[0].length&&this.frameDue(this.queues[0][0]);){const e=this.queues[0].shift();if(e.timestamp<this.seekTargetUs){e.close();continue}this.seekTargetUs=0,this.streamSyncMs=0,this.setFrame(0,e),this.startClock(e),this.onPair(e,e),this.finishSeek(e)}return}for(;this.queues[0].length&&this.queues[1].length;){const e=this.queues[0][0],i=this.queues[1][0];if(!this.frameDue(e)||!this.frameDue(i))break;const n=e.timestamp-i.timestamp,r=Math.max(e.duration||0,i.duration||0,16667)/2;if(Math.abs(n)<=r){if(this.queues[0].shift(),this.queues[1].shift(),Math.min(e.timestamp,i.timestamp)<this.seekTargetUs){e.close(),i.close();continue}this.seekTargetUs=0,this.streamSyncMs=Math.abs(n)/1e3,this.setFrame(0,e),this.setFrame(1,i),this.startClock(e),this.onPair(e,i),this.finishSeek(e)}else{const o=n<0?this.queues[0].shift():this.queues[1].shift();o==null||o.close()}}}}frameDue(e){return!this.clockRunning||e.timestamp<=this.currentTime*1e6}startClock(e){this.clockRunning||(this.clockTime=e.timestamp/1e6,this.startedAt=performance.now(),this.clockRunning=true)}finishSeek(e){this.pauseAfterSeek&&(this.clockTime=e.timestamp/1e6,this.isPaused=true,this.pauseAfterSeek=false)}setFrame(e,i){var n,r;(n=this.currentFrames[e])==null||n.close(),this.currentFrames[e]=i,(r=this.textures[e])==null||r.setFrame(i)}}class ks{constructor(e,i,n){L(this,"available");L(this,"mode");L(this,"samples",[]);L(this,"nextIndex",0);L(this,"loading",false);L(this,"generation",0);var r,o;this.processor=e,this.manifest=i,this.material=n,this.available=!!(i.metadataTrack&&((r=i.imu)==null?void 0:r.imuToCameraConfirmed)===true),this.mode=this.available?((o=i.imu)==null?void 0:o.stabilizationDefault)??"off":"off"}setMode(e){return this.mode=this.available?e:"off",(this.mode==="off"||this.mode==="camera")&&(this.material.uniforms.stabilizationQuaternion.value=[1,0,0,0]),this.mode}reset(){this.generation+=1,this.samples=[],this.nextIndex=0,this.material.uniforms.stabilizationQuaternion.value=[1,0,0,0]}async prepare(e){const i=this.manifest.metadataTrack;if(!this.available||this.mode!=="horizon-lock"||!i||this.loading)return;const n=this.samples.at(-1);if(n&&n.pts/n.timescale>=e+.25||(this.samples.length||(this.nextIndex=i.samples.findIndex(a=>a.pts/i.timescale>=Math.max(0,e-.25))),this.nextIndex<0||this.nextIndex>=i.samples.length))return;let r=0;const o=i.samples[this.nextIndex].pts+i.timescale;for(;this.nextIndex+r<i.samples.length&&r<120&&i.samples[this.nextIndex+r].pts<=o;)r+=1;this.loading=true;const s=this.generation;try{const a=await this.processor.readImuWindow(this.nextIndex,r);if(s!==this.generation)return;this.samples=[...this.samples.slice(-1),...a],this.nextIndex+=r}catch{this.setMode("off")}finally{this.loading=false}}apply(e){if(!this.available||this.mode!=="horizon-lock")return;const i=this.samples.filter(f=>Rs(f.cameraRotation));if(!i.length)return;let n=i.findIndex(f=>f.pts/f.timescale>=e);n<0&&(n=i.length-1);const r=Math.max(0,n-1),o=i[r],s=i[n],a=o.pts/o.timescale,c=s.pts/s.timescale-a,l=Ts(o.cameraRotation,s.cameraRotation,c>0?(e-a)/c:0),u=Math.atan2(2*(l[0]*l[3]+l[1]*l[2]),1-2*(l[2]**2+l[3]**2));this.material.uniforms.stabilizationQuaternion.value=Ps(_a(l),[Math.cos(u/2),0,0,Math.sin(u/2)])}}function Ts(t,e,i){const n=Fi(t);let r=Fi(e),o=n.reduce((l,u,f)=>l+u*r[f],0);o<0&&(r=r.map(l=>-l),o=-o);const s=Math.max(0,Math.min(1,i));if(o>.9995)return Fi(n.map((l,u)=>l+s*(r[u]-l)));const a=Math.acos(Math.max(-1,Math.min(1,o))),c=Math.sin(a);return n.map((l,u)=>(l*Math.sin((1-s)*a)+r[u]*Math.sin(s*a))/c)}function Rs(t){return(t==null?void 0:t.length)===4&&t.every(e=>typeof e=="number"&&Number.isFinite(e))}function Fi(t){const e=Math.hypot(...t)||1;return[0,1,2,3].map(i=>Number(t[i]??(i===0?1:0))/e)}function _a(t){return[t[0],-t[1],-t[2],-t[3]]}function Ps(t,e){return[t[0]*e[0]-t[1]*e[1]-t[2]*e[2]-t[3]*e[3],t[0]*e[1]+t[1]*e[0]+t[2]*e[3]-t[3]*e[2],t[0]*e[2]-t[1]*e[3]+t[2]*e[0]+t[3]*e[1],t[0]*e[3]+t[1]*e[2]-t[2]*e[1]+t[3]*e[0]]}const N=128,ae=64,Je=256;class jn{constructor(e,i,n,r,o){L(this,"lastAnalysis",-1/0);L(this,"busy",false);L(this,"closed",false);L(this,"previousLeft");L(this,"previousRight");L(this,"generation",0);L(this,"active",false);this.processor=e,this.manifest=i,this.lensSources=n,this.material=r,this.seamTexture=o}accept(e,i){const n=performance.now();if(this.closed||this.busy||n-this.lastAnalysis<500)return;this.lastAnalysis=n,this.busy=true;const r=this.generation,o=[e.clone(),i.clone()];this.analyze(o,r).catch(()=>{}).finally(()=>{o.forEach(s=>s.close()),this.busy=false})}async acceptImage(e){if(this.closed||this.busy)return;this.busy=true;const i=this.generation;await this.analyze([e,e],i).catch(()=>{}).finally(()=>{this.busy=false})}close(){this.closed=true}reset(){this.generation+=1,this.previousLeft=void 0,this.previousRight=void 0,this.lastAnalysis=-1/0,this.material.uniforms.useDynamicSeam.value=0,this.material.uniforms.exposureGain0.value=[1,1,1],this.material.uniforms.exposureGain1.value=[1,1,1],this.active=false}async analyze(e,i){const n=e.map(x=>Cs(x)),r=[new Uint8Array(N*ae*3),new Uint8Array(N*ae*3)],o=[new Float32Array(N*ae),new Float32Array(N*ae)],s=this.manifest.lenses.slice(0,2);let a=0;const c=[new Float64Array(3),new Float64Array(3)];for(let x=0;x<ae;x+=1)for(let v=0;v<N;v+=1){const w=Ns((v+.5)/N,(x+.5)/ae,this.manifest.projection.kind),k=x*N+v;for(let D=0;D<2;D+=1){const F=zs(w,s[D],this.manifest.projection.kind);if(!F)continue;const S=k*3,R=n[D],_=Ds(F[0],F[1],this.lensSources[D],this.manifest.textureOrigin);Es(R,Je,_[0],_[1],r[D],S),o[D][k]=F[2]*(this.manifest.projection.kind==="mei-extended"?Os((v+.5)/N,D):1)}if(o[0][k]>0&&o[1][k]>0){a+=1;const D=k*3;for(let F=0;F<3;F+=1)c[0][F]+=r[0][D+F],c[1][F]+=r[1][D+F]}}let l=[this.material.uniforms.exposureGain0.value,this.material.uniforms.exposureGain1.value];if(a>64){const x=_s(c[0],c[1]);l=this.active?x.map((v,w)=>v.map((k,D)=>l[w][D]*.8+k*.2)):x,this.material.uniforms.exposureGain0.value=l[0],this.material.uniforms.exposureGain1.value=l[1]}if(a<=64)return;const u=new Uint16Array(N*ae);u.fill(65535);for(let x=0;x<ae;x+=1)for(let v=0;v<N;v+=1){const w=x*N+v;if(o[0][w]<=0||o[1][w]<=0)continue;const k=w*3,D=Math.abs(r[0][k]*l[0][0]-r[1][k]*l[1][0])+Math.abs(r[0][k+1]*l[0][1]-r[1][k+1]*l[1][1])+Math.abs(r[0][k+2]*l[0][2]-r[1][k+2]*l[1][2]),F=v>0?w-1:w,S=x>0?w-N:w,R=hn(r[0],l[0],w,F,S),_=hn(r[1],l[1],w,F,S);u[w]=Math.min(65534,D+Math.abs(R-_)*2+Us(o[0][w],o[1][w]))}const f=this.manifest.projection.kind==="dji-fisheye-lut",y=f?$s(u,N,ae,N/4):u,p=N/2,[h,d]=await Promise.all([this.processor.computeSeam({width:p,height:ae,costs:mn(y,0),previous:this.previousLeft,temporalWeight:3,maxStep:2}),this.processor.computeSeam({width:p,height:ae,costs:mn(y,p),previous:this.previousRight,temporalWeight:3,maxStep:2})]);if(this.closed||i!==this.generation)return;if(!Ls([h,d],ae)){this.material.uniforms.useDynamicSeam.value=0,this.active=false;return}const m=dn(un(h.seam),this.previousLeft),g=dn(un(d.seam),this.previousRight);if(!fn(y,m,0)||!fn(y,g,p)){this.material.uniforms.useDynamicSeam.value=0,this.active=false;return}this.previousLeft=m,this.previousRight=g;const b=f?Xs(o,pn(m,N,N/4),pn(g.map(x=>x+p),N,N/4)):qs(o,m,g.map(x=>x+p));this.seamTexture.image.data.set(b),this.seamTexture.needsUpdate=true,this.material.uniforms.useDynamicSeam.value=1,this.active=true}}function As(t,e){if(!(t>0)||!(e>0))return[1,1];const i=Math.sqrt(Math.max(.64,Math.min(1.5625,e/t)));return[i,1/i]}function Ls(t,e,i=120){return t.length>0&&t.every(n=>Number.isFinite(n.cost)&&n.cost/e<=i)}function _s(t,e){const i=[0,1,2].map(n=>As(Number(t[n]),Number(e[n])));return[i.map(n=>n[0]),i.map(n=>n[1])]}function Us(t,e){const i=t+e;return!(t>0)||!(e>0)||!(i>0)?128:Math.round((1-2*Math.min(t,e)/i)*128)}function un(t,e=2){if(e<=0||t.length<=e*2)return t.slice();const i=t.slice();return i.fill(t[e],0,e),i.fill(t[t.length-e-1],t.length-e),i}function dn(t,e,i=4){return!e||e.length!==t.length||i<0?t.slice():t.map((n,r)=>Math.max(e[r]-i,Math.min(e[r]+i,n)))}function fn(t,e,i=0,n=N){return e.length>0&&e.every((r,o)=>r>=0&&i+r<n&&t[o*n+i+r]<65535)}function hn(t,e,i,n,r){const o=xa(t,e,i);return Math.abs(o-xa(t,e,n))+Math.abs(o-xa(t,e,r))}function xa(t,e,i){const n=i*3;return(t[n]*e[0]*77+t[n+1]*e[1]*150+t[n+2]*e[2]*29)/256}function Cs(t){const i=(typeof OffscreenCanvas<"u"?new OffscreenCanvas(Je,Je):Object.assign(document.createElement("canvas"),{width:Je,height:Je})).getContext("2d",{willReadFrequently:true});if(!i)throw new Error("A 2D canvas is required for panorama seam analysis.");return i.drawImage(t,0,0,Je,Je),i.getImageData(0,0,Je,Je).data}function Es(t,e,i,n,r=new Uint8Array(3),o=0){const s=Math.max(0,Math.min(e-1,i*e-.5)),a=Math.max(0,Math.min(e-1,n*e-.5)),c=Math.floor(s),l=Math.floor(a),u=Math.min(e-1,c+1),f=Math.min(e-1,l+1),y=s-c,p=a-l;for(let h=0;h<3;h+=1){const d=t[(l*e+c)*4+h]*(1-y)+t[(l*e+u)*4+h]*y,m=t[(f*e+c)*4+h]*(1-y)+t[(f*e+u)*4+h]*y;r[o+h]=Math.round(d*(1-p)+m*p)}return r}function Ua(t){return t!=="top-left"}function Is(t,e){return e==="top-left"?t:1-t}function zs(t,e,i){const n=ft(e),r=Nn(i==="mei-extended"?_a(n):n,t),o=Math.acos(Math.max(-1,Math.min(1,r[2])));let s,a;if(i==="mei-extended"){const p=r[2]+(e.xi||0);if(p<=1e-6)return;const h=r[0]/p,d=r[1]/p,m=h*h+d*d;if(!Number.isFinite(m)||m>16)return;const g=m*m,b=Ze(e),x=ve(e.tangential),v=Dt(e.thinPrism),w=1+b[0]*m+b[1]*g+b[2]*m*g+b[3]*g*g,k=h*w+2*x[0]*h*d+x[1]*(m+2*h*h)+v[0]*m+v[1]*g,D=d*w+x[0]*(m+2*d*d)+2*x[1]*h*d+v[2]*m+v[3]*g,F=e.distortionModel==="radtan_pro"?Bs([h,d],e.distortionCoeffs):Ws([k,D],ve(e.sensorTilt));s=(e.cx||0)+(e.fx||1)*F[0],a=(e.cy||0)+(e.fy||e.fx||1)*F[1]}else{if(o>=96*Math.PI/180)return;const p=Math.max(1e-6,Math.hypot(r[0],r[1])),h=Gs(o,e);s=(e.cx||0)+h*r[0]/p,a=(e.cy||0)+h*r[1]/p}const c=e.width||1,l=e.height||1;if(!Number.isFinite(s)||!Number.isFinite(a)||s<0||s>c-1||a<0||a>l-1)return;const u=(s+.5)/c,f=(a+.5)/l,y=.475*Math.min(c,l)-Math.hypot(s-(e.cx||0),a-(e.cy||0));if(!(i==="mei-extended"&&y<=0))return[u,f,i==="mei-extended"?y:js(o)]}function Bs([t,e],i){const n=t*t+e*e,r=n*n,o=1+i[0]*n+i[1]*r+i[2]*n*r+i[3]*r*r+i[4]*r*r*n,s=i[5]+i[7]*n,a=i[6]+i[8]*n;return[t*o+(n+2*t*t)*s+2*t*e*a+i[9]*n+i[11]*r,e*o+(n+2*e*e)*a+2*t*e*s+i[10]*n+i[12]*r]}function Ca(t,e){if(!e.some(r=>r.distortionModel==="radtan_pro"))return;const n=`${e.slice(0,2).map((r,o)=>{const s=Array.from({length:13},(a,c)=>{var l;return((l=r.distortionCoeffs)==null?void 0:l[c])??0});for(let a=0;a<3;a+=1)t.uniforms[`pro${o}_${a}`]={value:s.slice(a*4,a*4+4)};return t.uniforms[`pro${o}_last`]={value:s[12]},t.uniforms[`usePro${o}`]={value:r.distortionModel==="radtan_pro"?1:0},`uniform vec4 pro${o}_0, pro${o}_1, pro${o}_2;
|
|
380
|
+
uniform float pro${o}_last;
|
|
381
|
+
uniform int usePro${o};`}).join(`
|
|
382
|
+
`)}
|
|
383
|
+
vec2 radtanPro(vec2 p, vec4 a, vec4 b, vec4 c, float last) {
|
|
384
|
+
float r2 = dot(p, p), r4 = r2*r2;
|
|
385
|
+
float radial = 1.0+a.x*r2+a.y*r4+a.z*r2*r4+a.w*r4*r4+b.x*r4*r4*r2;
|
|
386
|
+
float u = b.y+b.w*r2, v = b.z+c.x*r2;
|
|
387
|
+
return vec2(p.x*radial+(r2+2.0*p.x*p.x)*u+2.0*p.x*p.y*v+c.y*r2+c.w*r4,
|
|
388
|
+
p.y*radial+(r2+2.0*p.y*p.y)*v+2.0*p.x*p.y*u+c.z*r2+last*r4);
|
|
389
|
+
}
|
|
390
|
+
vec2 calibratedDistortion(vec2 point, vec2 fallback, int lensIndex) {
|
|
391
|
+
if (lensIndex == 0 && usePro0 == 1) return radtanPro(point, pro0_0, pro0_1, pro0_2, pro0_last);
|
|
392
|
+
if (lensIndex == 1 && usePro1 == 1) return radtanPro(point, pro1_0, pro1_1, pro1_2, pro1_last);
|
|
393
|
+
return fallback;
|
|
394
|
+
}
|
|
395
|
+
`;t.fragmentShader=t.fragmentShader.replace("precision highp float;",`precision highp float;
|
|
396
|
+
${n}`).replace("sampler2D image) {","sampler2D image, int lensIndex) {").replace("intrinsics.xy * applySensorTilt(distorted, sensorTilt)","intrinsics.xy * calibratedDistortion(normalized, applySensorTilt(distorted, sensorTilt), lensIndex)").replace("sensorTilt0, lens0);","sensorTilt0, lens0, 0);").replace("sensorTilt1, lens1);","sensorTilt1, lens1, 1);")}function js(t){return Math.max(0,Math.min(1,(95*Math.PI/180-t)/(10*Math.PI/180)))}function Ns(t,e,i){const n=t*Math.PI*2-Math.PI,r=(e-.5)*Math.PI,o=Math.cos(r);return i==="mei-extended"?[o*Math.sin(n),-Math.sin(r),o*Math.cos(n)]:[o*Math.sin(n+Math.PI/2),o*Math.cos(n+Math.PI/2),Math.sin(r)]}function Os(t,e){const i=t*360-180,n=1-Vs(75,105,Math.abs(i));return e===0?n:1-n}function Vs(t,e,i){const n=Math.max(0,Math.min(1,(i-t)/(e-t)));return n*n*(3-2*n)}function Ws(t,e){const[i,n]=t,[r,o]=e,s=Math.cos(r),a=Math.sin(r),c=Math.cos(o),l=Math.sin(o),u=c*i+l*a*n-l*s,f=s*n+a,y=l*i-c*a*n+c*s,h=1/(Math.abs(y)>1e-6?y:y<0?-1e-6:1e-6);return[s*(c*u+l*y)*h,(c*s*f-a*y)*h]}function Nn(t,e){const i=Math.hypot(...t)||1,[n,r,o,s]=t.map(u=>u/i),a=r*e[0]+o*e[1]+s*e[2],c=[o*e[2]-s*e[1],s*e[0]-r*e[2],r*e[1]-o*e[0]],l=n*n-r*r-o*o-s*s;return[2*a*r+l*e[0]+2*n*c[0],2*a*o+l*e[1]+2*n*c[1],2*a*s+l*e[2]+2*n*c[2]]}function Gs(t,e){const i=85*Math.PI/180,n=Math.min(t,i),r=Ze(e),o=n+r[0]*n**3+r[1]*n**5+r[2]*n**7+r[3]*n**9,s=1+3*r[0]*n**2+5*r[1]*n**4+7*r[2]*n**6+9*r[3]*n**8;return St(e)*(e.fx||1)*(t>i?o+s*(t-i):o)}function mn(t,e){const i=N/2,n=new Uint16Array(i*ae);for(let r=0;r<ae;r+=1)n.set(t.subarray(r*N+e,r*N+e+i),r*i);return n}function qs(t,e,i){const n=new Uint8Array(N*ae);for(let r=0;r<ae;r+=1){let o=t[1][r*N]>t[0][r*N];for(let s=0;s<N;s+=1)(s===e[r]||s===i[r])&&(o=!o),n[r*N+s]=o?255:0}return On(n,false)}function Xs(t,e,i){const n=new Uint8Array(N*ae),r=N/4,o=ae/8;for(let s=0;s<ae;s+=1){if(s<o||s>=ae-o){for(let f=0;f<N;f+=1){const y=s*N+f,p=t[0][y]+t[1][y];n[y]=p>0?Math.round(255*t[1][y]/p):128}continue}const a=Math.min(e[s],i[s]),c=Math.max(e[s],i[s]),l=r>=a&&r<c,u=t[1][s*N+r]>t[0][s*N+r];for(let f=0;f<N;f+=1){const y=(f>=a&&f<c)===l;n[s*N+f]=(y?u:!u)?255:0}}return On(n,true)}function On(t,e){const i=t.slice();for(let n=0;n<ae;n+=1)for(let r=0;r<N;r+=1){const o=n*N+r,s=t[o];if(s!==0&&s!==255)continue;const a=r>0?r-1:e?N-1:r,c=r+1<N?r+1:e?0:r;(t[n*N+a]===255-s||t[n*N+c]===255-s)&&(i[o]=s===0?64:191)}return i}function $s(t,e,i,n){const r=new Uint16Array(t.length);for(let o=0;o<i;o+=1)for(let s=0;s<e;s+=1)r[o*e+(s+n)%e]=t[o*e+s];return r}function pn(t,e,i){return t.map(n=>(n-i+e)%e)}function Yt(t){return[t.fx||1,t.fy||t.fx||1,t.cx||0,t.cy||0]}function Ze(t){const e=t.radial??t.distortion;return[0,1,2,3].map(i=>Number((e==null?void 0:e[i])??0))}function ve(t){return[Number((t==null?void 0:t[0])??0),Number((t==null?void 0:t[1])??0)]}function Dt(t){return[0,1,2,3].map(e=>Number((t==null?void 0:t[e])??0))}function ft(t){const e=t.extrinsicQuaternion;return(e==null?void 0:e.length)===4&&e.every(Number.isFinite)?e:[1,0,0,0]}function Ys(t){const e=t.samples.at(-1);return e&&t.timescale>0?(e.pts+e.duration)/t.timescale:0}function St(t){const e=t.radialLut1,i=t.radialLut2;if(!e||!i||e.length<14||i.length<14||!t.fx)return 1;let n=0;for(let u=1;u<14;u+=1)n+=Math.hypot(e[u]-(t.cx||0),i[u]-(t.cy||0));n/=13;const r=Math.PI/2,o=85*Math.PI/180,s=Ze(t),a=u=>u+s[0]*u**3+s[1]*u**5+s[2]*u**7+s[3]*u**9,c=1+3*s[0]*o**2+5*s[1]*o**4+7*s[2]*o**6+9*s[3]*o**8,l=t.fx*(a(o)+c*(r-o));return l>0?n/l:1}const ee=Object.freeze({mode:"auto",projection:"auto",autoplay:false,muted:true,loop:true,enableGyro:false,gyroMaxPitchDeg:85,gyroYawOffsetDeg:0,gyroPitchOffsetDeg:0,gyroSmoothing:.15,stabilize:false,stabilizeMode:"roll",stabilizeStrength:.06,stabilizeMaxRollDeg:45,telemetryURL:"",telemetryMaxSamples:2e3,imuRollGyroAxis:"gyro_y",imuRollAccelAxes:"accel_x,accel_y",equirectFlipX:true,equirectFlipY:false,dualFisheyeFlipX:true,dualFisheyeFlipY:false,dualFisheyeFovDeg:190,dualFisheyeFrontLens:"right",dualFisheyeSeamBlendDeg:12,dualFisheyeSeamLongitudesDeg:[90,270],dualFisheyeGainFront:1,dualFisheyeGainBack:1,dualFisheyeAutoGain:true,dualFisheyeRefineFocal:false,dualFisheyeVideoRegistration:false,dualFisheyeCalibration:null,dragYawSign:-1,dragPitchSign:1,fovDeg:75,maxFovDeg:95,minFovDeg:35,progressiveUpgrade:true,progressivePollIntervalMS:1200,background:"#000",maxRenderPixelRatio:0,preferredImageWidth:0,videoMetadataTimeoutMS:15e3}),yn=[16384,8192,4096,2048];function O(t,e,i){return Math.min(i,Math.max(e,t))}function me(t,e){const i=Number(t);return Number.isFinite(i)?i:e}function de(t,e,i=0){const n=Array.isArray(t)?t:e,r=i||n.length,o=[];for(let s=0;s<r;s+=1)o.push(me(n&&n[s],e[s]??0));return o}function Da(t,e){const i=de(t,e,2);return[Math.max(1,Math.round(i[0])),Math.max(1,Math.round(i[1]))]}function Sa(t){return(me(t,0)%360+360)%360}function aa(t,e=ee.dualFisheyeSeamLongitudesDeg){const i=Array.isArray(t)&&t.length>=2?t:e,n=Sa(i[0]),r=Sa(i[1]);return Math.abs(n-r)<.001?e.slice():[n,r]}function gn(t,e){if(t instanceof Uint8Array)return!e||t.length===e?t:t.length>e?t.slice(0,e):null;if(Array.isArray(t)){const i=Uint8Array.from(t.map(n=>O(Math.round(me(n,0)),0,255)));if(!e||i.length===e)return i}return null}function Vn(t){const e={...ee,...t||{}};if(e.fovDeg=O(Number(e.fovDeg)||ee.fovDeg,1,179),e.maxFovDeg=O(Number(e.maxFovDeg)||ee.maxFovDeg,1,179),e.minFovDeg=O(Number(e.minFovDeg)||ee.minFovDeg,1,179),e.minFovDeg>e.maxFovDeg){const r=e.minFovDeg;e.minFovDeg=e.maxFovDeg,e.maxFovDeg=r}e.fovDeg=O(e.fovDeg,e.minFovDeg,e.maxFovDeg),e.mode=String(e.mode||"auto"),e.mode!=="auto"&&e.mode!=="flat"&&e.mode!=="equirect"&&(e.mode="auto"),e.projection=String(e.projection||ee.projection),e.projection!=="auto"&&e.projection!=="equirect"&&e.projection!=="dual_fisheye"&&(e.projection="auto"),e.background=String(e.background||ee.background),e.autoplay=!!e.autoplay,e.muted=!!e.muted,e.loop=!!e.loop,e.enableGyro=!!e.enableGyro,e.gyroMaxPitchDeg=O(Number(e.gyroMaxPitchDeg)||ee.gyroMaxPitchDeg,1,89),e.gyroYawOffsetDeg=Number(e.gyroYawOffsetDeg)||0,e.gyroPitchOffsetDeg=Number(e.gyroPitchOffsetDeg)||0,e.gyroSmoothing=O(Number(e.gyroSmoothing)||ee.gyroSmoothing,0,1),e.stabilize=!!e.stabilize,e.stabilizeMode=String(e.stabilizeMode||ee.stabilizeMode),e.stabilizeMode!=="roll"&&e.stabilizeMode!=="horizon"&&(e.stabilizeMode="roll"),e.stabilizeStrength=O(Number(e.stabilizeStrength)||ee.stabilizeStrength,0,1),e.stabilizeMaxRollDeg=O(Number(e.stabilizeMaxRollDeg)||ee.stabilizeMaxRollDeg,0,180),e.telemetryURL=String(e.telemetryURL||""),e.telemetryMaxSamples=Math.max(0,Number(e.telemetryMaxSamples)||ee.telemetryMaxSamples),e.imuRollGyroAxis=String(e.imuRollGyroAxis||ee.imuRollGyroAxis),e.imuRollAccelAxes=String(e.imuRollAccelAxes||ee.imuRollAccelAxes),e.equirectFlipX=e.equirectFlipX!==false,e.equirectFlipY=!!e.equirectFlipY,e.dualFisheyeFlipX=e.dualFisheyeFlipX!==false,e.dualFisheyeFlipY=!!e.dualFisheyeFlipY,e.dualFisheyeFovDeg=O(Number(e.dualFisheyeFovDeg)||ee.dualFisheyeFovDeg,120,220),e.dualFisheyeFrontLens=String(e.dualFisheyeFrontLens||ee.dualFisheyeFrontLens)==="left"?"left":"right",e.dualFisheyeSeamBlendDeg=O(Number(e.dualFisheyeSeamBlendDeg)||ee.dualFisheyeSeamBlendDeg,0,45),e.dualFisheyeSeamLongitudesDeg=aa(e.dualFisheyeSeamLongitudesDeg),e.dualFisheyeGainFront=Math.max(.2,Number(e.dualFisheyeGainFront)||ee.dualFisheyeGainFront),e.dualFisheyeGainBack=Math.max(.2,Number(e.dualFisheyeGainBack)||ee.dualFisheyeGainBack),e.dualFisheyeAutoGain=e.dualFisheyeAutoGain!==false,e.dualFisheyeRefineFocal=e.dualFisheyeRefineFocal===true,e.dualFisheyeVideoRegistration=e.dualFisheyeVideoRegistration===true,e.dualFisheyeCalibration=e.dualFisheyeCalibration&&typeof e.dualFisheyeCalibration=="object"?e.dualFisheyeCalibration:null;const i=Number(e.dragYawSign);e.dragYawSign=i===-1?-1:1;const n=Number(e.dragPitchSign);return e.dragPitchSign=n===-1?-1:1,e.progressiveUpgrade=e.progressiveUpgrade!==false,e.progressivePollIntervalMS=Math.max(250,Number(e.progressivePollIntervalMS)||ee.progressivePollIntervalMS),e.maxRenderPixelRatio=Math.max(0,Number(e.maxRenderPixelRatio)||0),e.preferredImageWidth=Math.max(0,Math.round(Number(e.preferredImageWidth)||0)),e.videoMetadataTimeoutMS=Math.max(0,me(e.videoMetadataTimeoutMS,ee.videoMetadataTimeoutMS)),e}function fe(t,e){const i=Array.isArray(t)?t:e;return[me(i&&i[0],e[0]),me(i&&i[1],e[1])]}function ka(t,e){const i=Math.max(1e-4,Number(e)||0);return[me(t&&t[0],0)/i,me(t&&t[1],0)/i]}function Wn(t,e){const i=Math.abs(t[0]-e[0]),n=Math.abs(t[1]-e[1]);return n>i?[.475,Math.max(1e-4,n*.475)]:[Math.max(1e-4,i*.475),.475]}function Ot(t,e){const i=Array.isArray(t)?t:e,n=me(i&&i[0],e[0]),r=me(i&&i[1],e[1]),o=me(i&&i[2],e[2]),s=Math.hypot(n,r,o);return s<=1e-6?e.slice():[n/s,r/s,o/s]}function vn(t,e=[1,0,0,0]){const i=Array.isArray(t)?t:e,n=de(i,e,4),r=Math.hypot(...n)||1;return n.map(o=>o/r)}function Qs(t,e){if(!t||typeof t!="object")return null;const i=e==="left"?[.25,.5]:[.75,.5],n=e==="left"?[.75,.5]:[.25,.5],r={center:i,focal:[.247,.494],principalOffset:[0,0],scale:[.247,.494],radial:[0,0,0,0],radialLUT1:[],radialLUT2:[],radialScale:1,tangential:[0,0],projectionModel:"equidistant",xi:0,thinPrism:[0,0,0,0],sensorTilt:[0,0],asymmetric:[0,0,0,0],axis:[0,0,-1],right:[1,0,0],up:[0,1,0]},o={center:n,focal:[.247,.494],principalOffset:[0,0],scale:[.247,.494],radial:[0,0,0,0],radialLUT1:[],radialLUT2:[],radialScale:1,tangential:[0,0],projectionModel:"equidistant",xi:0,thinPrism:[0,0,0,0],sensorTilt:[0,0],asymmetric:[0,0,0,0],axis:[0,0,1],right:[-1,0,0],up:[0,1,0]},s=t.front&&typeof t.front=="object"?t.front:{},a=t.back&&typeof t.back=="object"?t.back:{},c=t.pipeline&&typeof t.pipeline=="object"?t.pipeline:{},l=Hs(t.remap),u=String(t.textureOrigin??t.texture_origin??"").trim().toLowerCase(),f=Da(t.imageSize??t.image_size,[0,0]),y=fe(s.center,r.center),p=fe(a.center,o.center),h=Wn(y,p);return{textureOrigin:u==="top-left"||u==="bottom-left"?u:"",imageSize:f,front:{center:y,focal:fe(s.focal,r.focal),principalOffset:fe(s.principalOffset,r.principalOffset),rotationQuat:vn(s.rotationQuat||s.rotation_quat),scale:fe(s.scale,r.scale),validRadius:fe(s.validRadius||s.valid_radius,h),radial:de(s.radial,r.radial,4),radialLUT1:de(s.radialLUT1||s.radial_lut_1,r.radialLUT1,14),radialLUT2:de(s.radialLUT2||s.radial_lut_2,r.radialLUT2,14),radialScale:Math.max(0,me(s.radialScale??s.radial_scale,r.radialScale)),tangential:fe(s.tangential,r.tangential),projectionModel:String(s.projectionModel||s.projection_model||r.projectionModel).replace(/-/g,"_"),xi:me(s.xi,r.xi),thinPrism:de(s.thinPrism||s.thin_prism,r.thinPrism,4),sensorTilt:fe(s.sensorTilt||s.sensor_tilt,r.sensorTilt),distortionModel:String(s.distortionModel||s.distortion_model||""),distortionCoeffs:de(s.distortionCoeffs||s.distortion_coeffs,[],13),translationM:de(s.translationM,[0,0,0],3),asymmetric:de(s.asymmetric,r.asymmetric,4),axis:Ot(s.axis,r.axis),right:Ot(s.right,r.right),up:Ot(s.up,r.up)},back:{center:p,focal:fe(a.focal,o.focal),principalOffset:fe(a.principalOffset,o.principalOffset),rotationQuat:vn(a.rotationQuat||a.rotation_quat),scale:fe(a.scale,o.scale),validRadius:fe(a.validRadius||a.valid_radius,h),radial:de(a.radial,o.radial,4),radialLUT1:de(a.radialLUT1||a.radial_lut_1,o.radialLUT1,14),radialLUT2:de(a.radialLUT2||a.radial_lut_2,o.radialLUT2,14),radialScale:Math.max(0,me(a.radialScale??a.radial_scale,o.radialScale)),tangential:fe(a.tangential,o.tangential),projectionModel:String(a.projectionModel||a.projection_model||o.projectionModel).replace(/-/g,"_"),xi:me(a.xi,o.xi),thinPrism:de(a.thinPrism||a.thin_prism,o.thinPrism,4),sensorTilt:fe(a.sensorTilt||a.sensor_tilt,o.sensorTilt),distortionModel:String(a.distortionModel||a.distortion_model||""),distortionCoeffs:de(a.distortionCoeffs||a.distortion_coeffs,[],13),translationM:de(a.translationM,[0,0,0],3),asymmetric:de(a.asymmetric,o.asymmetric,4),axis:Ot(a.axis,o.axis),right:Ot(a.right,o.right),up:Ot(a.up,o.up)},pipeline:{featherWidthPx:Math.max(0,Number(c.featherWidthPx)||0),seamLongitudesDeg:aa(c.seamLongitudesDeg)},remap:l}}function Hs(t){if(!t||typeof t!="object")return null;const e=Da([t.width,t.height],[1,1]),i=e[0],n=e[1],r=i*n*4,o=gn(t.front,r),s=gn(t.back,r);return!o||!s?null:{strategy:"lut_rgba8",width:i,height:n,front:o,back:s,meshResolution:Da(t.meshResolution,[32,16])}}function Js(t,e){const i=Number(t)||0,n=Number(e)||0;return i>0&&n>i*1.6&&Math.abs(n/i-2)<=.15}function Ks(t){const e=String(t||"").trim();if(!e)return{r:0,g:0,b:0,a:1};if(e.startsWith("#")){const o=e.slice(1);if(o.length===3){const s=parseInt(o[0]+o[0],16),a=parseInt(o[1]+o[1],16),c=parseInt(o[2]+o[2],16);return{r:s,g:a,b:c,a:1}}if(o.length===6){const s=parseInt(o.slice(0,2),16),a=parseInt(o.slice(2,4),16),c=parseInt(o.slice(4,6),16);return{r:s,g:a,b:c,a:1}}if(o.length===8){const s=parseInt(o.slice(0,2),16),a=parseInt(o.slice(2,4),16),c=parseInt(o.slice(4,6),16),l=parseInt(o.slice(6,8),16)/255;return{r:s,g:a,b:c,a:Number.isFinite(l)?l:1}}}const i=document.createElement("div");i.style.color=e,document.body.appendChild(i);const n=getComputedStyle(i).color||"rgb(0,0,0)";document.body.removeChild(i);const r=n.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([0-9.]+))?\)/);return r?{r:O(Number(r[1])||0,0,255),g:O(Number(r[2])||0,0,255),b:O(Number(r[3])||0,0,255),a:r[4]==null?1:O(Number(r[4])||1,0,1)}:{r:0,g:0,b:0,a:1}}function xn(t,e,i){const n=t.createShader(e);if(!n)throw new Error("createShader failed");if(t.shaderSource(n,i),t.compileShader(n),!t.getShaderParameter(n,t.COMPILE_STATUS)){const r=t.getShaderInfoLog(n)||"";throw t.deleteShader(n),new Error(`shader compile failed: ${r}`)}return n}function Zs(t,e,i){const n=xn(t,t.VERTEX_SHADER,e),r=xn(t,t.FRAGMENT_SHADER,i),o=t.createProgram();if(!o)throw new Error("createProgram failed");if(t.attachShader(o,n),t.attachShader(o,r),t.linkProgram(o),t.deleteShader(n),t.deleteShader(r),!t.getProgramParameter(o,t.LINK_STATUS)){const s=t.getProgramInfoLog(o)||"";throw t.deleteProgram(o),new Error(`program link failed: ${s}`)}return o}function Yi(t){return t?t instanceof HTMLVideoElement?{width:Math.max(1,t.videoWidth||t.clientWidth||1),height:Math.max(1,t.videoHeight||t.clientHeight||1)}:t instanceof HTMLImageElement?{width:Math.max(1,t.naturalWidth||t.width||t.clientWidth||1),height:Math.max(1,t.naturalHeight||t.height||t.clientHeight||1)}:{width:Math.max(1,t.width||t.clientWidth||1),height:Math.max(1,t.height||t.clientHeight||1)}:{width:1,height:1}}const z=128,X=64,Ea=256,Be=new Int32Array(new Uint8Array([0,0,0,255]).buffer)[0],Gn=new WeakSet;function vi(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function ec(t,e,i=1){return[t[0]-e[0]*i,t[1]-e[1]*i,t[2]-e[2]*i]}function bn(t){return Math.hypot(t[0],t[1],t[2])}function qn(t,e,i=false){const n=(t-.5)*Math.PI*2,r=(.5-e)*Math.PI,o=Math.cos(r);return[o*Math.sin(n),Math.sin(r),(i?1:-1)*o*Math.cos(n)]}function tc(t,e=false){const i=Math.atan2(t[0],e?t[2]:-t[2]),n=Math.asin(O(e?-t[1]:t[1],-1,1));return[i/(Math.PI*2)+.5,e?n/Math.PI+.5:.5-n/Math.PI]}function Di(t,e,i,n,r,o,s=0){const a=O(n*e-.5,0,e-1),c=O(r*i-.5,0,i-1),l=Math.floor(a),u=Math.floor(c),f=Math.min(e-1,l+1),y=Math.min(i-1,u+1),p=a-l,h=c-u;for(let d=0;d<3;d+=1){const m=t[(u*e+l)*4+d]*(1-p)+t[(u*e+f)*4+d]*p,g=t[(y*e+l)*4+d]*(1-p)+t[(y*e+f)*4+d]*p;o[s+d]=m*(1-h)+g*h}return o}function ic(t,e,i,n=false){var l;const{pixels:r,width:o,height:s}=t,{uv:a,weights:c}=e;if(!n){for(let u=0;u<2;u++)for(let f=0;f<c[u].length;f++)c[u][f]>0&&Di(r,o,s,a[u][f*2],a[u][f*2+1],i[u],f*3);return}if(((l=e.sampling)==null?void 0:l.width)!==o||e.sampling.height!==s){const u=c.map((f,y)=>{let p=0;for(let g=0;g<f.length;g++)f[g]>0&&p++;const h=new Uint32Array(p),d=new Uint32Array(p*4),m=new Float64Array(p*2);for(let g=0,b=0;g<f.length;g++){if(!(f[g]>0))continue;const x=O(a[y][g*2]*o-.5,0,o-1),v=O(a[y][g*2+1]*s-.5,0,s-1),w=Math.floor(x),k=Math.floor(v),D=Math.min(o-1,w+1),F=Math.min(s-1,k+1);h[b]=g*3,d[b*4]=(k*o+w)*4,d[b*4+1]=(k*o+D)*4,d[b*4+2]=(F*o+w)*4,d[b*4+3]=(F*o+D)*4,m[b*2]=x-w,m[b*2+1]=v-k,b++}return{indices:h,taps:d,fractions:m}});e.sampling={width:o,height:s,lenses:u}}for(let u=0;u<2;u++){const{indices:f,taps:y,fractions:p}=e.sampling.lenses[u],h=i[u];for(let d=0;d<f.length;d++){const m=y[d*4],g=y[d*4+1],b=y[d*4+2],x=y[d*4+3],v=f[d],w=p[d*2],k=p[d*2+1],D=1-w,F=1-k,S=r[m]*D+r[g]*w,R=r[b]*D+r[x]*w;h[v]=S*F+R*k;const _=r[m+1]*D+r[g+1]*w,T=r[b+1]*D+r[x+1]*w;h[v+1]=_*F+T*k;const A=r[m+2]*D+r[g+2]*w,C=r[b+2]*D+r[x+2]*w;h[v+2]=A*F+C*k}}}function ac(t,e,i){if(!t||!(t.front instanceof Uint8Array)||!(t.back instanceof Uint8Array))return null;const n=r=>{const o=O(Math.round(e*(t.width-1)),0,t.width-1),a=(O(Math.round((1-i)*(t.height-1)),0,t.height-1)*t.width+o)*4;return{uv:[r[a]/255,r[a+1]/255],valid:r[a+2]>127,confidence:r[a+3]/255}};return[n(t.front),n(t.back)]}function rc(t,e){const i=Math.cos(e[0]),n=Math.sin(e[0]),r=Math.cos(e[1]),o=Math.sin(e[1]),s=r*t[0]+o*n*t[1]-o*i,a=i*t[1]+n,c=o*t[0]-r*n*t[1]+r*i,l=Math.abs(c)>1e-6?c:c<0?-1e-6:1e-6;return[i*(r*s+o*c)/l,(r*i*a-n*c)/l]}function kt(t,e,i,n,r,o,s=0){var p;const a=n&&Array.isArray(e.rotationQuat)?(()=>{const h=Ba({w:e.rotationQuat[0],x:-e.rotationQuat[1],y:-e.rotationQuat[2],z:-e.rotationQuat[3]},t[0],t[1],t[2]);return[h.x,h.y,h.z]})():[vi(t,e.right),-vi(t,e.up),vi(t,e.axis)];if(n&&s>0){for(let d=0;d<3;d+=1)a[d]=a[d]*s+(((p=e.translationM)==null?void 0:p[d])||0);const h=bn(a);if(h<=1e-9)return null;for(let d=0;d<3;d+=1)a[d]/=h}const c=a[2],l=r?Math.atan2(Math.hypot(a[0],a[1]),c):Math.acos(O(c,-1,1));if(!n&&l>i||r&&l>=96*Math.PI/180)return null;let u;if(n){const h=a[2]+e.xi;if(h<=1e-6)return null;const d=a[0]/h,m=a[1]/h,g=d*d+m*m;if(g>16)return null;const b=g*g,x=1+e.radial[0]*g+e.radial[1]*b+e.radial[2]*g*b+e.radial[3]*b*b,v=e.distortionModel==="radtan_pro"?nc(d,m,e.distortionCoeffs):rc([d*x+2*e.tangential[0]*d*m+e.tangential[1]*(g+2*d*d)+e.thinPrism[0]*g+e.thinPrism[1]*b,m*x+e.tangential[0]*(g+2*m*m)+2*e.tangential[1]*d*m+e.thinPrism[2]*g+e.thinPrism[3]*b],e.sensorTilt||[0,0]);u=[e.center[0]+e.principalOffset[0]+e.focal[0]*v[0],e.center[1]+e.principalOffset[1]+e.focal[1]*v[1]]}else if(r){const h=Math.hypot(a[0],a[1]);if(h<=1e-6)u=[e.center[0]+e.principalOffset[0],e.center[1]+e.principalOffset[1]];else if(e.distortionModel==="dji_fisheye_5"){const d=l*l,m=e.distortionCoeffs,g=l*(1+d*(m[0]+d*(m[1]+d*(m[2]+d*(m[3]+d*m[4]))))),b=g*a[0]/h,x=g*a[1]/h,v=b*b+x*x,[w,k]=e.tangential;u=[e.center[0]+e.principalOffset[0]+e.focal[0]*(b+2*w*b*x+k*(v+2*b*b)),e.center[1]+e.principalOffset[1]+e.focal[1]*(x+w*(v+2*x*x)+2*k*b*x)]}else{const d=85*Math.PI/180,m=Math.min(l,d),g=m*m,b=m*(1+e.radial[0]*g+e.radial[1]*g*g+e.radial[2]*g*g*g+e.radial[3]*g*g*g*g),x=1+3*e.radial[0]*g+5*e.radial[1]*g*g+7*e.radial[2]*g*g*g+9*e.radial[3]*g*g*g*g,v=o*(l>d?b+x*(l-d):b);u=[e.center[0]+e.principalOffset[0]+e.focal[0]*v*a[0]/h,e.center[1]+e.principalOffset[1]+e.focal[1]*v*a[1]/h]}}else{const h=ec(t,e.axis,c),d=bn(h),m=d>1e-5?[vi(h,e.right)/d,-vi(h,e.up)/d]:[0,0],g=l*l,b=e.radial||[0,0,0,0],x=l*(1+b[0]*g+b[1]*g**2+b[2]*g**3+b[3]*g**4),v=x*m[0],w=x*m[1],k=v*v+w*w,D=e.tangential||[0,0],F=e.asymmetric||[0,0,0,0],S=2*D[0]*v*w+D[1]*(k+2*v*v),R=D[0]*(k+2*w*w)+2*D[1]*v*w,_=F[0]*v+F[1]*w,T=F[2]*v+F[3]*w,A=e.focal||ka(e.scale,i),C=e.principalOffset||[0,0];u=[e.center[0]+C[0]+A[0]*(v+S+_),e.center[1]+C[1]+A[1]*(w+R+T)]}if(!Number.isFinite(u[0])||!Number.isFinite(u[1]))return null;const f=e.validRadius||[.475,.475],y=Math.max(1-Math.hypot((u[0]-e.center[0])/Math.max(1e-4,f[0]),(u[1]-e.center[1])/Math.max(1e-4,f[1])),0);return y<=0||u[0]<0||u[1]<0||u[0]>1||u[1]>1?null:{uv:u,confidence:y}}function nc(t,e,i){const n=t*t+e*e,r=n*n,o=1+i[0]*n+i[1]*r+i[2]*n*r+i[3]*r*r+i[4]*r*r*n,s=i[5]+i[7]*n,a=i[6]+i[8]*n;return[t*o+(n+2*t*t)*s+2*t*e*a+i[9]*n+i[11]*r,e*o+(n+2*e*e)*a+2*t*e*s+i[10]*n+i[12]*r]}function Xn(t,e,i,n=2,r=null){var p,h;const o=e*i,s=((p=r==null?void 0:r.dp)==null?void 0:p.length)===e*2?r.dp:new Float64Array(e*2),a=((h=r==null?void 0:r.parents)==null?void 0:h.length)===o?r.parents:new Int16Array(o);r&&(r.dp=s,r.parents=a);let c=0,l=e;for(let d=0;d<e;d+=1)s[d]=t[d]<65535?t[d]:Number.POSITIVE_INFINITY;for(let d=1;d<i;d+=1){const m=d*e;for(let b=0;b<e;b+=1){const x=t[m+b];if(!Number.isFinite(x)||x>=65535){s[l+b]=Number.POSITIVE_INFINITY;continue}let v=Number.POSITIVE_INFINITY,w=-1;const k=Math.max(0,b-n),D=Math.min(e-1,b+n);for(let F=k;F<=D;F+=1){const S=s[c+F];S<v&&(v=S,w=F)}s[l+b]=v+x,w>=0&&(a[m+b]=w)}const g=c;c=l,l=g}let u=0,f=s[c];for(let d=1;d<e;d+=1)s[c+d]<f&&(f=s[c+d],u=d);if(!Number.isFinite(f))return null;const y=new Array(i);y[i-1]=u;for(let d=i-1;d>0;d-=1){const m=a[d*e+y[d]];if(m<0)return null;y[d-1]=m}return{seam:y,cost:f}}function oc(t){const e=t.slice();for(let i=0;i<X;i+=1)for(let n=0;n<z;n+=1){const r=i*z+n,o=t[r];if(o!==0&&o!==255)continue;const s=t[i*z+(n>0?n-1:z-1)],a=t[i*z+(n+1<z?n+1:0)];(s===255-o||a===255-o)&&(e[r]=o===0?64:191)}return e}function sc(t,e,i){const n=new Uint8Array(z*X);for(let r=0;r<X;r+=1){let o=t[1][r*z]>t[0][r*z];for(let s=0;s<z;s+=1)(s===e[r]||s===i[r])&&(o=!o),n[r*z+s]=o?255:0}return oc(n)}function cc(t,e,i,n,r=false){if(!t)return null;const o=[new Float32Array(t.length),new Float32Array(t.length)];for(let a=0;a<X;a+=1)for(let c=0;c<z;c+=1){const l=a*z+c;if(i[0][l]<=0||i[1][l]<=0)continue;const u=i[0][l]>i[1][l]?0:1,f=1-u;if(i[u][l]<i[f][l]*1.5)continue;const y=l*3,p=e[u],h=e[f],d=n[u],m=n[f],g=p[y]*d,b=p[y+1]*d,x=p[y+2]*d,v=Math.abs(g-h[y]*m)/3+Math.abs(b-h[y+1]*m)/3+Math.abs(x-h[y+2]*m)/3;if(v<32||g*.2126+b*.7152+x*.0722<24)continue;const w=(i[u][l]-i[f][l])*Math.min(1,v/64),k=r?Math.max(.1,Math.sin((a+.5)/X*Math.PI)):1,D=Math.floor(2/k);for(let F=-2;F<=2;F+=1){const S=a+F;if(!(S<0||S>=X))for(let R=-D;R<=D;R+=1){const _=(c+R+z)%z;o[u][S*z+_]+=w*(3-Math.max(Math.abs(R)*k,Math.abs(F)))}}}const s=t.slice();for(let a=0;a<t.length;a+=1){const c=o[0][a]>o[1][a]?0:1;if(!(i[c][a]<=0||o[c][a]<.05||o[c][a]<o[1-c][a]*2)){if(i[1-c][a]>0){const l=a*3,u=e[c],f=n[c],y=u[l]*f*.2126+u[l+1]*f*.7152+u[l+2]*f*.0722;if(y<12){const p=e[1-c],h=n[1-c],d=p[l]*h*.2126+p[l+1]*h*.7152+p[l+2]*h*.0722;if(d>24&&y<d*.25)continue}}s[a]=c===0?0:255}}return s}function lc(t,e,i){const n=new Uint8Array(z*X);for(let r=0;r<X;r++)for(let o=0;o<z;o++){const s=r*z+o;if(e[0][s]<=0||e[1][s]<=0)continue;let a=0;for(let l=0;l<3;l++){const u=s*3+l;a+=Math.abs(t[0][u]*i[0]-t[1][u]*i[1])/3}const c=Math.round(O((a-12)/24,0,1)*255);if(c)for(let l=-2;l<=2;l++){const u=r+l;if(!(u<0||u>=X))for(let f=-2;f<=2;f++){const y=(o+f+z)%z,p=u*z+y;n[p]=Math.max(n[p],c)}}}return n}function uc(t){const e=z,i=X,n=new Uint8Array(e*i);for(let r=0;r<i;r++)for(let o=0;o<e;o++){const s=r*e+o;if(!(t[s]>0))continue;let a=0;for(let c=Math.max(0,r-2);c<=Math.min(i-1,r+2);c++)for(let l=-2;l<=2;l++)t[c*e+(o+l+e)%e]>0&&a++;n[s]=a}return n}function dc(t,e,i){const n=z,r=X,o=new Float64Array(n*5),s=new Float64Array(n),a=new Float32Array(n*r);for(let c=0;c<r;c++){const l=c*n,u=c%5*n,f=(c-2)*n;let y=0;for(let p=-2;p<=2;p++){const h=l+(p+n)%n;e[h]>0&&(y+=t[h])}for(let p=0;p<n;p++){let h=s[p];if(c>=5&&(h-=o[u+p]),o[u+p]=y,h+=y,s[p]=h,c>=2){const g=f+p;e[g]>0&&(a[g]=Math.abs(t[g]-h/Math.max(i[g],1)))}const d=l+(p+n-2)%n,m=l+(p+3)%n;e[d]>0&&(y-=t[d]),e[m]>0&&(y+=t[m])}}for(let c=r-2;c<r;c++){const l=c*n,u=(c-3)%5*n;for(let f=0;f<n;f++){const y=s[f]-o[u+f];s[f]=y;const p=l+f;e[p]>0&&(a[p]=Math.abs(t[p]-y/Math.max(i[p],1)))}}return a}function fc(t,e,i=null){if(i)return dc(t,e,i);const n=z,r=X,o=n*r,s=new Float64Array(n*5),a=new Uint8Array(n*5),c=new Float64Array(n),l=new Uint8Array(n),u=new Float32Array(o);for(let f=0;f<r;f++){const y=f*n,p=f%5*n,h=(f-2)*n;let d=0,m=0;for(let g=-2;g<=2;g++){const b=y+(g+n)%n;e[b]>0&&(d+=t[b],m++)}for(let g=0;g<n;g++){let b=c[g],x=l[g];if(f>=5&&(b-=s[p+g],x-=a[p+g]),s[p+g]=d,a[p+g]=m,b+=d,x+=m,c[g]=b,l[g]=x,f>=2){const k=h+g;e[k]>0&&(u[k]=Math.abs(t[k]-b/Math.max(x,1)))}const v=y+(g+n-2)%n,w=y+(g+3)%n;e[v]>0&&(d-=t[v],m--),e[w]>0&&(d+=t[w],m++)}}for(let f=r-2;f<r;f++){const y=f*n,p=(f-3)%5*n;for(let h=0;h<n;h++){const d=c[h]-s[p+h],m=l[h]-a[p+h];c[h]=d,l[h]=m;const g=y+h;e[g]>0&&(u[g]=Math.abs(t[g]-d/Math.max(m,1)))}}return u}function hc(t){const e=z,i=X,n=e>>>5,r=new Uint8Array(e*i);for(let o=2;o<i-2;o++)for(let s=0;s<n;s++){const a=(o-1)*n,c=a+s,l=a+(s+n-1)%n,u=a+(s+1)%n,f=t[c]|t[c+n]|t[c+n*2],y=t[l]|t[l+n]|t[l+n*2],p=t[u]|t[u+n]|t[u+n*2];let h=f|f<<1|f>>>1|y>>>31|p<<31;for(;h;){const d=31-Math.clz32(h&-h);r[o*e+s*32+d]=1,h&=h-1}}return r}function mc(t,e,i,n,r=null){const o=z,s=X,a=o*s,c=e.map((d,m)=>{const g=new Float32Array(a),b=n[m];for(let x=0;x<a;x++){const v=x*3;g[x]=(d[v]*.2126+d[v+1]*.7152+d[v+2]*.0722)*b}return g}),l=r?r.contrastSampleCounts||(r.contrastSampleCounts=i.map(uc)):null,u=c.map((d,m)=>fc(d,i[m],l==null?void 0:l[m])),f=new Uint32Array(a>>>5);for(let d=0;d<a;d++)i[0][d]<=0||i[1][d]<=0||Math.abs(c[0][d]-c[1][d])<12||Math.max(u[0][d],u[1][d])<12||(f[d>>>5]|=1<<(d&31));const y=hc(f),p=t.slice(),h=new Int32Array(a);for(let d=0;d<a;d++){if(y[d]!==1)continue;let m=1;h[0]=d,y[d]=2;const g=[0,0];for(let v=0;v<m;v++){const w=h[v],k=w%o,D=Math.floor(w/o);if(i[0][w]>0&&i[1][w]>0&&Math.abs(c[0][w]-c[1][w])>=12)for(let F=0;F<2;F++)g[F]+=u[F][w]*i[F][w]**2;for(const F of[D>2?w-o:-1,D<s-3?w+o:-1,D*o+(k+o-1)%o,D*o+(k+1)%o])F<0||y[F]!==1||(y[F]=2,h[m++]=F)}const b=g[0]>g[1]?0:1,x=1-b;if(!(g[b]<=0||g[b]<g[x]*1.15))for(let v=0;v<m;v++){const w=h[v];i[b][w]<=0||c[b][w]<4&&c[x][w]>24||(p[w]=b===0?0:255)}}return p}function pc(){const t=(n,r)=>typeof OffscreenCanvas<"u"?new OffscreenCanvas(n,r):Object.assign(document.createElement("canvas"),{width:n,height:r}),e=t(32,2),i=t(16,1);try{const n=e.getContext("2d",{willReadFrequently:true}),r=i.getContext("2d",{willReadFrequently:true});if(!n||!r)return null;const o=n.createImageData(32,2);for(let a=0;a<2;a++)for(let c=0;c<32;c++){const l=c>>1,u=(a*32+c)*4;for(let f=0;f<3;f++)o.data[u+f]=l*13+f*5+(a===0&&c%2===0?(l+f)%4:0);o.data[u+3]=255}n.putImageData(o,0,0),r.drawImage(e,0,0,16,1);const s=r.getImageData(0,0,16,1).data;for(const a of[0,2]){let c=true;for(let l=0;l<16;l++)for(let u=0;u<3;u++)s[l*4+u]!==4*(l*13+u*5)+(l+u)%4+a>>2&&(c=false);if(c)return a}return null}catch{return null}finally{e.width=e.height=i.width=i.height=0}}function wn(t,e=0){const i=new Uint8Array(524288);if(!t)i.fill(1);else{for(let o=0;o<512;o+=2)for(let s=0;s<1024;s+=2)i[o*1024+s]=1;for(let o=0;o<2;o++)for(let s=0;s<t.weights[o].length;s++){if(t.weights[o][s]<=0)continue;const a=O(t.uv[o][s*2]*1024-.5,0,1023),c=O(t.uv[o][s*2+1]*512-.5,0,511),l=Math.floor(a),u=Math.floor(c),f=Math.min(1023,l+1),y=Math.min(511,u+1);i[u*1024+l]=i[u*1024+f]=1,i[y*1024+l]=i[y*1024+f]=1}}const n=[0,0];for(let o=0;o<i.length;o++)i[o]&&n[o>>9&1]++;const r=n.map(o=>new Uint32Array(o));if(n.fill(0),t){for(let o=0;o<2;o++)if(e&1<<o)for(let s=0;s<512;s+=2)for(let a=0;a<512;a+=2)r[o][n[o]++]=(s*1024+o*512+a)*4}for(let o=0;o<i.length;o++)if(i[o]){const s=o>>9&1;if(t&&e&1<<s&&!(o&1025))continue;r[s][n[s]++]=o*4}return r}function yc(t,e,i=null,n=null){if((t==null?void 0:t.length)!==2||t.some(p=>!p||p.width<1024||p.width!==p.height||!ArrayBuffer.isView(p.data)||p.data.length!==p.width*p.height*4||p.colorSpace&&p.colorSpace!=="srgb")||(e.bias===void 0&&(e.bias=pc()),e.bias===null))return null;const r=e.bias,o=+(t[0].width===1024)|+(t[1].width===1024)<<1;!e.selection||e.selection.map!==n?(e.selection={map:n,nativeMask:o,targets:wn(n,o)},e.buffers=[],e.plans=[]):e.selection.nativeMask!==o&&(e.selection={map:n,nativeMask:o,targets:wn(n,o)});const s=e.buffers||(e.buffers=[]),a=(i==null?void 0:i.pixels)===s[0]?1:0,c=s[a]||(s[a]=new Uint8ClampedArray(1024*512*4)),l=new Uint32Array(c.buffer,c.byteOffset,c.byteLength/4),u=r*65537,f=r*16843009,y=e.plans||(e.plans=[]);for(let p=0;p<2;p++){const h=t[p],d=h.data,m=h.width,g=e.selection.targets[p],b=m===1024;let x=y[p];if((x==null?void 0:x.width)!==m)if(b)x=y[p]={width:m};else{const F=Uint32Array.from({length:1024},(T,A)=>Math.floor(A*m/1024)),S=new Uint32Array(g.length),R=new Uint32Array(512),_=new Uint32Array(512);for(let T=0;T<512;T++){const A=F[T*2+1]-F[T*2];R[T]=A,_[T]=A*m}for(let T=0;T<g.length;T++){const A=g[T]>>>2,C=A&511,j=A>>>10;S[T]=F[j*2]*m+F[C*2]}x=y[p]={width:m,origins:S,columns:R,rows:_}}const{origins:v,columns:w,rows:k}=x,D=(d instanceof Uint8Array||d instanceof Uint8ClampedArray)&&d.byteOffset%4===0?new Uint32Array(d.buffer,d.byteOffset,d.byteLength/4):null;if(D){if(b){if(n)for(let F=0;F<512;F+=2){const S=F*2048+1024;for(let R=F*2048,_=F*1024+p*512;R<S;R+=8,_+=4){const T=D[R],A=D[R+1],C=D[R+1024],j=D[R+1025];if((T&A&C&j&Be)!==Be)return null;const G=((T&4244438268)>>>2)+((A&4244438268)>>>2)+((C&4244438268)>>>2)+((j&4244438268)>>>2),q=(T&50529027)+(A&50529027)+(C&50529027)+(j&50529027)+f>>>2&50529027;l[_]=G+q;const te=D[R+4],ne=D[R+5],ue=D[R+1028],J=D[R+1029];if((te&ne&ue&J&Be)!==Be)return null;const Z=((te&4244438268)>>>2)+((ne&4244438268)>>>2)+((ue&4244438268)>>>2)+((J&4244438268)>>>2),Tt=(te&50529027)+(ne&50529027)+(ue&50529027)+(J&50529027)+f>>>2&50529027;l[_+2]=Z+Tt}}for(let F=n?65536:0;F<g.length;F++){const S=g[F]>>>2,R=(S&-513)*2,_=R+1,T=D[R],A=D[_],C=D[R+1024],j=D[_+1024];if((T&A&C&j&Be)!==Be)return null;const G=((T&4244438268)>>>2)+((A&4244438268)>>>2)+((C&4244438268)>>>2)+((j&4244438268)>>>2),q=(T&50529027)+(A&50529027)+(C&50529027)+(j&50529027)+f>>>2&50529027;l[S]=G+q}continue}if(m%512===0){const F=Math.floor(m/1024),S=F*m;for(let R=0;R<g.length;R++){const _=g[R]>>>2,T=v[R],A=T+F,C=D[T],j=D[A],G=D[T+S],q=D[A+S];if((C&j&G&q&Be)!==Be)return null;const te=(C&16711935)+(j&16711935)+(G&16711935)+(q&16711935)+u,ne=(C>>>8&16711935)+(j>>>8&16711935)+(G>>>8&16711935)+(q>>>8&16711935)+u;l[_]=te>>>2&16711935|(ne>>>2&16711935)<<8}continue}for(let F=0;F<g.length;F++){const S=g[F]>>>2,R=v[F],_=R+w[S&511],T=k[S>>>10],A=D[R],C=D[_],j=D[R+T],G=D[_+T];if((A&C&j&G&Be)!==Be)return null;const q=(A&16711935)+(C&16711935)+(j&16711935)+(G&16711935)+u,te=(A>>>8&16711935)+(C>>>8&16711935)+(j>>>8&16711935)+(G>>>8&16711935)+u;l[S]=q>>>2&16711935|(te>>>2&16711935)<<8}continue}for(let F=0;F<g.length;F++){const S=g[F],R=S>>>2,_=(b?(R&-513)*2:v[F])*4,T=_+(b?1:w[R&511])*4,A=(b?1024:k[R>>>10])*4,C=_+A,j=T+A;if((d[_+3]&d[T+3]&d[C+3]&d[j+3])!==255)return null;for(let G=0;G<3;G++)c[S+G]=d[_+G]+d[T+G]+d[C+G]+d[j+G]+r>>2;c[S+3]=255}}return{pixels:c,width:1024,height:512}}function Ft(t,e=Ea,i=null,n=false){var f,y,p;const r=Yi(t),o=Math.min(1,e/Math.max(r.width,r.height)),s=Math.max(1,Math.round(r.width*o)),a=Math.max(1,Math.round(r.height*o)),c=((f=i==null?void 0:i.readback)==null?void 0:f.surface)||(typeof OffscreenCanvas<"u"?new OffscreenCanvas(s,a):Object.assign(document.createElement("canvas"),{width:s,height:a}));c.width!==s&&(c.width=s),c.height!==a&&(c.height=a);const l=((y=i==null?void 0:i.readback)==null?void 0:y.context)||c.getContext("2d",{willReadFrequently:true});if(!l)return null;i&&(i.readback={surface:c,context:l}),(p=l.clearRect)==null||p.call(l,0,0,s,a);const u=Gn.has(t);return u&&(l.save(),l.translate(0,a),l.scale(1,-1)),l.imageSmoothingQuality=n?"high":"low",l.drawImage(t,0,0,s,a),u&&l.restore(),{pixels:l.getImageData(0,0,s,a).data,width:s,height:a}}function $n(t,e){const{width:i,height:n}=t;if(e.width!==i||e.height!==n)return null;const r=3,o=49,s=64,a=6,c=g=>{const b=i+1,x=new Float64Array(b*(n+1)),v=new Float64Array(x.length),w=new Uint32Array(x.length);for(let F=0;F<n;F+=1){let S=0,R=0,_=0;for(let T=0;T<i;T+=1){const A=F*i+T,C=(F+1)*b+T+1,j=g.gray[A];S+=j,R+=j*j,_+=g.valid[A],x[C]=x[C-b]+S,v[C]=v[C-b]+R,w[C]=w[C-b]+_}}const k=new Float32Array(i*n),D=new Float32Array(k.length);for(let F=r;F<n-r;F+=1)for(let S=r;S<i-r;S+=1){const R=F*i+S,_=(F-r)*b+S-r,T=(F-r)*b+S+r+1,A=(F+r+1)*b+S-r,C=(F+r+1)*b+S+r+1;if(w[C]-w[T]-w[A]+w[_]!==o)continue;const j=x[C]-x[T]-x[A]+x[_];k[R]=j/o,D[R]=Math.max(0,v[C]-v[T]-v[A]+v[_]-j*j/o)}return{means:k,energies:D}},l=c(t),u=c(e),f=[];for(let g=10;g<n-10;g+=2)for(let b=s+r+5;b<i-s-r-5;b+=2){const x=g*i+b;if(l.energies[x]<o*9)continue;let v=0,w=0,k=0;for(let F=-1;F<=1;F+=1)for(let S=-1;S<=1;S+=1){const R=x+F*i+S,_=t.gray[R+1]-t.gray[R-1],T=t.gray[R+i]-t.gray[R-i];v+=_*_,w+=_*T,k+=T*T}const D=(v+k-Math.hypot(v-k,2*w))/2;D>1&&f.push({x:b,y:g,score:D})}f.sort((g,b)=>b.score-g.score);const y=[];for(const g of f)if(!y.some(b=>Math.abs(b.x-g.x)<7&&Math.abs(b.y-g.y)<7)&&(y.push(g),y.length===48))break;const p=[],h=s*2+1;for(const{x:g,y:b}of y){const x=b*i+g,v=[];for(let T=-r;T<=r;T+=1)for(let A=-r;A<=r;A+=1)v.push(t.gray[x+T*i+A]-l.means[x]);const w=(T,A)=>{const C=(b+A)*i+g+T;if(u.energies[C]<o*9)return-1;let j=0,G=0;for(let q=-r;q<=r;q+=1)for(let te=-r;te<=r;te+=1)j+=v[G++]*e.gray[C+q*i+te];return j/Math.sqrt(l.energies[x]*u.energies[C])},k=new Float32Array(h*(a*2+1));let D=-1,F=0,S=0;for(let T=-a;T<=a;T+=1)for(let A=-s;A<=s;A+=1){const C=w(A,T);k[(T+a)*h+A+s]=C,C>D&&(D=C,F=A,S=T)}if(D<.85||Math.abs(F)===s||Math.abs(S)===a)continue;let R=-1;for(let T=-a;T<=a;T+=1)for(let A=-s;A<=s;A+=1)Math.abs(A-F)<=3&&Math.abs(T-S)<=2||(R=Math.max(R,k[(T+a)*h+A+s]));if(D-R<.015)continue;const _=(T,A,C)=>Math.abs(T-2*A+C)>1e-6?O(.5*(T-C)/(T-2*A+C),-.5,.5):0;p.push({dx:F+_(w(F-1,S),D,w(F+1,S)),dy:S+_(w(F,S-1),D,w(F,S+1)),y:b,gainRatio:u.means[(b+S)*i+g+F]/Math.max(1,l.means[x])})}let d=[];for(const g of p){const b=p.filter(x=>Math.abs(x.dx-g.dx)<3&&Math.abs(x.dy-g.dy)<1.5);b.length>d.length&&(d=b)}if(d.length<Math.max(6,p.length*.35)||Math.max(...d.map(g=>g.y))-Math.min(...d.map(g=>g.y))<24)return null;const m=g=>(g.sort((b,x)=>b-x),(g[Math.floor((g.length-1)/2)]+g[Math.floor(g.length/2)])/2);return{dx:m(d.map(g=>g.dx)),dy:m(d.map(g=>g.dy)),gainRatio:m(d.map(g=>g.gainRatio)),inliers:d.length}}function Wt(t){const[e,i]=t.center,n=e<.5?0:.5;return[Math.min(.25,e-n,n+.5-e),Math.min(.5,i,1-i)]}function Hi(t,e,i,n){const s=[],a=[];for(const c of[-90,90]){const l=i.map(()=>({width:193,height:241,gray:new Float32Array(46513),valid:new Uint8Array(46513)}));for(let f=0;f<241;f+=1){const y=(-60+f*.5)*Math.PI/180;for(let p=0;p<193;p+=1){const h=(c-12+p*.125)*Math.PI/180,d=[Math.cos(y)*Math.sin(h),Math.sin(y),Math.cos(y)*Math.cos(h)];for(let m=0;m<2;m+=1){const g=i[m],b=kt(d,g,Math.PI,g.projectionModel==="mei_extended",g.projectionModel==="dji_fisheye_lut",g.radialScale||1);if(!b)continue;const x=b.uv.slice();e.dualFisheyeFlipX&&(x[0]=2*i[m].center[0]-x[0]),e.dualFisheyeFlipY&&(x[1]=2*i[m].center[1]-x[1]);const v=[0,0,0];Di(t.pixels,t.width,t.height,x[0],n==="bottom-left"?1-x[1]:x[1],v);const w=f*193+p;l[m].gray[w]=v[0]*.2126+v[1]*.7152+v[2]*.0722,l[m].valid[w]=1}}}const u=$n(...l);if(!u)return null;s.push(u.dx*.125*Math.PI/180,u.dy*.5*Math.PI/180),a.push(u.gainRatio)}return{offsets:s,ratios:a}}function gc(t,e,i,n){const r=Ft(t,2048);if(!r)return null;if(r.pixels[3]===0)return;const o=n.map(f=>({...f,validRadius:Wt(f)})),s=Hi(r,e,o,i.textureOrigin);if(!s)return null;const{offsets:a,ratios:c}=s,l=Math.sqrt(O(Math.sqrt(c[0]*c[1]),.64,1.5625)),u=[-1,1].map(f=>{const y=Yn(r,o,i.textureOrigin,f,e,a);return y>0?1/y:0});return{offsets:a,polarInverseDepth:u,gain:e.dualFisheyeAutoGain?[l,1/l]:[e.dualFisheyeGainFront,e.dualFisheyeGainBack]}}function vc(t,e,i,n){const r=Ft(t,2048);if(!r)return null;if(r.pixels[3]!==0)return xc(r,e,i,n)}function xc(t,e,i,n){const r=n.map(l=>({...l,validRadius:Wt(l)})),o=Qn(t,r,e,i.textureOrigin,Math.PI),s=r.map(l=>({...l,focal:l.focal.map(u=>u*o)})),a=Hi(t,e,s,i.textureOrigin);if(!a)return null;const c=e.dualFisheyeAutoGain?za(t,e,i,null,s[0],s[1],Math.PI,{videoOffsets:a.offsets}):null;return{focalScale:o,offsets:a.offsets,gain:(c==null?void 0:c.gain)||[e.dualFisheyeGainFront,e.dualFisheyeGainBack]}}function Yn(t,e,i,n=0,r={},o=null){if(e.reduce((h,d)=>h+(d.translationM||[]).reduce((m,g)=>m+g*g,0),0)<1e-8)return 0;const a=(h,d)=>{const m=[];for(let g=0;g<e.length;g+=1){const b=e[g],x=g===1&&o?Ji(h,o):h,v=kt(x,b,Math.PI,true,false,1,d>0?1/d:0);if(!v)return null;r.dualFisheyeFlipX&&(v.uv[0]=2*b.center[0]-v.uv[0]),r.dualFisheyeFlipY&&(v.uv[1]=2*b.center[1]-v.uv[1]);const w=[0,0,0];Di(t.pixels,t.width,t.height,v.uv[0],i==="bottom-left"?1-v.uv[1]:v.uv[1],w),m.push(w)}return m},c=[];if(n)for(let h=0;h<9;h+=1){const d=n*(60+30*h/8)*Math.PI/180;for(let m=0;m<128;m+=1){const g=(m/128-.5)*2*Math.PI,b=[Math.cos(d)*Math.sin(g),Math.sin(d),Math.cos(d)*Math.cos(g)];let x=true;for(let v=0;v<=16;v+=1)if(!a(b,v/4)){x=false;break}x&&c.push(b)}}else for(let h=0;h<64;h+=1){const d=(-55+110*h/63)*Math.PI/180;for(const m of[-90,90])for(let g=0;g<9;g+=1){const b=(m-4+g)*Math.PI/180,x=[Math.cos(d)*Math.sin(b),Math.sin(d),Math.cos(d)*Math.cos(b)];let v=true;for(let w=0;w<=16;w+=1)if(!a(x,w/4)){v=false;break}v&&c.push(x)}}if(c.length<64)return 0;const l=h=>{const d=[],m=[0,0];for(const v of c){const w=a(v,h);if(!w)return 1/0;d.push(w);for(let k=0;k<2;k+=1)for(const D of w[k])m[k]+=D}if(m[0]<=c.length*3||m[1]<=c.length*3)return 1/0;const g=Math.sqrt(O(m[1]/m[0],.64,1.5625)),b=d.map(v=>v[0].reduce((w,k,D)=>w+Math.abs(k*g-v[1][D]/g)/3,0)).sort((v,w)=>v-w),x=Math.floor(b.length*.8);return b.slice(0,x).reduce((v,w)=>v+w,0)/x},u=l(0);let f=u,y=0;for(let h=1;h<=16;h+=1){const d=h/4,m=l(d);m<f&&(f=m,y=d)}const p=y;for(let h=-4;h<=4;h+=1){const d=p+h*.05;if(d<=0||d>4)continue;const m=l(d);m<f&&(f=m,y=d)}return y===0||!Number.isFinite(u)||u-f<.5||f>u*.9?0:1/y}function bc(t,e,i,n=false){const r=i[t[1]>0?1:0];if(!(r>0))return e;const o=Math.sin((n?50:30)*Math.PI/180),s=Math.sin((n?65:50)*Math.PI/180),a=O((Math.abs(t[1])-o)/(s-o),0,1),c=(e>0?1/e:0)*(1-a*a*(3-2*a))+r*a*a*(3-2*a);return c>0?1/c:0}function wc(t,e,i,n){const r=e.map(f=>{const y=f.rotationQuat,p=Ba({w:y[0],x:y[1],y:y[2],z:y[3]},...f.translationM||[0,0,0]);return[p.x,p.y,p.z]}),o=r[1].map((f,y)=>f-r[0][y]),s=Math.hypot(o[0],o[2]);if(s<.001||Math.abs(o[1])>s*.1)return[0,0];const a=[o[0]/s,o[2]/s],c=193,l=193,u=Math.tan(25*Math.PI/180);return[-1,1].map(f=>{const y=e.map(()=>({width:c,height:l,gray:new Float32Array(c*l),valid:new Uint8Array(c*l)}));for(let d=0;d<l;d+=1)for(let m=0;m<c;m+=1){const g=(2*m/(c-1)-1)*u,b=(2*d/(l-1)-1)*u,x=[a[0]*g+a[1]*b,f,a[1]*g-a[0]*b],v=Math.hypot(...x);for(let w=0;w<3;w+=1)x[w]/=v;for(let w=0;w<2;w+=1){const k=e[w],D=kt(x,k,Math.PI,true,false,1);if(!D)continue;i.dualFisheyeFlipX&&(D.uv[0]=2*k.center[0]-D.uv[0]),i.dualFisheyeFlipY&&(D.uv[1]=2*k.center[1]-D.uv[1]);const F=[0,0,0];Di(t.pixels,t.width,t.height,D.uv[0],n==="bottom-left"?1-D.uv[1]:D.uv[1],F);const S=d*c+m;y[w].gray[S]=F[0]*.2126+F[1]*.7152+F[2]*.0722,y[w].valid[S]=1}}const p=$n(...y);if(!p||Math.abs(p.dy)>1.5)return 0;const h=p.dx*2*u/(c-1)/s;return h>=.05&&h<=4?h:0})}function Qn(t,e,i,n,r){const o=Array.from({length:13},(p,h)=>.97+h*.005),s=o.map(p=>e.map(h=>({...h,focal:h.focal.map(d=>d*p)}))),a=(p,h,d)=>{const m=[];for(const g of h){const b=kt(p,g,r,false,g.projectionModel==="dji_fisheye_lut",g.radialScale||1);if(!b)return null;if(!d)continue;i.dualFisheyeFlipX&&(b.uv[0]=2*g.center[0]-b.uv[0]),i.dualFisheyeFlipY&&(b.uv[1]=2*g.center[1]-b.uv[1]);const x=[0,0,0];Di(t.pixels,t.width,t.height,b.uv[0],n==="bottom-left"?1-b.uv[1]:b.uv[1],x),m.push(x)}return m},c=[];for(const p of aa(i.dualFisheyeSeamLongitudesDeg)){const h=[];for(let d=-60;d<=60;d+=4)for(let m=-2;m<=2;m+=.5){const g=qn((p+m)/360+.5,.5-d/180,e.some(b=>b.projectionModel==="dji_fisheye_lut"));i.equirectFlipX&&(g[0]*=-1),i.equirectFlipY&&(g[1]*=-1),s.every(b=>a(g,b,false))&&h.push(g)}if(h.length<16)return 1;c.push(...h)}const l=p=>{const h=c.map(x=>a(x,p,true)),d=h.reduce((x,v)=>x.map((w,k)=>w+v[k].reduce((D,F)=>D+F,0)),[0,0]);if(Math.min(...d)<h.length*15)return Number.POSITIVE_INFINITY;const m=Math.sqrt(O(d[1]/d[0],.64,1.5625)),g=h.map(x=>x[0].reduce((v,w,k)=>v+Math.abs(w*m-x[1][k]/m)/3,0)).sort((x,v)=>x-v),b=Math.floor(g.length*.8);return g.slice(0,b).reduce((x,v)=>x+v,0)/b},u=l(e);if(!Number.isFinite(u)||u<.75)return 1;let f=6,y=u;return s.forEach((p,h)=>{const d=l(p);d<y&&(f=h,y=d)}),f===0||f===o.length-1||u-y<.75||y>u*.85?1:o[f]}function Fc(t,e,i,n,r,o,s){var k,D;const a=!n&&[r,o].every(F=>{var S;return F.distortionModel==="radtan_pro"&&((S=F.distortionCoeffs)==null?void 0:S.length)===13}),c=!!(e.dualFisheyeRefineFocal&&i&&!n&&[r,o].every(F=>{var S;return(F.projectionModel||"equidistant")==="equidistant"&&((S=F.focal)==null?void 0:S.every(R=>R>0))})),l=Ft(t,a||c?1024:Ea,null,true);if(!l)return null;let u=c?Qn(l,[r,o],e,i.textureOrigin,s):1;if(u!==1){const F={...r,focal:r.focal.map(R=>R*u)},S={...o,focal:o.focal.map(R=>R*u)};Mc(e,i,F,S,s)?(r=F,o=S):u=1}const f=[r,o],y=a?Yn(l,f,i==null?void 0:i.textureOrigin):0,p=i&&!n&&f.every(F=>F.projectionModel==="mei_extended"&&F.distortionModel!=="radtan_pro"&&Array.isArray(F.rotationQuat)),d=p&&f.some(F=>{var S;return(S=F.translationM)==null?void 0:S.some(R=>Math.abs(R)>.001)})?Ft(t,1024,null,true):null,m=d?wc(d,f,e,i.textureOrigin):[0,0],g=p&&((k=i.imageSize)==null?void 0:k[0])===2*((D=i.imageSize)==null?void 0:D[1]),b=g?Ft(t,2048,null,true):null;let x=b?Hi(b,e,f,i.textureOrigin):null;if(b&&!x&&b.width>512){const F=Ft(t,512,null,true);F&&(x=Hi(F,e,f,i.textureOrigin))}const v=(x==null?void 0:x.offsets)||[0,0,0,0],w=za(l,e,i,n,r,o,s,{convergenceM:y,polarInverseDepth:m,imageOffsets:g?v:null});return w?{...w,convergenceM:y,polarInverseDepth:m,focalScale:u,imageOffsets:v}:null}function Mc(t,e,i,n,r){const{weights:o}=Ia(t,e,null,i,n,r,{convergenceM:0,polarInverseDepth:[0,0],registrationOffsets:null,videoOffsets:null},null),s=z/2,a=new Float64Array(s*X),c={};for(const l of[0,s]){for(let u=0;u<X;u++)for(let f=0;f<s;f++){const y=u*z+l+f;a[u*s+f]=o[0][y]>0&&o[1][y]>0?1:65535}if(!Xn(a,s,X,2,c))return false}return true}function Hn(t){const e=z*X,i=new Uint8Array(e);for(let o=0;o<e;o++)t[0][o]<=0||t[1][o]<=0||(i[o]=1,o%z&&(i[o-1]=1),o>=z&&(i[o-z]=1));let n=0;for(let o=0;o<e;o++)n+=i[o];const r=new Uint16Array(n);for(let o=0,s=0;o<e;o++)i[o]&&(r[s++]=o);return r}function Ia(t,e,i,n,r,o,{convergenceM:s,polarInverseDepth:a,registrationOffsets:c,videoOffsets:l},u){var w,k,D,F;const f=u&&!i?JSON.stringify([n,r,o,e==null?void 0:e.textureOrigin,(w=e==null?void 0:e.front)==null?void 0:w.radialScale,(k=e==null?void 0:e.back)==null?void 0:k.radialScale,s,a,c,!!l,t.equirectFlipX,t.equirectFlipY,t.dualFisheyeFlipX,t.dualFisheyeFlipY]):null;if(f&&u.key===f)return u.map;const y=z*X,p=[new Float64Array(y*2),new Float64Array(y*2)],h=[new Float32Array(y),new Float32Array(y)],d=[n,r],m=d.map(S=>S.projectionModel==="mei_extended"),g=d.map(S=>S.projectionModel==="dji_fisheye_lut"),b=m.some(Boolean)||g.some(Boolean);for(let S=0;S<X;S++)for(let R=0;R<z;R++){const _=qn((R+.5)/z,(S+.5)/X,b);t.equirectFlipX&&(_[0]=-_[0]),t.equirectFlipY&&(_[1]=-_[1]);const T=tc(_,b),A=O(Math.floor(T[0]*z),0,z-1),j=O(Math.floor(T[1]*X),0,X-1)*z+A,G=ac(i,T[0],T[1]);for(let q=0;q<2;q++){const te=q===1&&c?Ji(_,c,!l):_,ne=d[q],ue=G?G[q].valid?{uv:G[q].uv,confidence:G[q].confidence}:null:kt(te,ne,o,m[q],g[q],q===0?((D=e==null?void 0:e.front)==null?void 0:D.radialScale)||1:((F=e==null?void 0:e.back)==null?void 0:F.radialScale)||1,bc(te,s,a,!!l));if(!ue)continue;let[J,Z]=ue.uv;t.dualFisheyeFlipX&&(J=2*ne.center[0]-J),t.dualFisheyeFlipY&&(Z=2*ne.center[1]-Z),p[q][j*2]=J,p[q][j*2+1]=(e==null?void 0:e.textureOrigin)==="bottom-left"?1-Z:Z,h[q][j]=ue.confidence}}let x=0;for(let S=0;S<y;S++)h[0][S]>0&&h[1][S]>0&&x++;const v={uv:p,weights:h,overlapCount:x,gradientIndices:Hn(h)};return f&&(u.key=f,u.map=v),v}function za(t,e,i,n,r,o,s,{convergenceM:a=0,polarInverseDepth:c=[0,0],imageOffsets:l=null,videoOffsets:u=null,previousMask:f=null,mapCache:y=null}={}){const p=u||l,h=[new Float32Array(z*X*3),new Float32Array(z*X*3)],d=Ia(e,i,n,r,o,s,{convergenceM:a,polarInverseDepth:c,registrationOffsets:p,videoOffsets:u},y),{weights:m}=d;ic(t,d,h,!!(y&&!n));const g=new Float64Array(z*X);g.fill(65535);const b=!!(i&&e.dualFisheyeAutoGain);let x=d.overlapCount??0,v=0,w=0;const k=[r.projectionModel==="dji_fisheye_lut",o.projectionModel==="dji_fisheye_lut"];if(b||d.overlapCount===void 0){x=0;for(let ce=0;ce<z*X;ce++)if(m[0][ce]>0&&m[1][ce]>0){if(x+=1,!b)continue;const $=ce*3,xe=h[0][$]*.2126+h[0][$+1]*.7152+h[0][$+2]*.0722,pe=h[1][$]*.2126+h[1][$+1]*.7152+h[1][$+2]*.0722;v+=xe,w+=pe}}if(x<64)return null;let D=e.dualFisheyeGainFront,F=e.dualFisheyeGainBack;b&&v>x&&w>x&&(D=Math.sqrt(O(w/v,.64,1.5625)),F=1/D);const S=[new Float32Array(g.length),new Float32Array(g.length)],R=d.gradientIndices||Hn(m),_=new Float64Array(z);let T=0;for(let ce=0;ce<R.length;ce++){const $=R[ce],xe=$%z,pe=$*3,re=h[0][pe]*D,ke=h[0][pe+1]*D,et=h[0][pe+2]*D,tt=h[1][pe]*F,Qt=h[1][pe+1]*F,Ht=h[1][pe+2]*F,Le=re*.2126+ke*.7152+et*.0722,_e=tt*.2126+Qt*.7152+Ht*.0722,it=Le-_e,ki=xe>0?T:it,Ti=$>=z?_[xe]:it;if(T=it,_[xe]=it,m[0][$]<=0||m[1][$]<=0)continue;const Ri=(Math.abs(re-tt)+Math.abs(ke-Qt)+Math.abs(et-Ht))/3;S[0][$]=Le<12&&_e>24&&Le<_e*.25?128*Math.min(1,(_e-Le)/64):0,S[1][$]=_e<12&&Le>24&&_e<Le*.25?128*Math.min(1,(Le-_e)/64):0,f&&(S[0][$]+=f[$]/255*12,S[1][$]+=(1-f[$]/255)*12);const at=Math.abs(it)+Math.abs(ki)+Math.abs(Ti),Pi=128*(1-2*Math.min(m[0][$],m[1][$])/Math.max(1e-4,m[0][$]+m[1][$]));g[$]=Math.min(65534,Ri+at*.35+Pi)}const A=z/2,C=new Float64Array(A*X),j=new Float64Array(A+1),G=new Float64Array(A+1),q={},te=ce=>{for(let $=0;$<X;$+=1){const xe=$*z,pe=m[1][xe]>m[0][xe]!=ce>0;for(let re=0;re<A;re+=1){const ke=xe+ce+re,et=S[0][ke],tt=S[1][ke];j[re+1]=j[re]+(pe?tt:et),G[re+1]=G[re]+(pe?et:tt)}for(let re=0;re<A;re+=1){const ke=g[xe+ce+re];C[$*A+re]=ke>=65535?65535:Math.min(65534,ke+j[re]+G[A]-G[re])}}return Xn(C,A,X,2,q)},ne=te(0),ue=te(A),J=ne&&ue&&ne.cost/X<=180&&ue.cost/X<=180?sc(m,ne.seam,ue.seam.map(ce=>ce+A)):null;let Z=cc(J,h,m,[D,F],!!l);Z&&u&&k.every(Boolean)&&(Z=mc(Z,h,m,[D,F],y&&!n?d:null)),Z&&p&&(Z=Dc(Z,h,m,[D,F],f));const Tt=Z&&u&&k.every(Boolean)?lc(h,m,[D,F]):null;return{mask:Z,strength:Tt,gain:[D,F]}}function Ji(t,e,i=false){const n=Math.asin(O(t[1],-1,1));let r=Math.atan2(t[0],t[2]);const o=Math.sin((i?30:50)*Math.PI/180),s=Math.sin((i?50:70)*Math.PI/180),a=O((Math.abs(t[1])-o)/(s-o),0,1),c=1-a*a*(3-2*a);if(c===0)return t.slice();const l=.5+.5*Math.sin(r);r+=(e[0]*(1-l)+e[2]*l)*c;const u=O(n+(e[1]*(1-l)+e[3]*l)*c,-Math.PI/2,Math.PI/2);return[Math.cos(u)*Math.sin(r),Math.sin(u),Math.cos(u)*Math.cos(r)]}function Dc(t,e,i,n,r){const o=t.slice();for(const s of[0,X-2]){const a=[0,0];for(let l=s;l<s+2;l+=1)for(let u=0;u<z;u+=1){const f=l*z+u,y=f*3;for(let p=0;p<2;p+=1){const h=(e[p][y]*.2126+e[p][y+1]*.7152+e[p][y+2]*.0722)*n[p];h>=12&&(a[p]+=Math.sqrt(i[p][f])*Math.min(h,128))}}let c=a[1]>a[0];r&&Math.abs(a[0]-a[1])<Math.max(...a)*.15&&(c=r[s*z]>=128),o.fill(c?255:0,s*z,(s+2)*z)}return o}function Sc(t,e,i=null){if(!e)return t;const n=new Uint8Array(t.length);for(let r=0;r<t.length;r++){const o=t[r];n[r]=(i==null?void 0:i[r])>=128?o:Math.round(e[r]+(o-e[r])*.35)}return n}function kc(t,e){if((e==null?void 0:e.width)!==t.width||(e==null?void 0:e.height)!==t.height)return true;const{width:i,height:n,pixels:r}=t,o=e.pixels,s=(r instanceof Uint8Array||r instanceof Uint8ClampedArray)&&(o instanceof Uint8Array||o instanceof Uint8ClampedArray)&&r.byteOffset%4===0&&o.byteOffset%4===0&&r.length===i*n*4&&o.length===r.length,a=s?new Uint32Array(r.buffer,r.byteOffset,r.byteLength/4):null,c=s?new Uint32Array(o.buffer,o.byteOffset,o.byteLength/4):null;for(let l=0;l<n;l+=8)for(let u=0;u<i;u+=8){let f=0,y=0;const p=Math.min(l+8,n),h=Math.min(u+8,i),d=l*i+u;if(a&&a[d]===c[d])for(let m=l;m<p;m+=2)for(let g=u;g<h;g+=2){const b=m*i+g;if(a[b]!==c[b]){const x=b*4;f+=Math.abs(r[x]-o[x]),f+=Math.abs(r[x+1]-o[x+1]),f+=Math.abs(r[x+2]-o[x+2])}y+=3}else for(let m=l;m<p;m+=2)for(let g=u;g<h;g+=2){const b=(m*i+g)*4;f+=Math.abs(r[b]-o[b]),f+=Math.abs(r[b+1]-o[b+1]),f+=Math.abs(r[b+2]-o[b+2]),y+=3}if(f/y>12)return true}return false}function Tc(t,e,i,n,r,o,s){var y;const a=n.every(p=>p.projectionModel==="dji_fisheye_lut"),c=a&&(s!=null&&s.softwareFrames)?Ia(e,i,null,...n,Math.PI,{convergenceM:0,polarInverseDepth:r.polarInverseDepth||[0,0],registrationOffsets:r.offsets,videoOffsets:r.offsets},s.projections||(s.projections={})):null;let l=a&&(s!=null&&s.softwareFrames)?yc(s.softwareFrames,s.softwareReadback||(s.softwareReadback={}),s.surface,c):null;if(l||(s!=null&&s.softwareFrames&&((y=s.prepareSoftwareFallback)==null||y.call(s)),l=Ft(t,a?1024:Ea,s)),!l)return null;if(l.pixels[3]===0)return;const u=s==null?void 0:s.surface;if(u&&!kc(l,u))return{reused:true};const f=za(l,{...e,dualFisheyeAutoGain:false,dualFisheyeGainFront:r.gain[0],dualFisheyeGainBack:r.gain[1]},i,null,...n,Math.PI,{polarInverseDepth:r.polarInverseDepth,videoOffsets:r.offsets,previousMask:o,mapCache:s?s.projections||(s.projections={}):null});return f!=null&&f.mask?(s&&(s.surface=l),{mask:f.mask,strength:f.strength}):null}function Jn(t,e,i,n){var Gr,qr,Xr;const r=i.externalFrames===true,o=e instanceof HTMLVideoElement,s=o||r,a=t.getContext("webgl",{alpha:false,antialias:!s,depth:!s,stencil:false,preserveDrawingBuffer:!s});if(!a)throw new Error("WebGL unavailable");const c=n==="dual_fisheye"?Qs(i.dualFisheyeCalibration,i.dualFisheyeFrontLens):null,l=(c==null?void 0:c.textureOrigin)!=="top-left",u=!!(n==="equirect"&&i.equirectCameraConvention==="mei"||n==="dual_fisheye"&&c&&[c.front,c.back].some(M=>["mei_extended","dji_fisheye_lut"].includes(M.projectionModel)));t.dataset.insta360MEIConvention=u?"true":"false",t.dataset.insta360ProjectionKind=n,t.dataset.insta360CalibrationFrontModel=((Gr=c==null?void 0:c.front)==null?void 0:Gr.projectionModel)||"";const f=`
|
|
397
|
+
attribute vec2 aClipPosition;
|
|
398
|
+
void main() {
|
|
399
|
+
gl_Position = vec4(aClipPosition, 0.0, 1.0);
|
|
400
|
+
}
|
|
401
|
+
`,y=i.equirectFlipX?"1.0 - baseUV.x":"baseUV.x",p=i.equirectFlipY?"1.0 - baseUV.y":"baseUV.y",h=i.equirectFlipX?"-dir.x":"dir.x",d=i.equirectFlipY?"-dir.y":"dir.y",m=n==="dual_fisheye"?"projectDualFisheye(dir)":n==="eac"||n==="cubemap"?"projectCube(dir)":"projectEquirect(dir)",g=n==="dual_fisheye"?`
|
|
402
|
+
gl_FragColor = sampleDualFisheye(vec3(${h}, ${d}, dir.z));
|
|
403
|
+
`:`
|
|
404
|
+
vec4 base = ${n==="eac"||n==="cubemap"?"sampleCubeTexture(uv)":"texture2D(uTex, clampTexelUV(uv))"};
|
|
405
|
+
float seamDist = min(uv.x, 1.0 - uv.x);
|
|
406
|
+
if (${n==="eac"||n==="cubemap"?"false":"seamDist < uSeamWidth"}) {
|
|
407
|
+
float oppositeX = uv.x < 0.5 ? 1.0 - seamDist : seamDist;
|
|
408
|
+
vec4 opposite = texture2D(uTex, clampTexelUV(vec2(oppositeX, uv.y)));
|
|
409
|
+
float seamMix = smoothstep(0.0, uSeamWidth, seamDist);
|
|
410
|
+
base = mix((base + opposite) * 0.5, base, seamMix);
|
|
411
|
+
}
|
|
412
|
+
gl_FragColor = base;
|
|
413
|
+
`,b=n==="dual_fisheye"?`
|
|
414
|
+
vec2 baseUV = ${m};
|
|
415
|
+
vec2 uv = vec2(${y}, ${p});
|
|
416
|
+
${g}
|
|
417
|
+
`:`
|
|
418
|
+
vec2 baseUV = ${m};
|
|
419
|
+
if (baseUV.x < 0.0 || baseUV.y < 0.0 || baseUV.x > 1.0 || baseUV.y > 1.0) {
|
|
420
|
+
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
vec2 uv = vec2(${y}, ${p});
|
|
424
|
+
${g}
|
|
425
|
+
`,x=`
|
|
426
|
+
precision highp float;
|
|
427
|
+
uniform sampler2D uTex;
|
|
428
|
+
uniform sampler2D uBackTex;
|
|
429
|
+
uniform float uSeparateLenses;
|
|
430
|
+
uniform float uVerticalLenses;
|
|
431
|
+
uniform float uVisibleLens;
|
|
432
|
+
uniform vec2 uViewport;
|
|
433
|
+
uniform vec2 uTexel;
|
|
434
|
+
uniform float uAspect;
|
|
435
|
+
uniform float uTanHalfFov;
|
|
436
|
+
uniform vec4 uViewQuat;
|
|
437
|
+
uniform float uSeamWidth;
|
|
438
|
+
uniform vec2 uDualFisheyeFrontCenter;
|
|
439
|
+
uniform vec2 uDualFisheyeBackCenter;
|
|
440
|
+
uniform vec2 uDualFisheyeFrontValidRadius;
|
|
441
|
+
uniform vec2 uDualFisheyeBackValidRadius;
|
|
442
|
+
uniform vec2 uDualFisheyeFrontFocal;
|
|
443
|
+
uniform vec2 uDualFisheyeBackFocal;
|
|
444
|
+
uniform vec2 uDualFisheyeFrontPrincipalOffset;
|
|
445
|
+
uniform vec2 uDualFisheyeBackPrincipalOffset;
|
|
446
|
+
uniform vec2 uDualFisheyeFrontScale;
|
|
447
|
+
uniform vec2 uDualFisheyeBackScale;
|
|
448
|
+
uniform vec4 uDualFisheyeFrontRadial;
|
|
449
|
+
uniform vec4 uDualFisheyeBackRadial;
|
|
450
|
+
uniform float uDualFisheyeFrontRadialScale;
|
|
451
|
+
uniform float uDualFisheyeBackRadialScale;
|
|
452
|
+
uniform vec2 uDualFisheyeDJIRadial5;
|
|
453
|
+
uniform vec2 uDualFisheyeFrontTangential;
|
|
454
|
+
uniform vec2 uDualFisheyeBackTangential;
|
|
455
|
+
uniform float uDualFisheyeFrontXi;
|
|
456
|
+
uniform float uDualFisheyeBackXi;
|
|
457
|
+
uniform vec4 uDualFisheyeFrontThinPrism;
|
|
458
|
+
uniform vec4 uDualFisheyeBackThinPrism;
|
|
459
|
+
uniform vec2 uDualFisheyeFrontSensorTilt;
|
|
460
|
+
uniform vec2 uDualFisheyeBackSensorTilt;
|
|
461
|
+
uniform float uDualFisheyeConvergenceM;
|
|
462
|
+
uniform vec2 uDualFisheyePolarInverseDepth;
|
|
463
|
+
uniform vec3 uDualFisheyeFrontTranslationM;
|
|
464
|
+
uniform vec3 uDualFisheyeBackTranslationM;
|
|
465
|
+
uniform vec4 uDualFisheyeFrontPro0;
|
|
466
|
+
uniform vec4 uDualFisheyeFrontPro1;
|
|
467
|
+
uniform vec4 uDualFisheyeFrontPro2;
|
|
468
|
+
uniform float uDualFisheyeFrontPro12;
|
|
469
|
+
uniform vec4 uDualFisheyeBackPro0;
|
|
470
|
+
uniform vec4 uDualFisheyeBackPro1;
|
|
471
|
+
uniform vec4 uDualFisheyeBackPro2;
|
|
472
|
+
uniform float uDualFisheyeBackPro12;
|
|
473
|
+
uniform float uDualFisheyeFrontUsePro;
|
|
474
|
+
uniform float uDualFisheyeBackUsePro;
|
|
475
|
+
uniform vec4 uDualFisheyeFrontRotationQuat;
|
|
476
|
+
uniform vec4 uDualFisheyeBackRotationQuat;
|
|
477
|
+
uniform float uDualFisheyeFrontUseMEI;
|
|
478
|
+
uniform float uDualFisheyeBackUseMEI;
|
|
479
|
+
uniform float uDualFisheyeFrontUseDJI;
|
|
480
|
+
uniform float uDualFisheyeBackUseDJI;
|
|
481
|
+
uniform vec4 uDualFisheyeFrontAsymmetric;
|
|
482
|
+
uniform vec4 uDualFisheyeBackAsymmetric;
|
|
483
|
+
uniform vec3 uDualFisheyeFrontAxis;
|
|
484
|
+
uniform vec3 uDualFisheyeBackAxis;
|
|
485
|
+
uniform vec3 uDualFisheyeFrontRight;
|
|
486
|
+
uniform vec3 uDualFisheyeBackRight;
|
|
487
|
+
uniform vec3 uDualFisheyeFrontUp;
|
|
488
|
+
uniform vec3 uDualFisheyeBackUp;
|
|
489
|
+
uniform float uDualFisheyeMaxTheta;
|
|
490
|
+
uniform float uDualFisheyeBlendBand;
|
|
491
|
+
uniform vec2 uDualFisheyeSeamX;
|
|
492
|
+
uniform float uDualFisheyeSeamBlendX;
|
|
493
|
+
uniform float uDualFisheyeSeamFrontWrap;
|
|
494
|
+
uniform float uDualFisheyeUseSeamLongitudes;
|
|
495
|
+
uniform vec2 uDualFisheyeGain;
|
|
496
|
+
uniform sampler2D uDualFisheyeFrontRemap;
|
|
497
|
+
uniform sampler2D uDualFisheyeBackRemap;
|
|
498
|
+
uniform float uDualFisheyeUseRemap;
|
|
499
|
+
uniform sampler2D uDualFisheyeSeamMask;
|
|
500
|
+
uniform float uDualFisheyeUseSeamMask;
|
|
501
|
+
uniform vec4 uDualFisheyeVideoOffsets;
|
|
502
|
+
uniform float uDualFisheyeVideoSeam;
|
|
503
|
+
|
|
504
|
+
const float PI = 3.1415926535897932384626433832795;
|
|
505
|
+
|
|
506
|
+
vec3 rotateByQuat(vec4 q, vec3 v) {
|
|
507
|
+
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
vec2 clampTexelUV(vec2 uv) {
|
|
511
|
+
return vec2(
|
|
512
|
+
clamp(uv.x, uTexel.x * 0.5, 1.0 - uTexel.x * 0.5),
|
|
513
|
+
clamp(uv.y, uTexel.y * 0.5, 1.0 - uTexel.y * 0.5)
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
vec2 flipDualFisheyeUV(vec2 uv, vec2 center) {
|
|
518
|
+
${i.dualFisheyeFlipX?"uv.x = center.x + (center.x - uv.x);":""}
|
|
519
|
+
${i.dualFisheyeFlipY?"uv.y = center.y + (center.y - uv.y);":""}
|
|
520
|
+
return uv;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
vec2 projectEquirect(vec3 dir) {
|
|
524
|
+
float lon = atan(dir.x, ${u?"dir.z":"-dir.z"});
|
|
525
|
+
float lat = asin(clamp(${u?"-dir.y":"dir.y"}, -1.0, 1.0));
|
|
526
|
+
return vec2(lon / (2.0 * PI) + 0.5, ${u?"lat / PI + 0.5":"0.5 - lat / PI"});
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
vec4 sampleDualFisheyeRemap(sampler2D remapTex, vec2 baseUV) {
|
|
530
|
+
return texture2D(remapTex, baseUV);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
float dualFisheyeGeometryWeight(float frontDot, float backDot) {
|
|
534
|
+
return smoothstep(-uDualFisheyeBlendBand, uDualFisheyeBlendBand, frontDot - backDot);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
float dualFisheyeSeamIntervalWeight(float x) {
|
|
538
|
+
float a = min(uDualFisheyeSeamX.x, uDualFisheyeSeamX.y);
|
|
539
|
+
float b = max(uDualFisheyeSeamX.x, uDualFisheyeSeamX.y);
|
|
540
|
+
float band = max(uDualFisheyeSeamBlendX, 0.0001);
|
|
541
|
+
float enter = smoothstep(a - band, a + band, x);
|
|
542
|
+
float exit = 1.0 - smoothstep(b - band, b + band, x);
|
|
543
|
+
float interval = clamp(enter * exit, 0.0, 1.0);
|
|
544
|
+
return uDualFisheyeSeamFrontWrap > 0.5 ? 1.0 - interval : interval;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
float dualFisheyeLensCoverage(vec2 uv, vec2 center, vec2 validRadius) {
|
|
548
|
+
vec2 normalizedRadius = max(validRadius, vec2(0.0001));
|
|
549
|
+
return max(1.0 - length((uv - center) / normalizedRadius), 0.0);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
float dualFisheyeBlendWeight(vec3 dir, float frontDot, float backDot, float frontConfidence, float backConfidence) {
|
|
553
|
+
float geometryWeight = dualFisheyeGeometryWeight(frontDot, backDot);
|
|
554
|
+
float seamWeight = dualFisheyeSeamIntervalWeight(projectEquirect(dir).x);
|
|
555
|
+
float seamBlend = mix(geometryWeight, seamWeight, uDualFisheyeUseSeamLongitudes);
|
|
556
|
+
vec4 contentMask = texture2D(uDualFisheyeSeamMask, projectEquirect(dir));
|
|
557
|
+
float contentAwareBlend = 1.0 - contentMask.r;
|
|
558
|
+
// DJI foreground can cross the ordinary seam. INSV keeps its calibrated
|
|
559
|
+
// sky/road blend and only protects the lower subject: lens exposure and
|
|
560
|
+
// night noise must not become a hard, intermittently changing sky owner.
|
|
561
|
+
float contentStrength = ${s&&(c==null?void 0:c.front.projectionModel)==="dji_fisheye_lut"?"contentMask.a":"mix(1.0, smoothstep(sin(radians(50.0)), sin(radians(65.0)), dir.y), uDualFisheyeVideoSeam)"};
|
|
562
|
+
seamBlend = mix(seamBlend, contentAwareBlend, uDualFisheyeUseSeamMask * contentStrength);
|
|
563
|
+
float frontWeight = frontConfidence * seamBlend;
|
|
564
|
+
float backWeight = backConfidence * (1.0 - seamBlend);
|
|
565
|
+
return clamp(frontWeight / max(frontWeight + backWeight, 0.0001), 0.0, 1.0);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
float dualFisheyeEdgeAwareBlend(float blend, vec4 frontColor, vec4 backColor) {
|
|
569
|
+
float colorDelta = length(frontColor.rgb - backColor.rgb);
|
|
570
|
+
float mismatch = smoothstep(0.08, 0.24, colorDelta);
|
|
571
|
+
float sharpenedBlend = smoothstep(0.34, 0.66, blend);
|
|
572
|
+
return mix(blend, sharpenedBlend, mismatch * 0.72);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
vec2 projectDualFisheye(vec3 dir) {
|
|
576
|
+
float frontDot = dot(dir, uDualFisheyeFrontAxis);
|
|
577
|
+
float backDot = dot(dir, uDualFisheyeBackAxis);
|
|
578
|
+
bool useFront = frontDot >= backDot;
|
|
579
|
+
vec3 axis = useFront ? uDualFisheyeFrontAxis : uDualFisheyeBackAxis;
|
|
580
|
+
float axisDot = useFront ? frontDot : backDot;
|
|
581
|
+
float theta = acos(clamp(axisDot, -1.0, 1.0));
|
|
582
|
+
if (theta > uDualFisheyeMaxTheta) {
|
|
583
|
+
return vec2(-1.0, -1.0);
|
|
584
|
+
}
|
|
585
|
+
vec3 right = useFront ? uDualFisheyeFrontRight : uDualFisheyeBackRight;
|
|
586
|
+
vec3 up = useFront ? uDualFisheyeFrontUp : uDualFisheyeBackUp;
|
|
587
|
+
vec3 radial3 = dir - axis * axisDot;
|
|
588
|
+
float radialLen = length(radial3);
|
|
589
|
+
vec2 radialCoord = radialLen > 0.00001
|
|
590
|
+
? vec2(dot(radial3 / radialLen, right), -dot(radial3 / radialLen, up))
|
|
591
|
+
: vec2(0.0, 0.0);
|
|
592
|
+
float radius = theta / uDualFisheyeMaxTheta;
|
|
593
|
+
vec2 center = useFront ? uDualFisheyeFrontCenter : uDualFisheyeBackCenter;
|
|
594
|
+
vec2 scale = useFront ? uDualFisheyeFrontScale : uDualFisheyeBackScale;
|
|
595
|
+
return center + radialCoord * radius * scale;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
vec2 projectDistortedDualLens(
|
|
599
|
+
vec3 dir,
|
|
600
|
+
vec3 axis,
|
|
601
|
+
vec2 center,
|
|
602
|
+
vec3 right,
|
|
603
|
+
vec3 up,
|
|
604
|
+
vec2 focal,
|
|
605
|
+
vec2 principalOffset,
|
|
606
|
+
vec4 radialCoeffs,
|
|
607
|
+
vec2 tangential,
|
|
608
|
+
vec4 asymmetric
|
|
609
|
+
) {
|
|
610
|
+
float axisDot = dot(dir, axis);
|
|
611
|
+
float theta = acos(clamp(axisDot, -1.0, 1.0));
|
|
612
|
+
if (theta > uDualFisheyeMaxTheta) {
|
|
613
|
+
return vec2(-1.0, -1.0);
|
|
614
|
+
}
|
|
615
|
+
vec3 radial3 = dir - axis * axisDot;
|
|
616
|
+
float radialLen = length(radial3);
|
|
617
|
+
vec2 radial = radialLen > 0.00001
|
|
618
|
+
? vec2(dot(radial3 / radialLen, right), -dot(radial3 / radialLen, up))
|
|
619
|
+
: vec2(0.0, 0.0);
|
|
620
|
+
vec2 radialCoord = radial;
|
|
621
|
+
float theta2 = theta * theta;
|
|
622
|
+
float distorted =
|
|
623
|
+
theta *
|
|
624
|
+
(1.0 +
|
|
625
|
+
radialCoeffs.x * theta2 +
|
|
626
|
+
radialCoeffs.y * theta2 * theta2 +
|
|
627
|
+
radialCoeffs.z * theta2 * theta2 * theta2 +
|
|
628
|
+
radialCoeffs.w * theta2 * theta2 * theta2 * theta2);
|
|
629
|
+
vec2 lensCoord = distorted * radialCoord;
|
|
630
|
+
float r2 = dot(lensCoord, lensCoord);
|
|
631
|
+
float tx = 2.0 * tangential.x * lensCoord.x * lensCoord.y + tangential.y * (r2 + 2.0 * lensCoord.x * lensCoord.x);
|
|
632
|
+
float ty = tangential.x * (r2 + 2.0 * lensCoord.y * lensCoord.y) + 2.0 * tangential.y * lensCoord.x * lensCoord.y;
|
|
633
|
+
float ax = asymmetric.x * lensCoord.x + asymmetric.y * lensCoord.y;
|
|
634
|
+
float ay = asymmetric.z * lensCoord.x + asymmetric.w * lensCoord.y;
|
|
635
|
+
return center + principalOffset + vec2(
|
|
636
|
+
focal.x * (lensCoord.x + tx + ax),
|
|
637
|
+
focal.y * (lensCoord.y + ty + ay)
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
vec2 applyDualFisheyeSensorTilt(vec2 point, vec2 tilt) {
|
|
642
|
+
float cx = cos(tilt.x), sx = sin(tilt.x);
|
|
643
|
+
float cy = cos(tilt.y), sy = sin(tilt.y);
|
|
644
|
+
float rx = cy*point.x + sy*sx*point.y - sy*cx;
|
|
645
|
+
float ry = cx*point.y + sx;
|
|
646
|
+
float rz = sy*point.x - cy*sx*point.y + cy*cx;
|
|
647
|
+
float safeRz = abs(rz) > 0.000001 ? rz : (rz < 0.0 ? -0.000001 : 0.000001);
|
|
648
|
+
return vec2(cx*(cy*rx + sy*rz), cy*cx*ry - sx*rz) / safeRz;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
vec3 projectMEIDualLens(
|
|
652
|
+
vec3 dir,
|
|
653
|
+
vec4 rotationQuat,
|
|
654
|
+
vec2 center,
|
|
655
|
+
vec2 focal,
|
|
656
|
+
vec2 principalOffset,
|
|
657
|
+
float xi,
|
|
658
|
+
vec4 radialCoeffs,
|
|
659
|
+
vec2 tangential,
|
|
660
|
+
vec4 thinPrism,
|
|
661
|
+
vec2 sensorTilt,
|
|
662
|
+
vec4 pro0,
|
|
663
|
+
vec4 pro1,
|
|
664
|
+
vec4 pro2,
|
|
665
|
+
float pro12,
|
|
666
|
+
float usePro,
|
|
667
|
+
vec3 translationM
|
|
668
|
+
) {
|
|
669
|
+
// Calibration quaternions arrive as [w, x, y, z], while rotateByQuat
|
|
670
|
+
// consumes the GPU-friendly [x, y, z, w] layout.
|
|
671
|
+
vec3 local = rotateByQuat(vec4(-rotationQuat.y, -rotationQuat.z, -rotationQuat.w, rotationQuat.x), dir);
|
|
672
|
+
float inverseDepth = uDualFisheyeConvergenceM > 0.0 ? 1.0 / uDualFisheyeConvergenceM : 0.0;
|
|
673
|
+
float polarDepth = dir.y > 0.0 ? uDualFisheyePolarInverseDepth.y : uDualFisheyePolarInverseDepth.x;
|
|
674
|
+
float polarStart = mix(sin(radians(30.0)), sin(radians(50.0)), uDualFisheyeVideoSeam);
|
|
675
|
+
float polarEnd = mix(sin(radians(50.0)), sin(radians(65.0)), uDualFisheyeVideoSeam);
|
|
676
|
+
if (polarDepth > 0.0) inverseDepth = mix(inverseDepth, polarDepth, smoothstep(polarStart, polarEnd, abs(dir.y)));
|
|
677
|
+
if (inverseDepth > 0.0) {
|
|
678
|
+
local = normalize(local / inverseDepth + translationM);
|
|
679
|
+
}
|
|
680
|
+
float denominator = local.z + xi;
|
|
681
|
+
if (denominator <= 0.000001) return vec3(-1.0, -1.0, 0.0);
|
|
682
|
+
vec2 normalized = local.xy / denominator;
|
|
683
|
+
float r2 = dot(normalized, normalized);
|
|
684
|
+
if (r2 > 16.0) return vec3(-1.0, -1.0, 0.0);
|
|
685
|
+
float r4 = r2 * r2;
|
|
686
|
+
float radialFactor = 1.0 + radialCoeffs.x*r2 + radialCoeffs.y*r4 + radialCoeffs.z*r2*r4 + radialCoeffs.w*r4*r4;
|
|
687
|
+
float x = normalized.x;
|
|
688
|
+
float y = normalized.y;
|
|
689
|
+
vec2 distorted = vec2(
|
|
690
|
+
x*radialFactor + 2.0*tangential.x*x*y + tangential.y*(r2 + 2.0*x*x) + thinPrism.x*r2 + thinPrism.y*r4,
|
|
691
|
+
y*radialFactor + tangential.x*(r2 + 2.0*y*y) + 2.0*tangential.y*x*y + thinPrism.z*r2 + thinPrism.w*r4
|
|
692
|
+
);
|
|
693
|
+
vec2 projected = applyDualFisheyeSensorTilt(distorted, sensorTilt);
|
|
694
|
+
if (usePro > 0.5) {
|
|
695
|
+
float radial = 1.0 + pro0.x*r2 + pro0.y*r4 + pro0.z*r2*r4 + pro0.w*r4*r4 + pro1.x*r4*r4*r2;
|
|
696
|
+
float a = pro1.y + pro1.w*r2;
|
|
697
|
+
float b = pro1.z + pro2.x*r2;
|
|
698
|
+
projected = vec2(
|
|
699
|
+
x*radial + (r2+2.0*x*x)*a + 2.0*x*y*b + pro2.y*r2 + pro2.w*r4,
|
|
700
|
+
y*radial + (r2+2.0*y*y)*b + 2.0*x*y*a + pro2.z*r2 + pro12*r4
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
vec2 uv = center + principalOffset + focal * projected;
|
|
704
|
+
return vec3(uv, 1.0);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
vec3 projectDJIDualLens(
|
|
708
|
+
vec3 dir,
|
|
709
|
+
vec3 axis,
|
|
710
|
+
vec2 center,
|
|
711
|
+
vec3 right,
|
|
712
|
+
vec3 up,
|
|
713
|
+
vec2 focal,
|
|
714
|
+
vec2 principalOffset,
|
|
715
|
+
vec4 radialCoeffs,
|
|
716
|
+
float radialScale,
|
|
717
|
+
float radial5,
|
|
718
|
+
vec2 tangential,
|
|
719
|
+
float fullModel
|
|
720
|
+
) {
|
|
721
|
+
vec3 local = vec3(dot(dir, right), -dot(dir, up), dot(dir, axis));
|
|
722
|
+
float theta = atan(length(local.xy), local.z);
|
|
723
|
+
if (theta >= radians(96.0)) return vec3(-1.0, -1.0, 0.0);
|
|
724
|
+
float rho = length(local.xy);
|
|
725
|
+
if (rho <= 0.000001) return vec3(center + principalOffset, 1.0);
|
|
726
|
+
if (fullModel > 1.5) {
|
|
727
|
+
float t2 = theta * theta;
|
|
728
|
+
float r = theta * (1.0 + t2*(radialCoeffs.x+t2*(radialCoeffs.y+t2*(radialCoeffs.z+t2*(radialCoeffs.w+t2*radial5)))));
|
|
729
|
+
vec2 xy = r * local.xy / rho;
|
|
730
|
+
float r2 = dot(xy, xy);
|
|
731
|
+
vec2 distorted = xy + vec2(
|
|
732
|
+
2.0*tangential.x*xy.x*xy.y + tangential.y*(r2+2.0*xy.x*xy.x),
|
|
733
|
+
tangential.x*(r2+2.0*xy.y*xy.y) + 2.0*tangential.y*xy.x*xy.y);
|
|
734
|
+
return vec3(center + principalOffset + focal * distorted, 1.0);
|
|
735
|
+
}
|
|
736
|
+
float limit = radians(85.0);
|
|
737
|
+
float t = min(theta, limit);
|
|
738
|
+
float t2 = t * t;
|
|
739
|
+
float polynomial = t * (1.0 + radialCoeffs.x*t2 + radialCoeffs.y*t2*t2 + radialCoeffs.z*t2*t2*t2 + radialCoeffs.w*t2*t2*t2*t2);
|
|
740
|
+
if (theta > limit) {
|
|
741
|
+
float derivative = 1.0 + 3.0*radialCoeffs.x*t2 + 5.0*radialCoeffs.y*t2*t2 + 7.0*radialCoeffs.z*t2*t2*t2 + 9.0*radialCoeffs.w*t2*t2*t2*t2;
|
|
742
|
+
polynomial += derivative * (theta - limit);
|
|
743
|
+
}
|
|
744
|
+
vec2 radius = radialScale * focal * polynomial;
|
|
745
|
+
return vec3(center + principalOffset + radius * local.xy / rho, 1.0);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
vec4 sampleLens(vec2 uv, bool back) {
|
|
749
|
+
if (uSeparateLenses < 0.5) return texture2D(uTex, clampTexelUV(uv));
|
|
750
|
+
vec2 center = back ? uDualFisheyeBackCenter : uDualFisheyeFrontCenter;
|
|
751
|
+
float physical = step(0.5, uVerticalLenses > 0.5 ? center.y : center.x);
|
|
752
|
+
vec2 local = uVerticalLenses > 0.5 ? vec2(uv.x, uv.y * 2.0 - physical)
|
|
753
|
+
: vec2(uv.x * 2.0 - physical, uv.y);
|
|
754
|
+
local = clamp(local, uTexel, vec2(1.0) - uTexel);
|
|
755
|
+
return physical > 0.5 ? texture2D(uBackTex, local) : texture2D(uTex, local);
|
|
756
|
+
}
|
|
757
|
+
vec4 sampleCubeTexture(vec2 uv) {
|
|
758
|
+
if (uSeparateLenses < 0.5) return texture2D(uTex, clampTexelUV(uv));
|
|
759
|
+
// Two independent EAC tracks each contain one row of the cube atlas.
|
|
760
|
+
vec2 local = vec2(uv.x, fract(uv.y * 2.0));
|
|
761
|
+
return uv.y >= 0.5 ? texture2D(uTex, local) : texture2D(uBackTex, local);
|
|
762
|
+
}
|
|
763
|
+
vec2 projectCube(vec3 d) {
|
|
764
|
+
// Convert the viewer's -Z forward ray to v360's +Z coordinate system.
|
|
765
|
+
d.z = -d.z;
|
|
766
|
+
vec3 a = abs(d);
|
|
767
|
+
vec2 q;
|
|
768
|
+
float face;
|
|
769
|
+
if (a.x >= a.y && a.x >= a.z) {
|
|
770
|
+
if (d.x > 0.0) { face = 0.0; q = vec2(-d.z, d.y) / d.x; }
|
|
771
|
+
else { face = 1.0; q = vec2(-d.z, -d.y) / d.x; }
|
|
772
|
+
} else if (a.y >= a.z) {
|
|
773
|
+
if (d.y < 0.0) { face = 2.0; q = vec2(-d.x, -d.z) / d.y; }
|
|
774
|
+
else { face = 3.0; q = vec2(d.x, -d.z) / d.y; }
|
|
775
|
+
} else {
|
|
776
|
+
if (d.z > 0.0) { face = 4.0; q = vec2(d.x, d.y) / d.z; }
|
|
777
|
+
else { face = 5.0; q = vec2(d.x, -d.y) / d.z; }
|
|
778
|
+
}
|
|
779
|
+
${n==="eac"?`
|
|
780
|
+
// EAC face order L/F/R, D/B/U and lower-row rotations follow v360's EAC convention.
|
|
781
|
+
if (face == 0.0) face = 2.0;
|
|
782
|
+
else if (face == 1.0) face = 0.0;
|
|
783
|
+
else if (face == 2.0) { face = 5.0; q = vec2(q.y, -q.x); }
|
|
784
|
+
else if (face == 3.0) { face = 3.0; q = vec2(q.y, -q.x); }
|
|
785
|
+
else if (face == 4.0) face = 1.0;
|
|
786
|
+
else { face = 4.0; q = vec2(-q.y, q.x); }
|
|
787
|
+
q = atan(q) * (2.0 / 3.141592653589793) + 0.5;
|
|
788
|
+
vec2 pad = 2.0 * uTexel;
|
|
789
|
+
return vec2((q.x + mod(face, 3.0)) * (1.0 - 2.0 * pad.x) / 3.0 + pad.x,
|
|
790
|
+
1.0 - (q.y * (0.5 - 2.0 * pad.y) + pad.y + 0.5 * floor(face / 3.0)));
|
|
791
|
+
`:"vec2 edge = uTexel * vec2(1.5, 1.0); vec2 local = clamp((q + 1.0) * 0.5, edge, vec2(1.0) - edge); vec2 uv = (vec2(mod(face, 3.0), floor(face / 3.0)) + local) / vec2(3.0, 2.0); return vec2(uv.x, 1.0 - uv.y);"}
|
|
792
|
+
}
|
|
793
|
+
vec3 projectFrontLens(vec3 dir) {
|
|
794
|
+
return uDualFisheyeFrontUseMEI > 0.5 ? projectMEIDualLens(
|
|
795
|
+
dir,
|
|
796
|
+
uDualFisheyeFrontRotationQuat,
|
|
797
|
+
uDualFisheyeFrontCenter,
|
|
798
|
+
uDualFisheyeFrontFocal,
|
|
799
|
+
uDualFisheyeFrontPrincipalOffset,
|
|
800
|
+
uDualFisheyeFrontXi,
|
|
801
|
+
uDualFisheyeFrontRadial,
|
|
802
|
+
uDualFisheyeFrontTangential,
|
|
803
|
+
uDualFisheyeFrontThinPrism,
|
|
804
|
+
uDualFisheyeFrontSensorTilt,
|
|
805
|
+
uDualFisheyeFrontPro0,
|
|
806
|
+
uDualFisheyeFrontPro1,
|
|
807
|
+
uDualFisheyeFrontPro2,
|
|
808
|
+
uDualFisheyeFrontPro12,
|
|
809
|
+
uDualFisheyeFrontUsePro,
|
|
810
|
+
uDualFisheyeFrontTranslationM
|
|
811
|
+
) : (uDualFisheyeFrontUseDJI > 0.5 ? projectDJIDualLens(
|
|
812
|
+
dir,
|
|
813
|
+
uDualFisheyeFrontAxis,
|
|
814
|
+
uDualFisheyeFrontCenter,
|
|
815
|
+
uDualFisheyeFrontRight,
|
|
816
|
+
uDualFisheyeFrontUp,
|
|
817
|
+
uDualFisheyeFrontFocal,
|
|
818
|
+
uDualFisheyeFrontPrincipalOffset,
|
|
819
|
+
uDualFisheyeFrontRadial,
|
|
820
|
+
uDualFisheyeFrontRadialScale,
|
|
821
|
+
uDualFisheyeDJIRadial5.x,
|
|
822
|
+
uDualFisheyeFrontTangential,
|
|
823
|
+
uDualFisheyeFrontUseDJI
|
|
824
|
+
) : vec3(projectDistortedDualLens(
|
|
825
|
+
dir,
|
|
826
|
+
uDualFisheyeFrontAxis,
|
|
827
|
+
uDualFisheyeFrontCenter,
|
|
828
|
+
uDualFisheyeFrontRight,
|
|
829
|
+
uDualFisheyeFrontUp,
|
|
830
|
+
uDualFisheyeFrontFocal,
|
|
831
|
+
uDualFisheyeFrontPrincipalOffset,
|
|
832
|
+
uDualFisheyeFrontRadial,
|
|
833
|
+
uDualFisheyeFrontTangential,
|
|
834
|
+
uDualFisheyeFrontAsymmetric
|
|
835
|
+
), float(acos(clamp(dot(dir, uDualFisheyeFrontAxis), -1.0, 1.0)) <= uDualFisheyeMaxTheta)));
|
|
836
|
+
}
|
|
837
|
+
vec3 projectBackLens(vec3 dir) {
|
|
838
|
+
vec3 backDirection = dir;
|
|
839
|
+
if (length(uDualFisheyeVideoOffsets) > 0.0) {
|
|
840
|
+
// A smooth spherical field joins independently registered overlaps;
|
|
841
|
+
// it does not jump when the camera crosses a seam or a video frame.
|
|
842
|
+
float fade = 1.0 - smoothstep(sin(radians(${s?"50.0":"30.0"})), sin(radians(${s?"70.0":"50.0"})), abs(dir.y));
|
|
843
|
+
// Keep the original polar ray, just like CPU sampling. Reconstructing
|
|
844
|
+
// it through atan/asin after the correction ends adds rounding drift.
|
|
845
|
+
if (fade > 0.0) {
|
|
846
|
+
float longitude = atan(dir.x, dir.z);
|
|
847
|
+
float latitude = asin(clamp(dir.y, -1.0, 1.0));
|
|
848
|
+
vec2 offset = mix(uDualFisheyeVideoOffsets.xy, uDualFisheyeVideoOffsets.zw, 0.5 + 0.5 * sin(longitude)) * fade;
|
|
849
|
+
longitude += offset.x;
|
|
850
|
+
latitude = clamp(latitude + offset.y, -PI * 0.5, PI * 0.5);
|
|
851
|
+
backDirection = vec3(cos(latitude) * sin(longitude), sin(latitude), cos(latitude) * cos(longitude));
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return uDualFisheyeBackUseMEI > 0.5 ? projectMEIDualLens(
|
|
855
|
+
backDirection,
|
|
856
|
+
uDualFisheyeBackRotationQuat,
|
|
857
|
+
uDualFisheyeBackCenter,
|
|
858
|
+
uDualFisheyeBackFocal,
|
|
859
|
+
uDualFisheyeBackPrincipalOffset,
|
|
860
|
+
uDualFisheyeBackXi,
|
|
861
|
+
uDualFisheyeBackRadial,
|
|
862
|
+
uDualFisheyeBackTangential,
|
|
863
|
+
uDualFisheyeBackThinPrism,
|
|
864
|
+
uDualFisheyeBackSensorTilt,
|
|
865
|
+
uDualFisheyeBackPro0,
|
|
866
|
+
uDualFisheyeBackPro1,
|
|
867
|
+
uDualFisheyeBackPro2,
|
|
868
|
+
uDualFisheyeBackPro12,
|
|
869
|
+
uDualFisheyeBackUsePro,
|
|
870
|
+
uDualFisheyeBackTranslationM
|
|
871
|
+
) : (uDualFisheyeBackUseDJI > 0.5 ? projectDJIDualLens(
|
|
872
|
+
backDirection,
|
|
873
|
+
uDualFisheyeBackAxis,
|
|
874
|
+
uDualFisheyeBackCenter,
|
|
875
|
+
uDualFisheyeBackRight,
|
|
876
|
+
uDualFisheyeBackUp,
|
|
877
|
+
uDualFisheyeBackFocal,
|
|
878
|
+
uDualFisheyeBackPrincipalOffset,
|
|
879
|
+
uDualFisheyeBackRadial,
|
|
880
|
+
uDualFisheyeBackRadialScale,
|
|
881
|
+
uDualFisheyeDJIRadial5.y,
|
|
882
|
+
uDualFisheyeBackTangential,
|
|
883
|
+
uDualFisheyeBackUseDJI
|
|
884
|
+
) : vec3(projectDistortedDualLens(
|
|
885
|
+
dir,
|
|
886
|
+
uDualFisheyeBackAxis,
|
|
887
|
+
uDualFisheyeBackCenter,
|
|
888
|
+
uDualFisheyeBackRight,
|
|
889
|
+
uDualFisheyeBackUp,
|
|
890
|
+
uDualFisheyeBackFocal,
|
|
891
|
+
uDualFisheyeBackPrincipalOffset,
|
|
892
|
+
uDualFisheyeBackRadial,
|
|
893
|
+
uDualFisheyeBackTangential,
|
|
894
|
+
uDualFisheyeBackAsymmetric
|
|
895
|
+
), float(acos(clamp(dot(dir, uDualFisheyeBackAxis), -1.0, 1.0)) <= uDualFisheyeMaxTheta)));
|
|
896
|
+
}
|
|
897
|
+
vec4 sampleDualFisheye(vec3 dir) {
|
|
898
|
+
// The padded viewport has one calibrated owner. Avoid the other
|
|
899
|
+
// distortion projection, texture fetch and blend for every visible pixel.
|
|
900
|
+
if (uVisibleLens > 0.5) {
|
|
901
|
+
bool back = uVisibleLens > 1.5;
|
|
902
|
+
vec3 projected;
|
|
903
|
+
if (back) projected = projectBackLens(dir);
|
|
904
|
+
else projected = projectFrontLens(dir);
|
|
905
|
+
vec2 center = back ? uDualFisheyeBackCenter : uDualFisheyeFrontCenter;
|
|
906
|
+
vec2 radius = back ? uDualFisheyeBackValidRadius : uDualFisheyeFrontValidRadius;
|
|
907
|
+
if (projected.z > 0.5 && dualFisheyeLensCoverage(projected.xy, center, radius) > 0.0 &&
|
|
908
|
+
projected.x >= 0.0 && projected.y >= 0.0 && projected.x <= 1.0 && projected.y <= 1.0) {
|
|
909
|
+
return sampleLens(flipDualFisheyeUV(projected.xy, center), back) *
|
|
910
|
+
vec4(vec3(back ? uDualFisheyeGain.y : uDualFisheyeGain.x), 1.0);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
float frontDot = dot(dir, uDualFisheyeFrontAxis);
|
|
914
|
+
float backDot = dot(dir, uDualFisheyeBackAxis);
|
|
915
|
+
if (uDualFisheyeUseRemap > 0.5) {
|
|
916
|
+
vec2 baseUV = projectEquirect(dir);
|
|
917
|
+
vec4 frontMap = sampleDualFisheyeRemap(uDualFisheyeFrontRemap, baseUV);
|
|
918
|
+
vec4 backMap = sampleDualFisheyeRemap(uDualFisheyeBackRemap, baseUV);
|
|
919
|
+
bool frontValid = frontMap.z > 0.5;
|
|
920
|
+
bool backValid = backMap.z > 0.5;
|
|
921
|
+
frontMap.xy = flipDualFisheyeUV(frontMap.xy, uDualFisheyeFrontCenter);
|
|
922
|
+
backMap.xy = flipDualFisheyeUV(backMap.xy, uDualFisheyeBackCenter);
|
|
923
|
+
vec4 frontColor = frontValid ? sampleLens(frontMap.xy, false) * vec4(vec3(uDualFisheyeGain.x), 1.0) : vec4(0.0);
|
|
924
|
+
vec4 backColor = backValid ? sampleLens(backMap.xy, true) * vec4(vec3(uDualFisheyeGain.y), 1.0) : vec4(0.0);
|
|
925
|
+
if (frontValid && backValid) {
|
|
926
|
+
float seamBlend = dualFisheyeBlendWeight(dir, frontDot, backDot, frontMap.w, backMap.w);
|
|
927
|
+
float totalConfidence = max(0.0001, frontMap.w + backMap.w);
|
|
928
|
+
float confidenceBlend = clamp(frontMap.w / totalConfidence, 0.0, 1.0);
|
|
929
|
+
float blend = clamp(mix(confidenceBlend, seamBlend, 0.75), 0.0, 1.0);
|
|
930
|
+
blend = dualFisheyeEdgeAwareBlend(blend, frontColor, backColor);
|
|
931
|
+
return mix(backColor, frontColor, blend);
|
|
932
|
+
}
|
|
933
|
+
if (frontValid) return frontColor;
|
|
934
|
+
if (backValid) return backColor;
|
|
935
|
+
return vec4(0.0, 0.0, 0.0, 1.0);
|
|
936
|
+
}
|
|
937
|
+
vec3 frontProjection = projectFrontLens(dir);
|
|
938
|
+
vec3 backProjection = projectBackLens(dir);
|
|
939
|
+
vec2 uvFront = frontProjection.xy;
|
|
940
|
+
vec2 uvBack = backProjection.xy;
|
|
941
|
+
float frontCoverage = dualFisheyeLensCoverage(uvFront, uDualFisheyeFrontCenter, uDualFisheyeFrontValidRadius);
|
|
942
|
+
float backCoverage = dualFisheyeLensCoverage(uvBack, uDualFisheyeBackCenter, uDualFisheyeBackValidRadius);
|
|
943
|
+
bool frontValid = frontProjection.z > 0.5 && frontCoverage > 0.0 && uvFront.x >= 0.0 && uvFront.y >= 0.0 && uvFront.x <= 1.0 && uvFront.y <= 1.0;
|
|
944
|
+
bool backValid = backProjection.z > 0.5 && backCoverage > 0.0 && uvBack.x >= 0.0 && uvBack.y >= 0.0 && uvBack.x <= 1.0 && uvBack.y <= 1.0;
|
|
945
|
+
uvFront = flipDualFisheyeUV(uvFront, uDualFisheyeFrontCenter);
|
|
946
|
+
uvBack = flipDualFisheyeUV(uvBack, uDualFisheyeBackCenter);
|
|
947
|
+
vec4 frontColor = frontValid ? sampleLens(uvFront, false) * vec4(vec3(uDualFisheyeGain.x), 1.0) : vec4(0.0);
|
|
948
|
+
vec4 backColor = backValid ? sampleLens(uvBack, true) * vec4(vec3(uDualFisheyeGain.y), 1.0) : vec4(0.0);
|
|
949
|
+
if (frontValid && backValid) {
|
|
950
|
+
float blend = dualFisheyeBlendWeight(dir, frontDot, backDot, frontCoverage, backCoverage);
|
|
951
|
+
blend = dualFisheyeEdgeAwareBlend(blend, frontColor, backColor);
|
|
952
|
+
return mix(backColor, frontColor, blend);
|
|
953
|
+
}
|
|
954
|
+
if (frontValid) return frontColor;
|
|
955
|
+
if (backValid) return backColor;
|
|
956
|
+
return vec4(0.0, 0.0, 0.0, 1.0);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
void main() {
|
|
960
|
+
${i.captureEquirectangular?`
|
|
961
|
+
vec2 sphereUV = vec2(gl_FragCoord.x / uViewport.x, 1.0 - gl_FragCoord.y / uViewport.y);
|
|
962
|
+
float longitude = (sphereUV.x - 0.5) * 2.0 * PI;
|
|
963
|
+
float latitude = (sphereUV.y - 0.5) * PI;
|
|
964
|
+
vec3 dir = vec3(cos(latitude) * sin(longitude), sin(latitude), ${u?"":"-"}cos(latitude) * cos(longitude));
|
|
965
|
+
`:`
|
|
966
|
+
vec2 ndc = (gl_FragCoord.xy / uViewport) * 2.0 - 1.0;
|
|
967
|
+
ndc.y = -ndc.y;
|
|
968
|
+
vec3 ray = normalize(vec3(ndc.x * uAspect * uTanHalfFov, ndc.y * uTanHalfFov, ${u?"1.0":"-1.0"}));
|
|
969
|
+
vec3 dir = normalize(rotateByQuat(uViewQuat, ray));
|
|
970
|
+
`}
|
|
971
|
+
${b}
|
|
972
|
+
}
|
|
973
|
+
`,v=Zs(a,f,x);a.useProgram(v);const w=a.getAttribLocation(v,"aClipPosition"),k=a.getUniformLocation(v,"uTex"),D=a.getUniformLocation(v,"uViewport"),F=a.getUniformLocation(v,"uTexel"),S=a.getUniformLocation(v,"uAspect"),R=a.getUniformLocation(v,"uTanHalfFov"),_=a.getUniformLocation(v,"uViewQuat"),T=a.getUniformLocation(v,"uVisibleLens"),A=a.getUniformLocation(v,"uSeamWidth"),C=a.getUniformLocation(v,"uDualFisheyeFrontCenter"),j=a.getUniformLocation(v,"uDualFisheyeBackCenter"),G=a.getUniformLocation(v,"uDualFisheyeFrontValidRadius"),q=a.getUniformLocation(v,"uDualFisheyeBackValidRadius"),te=a.getUniformLocation(v,"uDualFisheyeFrontFocal"),ne=a.getUniformLocation(v,"uDualFisheyeBackFocal"),ue=a.getUniformLocation(v,"uDualFisheyeFrontPrincipalOffset"),J=a.getUniformLocation(v,"uDualFisheyeBackPrincipalOffset"),Z=a.getUniformLocation(v,"uDualFisheyeFrontScale"),Tt=a.getUniformLocation(v,"uDualFisheyeBackScale"),ce=a.getUniformLocation(v,"uDualFisheyeFrontRadial"),$=a.getUniformLocation(v,"uDualFisheyeBackRadial"),xe=a.getUniformLocation(v,"uDualFisheyeFrontRadialScale"),pe=a.getUniformLocation(v,"uDualFisheyeBackRadialScale"),re=a.getUniformLocation(v,"uDualFisheyeDJIRadial5"),ke=a.getUniformLocation(v,"uDualFisheyeFrontTangential"),et=a.getUniformLocation(v,"uDualFisheyeBackTangential"),tt=a.getUniformLocation(v,"uDualFisheyeFrontXi"),Qt=a.getUniformLocation(v,"uDualFisheyeBackXi"),Ht=a.getUniformLocation(v,"uDualFisheyeFrontThinPrism"),Le=a.getUniformLocation(v,"uDualFisheyeBackThinPrism"),_e=a.getUniformLocation(v,"uDualFisheyeFrontSensorTilt"),it=a.getUniformLocation(v,"uDualFisheyeBackSensorTilt"),ki=a.getUniformLocation(v,"uDualFisheyeConvergenceM"),Ti=a.getUniformLocation(v,"uDualFisheyePolarInverseDepth"),Ri=["Front","Back"].map(M=>a.getUniformLocation(v,`uDualFisheye${M}TranslationM`)),at=["Front","Back"].map(M=>["Pro0","Pro1","Pro2","Pro12","UsePro"].map(P=>a.getUniformLocation(v,`uDualFisheye${M}${P}`))),Pi=a.getUniformLocation(v,"uDualFisheyeFrontRotationQuat"),ja=a.getUniformLocation(v,"uDualFisheyeBackRotationQuat"),Na=a.getUniformLocation(v,"uDualFisheyeFrontUseMEI"),Oa=a.getUniformLocation(v,"uDualFisheyeBackUseMEI"),Va=a.getUniformLocation(v,"uDualFisheyeFrontUseDJI"),Wa=a.getUniformLocation(v,"uDualFisheyeBackUseDJI"),Ga=a.getUniformLocation(v,"uDualFisheyeFrontAsymmetric"),qa=a.getUniformLocation(v,"uDualFisheyeBackAsymmetric"),Xa=a.getUniformLocation(v,"uDualFisheyeFrontAxis"),$a=a.getUniformLocation(v,"uDualFisheyeBackAxis"),Ya=a.getUniformLocation(v,"uDualFisheyeFrontRight"),Qa=a.getUniformLocation(v,"uDualFisheyeBackRight"),Ha=a.getUniformLocation(v,"uDualFisheyeFrontUp"),Ja=a.getUniformLocation(v,"uDualFisheyeBackUp"),Ka=a.getUniformLocation(v,"uDualFisheyeMaxTheta"),Za=a.getUniformLocation(v,"uDualFisheyeBlendBand"),er=a.getUniformLocation(v,"uDualFisheyeSeamX"),tr=a.getUniformLocation(v,"uDualFisheyeSeamBlendX"),ir=a.getUniformLocation(v,"uDualFisheyeSeamFrontWrap"),ar=a.getUniformLocation(v,"uDualFisheyeUseSeamLongitudes"),rr=a.getUniformLocation(v,"uDualFisheyeGain"),io=a.getUniformLocation(v,"uDualFisheyeFrontRemap"),ao=a.getUniformLocation(v,"uDualFisheyeBackRemap"),nr=a.getUniformLocation(v,"uDualFisheyeUseRemap"),or=a.getUniformLocation(v,"uDualFisheyeSeamMask"),sr=a.getUniformLocation(v,"uDualFisheyeUseSeamMask"),cr=a.getUniformLocation(v,"uDualFisheyeVideoOffsets"),lr=a.getUniformLocation(v,"uDualFisheyeVideoSeam"),ra=a.createBuffer();if(!ra)throw new Error("buffer create failed");a.bindBuffer(a.ARRAY_BUFFER,ra),a.bufferData(a.ARRAY_BUFFER,new Float32Array([-1,-1,3,-1,-1,3]),a.STATIC_DRAW),a.enableVertexAttribArray(w),a.vertexAttribPointer(w,2,a.FLOAT,false,0,0);const ht=a.createTexture();if(!ht)throw new Error("texture create failed");const Jt=r?a.createTexture():null,ro=a.getUniformLocation(v,"uSeparateLenses"),no=a.getUniformLocation(v,"uVerticalLenses");Jt&&(a.activeTexture(a.TEXTURE4),a.bindTexture(a.TEXTURE_2D,Jt),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.uniform1i(a.getUniformLocation(v,"uBackTex"),4));let Kt={width:1,height:1};a.activeTexture(a.TEXTURE0),a.bindTexture(a.TEXTURE_2D,ht),a.uniform1i(k,0),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,l?1:0),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,1,1,0,a.RGBA,a.UNSIGNED_BYTE,new Uint8Array([0,0,0,255]));function ur(M,P,E,I,V){if(!P||!(E instanceof Uint8Array)||I<=0||V<=0)return null;const U=a.createTexture();return U?(a.activeTexture(a.TEXTURE0+M),a.bindTexture(a.TEXTURE_2D,U),a.uniform1i(P,M),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,0),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,I,V,0,a.RGBA,a.UNSIGNED_BYTE,E),a.activeTexture(a.TEXTURE0),a.bindTexture(a.TEXTURE_2D,ht),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,1),U):null}a.disable(a.CULL_FACE),a.disable(a.DEPTH_TEST);function oo(){const P=aa(i.dualFisheyeSeamLongitudesDeg).map(V=>Sa(V)/360).sort((V,U)=>V-U),E=Fr?Math.atan2(Et[0],Et[2])/(2*Math.PI)+.5:.5,I=!(E>=P[0]&&E<=P[1]);return{seamX:P,frontWrap:I,blendX:O(i.dualFisheyeSeamBlendDeg/360,1e-4,.125),enabled:P.length>=2&&Math.abs(P[0]-P[1])>1e-4}}const Zt=s&&typeof e.requestVideoFrameCallback=="function"&&typeof e.cancelVideoFrameCallback=="function";let Rt=0,Pt=0,At=0,mt=i.fovDeg,ei=true,ti=true,rt=0,Lt=0,ii=true,na={width:1,height:1};const Ai=[];let je=null,_t=null,Ne=0,dr=0,fr=0,oa="initial";const hr=s&&!Zt,Li=Ks(i.background),mr=Yi(e),Me=n==="dual_fisheye"&&Js(mr.width,mr.height),be=c&&!Me?c.remap:null,Ut=i.dualFisheyeFovDeg*Math.PI/360,so=c?c.front.center:i.dualFisheyeFrontCenter||(i.dualFisheyeFrontLens==="left"?[.25,.5]:[.75,.5]),co=c?c.back.center:i.dualFisheyeBackCenter||(i.dualFisheyeFrontLens==="left"?[.75,.5]:[.25,.5]),lo=!!(c&&((qr=c.imageSize)==null?void 0:qr[1])>((Xr=c.imageSize)==null?void 0:Xr[0])),ye=M=>Me&&!lo?[M[1],M[0]]:M,Ct=ye(so),ai=ye(co),pr=Wn(Ct,ai);let Oe=c?ye(c.front.validRadius):pr,Ve=c?ye(c.back.validRadius):pr;const _i=ye(c?c.front.scale:fe(i.dualFisheyeScale,[.247,.494])),Ui=ye(c?c.back.scale:fe(i.dualFisheyeScale,[.247,.494]));let Te=c?ye(c.front.focal):ka(_i,Ut),Re=c?ye(c.back.focal):ka(Ui,Ut);const sa=c?ye(c.front.principalOffset):[0,0],ca=c?ye(c.back.principalOffset):[0,0],ri=c?c.front.radial:[0,0,0,0],ni=c?c.back.radial:[0,0,0,0],yr=c?c.front.radialScale:1,gr=c?c.back.radialScale:1,la=c?c.front.tangential:[0,0],ua=c?c.back.tangential:[0,0],vr=c?c.front.xi:0,xr=c?c.back.xi:0,oi=c?c.front.thinPrism:[0,0,0,0],si=c?c.back.thinPrism:[0,0,0,0],br=c?ye(c.front.sensorTilt):[0,0],wr=c?ye(c.back.sensorTilt):[0,0],uo=!!(c&&c.front.projectionModel==="mei_extended"),fo=!!(c&&c.back.projectionModel==="mei_extended"),Fr=!!(c&&c.front.projectionModel==="dji_fisheye_lut"),ho=!!(c&&c.back.projectionModel==="dji_fisheye_lut"),Ci=c?c.front.asymmetric:[0,0,0,0],Ei=c?c.back.asymmetric:[0,0,0,0],Et=c?c.front.axis:[0,0,-1],Ii=c?c.back.axis:[0,0,1],zi=c?c.front.right:[1,0,0],Bi=c?c.back.right:[-1,0,0],ji=c?c.front.up:[0,1,0],Ni=c?c.back.up:[0,1,0],We={...c?c.front:{},center:Ct,focal:Te,principalOffset:sa,scale:_i,validRadius:Oe,radial:ri,radialScale:yr,tangential:la,projectionModel:c?c.front.projectionModel:"equidistant",xi:vr,thinPrism:oi,axis:Et,right:zi,up:ji},Ge={...c?c.back:{},center:ai,focal:Re,principalOffset:ca,scale:Ui,validRadius:Ve,radial:ni,radialScale:gr,tangential:ua,projectionModel:c?c.back.projectionModel:"equidistant",xi:xr,thinPrism:si,axis:Ii,right:Bi,up:Ni},Mr=be?ur(1,io,be.front,be.width,be.height):null,Dr=be?ur(2,ao,be.back,be.width,be.height):null,qe=oo();let pt=null,Ue=0,da=false,It=[i.dualFisheyeGainFront,i.dualFisheyeGainBack],Oi=0,zt=[0,0];const mo=[c==null?void 0:c.front,c==null?void 0:c.back].map(M=>(M==null?void 0:M.distortionCoeffs)||Array(13).fill(0)),po=!!(s&&n==="dual_fisheye"&&c&&!be&&!Me&&c.imageSize[0]===2*c.imageSize[1]&&[We,Ge].every(M=>M.projectionModel==="mei_extended"&&(M.distortionModel==="radtan_pro"||i.dualFisheyeVideoProtection===true))),nt=!!(s&&n==="dual_fisheye"&&c&&!be&&!Me&&c.imageSize[0]===2*c.imageSize[1]&&[We,Ge].every(M=>M.projectionModel==="dji_fisheye_lut"));nt&&(Oe=We.validRadius=Wt(We),Ve=Ge.validRadius=Wt(Ge));const yt=po||nt,Bt=yt&&i.dualFisheyeVideoRegistration===true;let ot=[0,0,0,0],st=yt&&!Bt,jt=0,fa=0;t.dataset.insta360VideoRegistration=Bt?"pending":yt?"calibrated":"unsupported";function Sr(){if(!Bt||st||jt>=3||e.currentTime<fa)return;const M=Date.now();try{const P=(nt?vc:gc)(e,i,c,[We,Ge]);if(P===void 0)return;P&&(ot=P.offsets,zt=P.polarInverseDepth||[0,0],It=P.gain,nt?(Te=Te.map(E=>E*P.focalScale),Re=Re.map(E=>E*P.focalScale),t.dataset.insta360VideoFocalScale=String(P.focalScale)):(Oe=Wt(We),Ve=Wt(Ge)),st=true)}catch{}jt+=1,fa=e.currentTime+1,t.dataset.insta360VideoRegistration=st?"ready":jt<3?"pending":"fallback",t.dataset.insta360VideoRegistrationAttempts=String(jt),t.dataset.insta360VideoRegistrationMS=String(Date.now()-M)}if(!s&&n==="dual_fisheye"){da=true;try{const M=Fc(e,i,c,be,We,Ge,Ut);M&&(It=M.gain,Oi=M.convergenceM,zt=M.polarInverseDepth||[0,0],ot=M.imageOffsets||[0,0,0,0],Te=Te.map(P=>P*M.focalScale),Re=Re.map(P=>P*M.focalScale)),kr(M==null?void 0:M.mask)}catch(M){t.dataset.insta360StaticSeamError=String((M==null?void 0:M.message)||M),pt=null,Ue=0}}t.dataset.insta360StaticSeamAnalyzed=da?"true":"false",t.dataset.insta360StaticSeamStatus=da?Ue?"ready":"fallback":"not-applicable";function kr(M,P=null){if(!(M instanceof Uint8Array)||!or||(pt||(pt=a.createTexture()),!pt))return false;try{a.activeTexture(a.TEXTURE3),a.bindTexture(a.TEXTURE_2D,pt),a.uniform1i(or,3),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,0),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,a.LINEAR);const E=P?a.LUMINANCE_ALPHA:a.LUMINANCE,I=P?Uint8Array.from({length:M.length*2},(V,U)=>U%2?P[U>>1]:M[U>>1]):M;return a.texImage2D(a.TEXTURE_2D,0,E,z,X,0,E,a.UNSIGNED_BYTE,I),Ue=1,true}finally{a.activeTexture(a.TEXTURE0),a.bindTexture(a.TEXTURE_2D,ht),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,l?1:0)}}let gt=null;const he={};let Vi=1,ci=null,vt=-1/0,Pe=0,Tr=0;function Rr(){if(!yt||!st||Pe>=3||e.seeking||e.currentTime+1e-6<vt)return;const M=Date.now();try{const E=Tc(e,i,c,[{...We,focal:Te,validRadius:Oe},{...Ge,focal:Re,validRadius:Ve}],{offsets:ot,gain:It,polarInverseDepth:zt},gt,he);if(E===void 0)return;if(E!=null&&E.reused){vt=e.currentTime+Vi,t.dataset.insta360VideoSeam="cached";return}const I=E==null?void 0:E.mask;if(I instanceof Uint8Array){const V=Sc(I,gt,E.strength);kr(V,E.strength)?(gt=V,Pe=0,Tr+=1):Pe+=1}else Pe+=1}catch{Pe+=1}Pe>=3&&(Ue=0,gt=null);const P=Date.now()-M;Vi=P>100?5:P>33?3:1,vt=e.currentTime+Vi,t.dataset.insta360VideoSeamUpdates=String(Tr),t.dataset.insta360VideoSeamMS=String(P),t.dataset.insta360VideoSeamInterval=String(Vi),t.dataset.insta360VideoSeam=Ue?"ready":Pe>=3?"fallback":"pending"}function ha(){!Zt||!ti||!s||e.paused||e.ended||Lt||(Lt=e.requestVideoFrameCallback(()=>{Lt=0,(Nt||pa(performance.now(),ui))&&(ii=true,xt()),ha()}))}function yo(){!Zt||!Lt||!s||(e.cancelVideoFrameCallback(Lt),Lt=0)}function go(M){let P=Number(M)||0;return P=(P%360+360)%360,P>180&&(P-=360),P}function vo(M,P,E,I){Rt=go(M),Pt=O(Number(P)||0,-85,85),typeof I=="number"?(At=O(Number(E)||0,-180,180),mt=O(Number(I)||ee.fovDeg,i.minFovDeg,i.maxFovDeg)):mt=O(Number(E)||ee.fovDeg,i.minFovDeg,i.maxFovDeg),ei=true}function xo(){const M=s?1.5:2,P=i.maxRenderPixelRatio>0?i.maxRenderPixelRatio:M,E=Math.max(1,Math.min(P,window.devicePixelRatio||1)),I=i.captureEquirectangular?1024:Math.max(1,t.clientWidth|0),V=i.captureEquirectangular?512:Math.max(1,t.clientHeight|0),U=Ee.maxRenderPixels>0?Math.min(1,Math.sqrt(Ee.maxRenderPixels/(I*V*E*E))):1,W=Math.max(1,Math.floor(I*E*U)),oe=Math.max(1,Math.floor(V*E*U));(t.width!==W||t.height!==oe)&&(t.width=W,t.height=oe,a.viewport(0,0,W,oe),ei=true,fr+=1,oa="resize",t.dataset.insta360ResizeCount=String(fr),t.dataset.insta360CanvasWidth=String(W),t.dataset.insta360CanvasHeight=String(oe))}function Pr(){for(let M=0;M<16&&a.getError()!==a.NO_ERROR;M+=1);}function Ar(M,P,E){const I=typeof performance<"u"?performance.now():Date.now(),V=Kt.width!==P||Kt.height!==E||I>=Ir;V&&Pr(),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,l?1:0);const U=Kt.width===P&&Kt.height===E;try{U?a.texSubImage2D(a.TEXTURE_2D,0,0,0,a.RGBA,a.UNSIGNED_BYTE,M):a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,M)}catch{return t.dataset.insta360TextureStatus="exception",false}const W=V?a.getError():a.NO_ERROR;return V&&(Ir=I+1e3),W!==a.NO_ERROR?(t.dataset.insta360TextureStatus=`error-${W}`,false):(Kt={width:P,height:E},na={width:P,height:E},t.dataset.insta360TextureStatus="ready",t.dataset.insta360TextureWidth=String(P),t.dataset.insta360TextureHeight=String(E),true)}function bo(M){const P=Yi(e);if(M>=P.width&&M>=P.height)return{source:e,width:P.width,height:P.height,retainUntilDestroy:typeof ImageBitmap<"u"&&e instanceof ImageBitmap,release:()=>{typeof ImageBitmap<"u"&&e instanceof ImageBitmap&&e.close()}};const E=Math.min(M/Math.max(1,P.width),M/Math.max(1,P.height)),I=Math.max(1,Math.floor(P.width*E)),V=Math.max(1,Math.floor(P.height*E)),U=document.createElement("canvas");U.width=I,U.height=V;const W=U.getContext("2d",{alpha:false});if(!W)return null;try{Gn.has(e)&&(W.translate(0,V),W.scale(1,-1)),W.drawImage(e,0,0,I,V)}catch{return U.width=0,U.height=0,null}return{source:U,width:I,height:V,release:()=>{U.width=0,U.height=0}}}function wo(){if(r||s&&e.readyState<2)return false;a.activeTexture(a.TEXTURE0),a.bindTexture(a.TEXTURE_2D,ht);const M=Yi(e);if(s){const U=Br(M.width,M.height);return Ar(jr(e,M.width,M.height,U,0),U.width,U.height)}const P=Math.max(1,Number(a.getParameter(a.MAX_TEXTURE_SIZE))||1),E=Math.max(M.width,M.height),V=[Math.min(E,P,yn[0]),...yn].filter((U,W,oe)=>U<=P&&U<=E&&oe.indexOf(U)===W).sort((U,W)=>W-U);for(const U of V){const W=bo(U);if(!W)continue;if(Ar(W.source,W.width,W.height))return Ne&&(cancelAnimationFrame(Ne),Ne=0),W.retainUntilDestroy?(_t&&_t(),_t=W.release,t.dataset.insta360TextureSource="retained"):(je&&je(),je=W.release,typeof ImageBitmap<"u"&&e instanceof ImageBitmap&&(_t=()=>e.close())),true;W.retainUntilDestroy||W.release()}return false}function Fo(){s||!je||Ne||(Ne=requestAnimationFrame(()=>{Ne=requestAnimationFrame(()=>{Ne=0,je&&(je(),je=null,t.dataset.insta360TextureSource="released")})}))}let Lr="";function ma(){var U;if(!ti)return;const M=typeof performance<"u"?performance.now():Date.now();rt=0,xo();const P=o&&!e.paused&&!e.ended,E=!P||Nt||pa(M,ui),V=(ii||hr&&P)&&(!o||E)?wo():false;if(V&&(ii=false,s&&(Sr(),Rr())),ei||V){const W=na,oe=Cr(),Ie=Ct[Me?1:0]<.5?0:1,$e=oe.every(Boolean)?0:oe[Ie]?1:2,De=[W.width,W.height,t.width,t.height,Rt,Pt,At,mt,Oe,Ve,Te,Re,Oi,zt,ot,It,Ue,$e].join(":");if(De!==Lr){const Ye=1/Math.max(1,W.width),we=1/Math.max(1,W.height),Qe=Math.max(Ye*6,.0035),ct=Vt(0,1,0,-Rt*Math.PI/180),bt=Vt(1,0,0,-Pt*Math.PI/180),lt=Vt(0,0,1,-At*Math.PI/180),ze=Fn(Gt(Gt(ct,bt),lt)),Y=t.width/t.height;F&&a.uniform2f(F,Ye,we),D&&a.uniform2f(D,t.width,t.height),S&&a.uniform1f(S,Y),R&&a.uniform1f(R,Math.tan(mt*Math.PI/360)),_&&a.uniform4f(_,ze.x,ze.y,ze.z,ze.w),A&&a.uniform1f(A,Qe),C&&a.uniform2f(C,Ct[0],Ct[1]),j&&a.uniform2f(j,ai[0],ai[1]),G&&a.uniform2f(G,Oe[0],Oe[1]),q&&a.uniform2f(q,Ve[0],Ve[1]),te&&a.uniform2f(te,Te[0],Te[1]),ne&&a.uniform2f(ne,Re[0],Re[1]),ue&&a.uniform2f(ue,sa[0],sa[1]),J&&a.uniform2f(J,ca[0],ca[1]),Z&&a.uniform2f(Z,_i[0],_i[1]),Tt&&a.uniform2f(Tt,Ui[0],Ui[1]),ce&&a.uniform4f(ce,ri[0],ri[1],ri[2],ri[3]),$&&a.uniform4f($,ni[0],ni[1],ni[2],ni[3]),xe&&a.uniform1f(xe,yr),pe&&a.uniform1f(pe,gr),re&&a.uniform2f(re,(c==null?void 0:c.front.distortionCoeffs[4])||0,(c==null?void 0:c.back.distortionCoeffs[4])||0),ke&&a.uniform2f(ke,la[0],la[1]),et&&a.uniform2f(et,ua[0],ua[1]),tt&&a.uniform1f(tt,vr),Qt&&a.uniform1f(Qt,xr),Ht&&a.uniform4f(Ht,oi[0],oi[1],oi[2],oi[3]),Le&&a.uniform4f(Le,si[0],si[1],si[2],si[3]),_e&&a.uniform2f(_e,br[0],br[1]),it&&a.uniform2f(it,wr[0],wr[1]),ki&&a.uniform1f(ki,Oi),Ti&&a.uniform2f(Ti,...zt),cr&&a.uniform4f(cr,...ot),lr&&a.uniform1f(lr,yt?1:0);for(let K=0;K<2;K+=1){const se=K===0?c==null?void 0:c.front:c==null?void 0:c.back;Ri[K]&&a.uniform3f(Ri[K],...(se==null?void 0:se.translationM)||[0,0,0]);const Fe=mo[K];for(let Ae=0;Ae<3;Ae+=1)at[K][Ae]&&a.uniform4fv(at[K][Ae],Fe.slice(Ae*4,Ae*4+4));at[K][3]&&a.uniform1f(at[K][3],Fe[12]),at[K][4]&&a.uniform1f(at[K][4],(se==null?void 0:se.distortionModel)==="radtan_pro"?1:0)}Pi&&a.uniform4f(Pi,...(c==null?void 0:c.front.rotationQuat)||[1,0,0,0]),ja&&a.uniform4f(ja,...(c==null?void 0:c.back.rotationQuat)||[1,0,0,0]),Na&&a.uniform1f(Na,uo?1:0),Oa&&a.uniform1f(Oa,fo?1:0),Va&&a.uniform1f(Va,Fr?c.front.distortionModel==="dji_fisheye_5"?2:1:0),Wa&&a.uniform1f(Wa,ho?c.back.distortionModel==="dji_fisheye_5"?2:1:0),Ga&&a.uniform4f(Ga,Ci[0],Ci[1],Ci[2],Ci[3]),qa&&a.uniform4f(qa,Ei[0],Ei[1],Ei[2],Ei[3]),Xa&&a.uniform3f(Xa,Et[0],Et[1],Et[2]),$a&&a.uniform3f($a,Ii[0],Ii[1],Ii[2]),Ya&&a.uniform3f(Ya,zi[0],zi[1],zi[2]),Qa&&a.uniform3f(Qa,Bi[0],Bi[1],Bi[2]),Ha&&a.uniform3f(Ha,ji[0],ji[1],ji[2]),Ja&&a.uniform3f(Ja,Ni[0],Ni[1],Ni[2]),Ka&&a.uniform1f(Ka,Ut),Za&&a.uniform1f(Za,Math.sin(i.dualFisheyeSeamBlendDeg*Math.PI/180)),er&&a.uniform2f(er,qe.seamX[0],qe.seamX[1]),tr&&a.uniform1f(tr,qe.blendX),ir&&a.uniform1f(ir,qe.frontWrap?1:0),ar&&a.uniform1f(ar,qe.enabled?1:0),rr&&a.uniform2f(rr,It[0],It[1]),nr&&a.uniform1f(nr,be?1:0),sr&&a.uniform1f(sr,Ue),T&&a.uniform1f(T,$e),Lr=De}a.clearColor(Li.r/255,Li.g/255,Li.b/255,Li.a),a.clear(a.COLOR_BUFFER_BIT),a.drawArrays(a.TRIANGLES,0,3),dr+=1,t.dataset.insta360DrawCount=String(dr),t.dataset.insta360LastDrawReason=oa,t.dataset.insta360ContextStatus="ready",V&&Fo(),ei=false}o&&V&&(ui=zr(M,ui,Nt),Nt=false,P&&((U=i.onPlaybackWork)==null||U.call(i,Math.max(0,performance.now()-M)))),hr&&P&&(rt=requestAnimationFrame(ma))}function Mo(){ti&&(s&&Zt&&ha(),xt())}function xt(M="request"){ei=true,oa=M,rt||(rt=requestAnimationFrame(ma))}function _r(M){t.dataset.insta360ContextStatus="lost",t.dispatchEvent(new CustomEvent("insta360previewerror",{bubbles:true,detail:{reason:"webgl-context-lost"}})),M.cancelable&&M.preventDefault()}t.addEventListener("webglcontextlost",_r);function Ce(M){Nt=true,yt&&(M==null?void 0:M.type)==="seeked"&&(he.surface=null,gt=null,vt=-1/0,Pe=0,Ue=0),Bt&&!st&&(M==null?void 0:M.type)==="seeked"&&(jt=0,fa=e.currentTime),ii=true,Zt&&ha(),xt()}o&&(e.addEventListener("play",Ce),e.addEventListener("pause",Ce),e.addEventListener("seeking",Ce),e.addEventListener("seeked",Ce),e.addEventListener("loadeddata",Ce));function Do(){ti=false,rt&&cancelAnimationFrame(rt),Ne&&cancelAnimationFrame(Ne),yo(),t.removeEventListener("webglcontextlost",_r),o&&(e.removeEventListener("play",Ce),e.removeEventListener("pause",Ce),e.removeEventListener("seeking",Ce),e.removeEventListener("seeked",Ce),e.removeEventListener("loadeddata",Ce)),je&&je(),_t&&_t(),he.readback&&(he.readback.surface.width=0,he.readback.surface.height=0);for(const M of fi)M!=null&&M.canvas&&(M.canvas.width=0,M.canvas.height=0);fi.length=0,he.surface=null,he.projections=null,he.readback=null,he.softwareReadback=null;for(const M of Wi)M&&(M.width=0,M.height=0);Wi.length=0;for(const M of li)M!=null&&M.canvas&&(M.canvas.width=0,M.canvas.height=0);li.length=0,a.deleteTexture(ht),Jt&&a.deleteTexture(Jt),Mr&&a.deleteTexture(Mr),Dr&&a.deleteTexture(Dr),pt&&a.deleteTexture(pt),a.deleteBuffer(ra),a.deleteProgram(v)}let Ur="",Xe=[true,true];function Cr(){if(i.captureEquirectangular||!r||n!=="dual_fisheye"||be||Bt&&(!st||!nt)||Oi>0||zt.some(Ie=>Ie>0)||!qe.enabled)return[true,true];const M=Math.max(1,t.clientWidth)/Math.max(1,t.clientHeight),P=[Rt,Pt,At,mt,M,Oe,Ve,Te,Re,ot].join(":");if(P===Ur)return Xe;Ur=P,Xe=[true,true];const E=Fn(Gt(Gt(Vt(0,1,0,-Rt*Math.PI/180),Vt(1,0,0,-Pt*Math.PI/180)),Vt(0,0,1,-At*Math.PI/180))),I=Math.tan(Math.min(160,mt+12)*Math.PI/360),V=[{...We,focal:Te,validRadius:Oe},{...Ge,focal:Re,validRadius:Ve}];let U=-1;for(let Ie=-4;Ie<=4;Ie+=1)for(let $e=-4;$e<=4;$e+=1){const De=Ba(E,$e/4*M*I,Ie/4*I,u?1:-1),Ye=Math.hypot(De.x,De.y,De.z),we=[De.x/Ye*(i.equirectFlipX?-1:1),De.y/Ye*(i.equirectFlipY?-1:1),De.z/Ye];if(Math.abs(we[1])>=Math.sin(45*Math.PI/180))return Xe;const Qe=Math.atan2(we[0],u?we[2]:-we[2])/(2*Math.PI)+.5,[ct,bt]=qe.seamX,lt=qe.blendX+.01,ze=Qe>ct+lt&&Qe<bt-lt,Y=Qe<ct-lt||Qe>bt+lt;if(!ze&&!Y)return Xe;const se=(qe.frontWrap?Y:ze)?0:1;if(U>=0&&U!==se)return Xe;U=se;const Fe=V[se],Ae=se===1?Ji(we,ot):we,He=kt(Ae,Fe,Ut,Fe.projectionModel==="mei_extended",Fe.projectionModel==="dji_fisheye_lut",Fe.radialScale||1);if(!He||He.confidence<.1)return Xe;if(nt){const Xi=V[1-se],ko=se===0?Ji(we,ot):we,$r=kt(ko,Xi,Ut,Xi.projectionModel==="mei_extended",Xi.projectionModel==="dji_fisheye_lut",Xi.radialScale||1);if($r&&$r.confidence>0)return Xe}}const oe=(U===0?Ct:ai)[Me?1:0]<.5?0:1;return Xe=[oe===0,oe===1],Xe}let Er=0,Ee={level:0,maxFps:0,maxRenderPixels:0,maxTextureSize:0};const Wi=[],li=[];let ui=0,Ir=0,Nt=true;function pa(M,P){const E=Ee.maxFps?1e3/Ee.maxFps:0;return!E||M+Math.min(20,E/2)>=P}function zr(M,P,E=false){const I=Ee.maxFps?1e3/Ee.maxFps:0;return I?E||!P||M-P>I?M+I:Math.max(P+I,M+I/2+Math.min(20,I/2)):0}function Br(M,P){const E=Ee.maxTextureSize>0?Math.min(1,Ee.maxTextureSize/Math.max(M,P)):1;return{width:Math.max(1,Math.floor(M*E)),height:Math.max(1,Math.floor(P*E))}}function jr(M,P,E,I,V){if(I.width===P&&I.height===E)return M;if(M instanceof ImageData)return Mn(M,I.width,li[V]||(li[V]={}),I.height);let U=Wi[V];return U||(U=Wi[V]=document.createElement("canvas")),(U.width!==I.width||U.height!==I.height)&&(U.width=I.width,U.height=I.height),U.getContext("2d").drawImage(M,0,0,I.width,I.height),U}function So(M){!s||!M||M.level===Ee.level||(Ee=M,ui=0,di=0,Gi=0,Nt=true,t.dataset.insta360QualityLevel=String(M.level),t.dataset.insta360MaxFps=String(M.maxFps),xt("quality"))}let Nr=-1/0,di=0,Gi=0,qi=0,Or="";const fi=[];function Vr(M){const P=e.getContext("2d",{willReadFrequently:true});M.forEach((E,I)=>{const V=E instanceof ImageData?Mn(E,nt?1024:512,fi[I]||(fi[I]={})):E,U=M.length===2&&!Me?e.width/2:e.width,W=M.length===2&&Me?e.height/2:e.height;P.drawImage(V,Me?0:I*U,Me?I*W:0,U,W)})}function Wr(M,P,E=false){if(!ti||!r)return;const I=ci!==null&&(P<ci||P-ci>.5);if(I&&(he.surface=null,gt=null,vt=-1/0,Ue=0,Pe=0),!M.find(Boolean))return;const U=typeof performance<"u"?performance.now():Date.now(),W=M.map(Boolean).join(":"),oe=M.map(Y=>Y?Br(Y.displayWidth||Y.videoWidth||Y.width,Y.displayHeight||Y.videoHeight||Y.height):null),Ie=oe.some((Y,K)=>{var se,Fe;return Y&&(((se=Ai[K])==null?void 0:se.width)!==Y.width||((Fe=Ai[K])==null?void 0:Fe.height)!==Y.height)}),$e=E||I||Ie||W!==Or;if(!$e&&(U<Gi||!pa(U,di)))return;ci=P;const{width:De,height:Ye}=oe.find(Boolean),we=Er||(Er=a.getParameter(a.MAX_TEXTURE_SIZE));if(oe.filter(Boolean).some(Y=>Y.width>we||Y.height>we))throw new Error("Panorama frame exceeds GPU texture limits; select a companion source");a.uniform1f(ro,M.length===2?1:0),a.uniform1f(no,Me?1:0);const Qe=Ie||U>=Nr;if(Qe&&Pr(),M.forEach((Y,K)=>{if(!Y)return;a.activeTexture(K===0?a.TEXTURE0:a.TEXTURE4),a.bindTexture(a.TEXTURE_2D,K===0?ht:Jt),a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,l?1:0);const{width:se,height:Fe}=oe[K],Ae=jr(Y,Y.displayWidth||Y.videoWidth||Y.width,Y.displayHeight||Y.videoHeight||Y.height,oe[K],K),He=Ai[K];(He==null?void 0:He.width)===se&&(He==null?void 0:He.height)===Fe?a.texSubImage2D(a.TEXTURE_2D,0,0,0,a.RGBA,a.UNSIGNED_BYTE,Ae):(a.texImage2D(a.TEXTURE_2D,0,a.RGBA,a.RGBA,a.UNSIGNED_BYTE,Ae),Ai[K]={width:se,height:Fe})}),Qe){if(a.getError()!==a.NO_ERROR)throw new Error("Panorama frame upload failed");Nr=U+1e3}const ct=Math.max(0,(typeof performance<"u"?performance.now():Date.now())-U);qi=qi?qi*.8+ct*.2:ct,di=zr(U,di,$e),Gi=U+Math.min(100,qi*1.5),Or=W;const bt=Me||n==="eac"||n==="cubemap";na={width:M.length===2&&!bt?De*2:De,height:M.length===2&&bt?Ye*2:Ye},ii=false;const lt=Bt&&!st&&jt<3,ze=yt&&st&&Pe<3;if((ze||lt)&&M.every(Boolean)&&P>=vt){e.currentTime=P;const Y=nt&&ze&&e.width===2048&&e.height===1024&&M.length===2&&M.every(K=>K instanceof ImageData);try{Y?(he.softwareFrames=M,he.prepareSoftwareFallback=()=>Vr(M)):Vr(M),Sr(),Rr()}finally{he.softwareFrames=null,he.prepareSoftwareFallback=null}}return xt("decoded-frame"),ct}return{reset:()=>{he.surface=null,gt=null,ci=null,vt=-1/0,di=0,Gi=0,Ue=0,Pe=0,t.dataset.insta360VideoSeam="pending",xt("seek")},presentFrames:Wr,captureFrames:(M,P)=>{Wr(M,P,true),rt&&cancelAnimationFrame(rt),ma()},setPlaybackQuality:So,getRequiredTracks:Cr,start:Mo,requestFrame:xt,destroy:Do,setView:vo,getView:()=>({yawDeg:Rt,pitchDeg:Pt,rollDeg:At,fovDeg:mt}),dragDirectionSign:u?-1:1}}function Gt(t,e){return{x:t.w*e.x+t.x*e.w+t.y*e.z-t.z*e.y,y:t.w*e.y-t.x*e.z+t.y*e.w+t.z*e.x,z:t.w*e.z+t.x*e.y-t.y*e.x+t.z*e.w,w:t.w*e.w-t.x*e.x-t.y*e.y-t.z*e.z}}function Fn(t){const e=Math.hypot(t.x,t.y,t.z,t.w)||1;return{x:t.x/e,y:t.y/e,z:t.z/e,w:t.w/e}}function Vt(t,e,i,n){const r=n/2,o=Math.sin(r);return{x:t*o,y:e*o,z:i*o,w:Math.cos(r)}}function Ba(t,e,i,n){const r={x:e,y:i,z:n,w:0},o={x:-t.x,y:-t.y,z:-t.z,w:t.w},s=Gt(t,r),a=Gt(s,o);return{x:a.x,y:a.y,z:a.z}}function Mn(t,e=512,i=null,n=null){const r=(i==null?void 0:i.canvas)||document.createElement("canvas"),o=Math.min(e,t.width),s=n??Math.max(1,Math.round(t.height*o/t.width));(r.width!==o||r.height!==s)&&(r.width=o,r.height=s,i&&(i.reduced=null)),i&&(i.canvas=r);const a=r.getContext("2d");if(o===t.width&&s===t.height)return a.putImageData(t,0,0),r;const c=(i==null?void 0:i.reduced)||a.createImageData(o,s);i&&(i.reduced=c);const l=t.data.byteOffset%4===0?new Uint32Array(t.data.buffer,t.data.byteOffset,t.data.byteLength/4):null,u=new Uint32Array(c.data.buffer,c.data.byteOffset,c.data.byteLength/4);let f=i==null?void 0:i.columns;if((!f||f.length!==o||i.sourceWidth!==t.width)&&(f=Uint32Array.from({length:o},(y,p)=>Math.floor(p*t.width/o)),i&&(i.columns=f,i.sourceWidth=t.width)),l)for(let y=0;y<s;y++){const p=Math.floor(y*t.height/s)*t.width,h=y*o;for(let d=0;d<o;d++)u[h+d]=l[p+f[d]]}else for(let y=0;y<s;y++){const p=Math.floor(y*t.height/s)*t.width,h=y*o;for(let d=0;d<o;d++)for(let m=0;m<4;m++)c.data[(h+d)*4+m]=t.data[(p+f[d])*4+m]}return a.putImageData(c,0,0),r}function Rc(t,e,i=null){var o;const n=i||document.createElement("canvas");i||(n.width=((o=e.dualFisheyeCalibration)==null?void 0:o.front.projectionModel)==="dji_fisheye_lut"?2048:1024,n.height=n.width/2);const r=Jn(t,n,Vn({...e,externalFrames:!i}),e.projection||"equirect");return{...r,destroy(){r.destroy(),i||(n.width=n.height=0)}}}function Pc(t,e,i){return Jn(t,e,Vn({...i,externalFrames:false}),i.projection||"dual_fisheye")}function Kn(t){if(!ta(t))return;const e=ia(t);if(!e)return;const i=e[0].track.id!==e[1].track.id;let n,r,o;if(i){const[a,c]=e;if(a.track.width!==c.track.width||a.track.height!==c.track.height||e.some(({rect:l})=>l.x!==0||l.y!==0||l.width!==1||l.height!==1))return;n=a.track.width*2,r=a.track.height,o=[{x:0,y:0,width:.5,height:1},{x:.5,y:0,width:.5,height:1}]}else if(n=e[0].track.width,r=e[0].track.height,o=e.map(({rect:a})=>a),o.some(a=>a.y!==0||a.width!==.5||a.height!==1)||![0,.5].every(a=>o.some(c=>c.x===a)))return;if(n!==r*2)return;const s=t.lenses.slice(0,2).map((a,c)=>Lc(a,e[c],o[c],t));return{imageSize:[n,r],textureOrigin:t.textureOrigin==="top-left"?"top-left":"bottom-left",front:s[0],back:s[1],pipeline:{seamLongitudesDeg:[90,270],featherWidthPx:Math.round(r*16/360)}}}async function Ac(t,e){const i=Kn(e),n=ia(e);if(!i||!n)throw new B("calibration_missing","Real-time stitching requires two calibrated side-by-side lenses.");if(typeof VideoDecoder>"u"||typeof EncodedVideoChunk>"u")throw new B("codec_unsupported","This browser does not expose WebCodecs video decoding.");const r=[...new Map(n.map(({track:h})=>[h.id,h])).values()];if(r.some(h=>h.timescale<=0||!h.samples.length))throw new B("invalid_manifest","The calibrated panorama tracks do not contain a playable sample timeline.");const o=r.map(En);if((await Promise.all(o.map(h=>VideoDecoder.isConfigSupported(h)))).some(h=>!h.supported))throw new B("codec_unsupported","This browser cannot decode the calibrated panorama tracks.");const a=document.createElement("canvas");a.className="panoramav-canvas";const c=Rc(a,{projection:"dual_fisheye",dualFisheyeCalibration:i,dualFisheyeFrontLens:i.front.center[0]<.5?"left":"right",dualFisheyeFlipX:false,dualFisheyeSeamBlendDeg:16,dualFisheyeVideoProtection:true,dualFisheyeVideoRegistration:e.projection.kind==="dji-fisheye-lut",equirectFlipX:false,minFovDeg:30,maxFovDeg:100});let l,u;try{l=new Bn(t,r,[],o,(h,d)=>{c.presentFrames(r.length===1?[h]:[h,d],h.timestamp/1e6)},async()=>{},()=>c.reset())}catch(h){throw c.destroy(),h}c.start(),l.start();const f=()=>{u=new Error("The panorama WebGL context was lost. Reload the preview to resume."),l.pause()};a.addEventListener("insta360previewerror",f);let y="",p=false;return{canvas:a,setView(h,d,m,g){const b=`${h}:${d}:${m}:${g}`;p||b===y||(y=b,c.setView(h,d,m,g),c.requestFrame("view"))},requestRender:()=>{p||c.requestFrame("resize")},update:()=>l.update(),play:()=>l.play(),pause:()=>l.pause(),seek:h=>l.seek(h),setPlaybackRate:h=>l.setPlaybackRate(h),close(){p||(p=true,l.close(),a.removeEventListener("insta360previewerror",f),c.destroy(),a.width=a.height=0)},get streamSyncMs(){return l.streamSyncMs},get dynamicSeam(){return["ready","cached"].includes(a.dataset.insta360VideoSeam??"")},get duration(){return l.duration},get currentTime(){return l.currentTime},get paused(){return l.paused},get error(){return u??l.error},stabilizationAvailable:false,stabilizationMode:"off",setStabilization:()=>"off"}}function Lc(t,e,i,n){const r=t.width??e.track.width*e.rect.width,o=t.height??e.track.height*e.rect.height,s=t.extrinsicQuaternion,a=n.projection.kind==="mei-extended",c=a?s:[s[0],-s[1],-s[2],-s[3]],l=h=>{const d=_c(c,h);return a?d:[d[0],-d[2],d[1]]},u=l([1,0,0]),f=l([0,a?1:-1,0]),y=[t.fx/r*i.width,(t.fy??t.fx)/o*i.height],p=Math.min(r,o)*.475;return{center:[i.x+(t.cx+.5)/r*i.width,i.y+(t.cy+.5)/o*i.height],focal:y,principalOffset:[0,0],rotationQuat:s,scale:y,validRadius:[p/r*i.width,p/o*i.height],radial:bi(t.radial??t.distortion,4),tangential:bi(t.tangential,2),thinPrism:bi(t.thinPrism,4),sensorTilt:bi(t.sensorTilt,2),xi:t.xi??0,radialScale:a?1:Uc(t),distortionModel:t.distortionModel,distortionCoeffs:t.distortionCoeffs,translationM:t.translation,axis:l([0,0,1]),right:u,up:f,projectionModel:a?"mei_extended":"dji_fisheye_lut"}}function bi(t,e){return Array.from({length:e},(i,n)=>Number((t==null?void 0:t[n])??0))}function _c(t,[e,i,n]){const r=Math.hypot(...t),[o,s,a,c]=t.map(f=>f/r),l=s*e+a*i+c*n,u=o*o-s*s-a*a-c*c;return[2*l*s+u*e+2*o*(a*n-c*i),2*l*a+u*i+2*o*(c*e-s*n),2*l*c+u*n+2*o*(s*i-a*e)]}function Uc(t){const e=t.radialLut1,i=t.radialLut2;if(!e||!i||e.length<14||i.length<14||!t.fx)return 1;let n=0;for(let y=1;y<14;y+=1)n+=Math.hypot(e[y]-t.cx,i[y]-t.cy);n/=13;const r=85*Math.PI/180,[o,s,a,c]=bi(t.radial??t.distortion,4),l=r+o*r**3+s*r**5+a*r**7+c*r**9,u=1+3*o*r**2+5*s*r**4+7*a*r**6+9*c*r**8,f=t.fx*(l+u*(Math.PI/2-r));return f>0?n/f:1}function Zn(t){var r;const{width:e,height:i}=t;if(!e||!i||t.lenses.length!==2||!["mei-extended","equidistant"].includes(t.projection.kind))return;const n=[];for(const[o,s]of t.lenses.entries()){const a=s.sourceRect,c=s.extrinsicQuaternion,l=s.width,u=s.height;if(!a||!l||!u||!c||c.length!==4||!c.every(Number.isFinite)||Math.hypot(...c)<1e-6||![s.fx,s.fy,s.cx,s.cy].every(x=>typeof x=="number"&&Number.isFinite(x))||!Object.values(a).every(Number.isFinite)||s.fx<=0||s.fy<=0||a.width<=0||a.height<=0||a.x<0||a.y<0||a.x+a.width>1||a.y+a.height>1)return;const f=((r=s.projection)==null?void 0:r.kind)==="mei-extended",y=c.map(x=>x/Math.hypot(...c)),p=f?[y[0],-y[1],-y[2],-y[3]]:y;let h=xi(p,[0,0,f?1:-1]),d=xi(p,[0,1,0]);if(!f&&o===1){const x=xi(p,[0,0,1]);x[2]>h[2]&&(h=x,d=xi(p,[0,-1,0]))}const m=x=>f?x:[x[0],-x[1],x[2]],g=Math.min(l,u)*.475,b=[s.fx/l*a.width,s.fy/u*a.height];n.push({center:[a.x+s.cx/l*a.width,a.y+s.cy/u*a.height],focal:b,scale:b,principalOffset:[0,0],rotationQuat:y,validRadius:[g/l*a.width,g/u*a.height],radial:s.radial??[0,0,0,0],tangential:s.tangential??[0,0],thinPrism:s.thinPrism??[0,0,0,0],sensorTilt:s.sensorTilt??[0,0],xi:s.xi??0,radialScale:1,translationM:s.translation,distortionModel:s.distortionModel,distortionCoeffs:s.distortionCoeffs,axis:m(h),right:m(xi(p,[1,0,0])),up:m(d),projectionModel:f?"mei_extended":"equidistant"})}return{imageSize:[e,i],textureOrigin:t.textureOrigin==="bottom-left"?"bottom-left":"top-left",front:n[0],back:n[1],pipeline:{seamLongitudesDeg:[90,270],featherWidthPx:Math.round(Math.min(e,i)*16/360)}}}function Cc(t,e){const i=Zn(e);if(!i)throw new B("calibration_missing","This DNG does not contain supported dual-fisheye calibration.");if(Math.abs(t.naturalWidth/t.naturalHeight-i.imageSize[0]/i.imageSize[1])>.005)throw new B("invalid_manifest","The developed DNG preview does not preserve the calibrated sensor geometry.");const n=document.createElement("canvas");n.className="panoramav-canvas";const r=Pc(n,t,{projection:"dual_fisheye",dualFisheyeCalibration:i,dualFisheyeFovDeg:196,dualFisheyeSeamBlendDeg:16,dualFisheyeFlipX:false,dualFisheyeRefineFocal:e.format==="dng",minFovDeg:30,maxFovDeg:100});let o="",s=false,a;const c=()=>{a=new Error("The panorama WebGL context was lost. Reload the preview to resume.")};return n.addEventListener("insta360previewerror",c),r.start(),{canvas:n,dragDirectionSign:e.projection.kind==="equidistant"?1:-1,setView(l,u,f,y){const p=`${l}:${u}:${f}:${y}`;s||p===o||(o=p,r.setView(l,u,f,y),r.requestFrame("view"))},requestRender(){s||r.requestFrame("resize")},update(){},play(){},pause(){},seek(){},close(){s||(s=true,n.removeEventListener("insta360previewerror",c),r.destroy(),n.width=n.height=0)},get error(){return a},get dynamicSeam(){return n.dataset.insta360StaticSeamStatus==="ready"},duration:0,currentTime:0,paused:true,streamSyncMs:0,stabilizationAvailable:false,stabilizationMode:"off",setStabilization:()=>"off"}}function xi([t,e,i,n],[r,o,s]){const a=e*r+i*o+n*s,c=t*t-e*e-i*i-n*n;return[2*a*e+c*r+2*t*(i*s-n*o),2*a*i+c*o+2*t*(n*r-e*s),2*a*n+c*s+2*t*(e*o-i*r)]}const Ec="Panorama is not close to a 2:1 equirectangular projection; raw dual-fisheye media requires vendor stitching, while stereoscopic media needs a compatible projection mode.",Ic=new Set(["insp","insv","osv"]),Dn=new Set(["insv","osv"]),Sn=[{extensions:["pano","panorama","360","insp"],family:"panorama",driverId:"panorama",targetFormat:"pano",contentTypes:["image/panorama","image/x-panorama","image/x-insta360","application/vnd.filens.panorama+image"]},{extensions:["360v","vr360","insv","osv"],family:"panorama-video",driverId:"panorama",targetFormat:"360v",contentTypes:["video/panorama","video/x-panorama","video/x-insta360","video/x-osmo360","application/vnd.filens.panorama+video"]}];class eo{constructor(e,i={},n){L(this,"listeners",{loading:new Set,rendered:new Set,error:new Set,statechange:new Set,warnings:new Set});L(this,"root");L(this,"stage");L(this,"hint");L(this,"notice");L(this,"createdUrl",null);L(this,"renderer",null);L(this,"scene",null);L(this,"camera",null);L(this,"texture",null);L(this,"video",null);L(this,"geometry",null);L(this,"material",null);L(this,"calibratedRenderer",null);L(this,"playbackControls",null);L(this,"lastPlaybackStateEmit",0);L(this,"osmoFallbackReason","");L(this,"animationFrame",0);L(this,"lon",180);L(this,"lat",0);L(this,"pointerDown",false);L(this,"pointerStartX",0);L(this,"pointerStartY",0);L(this,"pointerStartLon",0);L(this,"pointerStartLat",0);L(this,"resizeObserver",null);L(this,"loadController");L(this,"removeAbortListener");L(this,"interactionController");L(this,"resourceResolver");L(this,"state");L(this,"resize",()=>{var r,o;if((o=(r=this.calibratedRenderer)==null?void 0:r.requestRender)==null||o.call(r),!this.renderer||!this.camera)return;const e2=this.stage.getBoundingClientRect(),i2=Math.max(1,Math.floor(e2.width||this.stage.clientWidth||1)),n2=Math.max(1,Math.floor(e2.height||this.stage.clientHeight||1));this.camera.aspect=i2/n2,this.camera.updateProjectionMatrix(),this.renderer.setSize(i2,n2,false),this.scheduleFrame()});this.host=e,this.processor=n,this.resourceResolver=i.resourceResolver,this.root=document.createElement("div"),this.root.className="panoramav-preview",this.stage=document.createElement("div"),this.stage.className="panoramav-stage",this.hint=document.createElement("div"),this.hint.className="panoramav-hint",this.hint.textContent="Drag to look around \xB7 Pinch or scroll to zoom",this.notice=document.createElement("div"),this.notice.className="panoramav-notice",this.notice.setAttribute("role","status"),this.notice.setAttribute("aria-live","polite"),this.root.replaceChildren(this.stage,this.hint),this.host.replaceChildren(this.root),this.state={loading:false,error:null,family:"panorama",warnings:[],capabilities:{zoom:true,pan:true,fullscreen:true,download:true},scale:i.initialScale??1,rotation:0,panX:0,panY:0}}async load(e,i){var s,a,c,l,u,f,y;const n=this.beginLoad(i),r=n.signal,o=this.processor?ns(this.processor,r):void 0;this.state={...this.state,loading:true,error:null,title:i.descriptor.name,warnings:[],vendor:void 0,cameraModel:void 0,calibrationSource:void 0,projection:void 0,decodeMode:void 0,stitchMode:void 0,streamSyncMs:void 0,proxyPreview:false,stabilizationAvailable:false,stabilizationMode:"off",naturalWidth:void 0,naturalHeight:void 0,duration:void 0,currentTime:void 0,paused:true,muted:void 0,volume:void 0,playbackRate:1},this.emit("loading",this.state),this.emit("statechange",this.state);try{(s=i.signal)!=null&&s.aborted&&n.abort(),H(r),this.osmoFallbackReason="";const p=new Eo,h=new Io(this.scaleToFov(this.state.scale),1,1,1100),d=((a=i.route)==null?void 0:a.family)==="panorama-video",m=Si(i.descriptor.extension??((c=i.route)==null?void 0:c.sourceFormat)),g=Gc(m,i.descriptor.contentType);this.state.family=d?"panorama-video":"panorama",this.state.capabilities={...this.state.capabilities,playback:d,timeline:d,volume:d};const b=Dn.has(m)&&o&&await this.tryCalibratedVendor(e,m,i.descriptor.name,r,p,o);if(H(r),b&&((l=this.calibratedRenderer)!=null&&l.canvas)){this.finishRealtimeScene(this.calibratedRenderer.canvas);return}if(m==="insv"&&this.osmoFallbackReason)throw new Error(`INSV ${this.osmoFallbackReason}`);const x=new zo({antialias:true,alpha:false,preserveDrawingBuffer:true});if(this.renderer=x,x.setPixelRatio(Math.min(window.devicePixelRatio||1,2)),x.setClearColor(1120295,1),x.domElement.className="panoramav-canvas",this.stage.replaceChildren(x.domElement),b){this.finishScene(x,p,h);return}const v=m==="osv"?await this.resolveOsmoProxy(i.descriptor.name,r):await le(qc(e,m,r),r);if(H(r),m==="insp"&&o){const S=await o.open(v,{format:"insp",signal:r});if(H(r),S.projection.kind==="mei-extended"){const R=await le(new Yr().loadAsync(this.sourceToUrl(v,g)),r,T=>T.dispose());H(r),this.texture=R,R.anisotropy=x.capabilities.getMaxAnisotropy();const _=await le(ps(o,S,R),r,T=>T.close());H(r),_.mesh&&p.add(_.mesh),this.texture=R,this.calibratedRenderer=_,this.state.vendor=S.vendor,this.state.cameraModel=S.cameraModel,this.state.calibrationSource=S.calibrationSource,this.state.projection=S.projection.kind,this.state.decodeMode="browser-media",this.state.stitchMode="calibrated-blend",this.state.naturalWidth=S.width,this.state.naturalHeight=S.height,this.state.warnings=S.confidence==="experimental"?["Experimental calibrated INSP preview uses the image's embedded lens calibration, exposure matching, and a content-aware feathered seam."]:S.warnings,this.state.warnings.length&&this.emit("warnings",this.state.warnings),H(r),this.finishScene(x,p,h);return}if(o.close(),S.projection.kind==="unknown")throw new Error(S.warnings[0]||"INSP contains an unsupported raw dual-fisheye image.")}const w=d?await le(this.createVideoTexture(v,g,r),r,S=>S.dispose()):await le(new Yr().loadAsync(this.sourceToUrl(v,g)),r,S=>S.dispose());H(r),this.texture=w,w.colorSpace=Ki,w.anisotropy=x.capabilities.getMaxAnisotropy(),w.minFilter=Mt,w.generateMipmaps=false;const k=new Zi(500,64,40);k.scale(-1,1,1);const D=new Bo({map:w});p.add(new ea(k,D)),this.renderer=x,this.scene=p,this.camera=h,this.texture=w,this.geometry=k,this.material=D,this.state.proxyPreview=this.state.proxyPreview||m==="osv",this.state.decodeMode=this.state.proxyPreview?"proxy":"browser-media",this.state.stitchMode=this.state.proxyPreview?"proxy":"equirectangular",this.state.naturalWidth=((u=this.video)==null?void 0:u.videoWidth)||jc(w),this.state.naturalHeight=((f=this.video)==null?void 0:f.videoHeight)||Nc(w);const F=Oc(this.state.naturalWidth,this.state.naturalHeight);if(F){if(Dn.has(m))throw new Error(`${m.toUpperCase()} contains an unstitched or unsupported projection. Export a stitched 2:1 video with the camera vendor app before spherical preview.`);this.state.warnings=[F],this.notice.textContent=F,this.root.append(this.notice),this.emit("warnings",this.state.warnings)}H(r),this.finishScene(x,p,h)}catch(p){if(r.aborted)throw new DOMException("Panorama preview was aborted.","AbortError");const h=Vc(p,i.descriptor.extension??((y=i.route)==null?void 0:y.sourceFormat));throw this.disposeScene(),this.state.loading=false,this.state.error=h.message,this.emit("error",h),this.emit("statechange",this.state),h}}async loadCalibratedImage(e,i,n){var s;const r=this.beginLoad(n),o=r.signal;this.state={...this.state,loading:true,error:null,family:"panorama",title:n.descriptor.name,warnings:[...i.warnings,"Experimental RAW panorama preview uses lightweight development; camera color profiles and edits may differ."],vendor:i.vendor,cameraModel:i.cameraModel,calibrationSource:i.calibrationSource,projection:i.projection.kind,naturalWidth:i.width,naturalHeight:i.height,decodeMode:"wasm-image",proxyPreview:false,duration:void 0,currentTime:void 0,paused:true,muted:void 0,streamSyncMs:0,stabilizationAvailable:false,stabilizationMode:"off",capabilities:{zoom:true,pan:true,fullscreen:true,download:true}},this.emit("loading",this.state),this.emit("statechange",this.state);try{(s=n.signal)!=null&&s.aborted&&r.abort(),H(o);const a=document.createElement("img");await new Promise((c,l)=>{const u=()=>{a.onload=a.onerror=null,o.removeEventListener("abort",f)},f=()=>{u(),a.removeAttribute("src"),l(new DOMException("DNG preview was aborted.","AbortError"))};if(a.onload=()=>{u(),c()},a.onerror=()=>{u(),l(new Error("Failed to load the developed DNG preview."))},o.aborted){f();return}o.addEventListener("abort",f,{once:true}),a.src=this.sourceToUrl(e,"image/jpeg")}),H(o),this.calibratedRenderer=Cc(a,i),this.state.stitchMode=this.calibratedRenderer.dynamicSeam?"static-seam":"calibrated-blend",this.state.warnings.length&&this.emit("warnings",this.state.warnings),H(o),this.finishRealtimeScene(this.calibratedRenderer.canvas)}catch(a){throw o.aborted?new DOMException("Panorama preview was aborted.","AbortError"):(this.disposeScene(),this.state.loading=false,this.state.error=a instanceof Error?a.message:String(a),this.emit("statechange",this.state),a)}}destroy(){this.stopLoad(),this.state.loading=false,this.stage.replaceChildren(),this.root.replaceChildren(),this.root.parentElement===this.host&&this.host.replaceChildren()}beginLoad(e){var r;this.stopLoad();const i=new AbortController;this.loadController=i;const n=()=>i.abort();return i.signal.addEventListener("abort",()=>{var o;(o=this.removeAbortListener)==null||o.call(this),this.loadController===i&&(this.disposeScene(),this.state={...this.state,loading:false,error:null},this.emit("statechange",this.state))},{once:true}),(r=e.signal)==null||r.addEventListener("abort",n,{once:true}),this.removeAbortListener=()=>{var o;return(o=e.signal)==null?void 0:o.removeEventListener("abort",n)},this.root.parentElement!==this.host&&this.host.replaceChildren(this.root),this.root.replaceChildren(this.stage,this.hint),i}stopLoad(){var i;const e=this.loadController;this.loadController=void 0,(i=this.removeAbortListener)==null||i.call(this),this.removeAbortListener=void 0,e==null||e.abort(),this.disposeScene()}getState(){return{...this.state,warnings:this.state.warnings.slice()}}on(e,i){return this.listeners[e].add(i),()=>{this.listeners[e].delete(i)}}setScale(e){Number.isFinite(e)&&(this.state.scale=Math.max(.5,Math.min(e,2.4)),this.camera&&(this.camera.fov=this.scaleToFov(this.state.scale),this.camera.updateProjectionMatrix()),this.syncPlaybackControls(),this.scheduleFrame(),this.emit("statechange",this.state))}fit(){this.lon=180,this.lat=0,this.setScale(1)}setStabilization(e){var n;const i=((n=this.calibratedRenderer)==null?void 0:n.setStabilization(e))??"off";return this.state.stabilizationMode=i,this.emit("statechange",this.state),i}async fullscreen(){var e,i,n;if(document.fullscreenElement===this.root){await((e=document.exitFullscreen)==null?void 0:e.call(document));return}await((n=(i=this.root).requestFullscreen)==null?void 0:n.call(i))}bindInteractions(e){const i=(this.interactionController??(this.interactionController=new AbortController)).signal;Ao(e,{getScale:()=>this.state.scale,setScale:n=>this.setScale(n),pan:(n,r)=>{var s;const o=(s=this.calibratedRenderer)!=null&&s.canvas?this.calibratedRenderer.dragDirectionSign??-1:1;this.lon-=n*.1*o,this.lat=Math.max(-85,Math.min(85,this.lat+r*.1*o)),this.scheduleFrame()},signal:i}),e.addEventListener("pointerdown",n=>{n.pointerType!=="touch"&&(this.pointerDown=true,this.pointerStartX=n.clientX,this.pointerStartY=n.clientY,this.pointerStartLon=this.lon,this.pointerStartLat=this.lat,e.setPointerCapture(n.pointerId))},{signal:i}),e.addEventListener("pointermove",n=>{var o;if(!this.pointerDown)return;const r=(o=this.calibratedRenderer)!=null&&o.canvas?this.calibratedRenderer.dragDirectionSign??-1:1;this.lon=this.pointerStartLon-(n.clientX-this.pointerStartX)*.1*r,this.lat=Math.max(-85,Math.min(85,this.pointerStartLat+(n.clientY-this.pointerStartY)*.1*r)),this.scheduleFrame()},{signal:i}),e.addEventListener("pointerup",n=>{this.pointerDown=false,e.releasePointerCapture(n.pointerId)},{signal:i}),e.addEventListener("pointercancel",()=>{this.pointerDown=false},{signal:i}),e.addEventListener("wheel",n=>{n.preventDefault(),this.setScale(this.state.scale+(n.deltaY>0?-.08:.08))},{passive:false,signal:i})}observeResize(){var e;if((e=this.resizeObserver)==null||e.disconnect(),typeof ResizeObserver<"u"){this.resizeObserver=new ResizeObserver(()=>this.resize()),this.resizeObserver.observe(this.stage);return}window.addEventListener("resize",this.resize)}startAnimation(){this.scheduleFrame()}scheduleFrame(){this.animationFrame||!this.renderer&&!this.calibratedRenderer||(this.animationFrame=requestAnimationFrame(()=>{this.animationFrame=0,this.renderFrame(),this.state.family==="panorama-video"&&this.scheduleFrame()}))}renderFrame(){var n,r,o,s,a;if(!((n=this.calibratedRenderer)!=null&&n.canvas)&&(!this.renderer||!this.scene||!this.camera))return;const e=kn(90-this.lat),i=kn(this.lon);if((r=this.camera)==null||r.lookAt(500*Math.sin(e)*Math.cos(i),500*Math.cos(e),500*Math.sin(e)*Math.sin(i)),(s=(o=this.calibratedRenderer)==null?void 0:o.setView)==null||s.call(o,this.lon-180,this.lat,0,this.scaleToFov(this.state.scale)),(a=this.calibratedRenderer)==null||a.update(),this.calibratedRenderer){const c=this.calibratedRenderer.error;c&&this.state.error!==c.message&&(this.state.error=c.message,this.notice.textContent=`Panorama decode failed: ${c.message}`,this.root.append(this.notice),this.emit("error",c)),this.state.streamSyncMs=this.calibratedRenderer.streamSyncMs,this.state.stitchMode=this.calibratedRenderer.dynamicSeam?this.state.family==="panorama"?"static-seam":"dynamic-seam":"calibrated-blend",this.state.stabilizationMode=this.calibratedRenderer.stabilizationMode,this.syncCalibratedPlayback()}this.renderer&&this.scene&&this.camera&&this.renderer.render(this.scene,this.camera)}async tryCalibratedVendor(e,i,n,r,o,s){var l,u,f;let a,c;try{const y=i==="insv"?await le(this.resolveInstaCompanion(n),r):void 0;H(r),c=zc(e,y,n);const p=i==="insv"?await le(this.resolveInstaSidecar(c.primaryName),r):void 0;H(r),a=await s.open(c.source,{format:i,sidecar:p,companion:c.companion,signal:r}),H(r);const h=a.projection.kind==="unknown"&&a.tracks.length===1&&to(a.tracks[0].width,a.tracks[0].height);if(a.projection.kind==="equirectangular"||h)return this.state.vendor=a.vendor,this.state.cameraModel=a.cameraModel,this.state.calibrationSource=a.calibrationSource,this.state.projection=h?"equirectangular":a.projection.kind,this.state.proxyPreview=!!a.proxyPreview||h,this.state.warnings=h?[...a.warnings,"INSV calibration metadata was unavailable; using its browser-decodable 2:1 stitched track as a proxy."]:a.warnings,this.state.warnings.length&&this.emit("warnings",this.state.warnings),s.close(),false;const d=await le(Kn(a)&&!((l=a.imu)!=null&&l.imuToCameraConfirmed)?Ac(s,a):gs(s,a),r,m=>m.close());return H(r),d.mesh&&o.add(d.mesh),this.calibratedRenderer=d,this.state.vendor=a.vendor,this.state.cameraModel=a.cameraModel,this.state.calibrationSource=a.calibrationSource,this.state.projection=a.projection.kind,this.state.decodeMode="webcodecs",this.state.stitchMode="calibrated-blend",this.state.proxyPreview=false,this.state.stabilizationAvailable=d.stabilizationAvailable,this.state.stabilizationMode=d.stabilizationMode,this.state.naturalWidth=2048,this.state.naturalHeight=1024,this.state.duration=d.duration,this.state.currentTime=d.currentTime,this.state.paused=d.paused,this.state.muted=true,this.createPlaybackControls(),this.state.warnings=a.confidence==="experimental"?[`Experimental calibrated ${i.toUpperCase()} preview uses source-specific lens calibration. Dynamic seams and symmetric overlap exposure matching activate after paired frames; IMU stabilization ${d.stabilizationAvailable?"is available":"remains disabled until the IMU-to-camera rotation is confirmed"}.`]:a.warnings,this.state.warnings.length&&this.emit("warnings",this.state.warnings),true}catch(y){if(H(r),s.close(),i==="insv"&&a&&c&&y instanceof B&&y.code==="codec_unsupported")try{const p=await le(vs(a,c.source,c.companion),r,h=>h.close());return H(r),p.mesh&&o.add(p.mesh),this.calibratedRenderer=p,this.state.vendor=a.vendor,this.state.cameraModel=a.cameraModel,this.state.calibrationSource=a.calibrationSource,this.state.projection=a.projection.kind,this.state.decodeMode="browser-media",this.state.stitchMode="calibrated-blend",this.state.proxyPreview=false,this.state.stabilizationAvailable=false,this.state.stabilizationMode="off",this.state.naturalWidth=(u=a.tracks[0])==null?void 0:u.width,this.state.naturalHeight=(f=a.tracks[0])==null?void 0:f.height,this.state.duration=p.duration,this.state.currentTime=p.currentTime,this.state.paused=p.paused,this.state.muted=true,this.createPlaybackControls(),this.state.warnings=["WebCodecs is unavailable; using browser media decoding. Dynamic seams and IMU stabilization are disabled.",...a.warnings],this.emit("warnings",this.state.warnings),true}catch(p){H(r),y=p}return this.osmoFallbackReason=i==="insv"?Wc(y):y instanceof Error?y.message:String(y),this.state.warnings=[i==="osv"?`${this.osmoFallbackReason} Falling back to the camera-generated LRF proxy.`:this.osmoFallbackReason],false}}async resolveInstaSidecar(e){if(!e||!this.resourceResolver)return;const i=`${e}.pb`,n=await this.resourceResolver({family:"panorama-video",sourceFormat:"insv",source:i,name:i.split(/[\\/]/).pop(),relation:"sidecar"});return ba(n)}createPlaybackControls(){const e=(this.interactionController??(this.interactionController=new AbortController)).signal;this.state.capabilities={...this.state.capabilities,volume:!!this.video},this.playbackControls=Lo(this.root,{signal:e,mediaName:"panorama video",togglePlayback:()=>{const i=this.calibratedRenderer;i?(i.paused?i.play():i.pause(),this.syncCalibratedPlayback(true)):this.video&&(this.video.paused?this.video.play().catch(()=>{}):this.video.pause())},seek:i=>{this.calibratedRenderer?(this.calibratedRenderer.seek(i),this.syncCalibratedPlayback(true)):this.video&&Number.isFinite(this.video.duration)&&(this.video.currentTime=Math.max(0,Math.min(i,this.video.duration)))},toggleMuted:()=>{this.video&&(this.video.muted=!this.video.muted,!this.video.muted&&this.video.volume===0&&(this.video.volume=1))},setVolume:i=>{this.video&&(this.video.volume=i,this.video.muted=i===0)},setPlaybackRate:i=>{var n,r;(r=(n=this.calibratedRenderer)==null?void 0:n.setPlaybackRate)==null||r.call(n,i),this.video&&(this.video.playbackRate=i),this.state.playbackRate=i,this.syncPlaybackControls(),this.emit("statechange",this.state)},fullscreen:()=>this.fullscreen(),zoom:i=>this.setScale(this.state.scale+i),resetView:()=>this.fit()}),this.syncPlaybackControls()}syncPlaybackControls(){var e;(e=this.playbackControls)==null||e.sync({currentTime:this.state.currentTime??0,duration:this.state.duration??0,paused:this.state.paused??true,muted:this.state.muted??true,volume:this.state.volume??1,playbackRate:this.state.playbackRate??1,audioAvailable:!!this.video,scale:this.state.scale})}syncCalibratedPlayback(e=false){const i=this.calibratedRenderer;if(!i||this.state.family!=="panorama-video")return;const n=i.currentTime;this.state.duration=i.duration,this.state.currentTime=n,this.state.paused=i.paused,this.syncPlaybackControls();const r=performance.now();(e||r-this.lastPlaybackStateEmit>=250)&&(this.lastPlaybackStateEmit=r,this.emit("statechange",this.state))}async resolveInstaCompanion(e){if(!e||!this.resourceResolver)return;const i=/_00_/i.test(e)?e.replace(/_00_/i,"_10_"):/_10_/i.test(e)?e.replace(/_10_/i,"_00_"):"";if(!i)return;const n=await this.resourceResolver({family:"panorama-video",sourceFormat:"insv",source:i,name:i.split(/[\\/]/).pop(),relation:"companion"});return ba(n)}finishScene(e,i,n){this.renderer=e,this.scene=i,this.camera=n,this.state.loading=false,this.state.error=null,this.bindInteractions(e.domElement),this.observeResize(),this.resize(),this.startAnimation(),this.emit("rendered",this.state),this.emit("statechange",this.state)}finishRealtimeScene(e){this.stage.replaceChildren(e),this.state.loading=false,this.state.error=null,this.bindInteractions(e),this.observeResize(),this.resize(),this.startAnimation(),this.emit("rendered",this.state),this.emit("statechange",this.state)}scaleToFov(e){return Math.max(30,Math.min(100,75/Math.max(e,.5)))}sourceToUrl(e,i){if(this.revokeCreatedUrl(),typeof e=="string")return e;const n=e instanceof Blob&&(!i||e.type===i)?e:new Blob([e instanceof Blob?e:Bc(e)],i?{type:i}:void 0);return this.createdUrl=URL.createObjectURL(n),this.createdUrl}async createVideoTexture(e,i,n){const r=document.createElement("video");r.className="panoramav-video-source",r.hidden=true,r.setAttribute("aria-hidden","true"),r.loop=true,r.muted=true,r.playsInline=true,r.preload="metadata",r.crossOrigin="anonymous",this.video=r,await new Promise((a,c)=>{const l=()=>{r.removeEventListener("loadeddata",u),r.removeEventListener("error",f),n.removeEventListener("abort",y)},u=()=>{l(),a()},f=()=>{l(),c(new Error("Failed to load 360 video."))},y=()=>{l(),c(new DOMException("Panorama video was aborted.","AbortError"))};if(n.aborted){y();return}r.addEventListener("loadeddata",u),r.addEventListener("error",f),n.addEventListener("abort",y,{once:true}),r.src=this.sourceToUrl(e,i),r.load()}),H(n);const o=(this.interactionController??(this.interactionController=new AbortController)).signal,s=()=>{this.state.duration=Number.isFinite(r.duration)?r.duration:void 0,this.state.currentTime=r.currentTime,this.state.paused=r.paused,this.state.muted=r.muted,this.state.volume=r.volume,this.state.playbackRate=r.playbackRate,this.syncPlaybackControls(),this.emit("statechange",this.state)};for(const a of["durationchange","timeupdate","play","pause","volumechange","ratechange","seeked"])r.addEventListener(a,s,{signal:o});return this.video=r,this.root.append(r),s(),this.createPlaybackControls(),new Rn(r)}async resolveOsmoProxy(e,i){const n=String(e??"").replace(/\.osv$/i,".LRF");if(!n||n===e||!this.resourceResolver)throw new Error(this.osmoFallbackReason?`OSV ${this.osmoFallbackReason}`:"OSV spherical preview requires the matching camera-generated .LRF proxy file. Upload both files together.");const r=Promise.resolve(this.resourceResolver({family:"panorama-video",sourceFormat:"osv",source:n,name:n.split(/[\\/]/).pop(),relation:"proxy"})),o=i?await le(r,i):await r;H(i);const s=ba(o);if(!s)throw new Error(`OSV spherical preview requires the matching ${n} proxy file. Upload both files together.`);return this.state.warnings=["Experimental OSV preview uses the camera-generated low-resolution LRF proxy. Any lens seam or alignment error is embedded in that proxy; use a DJI Studio stitched 2:1 export for accurate spherical playback."],this.emit("warnings",this.state.warnings),s}disposeScene(){var e,i,n,r,o,s,a,c,l,u,f,y,p,h,d;(e=this.interactionController)==null||e.abort(),this.interactionController=void 0,this.pointerDown=false,this.animationFrame&&(cancelAnimationFrame(this.animationFrame),this.animationFrame=0),(i=this.resizeObserver)==null||i.disconnect(),this.resizeObserver=null,window.removeEventListener("resize",this.resize),(n=this.texture)==null||n.dispose(),(r=this.video)==null||r.pause(),(o=this.video)==null||o.removeAttribute("src"),(s=this.video)==null||s.load(),(a=this.video)==null||a.remove(),(c=this.geometry)==null||c.dispose(),(l=this.material)==null||l.dispose(),(u=this.renderer)==null||u.dispose(),(y=(f=this.renderer)==null?void 0:f.forceContextLoss)==null||y.call(f),(p=this.calibratedRenderer)==null||p.close(),(h=this.processor)==null||h.close(),this.texture=null,this.video=null,this.geometry=null,this.material=null,this.renderer=null,this.calibratedRenderer=null,(d=this.playbackControls)==null||d.remove(),this.playbackControls=null,this.lastPlaybackStateEmit=0,this.osmoFallbackReason="",this.scene=null,this.camera=null,this.revokeCreatedUrl(),this.stage.replaceChildren(),this.root.querySelectorAll(".panoramav-notice").forEach(m=>m.remove())}revokeCreatedUrl(){this.createdUrl&&(URL.revokeObjectURL(this.createdUrl),this.createdUrl=null)}emit(e,i){for(const n of this.listeners[e])n(i)}}function Kc(t={}){return{id:"panorama",family:"panorama",supports:e=>["pano","panorama","360","insp","360v","vr360","insv","osv"].includes(Si(e)),createSession:(e,i)=>new eo(e,i,t.processor)}}function Zc(t=Po()){const e=new Set(Sn.flatMap(i=>i.extensions));return[...Sn,...t.filter(i=>!i.extensions.some(n=>e.has(n)))]}function zc(t,e,i){return e&&i&&/_10_/i.test(i)?{source:e,companion:t,primaryName:i.replace(/_10_/i,"_00_")}:{source:t,companion:e,primaryName:i}}function Bc(t){if(ArrayBuffer.isView(t)){const e=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);if(e.buffer instanceof ArrayBuffer)return e;const i=new Uint8Array(e.byteLength);return i.set(e),i.buffer}return t}function jc(t){const e=t.image;return(e==null?void 0:e.naturalWidth)??(e==null?void 0:e.width)}function Nc(t){const e=t.image;return(e==null?void 0:e.naturalHeight)??(e==null?void 0:e.height)}function to(t,e){if(!t||!e)return false;const i=t/e;return i>=1.8&&i<=2.2}function Oc(t,e){return t&&e&&!to(t,e)?Ec:void 0}function Vc(t,e){const i=Si(e);return t instanceof Error&&t.message.startsWith(i.toUpperCase())?t:Ic.has(i)?new Error(`${i.toUpperCase()} source could not be decoded by this browser. Stitch or export it with the camera vendor app as a 2:1 JPEG, MP4, or WebM file.`):t instanceof Error?t:new Error(String(t))}function Wc(t){return t instanceof B?t.code==="sidecar_missing"?"This INSV needs its matching .insv.pb calibration sidecar. Upload the sidecar with the video, or export a stitched 2:1 MP4/WebM file.":t.code==="calibration_missing"||t.code==="invalid_manifest"?"This INSV needs both matching _00_/_10_ lens files and valid calibration metadata. Upload the pair, or export a stitched 2:1 MP4/WebM file.":t.message:t instanceof Error?t.message:String(t)}function ba(t){if(t)return typeof t=="object"&&"source"in t?t.source:t}function Gc(t,e){if(e&&e!=="application/octet-stream")return e;switch(Si(t)){case"insp":return"image/jpeg";case"insv":case"osv":return"video/mp4";default:return e}}async function qc(t,e,i){if(Si(e)!=="insp"||typeof t!="string")return t;const n=await fetch(t,{signal:i});if(!n.ok)throw new Error(`INSP source request failed: ${n.status} ${n.statusText}`.trim());return n.blob()}function kn(t){return t*Math.PI/180}function Si(t){return String(t??"").trim().replace(/^\./,"").toLowerCase()}const el=[{extensions:["dng"],family:"image",driverId:"raw-image",targetFormat:"jpg",contentTypes:["image/dng","image/x-adobe-dng"]}];function tl(t){return{id:"raw-image",family:"image",supports:e=>e.replace(/^\./,"").toLowerCase()==="dng",createSession:(e,i)=>new Xc(e,i??{},t)}}class Xc{constructor(e,i,n){L(this,"child");L(this,"controller");L(this,"state",{family:"image",loading:false,error:null,warnings:[],capabilities:{}});L(this,"listeners",new Map);L(this,"unsubscribes",[]);this.host=e,this.options=i,this.dependencies=n}async load(e,i){var a;this.destroy(),this.controller=new AbortController;const n=this.controller,r=n.signal;if(r.addEventListener("abort",()=>{this.controller===n&&(this.release(),this.state={...this.state,loading:false,error:null},this.emit("statechange",this.state))},{once:true}),i.signal){const c=()=>n.abort(i.signal.reason);i.signal.aborted||(i.signal.addEventListener("abort",c,{once:true}),this.unsubscribes.push(()=>i.signal.removeEventListener("abort",c)))}const o={...i,signal:r};this.state={...this.state,loading:true,error:null,title:i.descriptor.name,warnings:[]},this.emit("loading",this.state),this.emit("statechange",this.state);const s=this.dependencies.processor;try{(a=i.signal)!=null&&a.aborted&&n.abort(),H(r);const c=s?await le(s.open(e,{format:"dng",signal:r}),r):void 0;if(H(r),c&&Zn(c)){if(!(s!=null&&s.decodeImage))throw new Error("Calibrated DNG preview requires a panorama processor with WASM image decoding.");const l=await le(s.decodeImage(r),r);H(r),s.close();const u=new eo(this.host,this.options);this.attach(u),await le(u.loadCalibratedImage(l,c,o),r)}else{s==null||s.close();const l=await le(this.dependencies.converter.convert({source:e,sourceFormat:"dng",targetFormat:"jpg",name:i.descriptor.name},o),r);H(r);const u=[...(c==null?void 0:c.warnings)??[],...l.warnings??[]];this.state.warnings=u,u.length&&this.emit("warnings",u),H(r);const f=_o().createSession(this.host,this.options);this.attach(f,u),await le(f.load(l.source,{...o,descriptor:{...i.descriptor,source:l.source,extension:l.format,contentType:l.contentType},route:{family:"image",driverId:"image",sourceFormat:l.format,targetFormat:l.format}}),r)}}catch(c){if(r.aborted)throw new DOMException("RAW preview was aborted.","AbortError");this.release();const l=c instanceof Error?c:new Error(String(c));throw this.state={...this.state,loading:false,error:l.message},this.emit("error",l),this.emit("statechange",this.state),l}}attach(e,i=[]){this.child=e;const n=this.controller;for(const r of["loading","rendered","error","statechange","warnings"])this.unsubscribes.push(e.on(r,o=>{this.controller!==n||n!=null&&n.signal.aborted||this.child!==e||(r==="loading"||r==="rendered"||r==="statechange"?(this.state={...o,warnings:[...new Set([...i,...o.warnings])]},this.emit(r,this.state)):this.emit(r,o))}))}getState(){return{...this.state,warnings:[...this.state.warnings],capabilities:{...this.state.capabilities}}}on(e,i){const n=this.listeners.get(e)??new Set;return this.listeners.set(e,n),n.add(i),()=>n.delete(i)}emit(e,i){var n;(n=this.listeners.get(e))==null||n.forEach(r=>r(i))}setScale(e){var i,n;(n=(i=this.child)==null?void 0:i.setScale)==null||n.call(i,e)}fit(e){var i,n;(n=(i=this.child)==null?void 0:i.fit)==null||n.call(i,e)}rotate(e){var i,n;(n=(i=this.child)==null?void 0:i.rotate)==null||n.call(i,e)}pan(e,i){var n,r;(r=(n=this.child)==null?void 0:n.pan)==null||r.call(n,e,i)}async fullscreen(){var e,i;await((i=(e=this.child)==null?void 0:e.fullscreen)==null?void 0:i.call(e))}destroy(){const e=this.controller;this.controller=void 0,e==null||e.abort(),this.release(),this.state={...this.state,loading:false}}release(){var e,i;this.unsubscribes.splice(0).forEach(n=>n()),(e=this.child)==null||e.destroy(),this.child=void 0,(i=this.dependencies.processor)==null||i.close()}}export{el as R,Jc as a,Kc as b,wi as c,tl as d,Zc as e,cs as f,Hc as g,Se as t};
|