@zushah/wasmgpu 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +140 -143
- package/dist/WasmGPU.iife.min.js +17 -7
- package/dist/WasmGPU.js +15229 -9430
- package/dist/WasmGPU.min.js +17 -7
- package/dist/wasm.js +11 -1
- package/dist/wasm.wasm +0 -0
- package/package.json +2 -2
package/dist/WasmGPU.min.js
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
|
-
var Wn=null,Gi=(n,e)=>{Wn={wasm:n,frameArena:e}},de=()=>{if(!Wn)throw new Error("wasm interop host not set. This is an internal error: WasmGPU/src/wasm/index.ts should call setWasmInteropHost().");return Wn},Ui=typeof FinalizationRegistry<"u"?new FinalizationRegistry(n=>{try{let{wasm:e}=de(),t=n.ptr>>>0,r=n.length>>>0;switch(n.dtype){case"f32":e.freeF32(t,r);break;case"u32":e.freeU32(t,r);break;case"i32":e.freeU32(t,r);break;case"u8":e.freeBytes(t,r);break}}catch{}}):null,ge=class{kind;dtype;ptr;length;byteLength;ctor;epoch;epochProvider;freed=!1;_buf=null;_view=null;constructor(e,t,r,i,o,a,s){this.kind=e,this.dtype=t,this.ptr=r>>>0,this.length=i>>>0,this.ctor=o,this.epoch=a>>>0,this.epochProvider=s,this.byteLength=this.length*(o.BYTES_PER_ELEMENT>>>0)>>>0,this.kind==="heap"&&Ui?.register(this,{dtype:this.dtype,ptr:this.ptr,length:this.length},this)}isAlive(){if(this.freed)return!1;if(!this.epochProvider)return!0;try{return this.epoch>>>0===this.epochProvider()>>>0}catch{return!1}}assertAlive(){if(!this.isAlive()){if(this.freed)throw new Error(`WasmSlice<${this.dtype}> is no longer valid (freed).`);if(this.epochProvider){let e=0;try{e=this.epochProvider()>>>0}catch{}throw new Error(`WasmSlice<${this.dtype}> is no longer valid (epoch changed: allocEpoch=${this.epoch} currentEpoch=${e}).`)}throw new Error(`WasmSlice<${this.dtype}> is no longer valid.`)}}buffer(){return this.assertAlive(),de().wasm.memory().buffer}view(){this.assertAlive();let e=de().wasm.memory().buffer;return(this._buf!==e||!this._view)&&(this._buf=e,this._view=new this.ctor(e,this.ptr>>>0,this.length>>>0)),this._view}write(e,t=0,r=!0){let i=this.view();if(r&&i.fill(0),!e)return;let o=this.length>>>0,a=t>>>0,s=e.length>>>0,l=s>a?s-a:0,u=Math.min(o,l);if(u===0)return;let m=e;if(ArrayBuffer.isView(m)&&typeof m.subarray=="function"){i.set(m.subarray(a,a+u),0);return}for(let c=0;c<u;c++)i[c]=e[a+c]}handle(){let e={kind:this.kind,dtype:this.dtype,ptr:this.ptr>>>0,length:this.length>>>0};return this.epochProvider&&(e.epoch=this.epoch>>>0),e}free(){if(this.kind!=="heap")throw new Error(`WasmSlice.free(): cannot free a ${this.kind} allocation. Use reset() for arena-like allocators (frameArena.reset() / WasmHeapArena.reset()).`);if(this.freed)return;this.freed=!0,Ui?.unregister(this);let{wasm:e}=de(),t=this.ptr>>>0,r=this.length>>>0;switch(this.dtype){case"f32":e.freeF32(t,r);break;case"u32":e.freeU32(t,r);break;case"i32":e.freeU32(t,r);break;case"u8":e.freeBytes(t,r);break}this._buf=null,this._view=null}},Ba=(n,e)=>{let t=e>>>0;if(t===0||(t&t-1)!==0)throw new Error(`alignUp(${n}, ${e}): align must be a non-zero power of two`);return Math.ceil(n/t)*t},mr=class{basePtr;capBytes;headBytes=0;_epoch=1;destroyed=!1;constructor(e,t=16){let r=e>>>0;if(r===0)throw new Error("WasmHeapArena: capBytes must be > 0");let{wasm:i}=de(),o=i.allocBytes(r);if(!o)throw new Error(`WasmHeapArena(${e}): wasm.allocBytes failed`);let a=t>>>0;if(a!==0&&(o&a-1)!==0)throw new Error(`WasmHeapArena(${e}): basePtr 0x${o.toString(16)} is not ${t}-byte aligned`);this.basePtr=o>>>0,this.capBytes=r>>>0}epoch(){return this.assertAlive(),this._epoch>>>0}usedBytes(){return this.assertAlive(),this.headBytes>>>0}reset(){this.assertAlive(),this.headBytes=0,this._epoch=this._epoch+1>>>0,this._epoch===0&&(this._epoch=1)}destroy(){this.destroyed||(this.destroyed=!0,this.headBytes=0,this._epoch=this._epoch+1>>>0,this._epoch===0&&(this._epoch=1))}alloc(e,t=16){this.assertAlive();let r=e>>>0,i=t>>>0,o=this.basePtr>>>0,a=this.headBytes>>>0,s=Ba(o+a,i),l=s+r;if(l-o>this.capBytes>>>0)throw new Error(`WasmHeapArena.alloc(${e}, ${t}): out of memory (used=${a} cap=${this.capBytes})`);return this.headBytes=l-o>>>0,s>>>0}allocF32(e){let t=e>>>0,r=this.alloc(t*4,16),i=this.epoch();return new ge("arena","f32",r,t,Float32Array,i,()=>this.epoch())}allocU32(e){let t=e>>>0,r=this.alloc(t*4,16),i=this.epoch();return new ge("arena","u32",r,t,Uint32Array,i,()=>this.epoch())}allocI32(e){let t=e>>>0,r=this.alloc(t*4,16),i=this.epoch();return new ge("arena","i32",r,t,Int32Array,i,()=>this.epoch())}allocU8(e,t=16){let r=e>>>0,i=this.alloc(r,t),o=this.epoch();return new ge("arena","u8",i,r,Uint8Array,o,()=>this.epoch())}assertAlive(){if(this.destroyed)throw new Error("WasmHeapArena has been destroyed.")}},ki=null,zn=null,Ma=()=>{let n=de().wasm.memory().buffer;return(n!==ki||!zn)&&(ki=n,zn=new Uint8Array(n)),zn},oe={buffer:()=>de().wasm.memory().buffer,bytes:()=>Ma(),isSharedMemory:()=>{let n=de().wasm.memory().buffer;return typeof SharedArrayBuffer<"u"&&n instanceof SharedArrayBuffer},requireSharedMemory:()=>{let n=de().wasm.memory().buffer;if(typeof SharedArrayBuffer<"u"&&n instanceof SharedArrayBuffer)return n;throw new Error("WebAssembly memory is not a SharedArrayBuffer. Build with WASMGPU_SHARED_MEMORY=1 and serve with cross-origin isolation to enable SharedArrayBuffer.")},viewOn:(n,e,t,r)=>new n(e,t>>>0,r>>>0),view:(n,e,t)=>new n(de().wasm.memory().buffer,e>>>0,t>>>0),createHeapArena:(n,e=16)=>new mr(n,e),viewFromHandle:(n,e)=>{let t=e.ptr>>>0,r=e.length>>>0;switch(e.dtype){case"f32":return new Float32Array(n,t,r);case"u32":return new Uint32Array(n,t,r);case"i32":return new Int32Array(n,t,r);case"u8":return new Uint8Array(n,t,r)}},heap:{allocF32:n=>{let{wasm:e}=de(),t=e.allocF32(n);if(!t&&n>>>0)throw new Error(`wasmInterop.heap.allocF32(${n}) failed`);return new ge("heap","f32",t,n,Float32Array,0,null)},allocU32:n=>{let{wasm:e}=de(),t=e.allocU32(n);if(!t&&n>>>0)throw new Error(`wasmInterop.heap.allocU32(${n}) failed`);return new ge("heap","u32",t,n,Uint32Array,0,null)},allocI32:n=>{let{wasm:e}=de(),t=e.allocU32(n);if(!t&&n>>>0)throw new Error(`wasmInterop.heap.allocI32(${n}) failed`);return new ge("heap","i32",t,n,Int32Array,0,null)},allocU8:(n,e=16)=>{let{wasm:t}=de(),r=t.allocBytes(n>>>0);if(!r&&n>>>0)throw new Error(`wasmInterop.heap.allocU8(${n}) failed`);if(e!==0&&(r&(e>>>0)-1)!==0)throw new Error(`wasmInterop.heap.allocU8(${n}): returned ptr 0x${r.toString(16)} is not ${e}-byte aligned`);return new ge("heap","u8",r,n,Uint8Array,0,null)}},frame:{allocF32:n=>{let{frameArena:e}=de(),t=e.allocF32(n);if(!t&&n>>>0)throw new Error(`wasmInterop.frame.allocF32(${n}) failed`);return new ge("frame","f32",t,n,Float32Array,e.epoch(),()=>e.epoch())},allocU32:n=>{let{frameArena:e}=de(),t=e.alloc((n>>>0)*4,16);if(!t&&n>>>0)throw new Error(`wasmInterop.frame.allocU32(${n}) failed`);return new ge("frame","u32",t,n,Uint32Array,e.epoch(),()=>e.epoch())},allocI32:n=>{let{frameArena:e}=de(),t=e.alloc((n>>>0)*4,16);if(!t&&n>>>0)throw new Error(`wasmInterop.frame.allocI32(${n}) failed`);return new ge("frame","i32",t,n,Int32Array,e.epoch(),()=>e.epoch())},allocU8:(n,e=16)=>{let{frameArena:t}=de(),r=t.alloc(n>>>0,e>>>0);if(!r&&n>>>0)throw new Error(`wasmInterop.frame.allocU8(${n}) failed`);return new ge("frame","u8",r,n,Uint8Array,t.epoch(),()=>t.epoch())}}};var Ti=null,Ut=null,dr=0,Ri=8*1024*1024,Aa=(()=>{if(typeof document>"u")return null;let e=document.currentScript?.src;return e&&e.length>0?e:null})(),Ua=()=>{if(import.meta.url!=="__CURRENT_SCRIPT__")return new URL(".",import.meta.url).toString();let n=Aa??location.href;return new URL(".",n).toString()},Vn=async n=>{if(Ut)return;let e=n??Ua(),t=new URL("wasm.js",e).toString();Ti??=import(t),Ut=await Ti,Ut.wasmgpu_frame_arena_init(Ri),dr=Ut.wasmgpu_frame_arena_epoch()>>>0},y=()=>{if(!Ut)throw new Error("WebAssembly driver not initialized. Call await initWebAssembly() first.");return Ut},Nn=()=>(dr=y().wasmgpu_frame_arena_epoch()>>>0,dr),Be=n=>!!n,_={memory:()=>y().memory,seed:n=>{y().wasmgpu_seed(n>>>0)},allocF32:n=>y().wasmgpu_alloc_f32(n>>>0)>>>0,freeF32:(n,e)=>y().wasmgpu_free_f32(n>>>0,e>>>0),allocU32:n=>y().wasmgpu_alloc_u32(n>>>0)>>>0,freeU32:(n,e)=>y().wasmgpu_free_u32(n>>>0,e>>>0),allocBytes:n=>y().wasmgpu_alloc(n>>>0)>>>0,freeBytes:(n,e)=>y().wasmgpu_free(n>>>0,e>>>0),f32view:(n,e)=>y().f32view(n>>>0,e>>>0),u32view:(n,e)=>y().u32view(n>>>0,e>>>0),i32view:(n,e)=>y().i32view(n>>>0,e>>>0),u8view:(n,e)=>y().u8view(n>>>0,e>>>0),writeF32:(n,e,t)=>{let r=y().f32view(n>>>0,e>>>0),i=Math.min(e>>>0,t?t.length>>>0:0);for(let o=0;o<i;o++)r[o]=t[o];for(let o=i;o<e>>>0;o++)r[o]=0},readF32Array:(n,e)=>Array.from(y().f32view(n>>>0,e>>>0))},W={init:(n=Ri)=>{let e=y().wasmgpu_frame_arena_init(n>>>0)>>>0;if(!e)throw new Error(`wasmgpu_frame_arena_init(${n}) failed`);return Nn(),e},reset:()=>{y().wasmgpu_frame_arena_reset(),Nn()},alloc:(n,e=16)=>{let t=y().wasmgpu_frame_alloc(n>>>0,e>>>0)>>>0;if(!t)throw new Error(`wasmgpu_frame_alloc(${n}, ${e}) failed`);return t},allocF32:n=>{let e=y().wasmgpu_frame_alloc_f32(n>>>0)>>>0;if(!e)throw new Error(`wasmgpu_frame_alloc_f32(${n}) failed`);return e},epoch:()=>(dr||Nn(),dr),usedBytes:()=>y().wasmgpu_frame_arena_used()>>>0,capBytes:()=>y().wasmgpu_frame_arena_cap()>>>0};Gi(_,W);var kt={deinterleave:(n,e,t,r,i,o)=>{y().accessor_deinterleave(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0)},applySparse:(n,e,t,r,i,o,a,s)=>{y().accessor_apply_sparse(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a>>>0,s>>>0)},convertToF32:(n,e,t,r,i)=>{y().accessor_convert_to_f32(n>>>0,e>>>0,t>>>0,r>>>0,i?1:0)},convertToU16:(n,e,t,r)=>{y().accessor_convert_to_u16(n>>>0,e>>>0,t>>>0,r>>>0)},convertToU32:(n,e,t,r)=>{y().accessor_convert_to_u32(n>>>0,e>>>0,t>>>0,r>>>0)}},Gt={sampleClipTRS:(n,e,t,r,i,o,a,s,l)=>{y().anim_sample_clip_trs(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a>>>0,s>>>0,l)},computeJointMatricesTo:(n,e,t,r,i,o)=>{y().anim_compute_joint_matrices_to(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0)}},Tt={pointcloudXYZS:(n,e,t,r,i,o,a)=>{y().bounds_pointcloud_xyzs(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a>>>0)},glyphInstances:(n,e,t,r,i,o,a,s,l,u)=>{y().bounds_glyph_instances(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a>>>0,s>>>0,l>>>0,u)},geometryPositions:(n,e,t,r,i,o)=>{y().bounds_geometry_positions(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0)}},et={writePlanesFromViewProjection:(n,e)=>{y().cull_write_planes_from_view_projection(n>>>0,e>>>0)},prepareWorldSpheresFromPtrs:(n,e,t,r,i,o)=>{y().cull_prepare_world_spheres_from_ptrs(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0)},spheresFrustum:(n,e,t,r,i)=>y().cull_spheres_frustum(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)>>>0},pr={writePlanesFromViewProjection:(n,e)=>{if(typeof e=="number"){y().cull_write_planes_from_view_projection(n>>>0,e>>>0);return}let t=W.allocF32(16);_.writeF32(t,16,e),y().cull_write_planes_from_view_projection(n>>>0,t>>>0)}},ne={alloc:()=>_.allocF32(16),view:n=>_.f32view(n,16),set:(n,e)=>_.writeF32(n,16,e),abs:(n,e)=>{y().mat4_abs(n>>>0,e>>>0)},add:(n,e,t)=>{y().mat4_add(n>>>0,e>>>0,t>>>0)},copy:(n,e)=>{y().mat4_copy(n>>>0,e>>>0)},decomposeTRS:(n,e)=>{y().mat4_decompose_trs(n>>>0,e>>>0)},det:n=>y().mat4_det(n>>>0),identity:n=>{y().mat4_identity(n>>>0)},init:(n,e,t,r,i,o,a,s,l,u,m,c,d,f,p,b,g)=>{y().mat4_init(n>>>0,e,t,r,i,o,a,s,l,u,m,c,d,f,p,b,g)},invert:(n,e)=>{y().mat4_invert(n>>>0,e>>>0)},isEqual:(n,e)=>Be(y().mat4_isEqual(n>>>0,e>>>0)),isIdentity:n=>Be(y().mat4_isIdentity(n>>>0)),isInverse:(n,e)=>Be(y().mat4_isInverse(n>>>0,e>>>0)),isZero:n=>Be(y().mat4_isZero(n>>>0)),lookAt:(n,e,t,r)=>{y().mat4_lookAt(n>>>0,e>>>0,t>>>0,r>>>0)},mul:(n,e,t)=>{y().mat4_mul(n>>>0,e>>>0,t>>>0)},mulVec4:(n,e,t)=>{y().mat4_mul_vec4(n>>>0,e>>>0,t>>>0)},neg:(n,e)=>{y().mat4_neg(n>>>0,e>>>0)},norm:n=>y().mat4_norm(n>>>0),normalize:(n,e)=>{y().mat4_normalize(n>>>0,e>>>0)},normsq:n=>y().mat4_normsq(n>>>0),perspective:(n,e,t,r,i)=>{y().mat4_perspective(n>>>0,e,t,r,i)},random:n=>{y().mat4_random(n>>>0)},randomRange:(n,e,t)=>{y().mat4_random_range(n>>>0,e,t)},rotateX:(n,e,t)=>{y().mat4_rotateX(n>>>0,e>>>0,t)},rotateY:(n,e,t)=>{y().mat4_rotateY(n>>>0,e>>>0,t)},rotateZ:(n,e,t)=>{y().mat4_rotateZ(n>>>0,e>>>0,t)},round:(n,e)=>{y().mat4_round(n>>>0,e>>>0)},scl:(n,e,t)=>{y().mat4_scl(n>>>0,e>>>0,t)},sub:(n,e,t)=>{y().mat4_sub(n>>>0,e>>>0,t>>>0)},trace:n=>y().mat4_trace(n>>>0),translate:(n,e,t)=>{y().mat4_translate(n>>>0,e>>>0,t>>>0)},transpose:(n,e)=>{y().mat4_transpose(n>>>0,e>>>0)},print:n=>{let e=_.f32view(n,16);console.log(`[ ${e[0]} ${e[1]} ${e[2]} ${e[3]} ]
|
|
1
|
+
/*!
|
|
2
|
+
* WasmGPU v0.8.0
|
|
3
|
+
* WebGPU × WebAssembly rendering and computing engine for scientific workloads in the browser
|
|
4
|
+
* Copyright (c) Zushah and contributors
|
|
5
|
+
* SPDX-License-Identifier: MPL-2.0
|
|
6
|
+
* Source: https://www.github.com/Zushah/WasmGPU
|
|
7
|
+
* Website: https://zushah.github.io/WasmGPU
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var y=(n,e)=>{if(!n)throw new Error(e)},he=(n,e)=>Math.ceil(n/e)*e,se=(n,e,t)=>n<e?e:n>t?t:n,le=n=>se(n,0,1),Kr=(n,e,t)=>Number.isFinite(n)?Math.max(e,Math.min(t,Math.round(n))):e,Ve=(n,e,t)=>n+(e-n)*t,Ee=(n,e)=>(y(Number.isFinite(n)&&Number.isFinite(e),"ceilDiv expects finite numbers"),y(e!==0,"ceilDiv divisor must be non-zero"),Math.floor((n+e-1)/e)),ht=n=>Number.isInteger(n)&&n>0,Se=n=>Number.isInteger(n)&&n>=0,gt=(n,e)=>typeof n=="number"&&Number.isFinite(n)?n:e,Xr=(n,e)=>typeof n=="number"&&Number.isInteger(n)?n:e,Yr=n=>{let e=Math.max(1,n|0);return e--,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,e|=e>>16,e++,e},hr=()=>typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now(),gr=n=>typeof n=="object"&&n!==null&&n.mapState!==void 0,re=n=>gr(n)?n:n.buffer,br=(n,e="shape")=>{if(!n)return null;let t=[];for(let r=0;r<n.length;r++){let i=n[r];y(Number.isInteger(i)&&i>0,`${e}[${r}] must be an integer > 0.`),t.push(i|0)}return t.length>0?t:null},vr=(n,e)=>{if(!n||n.length===0||!Number.isInteger(e)||e<0)return null;let t=e|0,r=new Array(n.length);for(let i=n.length-1;i>=0;i--){let o=n[i];r[i]=t%o,t=Math.floor(t/o)}return t===0?r:null},Ze=(n,e=[[0,0,0,1],[1,1,1,1]],t=8)=>{let r=!n||n.length===0?e:n,i=Math.max(0,t|0),o=Math.min(i,Math.max(2,r.length)),a=[];for(let s=0;s<o;s++){let l=r[Math.min(s,r.length-1)]??e[Math.min(s,e.length-1)]??[0,0,0,1];a.push([l[0],l[1],l[2],l[3]])}return a},Xo=(n,e,t=8)=>{let r=Math.min(Math.max(2,t|0),Math.max(2,e.length)),i=Ze(e,[[0,0,0,1],[1,1,1,1]],r),o=le(n)*(r-1),a=Math.floor(o),s=Math.min(r-1,a+1),l=o-a;return a>=r-1?i[r-1]:[Ve(i[a][0],i[s][0],l),Ve(i[a][1],i[s][1],l),Ve(i[a][2],i[s][2],l),Ve(i[a][3],i[s][3],l)]},ne=(n,e,t,r)=>{let i=n.createBuffer({label:r,size:he(e.byteLength,4),usage:t,mappedAtCreation:!0});return new Uint8Array(i.getMappedRange()).set(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),i.unmap(),i},Dn=(n,e,t,r=1)=>n.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:"depth24plus",sampleCount:r,usage:GPUTextureUsage.RENDER_ATTACHMENT});var Zi=null,Rl=(n,e)=>{Zi={wasm:n,frameArena:e}},_e=()=>{if(!Zi)throw new Error("WebAssembly driver host not set. This is an internal error: WasmGPU/src/wasm/driver.ts should call setWebAssemblyDriverHost().");return Zi},Yo=typeof FinalizationRegistry<"u"?new FinalizationRegistry(n=>{try{let{wasm:e}=_e(),t=n.ptr>>>0,r=n.length>>>0;switch(n.dtype){case"f32":e.freeF32(t,r);break;case"u32":e.freeU32(t,r);break;case"i32":e.freeU32(t,r);break;case"u8":e.freeBytes(t,r);break}}catch{}}):null,Ue=class{kind;dtype;ptr;length;byteLength;ctor;epoch;epochProvider;freed=!1;_buf=null;_view=null;constructor(e,t,r,i,o,a,s){this.kind=e,this.dtype=t,this.ptr=r>>>0,this.length=i>>>0,this.ctor=o,this.epoch=a>>>0,this.epochProvider=s,this.byteLength=this.length*(o.BYTES_PER_ELEMENT>>>0)>>>0,this.kind==="heap"&&Yo?.register(this,{dtype:this.dtype,ptr:this.ptr,length:this.length},this)}isAlive(){if(this.freed)return!1;if(!this.epochProvider)return!0;try{return this.epoch>>>0===this.epochProvider()>>>0}catch{return!1}}assertAlive(){if(!this.isAlive()){if(this.freed)throw new Error(`WasmSlice<${this.dtype}> is no longer valid (freed).`);if(this.epochProvider){let e=0;try{e=this.epochProvider()>>>0}catch{}throw new Error(`WasmSlice<${this.dtype}> is no longer valid (epoch changed: allocEpoch=${this.epoch} currentEpoch=${e}).`)}throw new Error(`WasmSlice<${this.dtype}> is no longer valid.`)}}buffer(){return this.assertAlive(),_e().wasm.memory().buffer}view(){this.assertAlive();let e=_e().wasm.memory().buffer;return(this._buf!==e||!this._view)&&(this._buf=e,this._view=new this.ctor(e,this.ptr>>>0,this.length>>>0)),this._view}write(e,t=0,r=!0){let i=this.view();if(r&&i.fill(0),!e)return;let o=this.length>>>0,a=t>>>0,s=e.length>>>0,l=s>a?s-a:0,u=Math.min(o,l);if(u===0)return;let c=e;if(ArrayBuffer.isView(c)&&typeof c.subarray=="function"){i.set(c.subarray(a,a+u),0);return}for(let m=0;m<u;m++)i[m]=e[a+m]}handle(){let e={kind:this.kind,dtype:this.dtype,ptr:this.ptr>>>0,length:this.length>>>0};return this.epochProvider&&(e.epoch=this.epoch>>>0),e}free(){if(this.kind!=="heap")throw new Error(`WasmSlice.free(): cannot free a ${this.kind} allocation. Use reset() for arena-like allocators (frameArena.reset() / WasmHeapArena.reset()).`);if(this.freed)return;this.freed=!0,Yo?.unregister(this);let{wasm:e}=_e(),t=this.ptr>>>0,r=this.length>>>0;switch(this.dtype){case"f32":e.freeF32(t,r);break;case"u32":e.freeU32(t,r);break;case"i32":e.freeU32(t,r);break;case"u8":e.freeBytes(t,r);break}this._buf=null,this._view=null}},Ul=(n,e)=>{let t=e>>>0;if(t===0||(t&t-1)!==0)throw new Error(`alignUp(${n}, ${e}): align must be a non-zero power of two`);return Math.ceil(n/t)*t},Zr=class{basePtr;capBytes;headBytes=0;_epoch=1;destroyed=!1;constructor(e,t=16){let r=e>>>0;if(r===0)throw new Error("WasmHeapArena: capBytes must be > 0");let{wasm:i}=_e(),o=i.allocBytes(r);if(!o)throw new Error(`WasmHeapArena(${e}): wasm.allocBytes failed`);let a=t>>>0;if(a!==0&&(o&a-1)!==0)throw new Error(`WasmHeapArena(${e}): basePtr 0x${o.toString(16)} is not ${t}-byte aligned`);this.basePtr=o>>>0,this.capBytes=r>>>0}epoch(){return this.assertAlive(),this._epoch>>>0}usedBytes(){return this.assertAlive(),this.headBytes>>>0}reset(){this.assertAlive(),this.headBytes=0,this._epoch=this._epoch+1>>>0,this._epoch===0&&(this._epoch=1)}destroy(){this.destroyed||(this.destroyed=!0,this.headBytes=0,this._epoch=this._epoch+1>>>0,this._epoch===0&&(this._epoch=1))}alloc(e,t=16){this.assertAlive();let r=e>>>0,i=t>>>0,o=this.basePtr>>>0,a=this.headBytes>>>0,s=Ul(o+a,i),l=s+r;if(l-o>this.capBytes>>>0)throw new Error(`WasmHeapArena.alloc(${e}, ${t}): out of memory (used=${a} cap=${this.capBytes})`);return this.headBytes=l-o>>>0,s>>>0}allocF32(e){let t=e>>>0,r=this.alloc(t*4,16),i=this.epoch();return new Ue("arena","f32",r,t,Float32Array,i,()=>this.epoch())}allocU32(e){let t=e>>>0,r=this.alloc(t*4,16),i=this.epoch();return new Ue("arena","u32",r,t,Uint32Array,i,()=>this.epoch())}allocI32(e){let t=e>>>0,r=this.alloc(t*4,16),i=this.epoch();return new Ue("arena","i32",r,t,Int32Array,i,()=>this.epoch())}allocU8(e,t=16){let r=e>>>0,i=this.alloc(r,t),o=this.epoch();return new Ue("arena","u8",i,r,Uint8Array,o,()=>this.epoch())}assertAlive(){if(this.destroyed)throw new Error("WasmHeapArena has been destroyed.")}},Zo=null,Xi=null,Gl=()=>{let n=_e().wasm.memory().buffer;return(n!==Zo||!Xi)&&(Zo=n,Xi=new Uint8Array(n)),Xi},de={buffer:()=>_e().wasm.memory().buffer,bytes:()=>Gl(),isSharedMemory:()=>{let n=_e().wasm.memory().buffer;return typeof SharedArrayBuffer<"u"&&n instanceof SharedArrayBuffer},requireSharedMemory:()=>{let n=_e().wasm.memory().buffer;if(typeof SharedArrayBuffer<"u"&&n instanceof SharedArrayBuffer)return n;throw new Error("WebAssembly memory is not a SharedArrayBuffer. Build with WASMGPU_SHARED_MEMORY=1 and serve with cross-origin isolation to enable SharedArrayBuffer.")},viewOn:(n,e,t,r)=>new n(e,t>>>0,r>>>0),view:(n,e,t)=>new n(_e().wasm.memory().buffer,e>>>0,t>>>0),createHeapArena:(n,e=16)=>new Zr(n,e),viewFromHandle:(n,e)=>{let t=e.ptr>>>0,r=e.length>>>0;switch(e.dtype){case"f32":return new Float32Array(n,t,r);case"u32":return new Uint32Array(n,t,r);case"i32":return new Int32Array(n,t,r);case"u8":return new Uint8Array(n,t,r)}},heap:{allocF32:n=>{let{wasm:e}=_e(),t=e.allocF32(n);if(!t&&n>>>0)throw new Error(`driver.heap.allocF32(${n}) failed`);return new Ue("heap","f32",t,n,Float32Array,0,null)},allocU32:n=>{let{wasm:e}=_e(),t=e.allocU32(n);if(!t&&n>>>0)throw new Error(`driver.heap.allocU32(${n}) failed`);return new Ue("heap","u32",t,n,Uint32Array,0,null)},allocI32:n=>{let{wasm:e}=_e(),t=e.allocU32(n);if(!t&&n>>>0)throw new Error(`driver.heap.allocI32(${n}) failed`);return new Ue("heap","i32",t,n,Int32Array,0,null)},allocU8:(n,e=16)=>{let{wasm:t}=_e(),r=t.allocBytes(n>>>0);if(!r&&n>>>0)throw new Error(`driver.heap.allocU8(${n}) failed`);if(e!==0&&(r&(e>>>0)-1)!==0)throw new Error(`driver.heap.allocU8(${n}): returned ptr 0x${r.toString(16)} is not ${e}-byte aligned`);return new Ue("heap","u8",r,n,Uint8Array,0,null)}},frame:{allocF32:n=>{let{frameArena:e}=_e(),t=e.allocF32(n);if(!t&&n>>>0)throw new Error(`driver.frame.allocF32(${n}) failed`);return new Ue("frame","f32",t,n,Float32Array,e.epoch(),()=>e.epoch())},allocU32:n=>{let{frameArena:e}=_e(),t=e.alloc((n>>>0)*4,16);if(!t&&n>>>0)throw new Error(`driver.frame.allocU32(${n}) failed`);return new Ue("frame","u32",t,n,Uint32Array,e.epoch(),()=>e.epoch())},allocI32:n=>{let{frameArena:e}=_e(),t=e.alloc((n>>>0)*4,16);if(!t&&n>>>0)throw new Error(`driver.frame.allocI32(${n}) failed`);return new Ue("frame","i32",t,n,Int32Array,e.epoch(),()=>e.epoch())},allocU8:(n,e=16)=>{let{frameArena:t}=_e(),r=t.alloc(n>>>0,e>>>0);if(!r&&n>>>0)throw new Error(`driver.frame.allocU8(${n}) failed`);return new Ue("frame","u8",r,n,Uint8Array,t.epoch(),()=>t.epoch())}}},Qo=null,yr=null,Qr=0,Jo=8*1024*1024,Al=(()=>{if(typeof document>"u")return null;let e=document.currentScript?.src;return e&&e.length>0?e:null})(),Fl=()=>{if(import.meta.url!=="__CURRENT_SCRIPT__")return new URL(".",import.meta.url).toString();let n=Al??location.href;return new URL(".",n).toString()},Nn=async n=>{if(yr)return;let e=n??Fl(),t=new URL("wasm.js",e).toString();Qo??=import(t),yr=await Qo,yr.wasmgpu_frame_arena_init(Jo),Qr=yr.wasmgpu_frame_arena_epoch()>>>0},C=()=>{if(!yr)throw new Error("WebAssembly driver not initialized. Call await initWebAssembly() first.");return yr},Yi=()=>(Qr=C().wasmgpu_frame_arena_epoch()>>>0,Qr),Qe=n=>!!n,_={memory:()=>C().memory,seed:n=>{C().wasmgpu_seed(n>>>0)},allocF32:n=>C().wasmgpu_alloc_f32(n>>>0)>>>0,freeF32:(n,e)=>C().wasmgpu_free_f32(n>>>0,e>>>0),allocU32:n=>C().wasmgpu_alloc_u32(n>>>0)>>>0,freeU32:(n,e)=>C().wasmgpu_free_u32(n>>>0,e>>>0),allocBytes:n=>C().wasmgpu_alloc(n>>>0)>>>0,freeBytes:(n,e)=>C().wasmgpu_free(n>>>0,e>>>0),f32view:(n,e)=>C().f32view(n>>>0,e>>>0),u32view:(n,e)=>C().u32view(n>>>0,e>>>0),i32view:(n,e)=>C().i32view(n>>>0,e>>>0),u8view:(n,e)=>C().u8view(n>>>0,e>>>0),writeF32:(n,e,t)=>{let r=C().f32view(n>>>0,e>>>0),i=Math.min(e>>>0,t?t.length>>>0:0);for(let o=0;o<i;o++)r[o]=t[o];for(let o=i;o<e>>>0;o++)r[o]=0},readF32Array:(n,e)=>Array.from(C().f32view(n>>>0,e>>>0))},W={init:(n=Jo)=>{let e=C().wasmgpu_frame_arena_init(n>>>0)>>>0;if(!e)throw new Error(`wasmgpu_frame_arena_init(${n}) failed`);return Yi(),e},reset:()=>{C().wasmgpu_frame_arena_reset(),Yi()},alloc:(n,e=16)=>{let t=C().wasmgpu_frame_alloc(n>>>0,e>>>0)>>>0;if(!t)throw new Error(`wasmgpu_frame_alloc(${n}, ${e}) failed`);return t},allocF32:n=>{let e=C().wasmgpu_frame_alloc_f32(n>>>0)>>>0;if(!e)throw new Error(`wasmgpu_frame_alloc_f32(${n}) failed`);return e},epoch:()=>(Qr||Yi(),Qr),usedBytes:()=>C().wasmgpu_frame_arena_used()>>>0,capBytes:()=>C().wasmgpu_frame_arena_cap()>>>0};Rl(_,W);var jt={deinterleave:(n,e,t,r,i,o)=>{C().accessor_deinterleave(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0)},applySparse:(n,e,t,r,i,o,a,s)=>{C().accessor_apply_sparse(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a>>>0,s>>>0)},convertToF32:(n,e,t,r,i)=>{C().accessor_convert_to_f32(n>>>0,e>>>0,t>>>0,r>>>0,i?1:0)},convertToU16:(n,e,t,r)=>{C().accessor_convert_to_u16(n>>>0,e>>>0,t>>>0,r>>>0)},convertToU32:(n,e,t,r)=>{C().accessor_convert_to_u32(n>>>0,e>>>0,t>>>0,r>>>0)}},Gt={sampleClipTRS:(n,e,t,r,i,o,a,s,l)=>{C().anim_sample_clip_trs(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a>>>0,s>>>0,l)},computeJointMatricesTo:(n,e,t,r,i,o)=>{C().anim_compute_joint_matrices_to(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0)}},Ht={pointcloudXYZS:(n,e,t,r,i,o,a)=>{C().bounds_pointcloud_xyzs(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a>>>0)},glyphInstances:(n,e,t,r,i,o,a,s,l,u)=>{C().bounds_glyph_instances(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a>>>0,s>>>0,l>>>0,u)},geometryPositions:(n,e,t,r,i,o)=>{C().bounds_geometry_positions(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0)}},We={writePlanesFromViewProjection:(n,e)=>{C().cull_write_planes_from_view_projection(n>>>0,e>>>0)},prepareWorldSpheresFromPtrs:(n,e,t,r,i,o)=>{C().cull_prepare_world_spheres_from_ptrs(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0)},spheresFrustum:(n,e,t,r,i)=>C().cull_spheres_frustum(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)>>>0,spheresOcclusion:(n,e,t,r,i,o,a,s,l,u,c,m,d,f,p,h,g)=>C().cull_spheres_occlusion(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a,s,l>>>0,u>>>0,c>>>0,m>>>0,d>>>0,f>>>0,p,h,g)>>>0},$t={writePlanesFromViewProjection:(n,e)=>{if(typeof e=="number"){C().cull_write_planes_from_view_projection(n>>>0,e>>>0);return}let t=W.allocF32(16);_.writeF32(t,16,e),C().cull_write_planes_from_view_projection(n>>>0,t>>>0)}},ie={alloc:()=>_.allocF32(16),view:n=>_.f32view(n,16),set:(n,e)=>_.writeF32(n,16,e),abs:(n,e)=>{C().mat4_abs(n>>>0,e>>>0)},add:(n,e,t)=>{C().mat4_add(n>>>0,e>>>0,t>>>0)},copy:(n,e)=>{C().mat4_copy(n>>>0,e>>>0)},decomposeTRS:(n,e)=>{C().mat4_decompose_trs(n>>>0,e>>>0)},det:n=>C().mat4_det(n>>>0),identity:n=>{C().mat4_identity(n>>>0)},init:(n,e,t,r,i,o,a,s,l,u,c,m,d,f,p,h,g)=>{C().mat4_init(n>>>0,e,t,r,i,o,a,s,l,u,c,m,d,f,p,h,g)},invert:(n,e)=>{C().mat4_invert(n>>>0,e>>>0)},isEqual:(n,e)=>Qe(C().mat4_isEqual(n>>>0,e>>>0)),isIdentity:n=>Qe(C().mat4_isIdentity(n>>>0)),isInverse:(n,e)=>Qe(C().mat4_isInverse(n>>>0,e>>>0)),isZero:n=>Qe(C().mat4_isZero(n>>>0)),lookAt:(n,e,t,r)=>{C().mat4_lookAt(n>>>0,e>>>0,t>>>0,r>>>0)},mul:(n,e,t)=>{C().mat4_mul(n>>>0,e>>>0,t>>>0)},mulVec4:(n,e,t)=>{C().mat4_mul_vec4(n>>>0,e>>>0,t>>>0)},neg:(n,e)=>{C().mat4_neg(n>>>0,e>>>0)},norm:n=>C().mat4_norm(n>>>0),normalize:(n,e)=>{C().mat4_normalize(n>>>0,e>>>0)},normsq:n=>C().mat4_normsq(n>>>0),perspective:(n,e,t,r,i)=>{C().mat4_perspective(n>>>0,e,t,r,i)},random:n=>{C().mat4_random(n>>>0)},randomRange:(n,e,t)=>{C().mat4_random_range(n>>>0,e,t)},rotateX:(n,e,t)=>{C().mat4_rotateX(n>>>0,e>>>0,t)},rotateY:(n,e,t)=>{C().mat4_rotateY(n>>>0,e>>>0,t)},rotateZ:(n,e,t)=>{C().mat4_rotateZ(n>>>0,e>>>0,t)},round:(n,e)=>{C().mat4_round(n>>>0,e>>>0)},scl:(n,e,t)=>{C().mat4_scl(n>>>0,e>>>0,t)},sub:(n,e,t)=>{C().mat4_sub(n>>>0,e>>>0,t>>>0)},trace:n=>C().mat4_trace(n>>>0),translate:(n,e,t)=>{C().mat4_translate(n>>>0,e>>>0,t>>>0)},transpose:(n,e)=>{C().mat4_transpose(n>>>0,e>>>0)},print:n=>{let e=_.f32view(n,16);console.log(`[ ${e[0]} ${e[1]} ${e[2]} ${e[3]} ]
|
|
2
11
|
[ ${e[4]} ${e[5]} ${e[6]} ${e[7]} ]
|
|
3
12
|
[ ${e[8]} ${e[9]} ${e[10]} ${e[11]} ]
|
|
4
|
-
[ ${e[12]} ${e[13]} ${e[14]} ${e[15]} ]`)}},Li={computeVertexNormals:(n,e,t,r,i)=>{y().mesh_compute_vertex_normals(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)}},jn={numel:(n,e)=>y().ndarray_numel(n>>>0,e>>>0)>>>0,stridesRowMajorTo:(n,e,t,r)=>!!y().ndarray_strides_row_major(n>>>0,e>>>0,t>>>0,r>>>0),offsetBytes:(n,e,t,r,i)=>y().ndarray_offset_bytes(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)>>>0},be={alloc:()=>_.allocF32(4),view:n=>_.f32view(n,4),set:(n,e)=>_.writeF32(n,4,e),abs:(n,e)=>{y().quat_abs(n>>>0,e>>>0)},add:(n,e,t)=>{y().quat_add(n>>>0,e>>>0,t>>>0)},copy:(n,e)=>{y().quat_copy(n>>>0,e>>>0)},dist:(n,e)=>y().quat_dist(n>>>0,e>>>0),distsq:(n,e)=>y().quat_distsq(n>>>0,e>>>0),fromAxisAngle:(n,e,t)=>{y().quat_fromAxisAngle(n>>>0,e>>>0,t)},init:(n,e,t,r,i)=>{y().quat_init(n>>>0,e,t,r,i)},invert:(n,e)=>{y().quat_invert(n>>>0,e>>>0)},isEqual:(n,e)=>Be(y().quat_isEqual(n>>>0,e>>>0)),isNormalized:n=>Be(y().quat_isNormalized(n>>>0)),isZero:n=>Be(y().quat_isZero(n>>>0)),mul:(n,e,t)=>{y().quat_mul(n>>>0,e>>>0,t>>>0)},neg:(n,e)=>{y().quat_neg(n>>>0,e>>>0)},norm:n=>y().quat_norm(n>>>0),normalize:(n,e)=>{y().quat_normalize(n>>>0,e>>>0)},normscl:(n,e,t)=>{y().quat_normscl(n>>>0,e>>>0,t)},normsq:n=>y().quat_normsq(n>>>0),random:n=>{y().quat_random(n>>>0)},randomRange:(n,e,t)=>{y().quat_random_range(n>>>0,e,t)},round:(n,e)=>{y().quat_round(n>>>0,e>>>0)},scl:(n,e,t)=>{y().quat_scl(n>>>0,e>>>0,t)},slerp:(n,e,t,r)=>{y().quat_slerp(n>>>0,e>>>0,t>>>0,r)},sub:(n,e,t)=>{y().quat_sub(n>>>0,e>>>0,t>>>0)},toRotation:(n,e,t)=>{y().quat_toRotation(n>>>0,e>>>0,t>>>0)},print:n=>{let e=_.f32view(n,4);console.log(`[ ${e[0]} ${e[1]} ${e[2]} ${e[3]} ]`)}},Rt={composeLocalMany:(n,e,t,r,i)=>{y().transform_compose_local_many(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)},updateWorldOrdered:(n,e,t,r,i)=>{y().transform_update_world_ordered(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)},updatePartialOrdered:(n,e,t,r,i,o,a,s,l,u)=>{y().transform_update_partial_ordered(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a>>>0,s>>>0,l>>>0,u>>>0)},packModelNormalMat4FromPtrs:(n,e,t)=>{y().transform_pack_model_normal_mat4_from_ptrs(n>>>0,e>>>0,t>>>0)}},Lt={alloc:()=>_.allocF32(4),view3:n=>_.f32view(n,3),view4:n=>_.f32view(n,4),set3:(n,e)=>_.writeF32(n,3,e),abs:(n,e)=>{y().vec3_abs(n>>>0,e>>>0)},add:(n,e,t)=>{y().vec3_add(n>>>0,e>>>0,t>>>0)},ang:(n,e)=>{y().vec3_ang(n>>>0,e>>>0)},angBetween:(n,e)=>y().vec3_angBetween(n>>>0,e>>>0),copy:(n,e)=>{y().vec3_copy(n>>>0,e>>>0)},cross:(n,e,t)=>{y().vec3_cross(n>>>0,e>>>0,t>>>0)},dist:(n,e)=>y().vec3_dist(n>>>0,e>>>0),distsq:(n,e)=>y().vec3_distsq(n>>>0,e>>>0),dot:(n,e)=>y().vec3_dot(n>>>0,e>>>0),init:(n,e,t,r)=>{y().vec3_init(n>>>0,e,t,r)},interp:(n,e,t,r,i)=>{y().vec3_interp(n>>>0,e>>>0,t,r,i)},isEqual:(n,e)=>Be(y().vec3_isEqual(n>>>0,e>>>0)),isNormalized:n=>Be(y().vec3_isNormalized(n>>>0)),isOrthogonal:(n,e)=>Be(y().vec3_isOrthogonal(n>>>0,e>>>0)),isParallel:(n,e)=>Be(y().vec3_isParallel(n>>>0,e>>>0)),isZero:n=>Be(y().vec3_isZero(n>>>0)),neg:(n,e)=>{y().vec3_neg(n>>>0,e>>>0)},norm:n=>y().vec3_norm(n>>>0),normalize:(n,e)=>{y().vec3_normalize(n>>>0,e>>>0)},normscl:(n,e,t)=>{y().vec3_normscl(n>>>0,e>>>0,t)},normsq:n=>y().vec3_normsq(n>>>0),oproj:(n,e,t)=>{y().vec3_oproj(n>>>0,e>>>0,t>>>0)},proj:(n,e,t)=>{y().vec3_proj(n>>>0,e>>>0,t>>>0)},random:n=>{y().vec3_random(n>>>0)},randomRange:(n,e,t)=>{y().vec3_random_range(n>>>0,e,t)},reflect:(n,e,t)=>{y().vec3_reflect(n>>>0,e>>>0,t>>>0)},refract:(n,e,t,r)=>{y().vec3_refract(n>>>0,e>>>0,t>>>0,r)},round:(n,e)=>{y().vec3_round(n>>>0,e>>>0)},scl:(n,e,t)=>{y().vec3_scl(n>>>0,e>>>0,t)},sub:(n,e,t)=>{y().vec3_sub(n>>>0,e>>>0,t>>>0)},print:n=>{let e=_.f32view(n,3);console.log(`[ ${e[0]} ${e[1]} ${e[2]} ]`)}},ze={abs:n=>y().mat4abs(n),add:(n,e)=>y().mat4add(n,e),copy:n=>y().mat4copy(n),det:n=>y().mat4det(n),identity:()=>y().mat4identity(),init:(n,e,t,r,i,o,a,s,l,u,m,c,d,f,p,b)=>y().mat4init(n,e,t,r,i,o,a,s,l,u,m,c,d,f,p,b),invert:n=>y().mat4invert(n),isEqual:(n,e)=>y().mat4isEqual(n,e),isIdentity:n=>y().mat4isIdentity(n),isInverse:(n,e)=>y().mat4isInverse(n,e),isZero:n=>y().mat4isZero(n),lookAt:(n,e,t)=>y().mat4lookAt(n,e,t),mul:(n,e)=>y().mat4mul(n,e),neg:n=>y().mat4neg(n),norm:n=>y().mat4norm(n),normalize:n=>y().mat4normalize(n),normsq:n=>y().mat4normsq(n),perspective:(n,e,t,r)=>y().mat4perspective(n,e,t,r),print:n=>y().mat4print(n),random:(n,e)=>y().mat4random(n,e),rotateX:(n,e)=>y().mat4rotateX(n,e),rotateY:(n,e)=>y().mat4rotateY(n,e),rotateZ:(n,e)=>y().mat4rotateZ(n,e),round:n=>y().mat4round(n),scl:(n,e)=>y().mat4scl(n,e),sub:(n,e)=>y().mat4sub(n,e),trace:n=>y().mat4trace(n),translate:(n,e)=>y().mat4translate(n,e),transpose:n=>y().mat4transpose(n)},Kr={abs:n=>y().quatabs(n),add:(n,e)=>y().quatadd(n,e),copy:n=>y().quatcopy(n),dist:(n,e)=>y().quatdist(n,e),distsq:(n,e)=>y().quatdistsq(n,e),fromAxisAngle:(n,e)=>y().quatfromAxisAngle(n,e),init:(n,e,t,r)=>y().quatinit(n,e,t,r),invert:n=>y().quatinvert(n),isEqual:(n,e)=>y().quatisEqual(n,e),isNormalized:n=>y().quatisNormalized(n),isZero:n=>y().quatisZero(n),mul:(n,e)=>y().quatmul(n,e),neg:n=>y().quatneg(n),norm:n=>y().quatnorm(n),normalize:n=>y().quatnormalize(n),normscl:(n,e)=>y().quatnormscl(n,e),normsq:n=>y().quatnormsq(n),print:n=>y().quatprint(n),random:(n,e)=>y().quatrandom(n,e),round:n=>y().quatround(n),scl:(n,e)=>y().quatscl(n,e),slerp:(n,e,t)=>y().quatslerp(n,e,t),sub:(n,e)=>y().quatsub(n,e),toRotation:(n,e)=>y().quattoRotation(n,e)},Ge={abs:n=>y().vec3abs(n),add:(n,e)=>y().vec3add(n,e),ang:n=>y().vec3ang(n),angBetween:(n,e)=>y().vec3angBetween(n,e),copy:n=>y().vec3copy(n),cross:(n,e)=>y().vec3cross(n,e),dist:(n,e)=>y().vec3dist(n,e),distsq:(n,e)=>y().vec3distsq(n,e),dot:(n,e)=>y().vec3dot(n,e),init:(n,e,t)=>y().vec3init(n,e,t),interp:(n,e,t,r)=>y().vec3interp(n,e,t,r),isEqual:(n,e)=>y().vec3isEqual(n,e),isNormalized:n=>y().vec3isNormalized(n),isOrthogonal:(n,e)=>y().vec3isOrthogonal(n,e),isParallel:(n,e)=>y().vec3isParallel(n,e),isZero:n=>y().vec3isZero(n),neg:n=>y().vec3neg(n),norm:n=>y().vec3norm(n),normalize:n=>y().vec3normalize(n),normscl:(n,e)=>y().vec3normscl(n,e),normsq:n=>y().vec3normsq(n),oproj:(n,e)=>y().vec3oproj(n,e),print:n=>y().vec3print(n),proj:(n,e)=>y().vec3proj(n,e),random:(n,e)=>y().vec3random(n,e),reflect:(n,e)=>y().vec3reflect(n,e),refract:(n,e,t)=>y().vec3refract(n,e,t),round:n=>y().vec3round(n),scl:(n,e)=>y().vec3scl(n,e),sub:(n,e)=>y().vec3sub(n,e)};var fr=4294967295,N=class n{static _global=null;static global(){return n._global||(n._global=new n(16384)),n._global}cap;count=0;posPtr=0;rotPtr=0;sclPtr=0;localPtr=0;worldPtr=0;parentPtr=0;orderPtr=0;tmpAxisPtr=0;tmpQuatPtr=0;dirtyIndicesPtr=0;dirtyIndicesCap=0;_buf=null;_f32=null;_u32=null;_dirty=!0;_orderDirty=!0;_dirtyAll=!0;_dirtyList=[];_dirtyMark=new Uint8Array(0);_nodes=[];_freeList=[];_visited=new Uint8Array(0);_stack=[];constructor(e){this.cap=Math.max(1,e|0),this.allocateArrays(this.cap)}allocateArrays(e){this.posPtr=_.allocF32(e*3),this.rotPtr=_.allocF32(e*4),this.sclPtr=_.allocF32(e*3),this.localPtr=_.allocF32(e*16),this.worldPtr=_.allocF32(e*16),this.parentPtr=_.allocU32(e),this.orderPtr=_.allocU32(e),this.tmpAxisPtr=_.allocF32(4),this.tmpQuatPtr=_.allocF32(4),this.ensureViews();let t=this.u32(),r=this.parentPtr>>>2;for(let i=0;i<e;i++)t[r+i]=fr}ensureViews(){let e=_.memory().buffer;this._buf!==e&&(this._buf=e,this._f32=new Float32Array(e),this._u32=new Uint32Array(e))}f32(){return this.ensureViews(),this._f32}u32(){return this.ensureViews(),this._u32}ensureDirtyMarkCapacity(){if(this._dirtyMark.length>=this.cap)return;let e=new Uint8Array(this.cap);for(let t=0;t<this._dirtyList.length;t++)e[this._dirtyList[t]]=1;this._dirtyMark=e}ensureDirtyIndexCapacity(e){if(this.dirtyIndicesCap>=e)return;let t=Math.max(1,this.dirtyIndicesCap|0);for(;t<e;)t*=2;this.dirtyIndicesPtr=_.allocU32(t),this.dirtyIndicesCap=t}clearDirtyList(){for(let e=0;e<this._dirtyList.length;e++)this._dirtyMark[this._dirtyList[e]]=0;this._dirtyList.length=0}markDirty(){this._dirty=!0,this._dirtyAll=!0,this.clearDirtyList()}markOrderDirty(){this._orderDirty=!0,this._dirty=!0,this._dirtyAll=!0,this.clearDirtyList()}markIndexDirty(e){e<0||e>=this.count||(this._dirty=!0,!this._dirtyAll&&(this.ensureDirtyMarkCapacity(),!this._dirtyMark[e]&&(this._dirtyMark[e]=1,this._dirtyList.push(e))))}alloc(e){let t;if(this._freeList.length>0){if(t=this._freeList.pop(),t<0)throw new Error("TransformStore.alloc: corrupted free list (negative index).");if(t>=this.count&&(this.count=t+1),this._nodes[t]!==null&&this._nodes[t]!==void 0)throw new Error(`TransformStore.alloc: free list returned an in-use slot ${t}.`)}else this.count>=this.cap&&this.growTo(this.cap*2),t=this.count++;return this._nodes[t]=e,this.initDefaults(t),this._orderDirty=!0,this._dirty=!0,this._dirtyAll=!0,t}initDefaults(e){this.ensureViews();let t=this.f32(),r=this.u32(),i=(this.posPtr>>>2)+e*3;t[i+0]=0,t[i+1]=0,t[i+2]=0;let o=(this.rotPtr>>>2)+e*4;t[o+0]=0,t[o+1]=0,t[o+2]=0,t[o+3]=1;let a=(this.sclPtr>>>2)+e*3;t[a+0]=1,t[a+1]=1,t[a+2]=1,r[(this.parentPtr>>>2)+e]=fr}setParent(e,t){this.ensureViews();let r=this.u32();r[(this.parentPtr>>>2)+e]=t===null?fr:t>>>0,this._orderDirty=!0,this._dirty=!0,this._dirtyAll=!0}free(e){if(e<0||e>=this.count)throw new Error(`TransformStore.free: index out of range: ${e} (count=${this.count})`);if(!this._nodes[e])throw new Error(`TransformStore.free: double free or invalid slot: ${e}`);this._nodes[e]=null,this.ensureViews();let r=this.f32(),i=this.u32(),o=(this.posPtr>>>2)+e*3;r[o+0]=0,r[o+1]=0,r[o+2]=0;let a=(this.rotPtr>>>2)+e*4;r[a+0]=0,r[a+1]=0,r[a+2]=0,r[a+3]=1;let s=(this.sclPtr>>>2)+e*3;r[s+0]=1,r[s+1]=1,r[s+2]=1,i[(this.parentPtr>>>2)+e]=fr;let l=(this.localPtr>>>2)+e*16,u=(this.worldPtr>>>2)+e*16;for(let m=0;m<16;m++)r[l+m]=0,r[u+m]=0;for(r[l+0]=1,r[l+5]=1,r[l+10]=1,r[l+15]=1,r[u+0]=1,r[u+5]=1,r[u+10]=1,r[u+15]=1,this._freeList.push(e),this._orderDirty=!0,this._dirty=!0,this._dirtyAll=!0;this.count>0;){let m=this.count-1;if(this._nodes[m])break;this.count--}}updateIfNeeded(){this._dirty&&this.update()}update(){let e=this.count|0;if(e===0){this._dirty=!1,this._dirtyAll=!1,this._orderDirty=!1,this.clearDirtyList();return}this.ensureDirtyMarkCapacity();let t=this._dirtyAll?e:this._dirtyList.length|0;if(this._orderDirty||this._dirtyAll||t>e>>>2){this._orderDirty&&this.buildOrder(),Rt.composeLocalMany(this.localPtr,this.posPtr,this.rotPtr,this.sclPtr,e),Rt.updateWorldOrdered(this.worldPtr,this.localPtr,this.parentPtr,this.orderPtr,e),this._dirty=!1,this._dirtyAll=!1,this._orderDirty=!1,this.clearDirtyList();return}if(this._dirtyList.length===0){this._dirty=!1;return}this.ensureViews(),this.ensureDirtyIndexCapacity(this._dirtyList.length);let i=this.u32().subarray(this.dirtyIndicesPtr>>>2,(this.dirtyIndicesPtr>>>2)+this._dirtyList.length);for(let o=0;o<this._dirtyList.length;o++)i[o]=this._dirtyList[o]>>>0;Rt.updatePartialOrdered(this.worldPtr,this.localPtr,this.posPtr,this.rotPtr,this.sclPtr,this.parentPtr,this.orderPtr,this.dirtyIndicesPtr,this._dirtyList.length,e),this._dirty=!1,this.clearDirtyList()}buildOrder(){let e=this.count;this._visited.length<e&&(this._visited=new Uint8Array(e)),this._visited.fill(0,0,e);let t=this.u32(),r=this.parentPtr>>>2,i=this.orderPtr>>>2,o=0,a=this._stack;a.length=0;for(let s=0;s<e;s++)if(!this._visited[s]&&t[r+s]===fr)for(a.push(s);a.length;){let l=a.pop();if(this._visited[l])continue;this._visited[l]=1,t[i+o++]=l>>>0;let m=this._nodes[l]?.children??[];for(let c=m.length-1;c>=0;c--)a.push(m[c].index)}for(let s=0;s<e;s++)this._visited[s]||(this._visited[s]=1,t[i+o++]=s>>>0);this._orderDirty=!1}growTo(e){let t=this.cap;for(;t<e;)t*=2;let r=this.count,i=this.posPtr,o=this.rotPtr,a=this.sclPtr,s=this.localPtr,l=this.worldPtr,u=this.parentPtr,m=this.orderPtr;this.cap=t,this.allocateArrays(t),this.ensureViews();let c=this.f32(),d=this.u32();c.set(c.subarray(i>>>2,(i>>>2)+r*3),this.posPtr>>>2),c.set(c.subarray(o>>>2,(o>>>2)+r*4),this.rotPtr>>>2),c.set(c.subarray(a>>>2,(a>>>2)+r*3),this.sclPtr>>>2),c.set(c.subarray(s>>>2,(s>>>2)+r*16),this.localPtr>>>2),c.set(c.subarray(l>>>2,(l>>>2)+r*16),this.worldPtr>>>2),d.set(d.subarray(u>>>2,(u>>>2)+r),this.parentPtr>>>2),d.set(d.subarray(m>>>2,(m>>>2)+r),this.orderPtr>>>2),this._orderDirty=!0,this._dirty=!0,this._dirtyAll=!0}},pe=class n{index;_parent=null;_children=[];_position=[0,0,0];_rotation=[0,0,0,1];_scale=[1,1,1];_localMatrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];_worldMatrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];_disposed=!1;constructor(){let e=N.global();this.index=e.alloc(this)}static updateAll(){N.global().updateIfNeeded()}assertAlive(){if(this._disposed)throw new Error("Transform is disposed (use-after-dispose).")}get disposed(){return this._disposed}get parent(){return this._parent}get children(){return this._children}get root(){let e=this;for(;e._parent;)e=e._parent;return e}traverse(e){e(this);for(let t of this._children)t.traverse(e)}readVec3FromStore(e,t){let i=N.global().f32();t[0]=i[e+0],t[1]=i[e+1],t[2]=i[e+2]}readQuatFromStore(e,t){let i=N.global().f32();t[0]=i[e+0],t[1]=i[e+1],t[2]=i[e+2],t[3]=i[e+3]}readMat4FromStore(e,t){let i=N.global().f32();for(let o=0;o<16;o++)t[o]=i[e+o]}get positionPtr(){return this.assertAlive(),N.global().posPtr+this.index*3*4>>>0}get rotationPtr(){return this.assertAlive(),N.global().rotPtr+this.index*4*4>>>0}get scalePtr(){return this.assertAlive(),N.global().sclPtr+this.index*3*4>>>0}get localMatrixPtr(){return this.assertAlive(),N.global().localPtr+this.index*16*4>>>0}get worldMatrixPtr(){return this.assertAlive(),N.global().worldPtr+this.index*16*4>>>0}get position(){return this._position}setPosition(e,t,r){this.assertAlive();let i=N.global(),o=i.f32(),a=(i.posPtr>>>2)+this.index*3;return o[a+0]=e,o[a+1]=t,o[a+2]=r,this._position[0]=e,this._position[1]=t,this._position[2]=r,i.markIndexDirty(this.index),this}translate(e,t,r){return this.assertAlive(),this.setPosition(this._position[0]+e,this._position[1]+t,this._position[2]+r)}get rotation(){return this._rotation}setRotation(e,t,r,i){this.assertAlive();let o=N.global(),a=this.rotationPtr;be.init(a,e,t,r,i),be.normalize(a,a);let s=(o.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(s,this._rotation),o.markIndexDirty(this.index),this}setRotationFromAxisAngle(e,t){this.assertAlive();let r=N.global(),i=r.f32(),o=r.tmpAxisPtr>>>2;i[o+0]=e[0],i[o+1]=e[1],i[o+2]=e[2],Lt.normalize(r.tmpAxisPtr,r.tmpAxisPtr);let a=this.rotationPtr;be.fromAxisAngle(a,r.tmpAxisPtr,t),be.normalize(a,a);let s=(r.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(s,this._rotation),r.markIndexDirty(this.index),this}setRotationFromEuler(e,t,r){this.assertAlive();let i=e*.5,o=t*.5,a=r*.5,s=Math.sin(i),l=Math.cos(i),u=Math.sin(o),m=Math.cos(o),c=Math.sin(a),d=Math.cos(a),f=s*m*d+l*u*c,p=l*u*d-s*m*c,b=l*m*c+s*u*d,g=l*m*d-s*u*c;return this.setRotation(f,p,b,g)}rotateOnAxis(e,t){this.assertAlive();let r=N.global(),i=r.f32(),o=r.tmpAxisPtr>>>2;i[o+0]=e[0],i[o+1]=e[1],i[o+2]=e[2],Lt.normalize(r.tmpAxisPtr,r.tmpAxisPtr),be.fromAxisAngle(r.tmpQuatPtr,r.tmpAxisPtr,t);let a=this.rotationPtr;be.mul(a,a,r.tmpQuatPtr),be.normalize(a,a);let s=(r.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(s,this._rotation),r.markIndexDirty(this.index),this}rotateX(e){this.assertAlive();let t=N.global(),r=t.f32(),i=t.tmpAxisPtr>>>2;r[i+0]=1,r[i+1]=0,r[i+2]=0,Lt.normalize(t.tmpAxisPtr,t.tmpAxisPtr),be.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;be.mul(o,o,t.tmpQuatPtr),be.normalize(o,o);let a=(t.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(a,this._rotation),t.markIndexDirty(this.index),this}rotateY(e){this.assertAlive();let t=N.global(),r=t.f32(),i=t.tmpAxisPtr>>>2;r[i+0]=0,r[i+1]=1,r[i+2]=0,Lt.normalize(t.tmpAxisPtr,t.tmpAxisPtr),be.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;be.mul(o,o,t.tmpQuatPtr),be.normalize(o,o);let a=(t.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(a,this._rotation),t.markIndexDirty(this.index),this}rotateZ(e){this.assertAlive();let t=N.global(),r=t.f32(),i=t.tmpAxisPtr>>>2;r[i+0]=0,r[i+1]=0,r[i+2]=1,Lt.normalize(t.tmpAxisPtr,t.tmpAxisPtr),be.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;be.mul(o,o,t.tmpQuatPtr),be.normalize(o,o);let a=(t.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(a,this._rotation),t.markIndexDirty(this.index),this}get scale(){return this._scale}setScale(e,t,r){this.assertAlive();let i=N.global(),o=i.f32(),a=(i.sclPtr>>>2)+this.index*3;return o[a+0]=e,o[a+1]=t,o[a+2]=r,this._scale[0]=e,this._scale[1]=t,this._scale[2]=r,i.markIndexDirty(this.index),this}setUniformScale(e){return this.assertAlive(),this.setScale(e,e,e)}get localMatrix(){this.assertAlive();let e=N.global();e.updateIfNeeded();let t=(e.localPtr>>>2)+this.index*16;return this.readMat4FromStore(t,this._localMatrix),this._localMatrix}get worldMatrix(){this.assertAlive();let e=N.global();e.updateIfNeeded();let t=(e.worldPtr>>>2)+this.index*16;return this.readMat4FromStore(t,this._worldMatrix),this._worldMatrix}get worldPosition(){this.assertAlive();let e=N.global();e.updateIfNeeded();let t=(e.worldPtr>>>2)+this.index*16,r=e.f32();return[r[t+12],r[t+13],r[t+14]]}setParent(e){if(this.assertAlive(),e===this._parent)return this;if(e===this)throw new Error("Transform cannot be parented to itself.");for(let t=e;t;t=t._parent)if(t===this)throw new Error("Transform parenting would create a cycle.");return this.removeFromParent(),this._parent=e,e?(e._children.push(this),N.global().setParent(this.index,e.index)):N.global().setParent(this.index,null),this}addChild(e){return this.assertAlive(),e.setParent(this),this}removeChild(e){return this.assertAlive(),e._parent!==this?this:(e.setParent(null),this)}removeFromParent(){if(this.assertAlive(),!this._parent)return this;let e=this._parent,t=e._children.indexOf(this);return t>=0&&e._children.splice(t,1),this._parent=null,N.global().setParent(this.index,null),this}reset(){return this.assertAlive(),this._parent=null,this._children.length=0,N.global().setParent(this.index,null),this.setPosition(0,0,0),this.setRotation(0,0,0,1),this.setScale(1,1,1),this}copyFrom(e){return this.assertAlive(),this.setPosition(e._position[0],e._position[1],e._position[2]),this.setRotation(e._rotation[0],e._rotation[1],e._rotation[2],e._rotation[3]),this.setScale(e._scale[0],e._scale[1],e._scale[2]),this}clone(){this.assertAlive();let e=new n;return e.copyFrom(this),e}dispose(){if(this._disposed)return;let e=this._children.slice();for(let t of e)t.setParent(null);this._children.length=0,this.removeFromParent(),N.global().free(this.index),this._disposed=!0}};var He=n=>[n[0]??0,n[1]??0,n[2]??0],ut=(n=!1)=>({boxMin:[0,0,0],boxMax:[0,0,0],sphereCenter:[0,0,0],sphereRadius:0,empty:!0,partial:n}),hr=n=>({boxMin:He(n.boxMin),boxMax:He(n.boxMax),sphereCenter:He(n.sphereCenter),sphereRadius:n.sphereRadius,empty:n.empty,partial:n.partial}),qe=(n,e,t=!1)=>{let r=He(n),i=He(e),o=(r[0]+i[0])*.5,a=(r[1]+i[1])*.5,s=(r[2]+i[2])*.5,l=i[0]-o,u=i[1]-a,m=i[2]-s;return{boxMin:r,boxMax:i,sphereCenter:[o,a,s],sphereRadius:Math.sqrt(l*l+u*u+m*m),empty:!1,partial:t}},ct=(n,e,t=!1)=>{let r=He(n),i=Math.max(0,e);return{boxMin:[r[0]-i,r[1]-i,r[2]-i],boxMax:[r[0]+i,r[1]+i,r[2]+i],sphereCenter:r,sphereRadius:i,empty:!1,partial:t}},mt=(n,e,t,r,i=!1)=>({boxMin:He(n),boxMax:He(e),sphereCenter:He(t),sphereRadius:Math.max(0,r),empty:!1,partial:i}),$n=n=>"getBounds"in n&&typeof n.getBounds=="function"?n.getBounds():n,Hn=(n,e)=>{if(n.empty){let t=hr(e);return t.partial=n.partial||e.partial,t}if(e.empty){let t=hr(n);return t.partial=n.partial||e.partial,t}return qe([Math.min(n.boxMin[0],e.boxMin[0]),Math.min(n.boxMin[1],e.boxMin[1]),Math.min(n.boxMin[2],e.boxMin[2])],[Math.max(n.boxMax[0],e.boxMax[0]),Math.max(n.boxMax[1],e.boxMax[1]),Math.max(n.boxMax[2],e.boxMax[2])],n.partial||e.partial)},Xr=n=>n.empty?[0,0,0]:[(n.boxMin[0]+n.boxMax[0])*.5,(n.boxMin[1]+n.boxMax[1])*.5,(n.boxMin[2]+n.boxMax[2])*.5],ka=n=>n.empty?[0,0,0]:[n.boxMax[0]-n.boxMin[0],n.boxMax[1]-n.boxMin[1],n.boxMax[2]-n.boxMin[2]],qn=(n,e)=>{if(n.empty)return hr(n);let t=Math.max(1,e),r=Xr(n),i=(n.boxMax[0]-n.boxMin[0])*.5*t,o=(n.boxMax[1]-n.boxMin[1])*.5*t,a=(n.boxMax[2]-n.boxMin[2])*.5*t;return qe([r[0]-i,r[1]-o,r[2]-a],[r[0]+i,r[1]+o,r[2]+a],n.partial)},Yr=n=>{if(n.empty)return[];let e=n.boxMin,t=n.boxMax;return[[e[0],e[1],e[2]],[t[0],e[1],e[2]],[e[0],t[1],e[2]],[t[0],t[1],e[2]],[e[0],e[1],t[2]],[t[0],e[1],t[2]],[e[0],t[1],t[2]],[t[0],t[1],t[2]]]},dt=(n,e)=>{if(n.empty)return hr(n);let t=(n.boxMin[0]+n.boxMax[0])*.5,r=(n.boxMin[1]+n.boxMax[1])*.5,i=(n.boxMin[2]+n.boxMax[2])*.5,o=(n.boxMax[0]-n.boxMin[0])*.5,a=(n.boxMax[1]-n.boxMin[1])*.5,s=(n.boxMax[2]-n.boxMin[2])*.5,l=e[0]*t+e[4]*r+e[8]*i+e[12],u=e[1]*t+e[5]*r+e[9]*i+e[13],m=e[2]*t+e[6]*r+e[10]*i+e[14],c=Math.abs(e[0])*o+Math.abs(e[4])*a+Math.abs(e[8])*s,d=Math.abs(e[1])*o+Math.abs(e[5])*a+Math.abs(e[9])*s,f=Math.abs(e[2])*o+Math.abs(e[6])*a+Math.abs(e[10])*s,p=Math.hypot(e[0],e[1],e[2]),b=Math.hypot(e[4],e[5],e[6]),g=Math.hypot(e[8],e[9],e[10]),x=Math.max(p,b,g),M=e[0]*n.sphereCenter[0]+e[4]*n.sphereCenter[1]+e[8]*n.sphereCenter[2]+e[12],h=e[1]*n.sphereCenter[0]+e[5]*n.sphereCenter[1]+e[9]*n.sphereCenter[2]+e[13],w=e[2]*n.sphereCenter[0]+e[6]*n.sphereCenter[1]+e[10]*n.sphereCenter[2]+e[14];return mt([l-c,u-d,m-f],[l+c,u+d,m+f],[M,h,w],n.sphereRadius*x,n.partial)};var Me=class n{geometry;material;transform;_visible=!0;_castShadow=!0;_receiveShadow=!0;name="";userData={};skin=null;constructor(e,t){this.geometry=e,this.material=t,this.transform=new pe}get visible(){return this._visible}set visible(e){this._visible=e}get castShadow(){return this._castShadow}set castShadow(e){this._castShadow=e}get receiveShadow(){return this._receiveShadow}set receiveShadow(e){this._receiveShadow=e}setParent(e){return this.transform.setParent(e?.transform??null),this}addChild(e){return this.transform.addChild(e.transform),this}removeChild(e){return this.transform.removeChild(e.transform),this}get worldMatrix(){return this.transform.worldMatrix}getLocalBounds(){return mt(this.geometry.boundsMin,this.geometry.boundsMax,this.geometry.boundsCenter,this.geometry.boundsRadius)}getWorldBounds(){return dt(this.getLocalBounds(),this.transform.worldMatrix)}getBounds(){return this.getWorldBounds()}destroy(){this.skin?.dispose(),this.skin=null,this.transform.dispose(),this.geometry.destroy(),this.material.destroy()}clone(){let e=new n(this.geometry,this.material);return e.transform.copyFrom(this.transform),e.name=this.name,e.visible=this.visible,e.castShadow=this.castShadow,e.receiveShadow=this.receiveShadow,e}cloneWithMaterial(e){let t=new n(this.geometry,e);return t.transform.copyFrom(this.transform),t.name=this.name,t.visible=this.visible,t.castShadow=this.castShadow,t.receiveShadow=this.receiveShadow,t}};var P=(n,e)=>{if(!n)throw new Error(e)},le=(n,e)=>Math.ceil(n/e)*e,ve=(n,e,t)=>{let r=n.createBuffer({size:le(e.byteLength,4),usage:t,mappedAtCreation:!0});return new Uint8Array(r.getMappedRange()).set(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),r.unmap(),r},Kn=(n,e,t,r=1)=>n.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:"depth24plus",sampleCount:r,usage:GPUTextureUsage.RENDER_ATTACHMENT});var pt=256,Fi={grayscale:"AAAA/wEBAf8CAgL/AwMD/wQEBP8FBQX/BgYG/wcHB/8ICAj/CQkJ/woKCv8LCwv/DAwM/w0NDf8ODg7/Dw8P/xAQEP8RERH/EhIS/xMTE/8UFBT/FRUV/xYWFv8XFxf/GBgY/xkZGf8aGhr/Gxsb/xwcHP8dHR3/Hh4e/x8fH/8gICD/ICAg/yIiIv8jIyP/JCQk/yQkJP8mJib/Jycn/ygoKP8oKCj/Kioq/ysrK/8sLCz/LCws/y4uLv8vLy//MDAw/zAwMP8yMjL/MzMz/zQ0NP80NDT/NjY2/zc3N/84ODj/ODg4/zo6Ov87Ozv/PDw8/zw8PP8+Pj7/Pz8//0BAQP9BQUH/QUFB/0NDQ/9ERET/RUVF/0ZGRv9HR0f/SEhI/0lJSf9JSUn/S0tL/0xMTP9NTU3/Tk5O/09PT/9QUFD/UVFR/1FRUf9TU1P/VFRU/1VVVf9WVlb/V1dX/1hYWP9ZWVn/WVlZ/1tbW/9cXFz/XV1d/15eXv9fX1//YGBg/2FhYf9hYWH/Y2Nj/2RkZP9lZWX/ZmZm/2dnZ/9oaGj/aWlp/2lpaf9ra2v/bGxs/21tbf9ubm7/b29v/3BwcP9xcXH/cXFx/3Nzc/90dHT/dXV1/3Z2dv93d3f/eHh4/3l5ef95eXn/e3t7/3x8fP99fX3/fn5+/39/f/+AgID/gYGB/4KCgv+Dg4P/g4OD/4WFhf+Ghob/h4eH/4iIiP+JiYn/ioqK/4uLi/+MjIz/jY2N/46Ojv+Pj4//kJCQ/5GRkf+SkpL/k5OT/5OTk/+VlZX/lpaW/5eXl/+YmJj/mZmZ/5qamv+bm5v/nJyc/52dnf+enp7/n5+f/6CgoP+hoaH/oqKi/6Ojo/+jo6P/paWl/6ampv+np6f/qKio/6mpqf+qqqr/q6ur/6ysrP+tra3/rq6u/6+vr/+wsLD/sbGx/7Kysv+zs7P/s7Oz/7W1tf+2trb/t7e3/7i4uP+5ubn/urq6/7u7u/+8vLz/vb29/76+vv+/v7//wMDA/8HBwf/CwsL/w8PD/8PDw//FxcX/xsbG/8fHx//IyMj/ycnJ/8rKyv/Ly8v/zMzM/83Nzf/Ozs7/z8/P/9DQ0P/R0dH/0tLS/9PT0//T09P/1dXV/9bW1v/X19f/2NjY/9nZ2f/a2tr/29vb/9zc3P/d3d3/3t7e/9/f3//g4OD/4eHh/+Li4v/j4+P/4+Pj/+Xl5f/m5ub/5+fn/+jo6P/p6en/6urq/+vr6//s7Oz/7e3t/+7u7v/v7+//8PDw//Hx8f/y8vL/8/Pz//Pz8//19fX/9vb2//f39//4+Pj/+fn5//r6+v/7+/v//Pz8//39/f/+/v7//////w==",turbo:"MBI7/zEVQv8yGEr/NBtR/zUeWP82IV//NyNl/zgmbP85KXL/Oix5/zsvf/88MoX/PDWL/z03kf8+Opb/Pz2c/0BAof9AQ6b/QUWr/0FIsP9CS7X/Q066/0NQvv9DU8L/RFbH/0RYy/9FW87/RV7S/0Vg1v9FY9n/Rmbd/0Zo4P9Ga+P/Rm3m/0Zw6P9Gc+v/RnXt/0Z48P9GevL/Rn30/0Z/9v9Ggvj/RYT5/0WH+/9Fifz/RIz9/0OO/f9Ckf7/QZP+/0CW/v8/mP7/Ppv+/zyd/f87oPz/OaL8/zil+/82qPn/NKr4/zOs9v8xr/X/L7Hz/y208f8rtu//Krnt/yi76/8mven/JcDm/yPC5P8hxOH/IMbf/x7J3P8dy9r/HM3X/xvP1P8a0dL/GdPP/xjVzP8Y18r/F9nH/xfaxP8X3ML/F96//xjgvf8Y4br/GeO4/xrktv8b5bT/Heex/x7or/8g6az/Iuup/yTspv8n7aP/Ke6g/yzvnf8v8Jr/MvGX/zXzlP849JH/O/SN/z/1iv9C9of/RveD/0r4gP9N+Xz/Ufl5/1X6dv9Z+3L/Xftv/2H8bP9l/Gj/af1l/239Yv9x/V//dP5c/3j+Wf98/lb/gP5T/4T+UP+H/k3/i/5L/47+SP+S/kb/lf5E/5j+Qv+b/UD/nv0+/6H8Pf+k/Dv/pvs6/6n7Of+s+jf/rvk3/7H4Nv+z+DX/tvc1/7n1NP+79DT/vvM0/8DyM//D8TP/xe8z/8juM//K7TP/zes0/8/qNP/R6DT/1Oc1/9blNf/Y4zX/2uI2/93gNv/f3jb/4dw3/+PaN//l2Dj/59c4/+jVOP/q0zn/7NE5/+3POf/vzTn/8Ms6//LIOv/zxjr/9MQ6//bCOv/3wDn/+L45//m8Of/5ujj/+rc3//u1N//7szb//LA1//yuNP/9qzP//aky//2mMf/9ozD//qEv//6eLv/+my3//pgs//2VK//9kin//Y8o//2MJ//8iSb//IYk//uDI//7gCL/+n0g//p6H//5dx7/+HQc//dxG//3bhr/9msY//VoF//0ZRb/82MV//JgFP/xXRP/71oR/+5YEP/tVQ//7FIO/+pQDf/pTQ3/6EsM/+ZJC//lRgr/40QK/+JCCf/gQAj/3j4I/908B//bOgf/2TgG/9c2Bv/WNAX/1DIF/9IwBf/QLwT/zi0E/8srA//JKQP/xygD/8UmAv/DJAL/wCMC/74hAv+7HwH/uR4B/7YcAf+0GwH/sRkB/64YAf+sFgH/qRUB/6YUAf+jEgH/oBEB/50QAf+aDgH/lw0B/5QMAf+RCwH/jgoB/4sJAf+HCAH/hAcB/4EGAv99BQL/egQC/w==",viridis:"RAFU/0QCVf9EA1f/RQVY/0UGWv9FCFv/Rglc/0YLXv9GDF//Rg5h/0cPYv9HEWP/RxJl/0cUZv9HFWf/RxZp/0cYav9IGWv/SBps/0gcbv9IHW//SB5w/0ggcf9IIXL/SCJz/0gjdP9HJXX/RyZ2/0cnd/9HKHj/Ryp5/0crev9HLHv/Ri18/0YvfP9GMH3/RjF+/0Uyf/9FNH//RTWA/0U2gf9EN4H/RDmC/0M6g/9DO4P/QzyE/0I9hP9CPoX/QkCF/0FBhv9BQob/QEOH/0BEh/8/RYf/P0eI/z5IiP8+SYn/PUqJ/z1Lif89TIn/PE2K/zxOiv87UIr/O1GK/zpSi/86U4v/OVSL/zlVi/84Vov/OFeM/zdYjP83WYz/NlqM/zZbjP81XIz/NV2M/zRejf80X43/M2CN/zNhjf8yYo3/MmON/zFkjf8xZY3/MWaN/zBnjf8waI3/L2mN/y9qjf8ua47/LmyO/y5tjv8tbo7/LW+O/yxwjv8scY7/LHKO/ytzjv8rdI7/KnWO/yp2jv8qd47/KXiO/yl5jv8oeo7/KHqO/yh7jv8nfI7/J32O/yd+jv8mf47/JoCO/yaBjv8lgo7/JYON/ySEjf8khY3/JIaN/yOHjf8jiI3/I4mN/yKJjf8iio3/IouN/yGMjf8hjYz/IY6M/yCPjP8gkIz/IJGM/x+SjP8fk4v/H5SL/x+Vi/8flov/HpeK/x6Yiv8emYr/HpmK/x6aif8em4n/HpyJ/x6diP8enoj/Hp+I/x6gh/8foYf/H6KG/x+jhv8gpIX/IKWF/yGmhf8hp4T/IqeE/yOog/8jqYL/JKqC/yWrgf8mrIH/J62A/yiuf/8pr3//KrB+/yuxff8ssX3/LrJ8/y+ze/8wtHr/MrV6/zO2ef81t3j/Nrh3/zi5dv85uXb/O7p1/z27dP8+vHP/QL1y/0K+cf9EvnD/Rb9v/0fAbv9JwW3/S8Js/03Ca/9Pw2n/UcRo/1PFZ/9Vxmb/V8Zl/1nHZP9byGL/Xslh/2DJYP9iyl//ZMtd/2fMXP9pzFv/a81Z/23OWP9wzlb/cs9V/3TQVP930FL/edFR/3zST/9+0k7/gdNM/4PTS/+G1En/iNVH/4vVRv+N1kT/kNZD/5LXQf+V1z//l9g+/5rYPP+d2Tr/n9k4/6LaN/+l2jX/p9sz/6rbMv+t3DD/r9wu/7LdLP+13Sv/t90p/7reJ/+93ib/v98k/8LfIv/F3yH/x+Af/8rgHv/N4B3/z+Ec/9LhG//U4Rr/1+IZ/9riGP/c4hj/3+MY/+HjGP/k4xj/5+QZ/+nkGf/s5Br/7uUb//HlHP/z5R7/9uYf//jmIf/65iL//eck/w==",magma:"AAAD/wAABP8AAAb/AQAH/wEBCf8BAQv/AgIN/wICD/8DAxH/BAMT/wQEFf8FBBf/BgUZ/wcFG/8IBh3/CQcf/woHIv8LCCT/DAkm/w0KKP8OCir/Dwss/xAML/8RDDH/Eg0z/xQNNf8VDjj/Fg46/xcPPP8YDz//GhBB/xsQRP8cEEb/HhBJ/x8RS/8gEU3/IhFQ/yMRUv8lEVX/JhFX/ygRWf8qEVz/KxFe/y0QYP8vEGL/MBBl/zIQZ/80EGj/NQ9q/zcPbP85D27/Ow9v/zwPcf8+D3L/QA9z/0IPdP9DD3X/RQ92/0cPd/9IEHj/ShB5/0sQef9NEXr/TxF7/1ASe/9SEnz/UxN8/1UTff9XFH3/WBV+/1oVfv9bFn7/XRd+/14Xf/9gGH//YRh//2MZf/9lGoD/ZhqA/2gbgP9pHID/axyA/2wdgP9uHoH/bx6B/3Efgf9zH4H/dCCB/3Yhgf93IYH/eSKB/3oigf98I4H/fiSB/38kgf+BJYH/giWB/4Qmgf+FJoH/hyeB/4kogf+KKIH/jCmA/40pgP+PKoD/kSqA/5IrgP+UK4D/lSyA/5csf/+ZLX//mi1//5wuf/+eLn7/ny9+/6Evfv+jMH7/pDB9/6Yxff+nMX3/qTJ8/6szfP+sM3v/rjR7/7A0e/+xNXr/szV6/7U2ef+2Nnn/uDd4/7k3eP+7OHf/vTl3/745dv/AOnX/wjp1/8M7dP/FPHT/xjxz/8g9cv/KPnL/yz5x/80/cP/OQHD/0EFv/9FCbv/TQm3/1ENt/9ZEbP/XRWv/2UZq/9pHaf/cSGn/3Ulo/95KZ//gS2b/4Uxm/+JNZf/kTmT/5VBj/+ZRYv/nUmL/6FRh/+pVYP/rVmD/7Fhf/+1ZX//uW17/7l1d/+9eXf/wYF3/8WFc//JjXP/zZVz/82db//RoW//1alv/9Wxb//ZuW//2cFv/93Fb//dzXP/4dVz/+Hdc//l5XP/5e13/+X1d//p/Xv/6gF7/+oJf//uEYP/7hmD/+4hh//uKYv/8jGP//I5j//yQZP/8kmX//JNm//2VZ//9l2j//Zlp//2bav/9nWv//Z9s//2hbv/9om///aRw//6mcf/+qHP//qp0//6sdf/+rnb//q94//6xef/+s3v//rV8//63ff/+uX///ruA//68gv/+voP//sCF//7Chv/+xIj//saJ//7Hi//+yY3//suO//3NkP/9z5L//dGT//3Slf/91Jf//daY//3Ymv/92pz//dyd//3dn//936H//eGj//zjpf/85ab//Oao//zoqv/86qz//Oyu//zusP/88LH//PGz//zztf/89bf/+/e5//v5u//7+r3/+/y//w==",plasma:"DAeG/xAHh/8TBon/FQaK/xgGi/8bBoz/HQaN/x8Fjv8hBY//IwWQ/yUFkf8nBZL/KQWT/ysFlP8tBJT/LwSV/zEElv8zBJf/NASY/zYEmP84BJn/OgSa/zsDmv89A5v/PwOc/0ADnP9CA53/RAOe/0UDnv9HAp//SQKf/0oCoP9MAqH/TgKh/08Cov9RAaL/UgGj/1QBo/9WAaP/VwGk/1kBpP9aAKX/XACl/14Apf9fAKb/YQCm/2IApv9kAKf/ZQCn/2cAp/9oAKf/agCn/2wAqP9tAKj/bwCo/3AAqP9yAKj/cwCo/3UAqP92Aaj/eAGo/3kBqP97Aqj/fAKn/34Dp/9/A6f/gQSn/4IEp/+EBab/hQam/4YHpv+IB6X/iQil/4sJpP+MCqT/jgyk/48No/+QDqP/kg+i/5MQof+VEaH/lhKg/5cToP+ZFJ//mhWe/5sXnv+dGJ3/nhmc/58am/+gG5v/ohya/6Mdmf+kHpj/pR+X/6chl/+oIpb/qSOV/6oklP+sJZP/rSaS/64nkf+vKJD/sCqP/7Erj/+yLI7/tC2N/7UujP+2L4v/tzCK/7gyif+5M4j/ujSH/7s1hv+8NoX/vTeE/744g/+/OYL/wDuB/8E8gP/CPYD/wz5//8Q/fv/FQH3/xkF8/8dCe//IRHr/yUV5/8pGeP/LR3f/zEh2/81Jdf/OSnX/z0t0/9BNc//RTnL/0U9x/9JQcP/TUW//1FJu/9VTbf/WVW3/11Zs/9dXa//YWGr/2Vlp/9paaP/bW2f/3F1m/9xeZv/dX2X/3mBk/99hY//fYmL/4GRh/+FlYP/iZmD/42df/+NoXv/kal3/5Wtc/+VsW//mbVr/525a/+hwWf/ocVj/6XJX/+pzVv/qdFX/63ZU/+x3VP/seFP/7XlS/+17Uf/ufFD/731P/+9+Tv/wgE3/8IFN//GCTP/yhEv/8oVK//OGSf/zh0j/9IlH//SKR//1i0b/9Y1F//aORP/2j0P/9pFC//eSQf/3k0H/+JVA//iWP//4mD7/+Zk9//maPP/6nDv/+p06//qfOv/6oDn/+6I4//ujN//7pDb//KY1//ynNf/8qTT//Koz//ysMv/8rTH//a8x//2wMP/9si///bMu//21Lf/9ti3//bgs//25K//9uyv//bwq//2+Kf/9wCn//cEo//3DKP/9xCf//cYm//zHJv/8ySb//Msl//zMJf/8ziX/+9Ak//vRJP/70yT/+tUk//rWJP/62CT/+dkk//nbJP/43ST/+N8k//fgJP/34iX/9uQl//blJf/15yb/9ekm//TqJv/z7Cb/8+4m//LwJv/y8Sb/8fMm//D1Jf/w9iP/7/gh/w==",inferno:"AAAD/wAABP8AAAb/AQAH/wEBCf8BAQv/AgEO/wICEP8DAhL/BAMU/wQDFv8FBBj/BgQb/wcFHf8IBh//CQYh/woHI/8LByb/DQgo/w4IKv8PCS3/EAkv/xIKMv8TCjT/FAs2/xYLOf8XCzv/GQs+/xoLQP8cDEP/HQxF/x8MR/8gDEr/IgtM/yQLTv8mC1D/JwtS/ykLVP8rClb/LQpY/y4KWv8wClz/Mgld/zQJX/81CWD/Nwlh/zkJYv87CWT/PAll/z4JZv9ACWb/QQln/0MKaP9FCmn/Rgpp/0gLav9KC2r/Swxr/00Ma/9PDWz/UA1s/1IObP9TDm3/VQ9t/1cPbf9YEG3/WhFt/1sRbv9dEm7/XxJu/2ATbv9iFG7/YxRu/2UVbv9mFW7/aBZu/2oXbv9rF27/bRhu/24Ybv9wGW7/chlt/3Mabf91G23/dhtt/3gcbf96HG3/ex1s/30dbP9+Hmz/gB9r/4Efa/+DIGv/hSBq/4Yhav+IIWr/iSJp/4siaf+NI2n/jiRo/5AkaP+RJWf/kyVn/5UmZv+WJmb/mCdl/5koZP+bKGT/nClj/54pY/+gKmL/oSth/6MrYf+kLGD/pixf/6ctX/+pLl7/qy5d/6wvXP+uMFv/rzFb/7ExWv+yMln/tDNY/7UzV/+3NFb/uDVW/7o2Vf+7N1T/vTdT/744Uv+/OVH/wTpQ/8I7T//EPE7/xT1N/8c+TP/IPkv/yT9K/8tASf/MQUj/zUJH/89ERv/QRUT/0UZD/9JHQv/USEH/1UlA/9ZKP//XSz7/2U09/9pOO//bTzr/3FA5/91SOP/eUzf/31Q2/+BWNP/iVzP/41gy/+RaMf/lWzD/5lwu/+ZeLf/nXyz/6GEr/+liKv/qZCj/62Un/+xnJv/taCX/7Woj/+5sIv/vbSH/8G8f//BwHv/xch3/8nQc//J1Gv/zdxn/83kY//R6Fv/1fBX/9X4U//aAEv/2gRH/94MQ//eFDv/4hw3/+IgM//iKC//5jAn/+Y4I//mQCP/6kQf/+pMG//qVBv/6lwb/+5kG//ubBv/7nQb/+54H//ugB//7ogj/+6QK//umC//7qA3/+6oO//usEP/7rhL/+7AU//uxFv/7sxj/+7Ua//u3HP/7uR7/+rsh//q9I//6vyX/+sEo//nDKv/5xSz/+ccv//jJMf/4yzT/+M03//fPOv/30Tz/9tM///bVQv/110X/9dlI//TbS//03E//895S//PgVv/z4ln/8uRd//LmYP/x6GT/8elo//HrbP/x7XD/8e50//Hwef/x8n3/8vOB//L0hf/z9on/9PeN//X4kf/2+pX/9/uZ//n8nf/6/aD//P6k/w=="},tt=n=>n<0?0:n>1?1:n,Xn=n=>n<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4),Ga=n=>{if(typeof globalThis.atob=="function"){let t=globalThis.atob(n),r=new Uint8Array(t.length);for(let i=0;i<t.length;i++)r[i]=t.charCodeAt(i)&255;return r}let e=globalThis.Buffer;if(e&&typeof e.from=="function")return Uint8Array.from(e.from(n,"base64"));throw new Error("Colormap: No base64 decoder available (expected atob() or Buffer).")},Ft=n=>{let e=Fi,t=e[n];if(t instanceof Uint8Array)return t;let r=Ga(Fi[n]);return e[n]=r,r},Ta=n=>{P(n.length>=2,"Colormap: expected at least 2 stops.");let e=[],t=0;for(let i of n)Array.isArray(i)?(e.push({t:n.length<=1?0:t/(n.length-1),color:[i[0],i[1],i[2],i[3]]}),t++):e.push({t:i.t,color:[i.color[0],i.color[1],i.color[2],i.color[3]]});e.sort((i,o)=>i.t-o.t);for(let i of e)i.t=tt(i.t);e[0].t>0&&e.unshift({t:0,color:e[0].color});let r=e.length-1;return e[r].t<1&&e.push({t:1,color:e[r].color}),e},rt=(n,e,t)=>n+(e-n)*t,Ra=(n,e)=>{let t=tt(e);if(t<=n[0].t)return n[0].color;let r=n.length-1;if(t>=n[r].t)return n[r].color;for(let i=0;i<r;i++){let o=n[i],a=n[i+1];if(t>=o.t&&t<=a.t){let s=a.t-o.t||1e-6,l=(t-o.t)/s;return[rt(o.color[0],a.color[0],l),rt(o.color[1],a.color[1],l),rt(o.color[2],a.color[2],l),rt(o.color[3],a.color[3],l)]}}return n[r].color},Di=(n,e)=>{let t=new Uint8Array(n.length*4);for(let r=0;r<n.length;r++){let i=tt(n[r][0]),o=tt(n[r][1]),a=tt(n[r][2]),s=tt(n[r][3]);e==="srgb"&&(i=Xn(i),o=Xn(o),a=Xn(a)),t[r*4+0]=Math.max(0,Math.min(255,Math.round(i*255))),t[r*4+1]=Math.max(0,Math.min(255,Math.round(o*255))),t[r*4+2]=Math.max(0,Math.min(255,Math.round(a*255))),t[r*4+3]=Math.max(0,Math.min(255,Math.round(s*255)))}return t},La=(n,e,t)=>{let r=Math.min(e-1,Math.max(0,Math.round(tt(t)*(e-1))));return[n[r*4+0]/255,n[r*4+1]/255,n[r*4+2]/255,n[r*4+3]/255]},Fa=(n,e,t)=>{let r=tt(t)*Math.max(0,e-1),i=Math.min(e-1,Math.max(0,Math.floor(r))),o=Math.min(e-1,i+1),a=r-i,s=i*4,l=o*4;return[rt(n[s+0]/255,n[l+0]/255,a),rt(n[s+1]/255,n[l+1]/255,a),rt(n[s+2]/255,n[l+2]/255,a),rt(n[s+3]/255,n[l+3]/255,a)]},Da=(n,e,t,r,i)=>{P(r>0,"Colormap: width must be > 0."),P(t.length>>>0===r*4,"Colormap: rgba8 length must be width*4.");let o=n.createTexture({label:i,size:{width:r,height:1,depthOrArrayLayers:1},dimension:"1d",format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST}),a=r*4,s=le(a,256),l=s===a?t:(()=>{let u=new Uint8Array(s);return u.set(t),u})();return e.writeTexture({texture:o},new Uint8Array(l),{bytesPerRow:s,rowsPerImage:1},{width:r,height:1,depthOrArrayLayers:1}),o},Ia=(n,e)=>n.createSampler({addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge",addressModeW:"clamp-to-edge",magFilter:e==="linear"?"linear":"nearest",minFilter:e==="linear"?"linear":"nearest",mipmapFilter:"nearest"}),Ea=1,H=class n{id=Ea++;_label;_filter;_width;_rgba8Linear;_external;_gpuByDevice=new WeakMap;constructor(e){this._label=e.label,this._width=e.width,this._filter=e.filter,this._rgba8Linear=e.rgba8Linear??null,this._external=e.external??null}static builtin(e){return Oa[e]}static fromStops(e,t={}){let r=Math.max(2,Math.floor(t.resolution??pt)),i=t.filter??"linear",o=t.colorSpace??"srgb",a=Ta(e),s=new Array(r);for(let u=0;u<r;u++){let m=r===1?0:u/(r-1);s[u]=Ra(a,m)}let l=Di(s,o);return new n({label:"Colormap.customStops",width:r,filter:i,rgba8Linear:l})}static fromPalette(e,t={}){P(e.length>=1,"Colormap.fromPalette: expected at least 1 color.");let r=t.filter??"nearest",i=t.colorSpace??"srgb",o=Di(e,i);return new n({label:"Colormap.palette",width:e.length,filter:r,rgba8Linear:o})}static fromGPUTextureView(e,t,r,i,o="linear"){return P(i>0,"Colormap.fromGPUTextureView: width must be > 0."),new n({label:"Colormap.external",width:i,filter:o,external:{device:e,view:t,sampler:r,width:i,filter:o}})}get width(){return this._width}get filter(){return this._filter}get canSampleCPU(){return this._rgba8Linear!==null}getRGBA8LinearLUT(){if(!this._rgba8Linear)throw new Error("Colormap: CPU sampling is unavailable for external GPU-only colormaps.");return this._rgba8Linear.slice()}sampleCPU(e){let t=this._rgba8Linear;if(!t)throw new Error("Colormap: CPU sampling is unavailable for external GPU-only colormaps.");return this._filter==="nearest"?La(t,this._width,e):Fa(t,this._width,e)}getGPUResources(e,t){if(this._external)return P(this._external.device===e,"Colormap: external texture was created with a different GPUDevice."),{texture:null,view:this._external.view,sampler:this._external.sampler,width:this._external.width,filter:this._external.filter};let r=this._gpuByDevice.get(e);if(r)return r;let i=this._rgba8Linear??(()=>{throw new Error("Colormap: no LUT data to upload.")})(),o=Da(e,t,i,this._width,this._label),a=o.createView({dimension:"1d"}),s=Ia(e,this._filter),l={texture:o,view:a,sampler:s,width:this._width,filter:this._filter};return this._gpuByDevice.set(e,l),l}toUniformStops(e=8,t="linear"){let r=Math.max(2,Math.min(8,Math.floor(e))),i=this._rgba8Linear;if(!i)return[[0,0,0,1],[1,1,1,1]];let o=new Array(r);for(let a=0;a<r;a++){let s=r===1?0:a/(r-1),l=Math.min(this._width-1,Math.max(0,Math.round(s*(this._width-1)))),u=i[l*4+0]/255,m=i[l*4+1]/255,c=i[l*4+2]/255,d=i[l*4+3]/255;if(t==="linear")o[a]=[u,m,c,d];else{let f=p=>p<=.0031308?12.92*p:1.055*Math.pow(p,.4166666666666667)-.055;o[a]=[f(u),f(m),f(c),d]}}return o}},Oa={grayscale:new H({label:"Colormap.grayscale",width:pt,filter:"linear",rgba8Linear:Ft("grayscale")}),turbo:new H({label:"Colormap.turbo",width:pt,filter:"linear",rgba8Linear:Ft("turbo")}),viridis:new H({label:"Colormap.viridis",width:pt,filter:"linear",rgba8Linear:Ft("viridis")}),magma:new H({label:"Colormap.magma",width:pt,filter:"linear",rgba8Linear:Ft("magma")}),plasma:new H({label:"Colormap.plasma",width:pt,filter:"linear",rgba8Linear:Ft("plasma")}),inferno:new H({label:"Colormap.inferno",width:pt,filter:"linear",rgba8Linear:Ft("inferno")})};var Ii="struct MaterialUniforms { color: vec4f, params: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseSampler: sampler; @group(1) @binding(2) var baseTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) normal: vec3f, @location(1) uv: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; fn linearToSrgb(c: vec3f) -> vec3f { return pow(c, vec3f(1.0 / 2.2)); } @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; out.position = camera.viewProjection * model.model * vec4f(in.position, 1.0); out.normal = (model.normalMatrix * vec4f(in.normal, 0.0)).xyz; out.uv = in.uv; return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let texColor = textureSample(baseTex, baseSampler, in.uv); var outColor = material.color * texColor; let alphaCutoff = material.params.x; if (alphaCutoff > 0.0 && outColor.a < alphaCutoff) { discard; } outColor.rgb = linearToSrgb(outColor.rgb); return outColor; }";var Ei="struct MaterialUniforms { color: vec4f, params: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseSampler: sampler; @group(1) @binding(2) var baseTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) m0: vec4f, @location(4) m1: vec4f, @location(5) m2: vec4f, @location(6) m3: vec4f, @location(7) n0: vec4f, @location(8) n1: vec4f, @location(9) n2: vec4f, @location(10) n3: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) normal: vec3f, @location(1) uv: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; fn linearToSrgb(c: vec3f) -> vec3f { return pow(c, vec3f(1.0 / 2.2)); } @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let modelM = mat4x4f(in.m0, in.m1, in.m2, in.m3); let normalM = mat4x4f(in.n0, in.n1, in.n2, in.n3); out.position = camera.viewProjection * modelM * vec4f(in.position, 1.0); out.normal = (normalM * vec4f(in.normal, 0.0)).xyz; out.uv = in.uv; return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let texColor = textureSample(baseTex, baseSampler, in.uv); var outColor = material.color * texColor; let alphaCutoff = material.params.x; if (alphaCutoff > 0.0 && outColor.a < alphaCutoff) { discard; } outColor.rgb = linearToSrgb(outColor.rgb); return outColor; }";var Oi="struct MaterialUniforms { color: vec4<f32> }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTexture: texture_2d<f32>; struct VertexInput { @location(0) position: vec3<f32>, @location(1) normal: vec3<f32>, @location(2) uv: vec2<f32>, @location(3) joints: vec4<u32>, @location(4) weights: vec4<f32> }; struct VertexOutput { @builtin(position) position: vec4<f32>, @location(0) uv: vec2<f32> }; struct CameraUniforms { viewProjection: mat4x4<f32>, position: vec4<f32> }; struct ModelUniforms { model: mat4x4<f32>, normalMatrix: mat4x4<f32> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; struct SkinBuffer { joints: array<mat4x4<f32>>, }; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let j = in.joints; let w = in.weights; let m = skin.joints[j.x] * w.x + skin.joints[j.y] * w.y + skin.joints[j.z] * w.z + skin.joints[j.w] * w.w; let localPos = m * vec4<f32>(in.position, 1.0); out.position = camera.viewProjection * model.model * localPos; out.uv = in.uv; return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { let baseColorSample = textureSample(baseColorTexture, baseColorSampler, in.uv); return material.color * baseColorSample; }";var zi="struct MaterialUniforms { color: vec4<f32> }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTexture: texture_2d<f32>; struct VertexInput { @location(0) position: vec3<f32>, @location(1) normal: vec3<f32>, @location(2) uv: vec2<f32>, @location(3) joints0: vec4<u32>, @location(4) weights0: vec4<f32>, @location(5) joints1: vec4<u32>, @location(6) weights1: vec4<f32> }; struct VertexOutput { @builtin(position) position: vec4<f32>, @location(0) uv: vec2<f32> }; struct CameraUniforms { viewProjection: mat4x4<f32>, position: vec4<f32> }; struct ModelUniforms { model: mat4x4<f32>, normalMatrix: mat4x4<f32> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; struct SkinBuffer { joints: array<mat4x4<f32>>, }; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let j0 = in.joints0; let w0 = in.weights0; let j1 = in.joints1; let w1 = in.weights1; let m = skin.joints[j0.x] * w0.x + skin.joints[j0.y] * w0.y + skin.joints[j0.z] * w0.z + skin.joints[j0.w] * w0.w + skin.joints[j1.x] * w1.x + skin.joints[j1.y] * w1.y + skin.joints[j1.z] * w1.z + skin.joints[j1.w] * w1.w; let localPos = m * vec4<f32>(in.position, 1.0); out.position = camera.viewProjection * model.model * localPos; out.uv = in.uv; return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { let baseColorSample = textureSample(baseColorTexture, baseColorSampler, in.uv); return material.color * baseColorSample; }";var Wi="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let worldPos4 = model.model * vec4f(in.position, 1.0); out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(in.normal, 0.0)).xyz); out.uv = in.uv; return out; } fn fresnelSchlick(cosTheta: f32, F0: vec3f) -> vec3f { return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } fn applyNormalMap(N: vec3f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let det = duv1.x * duv2.y - duv1.y * duv2.x; if (abs(det) < 1e-6) { return n; } let r = 1.0 / det; var T = (dp1 * duv2.y - dp2 * duv1.y) * r; T = normalize(T - n * dot(n, T)); let B = normalize(cross(n, T)) * sign(det); let tbn = mat3x3f(T, B, n); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(tbn * ns); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseSample = textureSample(baseColorTex, baseColorSampler, in.uv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, in.uv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, in.uv).xyz; let N = applyNormalMap(in.normal, in.worldPos, in.uv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, in.uv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, in.uv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a; let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let F0 = mix(vec3f(0.04), albedo, metallic); var Lo = lighting.ambient.rgb * albedo * ao; for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); L = normalize(lightDir); attenuation = 1.0 / (distance * distance); } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let F = fresnelSchlick(max(dot(H, V), 0.0), F0); let numerator = NDF * G * F; let denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; let specular = numerator / denominator; let kS = F; let kD = (1.0 - kS) * (1.0 - metallic); let NdotL = max(dot(N, L), 0.0); Lo += (kD * albedo / PI + specular) * radiance * NdotL; } Lo += emissive; Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var Ni="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) m0: vec4f, @location(4) m1: vec4f, @location(5) m2: vec4f, @location(6) m3: vec4f, @location(7) n0: vec4f, @location(8) n1: vec4f, @location(9) n2: vec4f, @location(10) n3: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct Light { position: vec4f, color: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let modelM = mat4x4f(in.m0, in.m1, in.m2, in.m3); let normalM = mat4x4f(in.n0, in.n1, in.n2, in.n3); let worldPos4 = modelM * vec4f(in.position, 1.0); out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((normalM * vec4f(in.normal, 0.0)).xyz); out.uv = in.uv; return out; } fn fresnelSchlick(cosTheta: f32, F0: vec3f) -> vec3f { return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } fn applyNormalMap(N: vec3f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let det = duv1.x * duv2.y - duv1.y * duv2.x; if (abs(det) < 1e-6) { return n; } let r = 1.0 / det; var T = (dp1 * duv2.y - dp2 * duv1.y) * r; T = normalize(T - n * dot(n, T)); let B = normalize(cross(n, T)) * sign(det); let tbn = mat3x3f(T, B, n); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(tbn * ns); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseSample = textureSample(baseColorTex, baseColorSampler, in.uv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, in.uv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, in.uv).xyz; let N = applyNormalMap(in.normal, in.worldPos, in.uv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, in.uv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, in.uv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a; let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let F0 = mix(vec3f(0.04), albedo, metallic); var Lo = lighting.ambient.rgb * albedo * ao; for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); L = normalize(lightDir); attenuation = 1.0 / (distance * distance); } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let F = fresnelSchlick(max(dot(H, V), 0.0), F0); let numerator = NDF * G * F; let denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; let specular = numerator / denominator; let kS = F; let kD = (1.0 - kS) * (1.0 - metallic); let NdotL = max(dot(N, L), 0.0); Lo += (kD * albedo / PI + specular) * radiance * NdotL; } Lo += emissive; Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var Vi="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) joints: vec4u, @location(4) weights: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; struct SkinBuffer { joints: array<mat4x4f> }; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let j = in.joints; let w = in.weights; let skinMatrix = skin.joints[j.x] * w.x + skin.joints[j.y] * w.y + skin.joints[j.z] * w.z + skin.joints[j.w] * w.w; let localPos = skinMatrix * vec4f(in.position, 1.0); let localNormal = (skinMatrix * vec4f(in.normal, 0.0)).xyz; let worldPos4 = model.model * localPos; out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(localNormal, 0.0)).xyz); out.uv = in.uv; return out; } fn fresnelSchlick(cosTheta: f32, F0: vec3f) -> vec3f { return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } fn applyNormalMap(N: vec3f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let det = duv1.x * duv2.y - duv1.y * duv2.x; if (abs(det) < 1e-6) { return n; } let r = 1.0 / det; var T = (dp1 * duv2.y - dp2 * duv1.y) * r; T = normalize(T - n * dot(n, T)); let B = normalize(cross(n, T)) * sign(det); let tbn = mat3x3f(T, B, n); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(tbn * ns); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseSample = textureSample(baseColorTex, baseColorSampler, in.uv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, in.uv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, in.uv).xyz; let N = applyNormalMap(in.normal, in.worldPos, in.uv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, in.uv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, in.uv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a; let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let F0 = mix(vec3f(0.04), albedo, metallic); var Lo = lighting.ambient.rgb * albedo * ao; for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); L = normalize(lightDir); attenuation = 1.0 / (distance * distance); } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let F = fresnelSchlick(max(dot(H, V), 0.0), F0); let numerator = NDF * G * F; let denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; let specular = numerator / denominator; let kS = F; let kD = (1.0 - kS) * (1.0 - metallic); let NdotL = max(dot(N, L), 0.0); Lo += (kD * albedo / PI + specular) * radiance * NdotL; } Lo += emissive; Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var ji="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) joints0: vec4u, @location(4) weights0: vec4f, @location(5) joints1: vec4u, @location(6) weights1: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; struct SkinBuffer { joints: array<mat4x4f> }; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let j0 = in.joints0; let w0 = in.weights0; let j1 = in.joints1; let w1 = in.weights1; let skinMatrix = skin.joints[j0.x] * w0.x + skin.joints[j0.y] * w0.y + skin.joints[j0.z] * w0.z + skin.joints[j0.w] * w0.w + skin.joints[j1.x] * w1.x + skin.joints[j1.y] * w1.y + skin.joints[j1.z] * w1.z + skin.joints[j1.w] * w1.w; let localPos = skinMatrix * vec4f(in.position, 1.0); let localNormal = (skinMatrix * vec4f(in.normal, 0.0)).xyz; let worldPos4 = model.model * localPos; out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(localNormal, 0.0)).xyz); out.uv = in.uv; return out; } fn fresnelSchlick(cosTheta: f32, F0: vec3f) -> vec3f { return F0 + (vec3f(1.0) - F0) * pow(1.0 - cosTheta, 5.0); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = (NdotH2 * (a2 - 1.0) + 1.0); return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); let ggx2 = geometrySchlickGGX(NdotV, roughness); let ggx1 = geometrySchlickGGX(NdotL, roughness); return ggx1 * ggx2; } fn toneMap(color: vec3f) -> vec3f { return color / (color + vec3f(1.0)); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseColor = material.color * textureSample(baseColorTex, baseColorSampler, in.uv); let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, in.uv); let metallic = material.params.z * mrSample.b; let roughness = material.params.y * mrSample.g; let N = normalize(in.normal); let V = normalize(camera.position - in.worldPos); let F0 = mix(vec3f(0.04), baseColor.rgb, metallic); var Lo = vec3f(0.0); for (var i: u32 = 0u; i < lighting.lightCount; i = i + 1u) { let light = lighting.lights[i]; let L = normalize(light.position.xyz - in.worldPos); let H = normalize(V + L); let distance = length(light.position.xyz - in.worldPos); let attenuation = 1.0 / max(distance * distance, 0.0001); let radiance = light.color.rgb * attenuation * light.params.x; let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let F = fresnelSchlick(max(dot(H, V), 0.0), F0); let kS = F; let kD = (vec3f(1.0) - kS) * (1.0 - metallic); let numerator = NDF * G * F; let denom = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; let specular = numerator / denom; let NdotL = max(dot(N, L), 0.0); Lo = Lo + (kD * baseColor.rgb / PI + specular) * radiance * NdotL; } let ambient = lighting.ambient.rgb * baseColor.rgb; let color = ambient + Lo + material.emissive.rgb * textureSample(emissiveTex, emissiveSampler, in.uv).rgb; let mapped = toneMap(color); return vec4f(mapped, baseColor.a); }";var $i="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct MaterialUniforms { scaleSource: vec4f, scaleDomain: vec4f, scaleClamp: vec4f, scaleParams: vec4f, scaleFlags: vec4f, colorParams: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var<storage, read> data: array<f32>; @group(1) @binding(2) var colormapSampler: sampler; @group(1) @binding(3) var colormapTex: texture_1d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) dataValue: vec4f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; fn srgbFromLinear(c: vec3f) -> vec3f { let a = vec3f(0.055); return select(12.92 * c, (1.0 + a) * pow(c, vec3f(1.0 / 2.4)) - a, c > vec3f(0.0031308)); } fn luminance(rgb: vec3f) -> f32 { return dot(rgb, vec3f(0.2126, 0.7152, 0.0722)); } @vertex fn vs_main(in: VertexInput, @builtin(vertex_index) vertexIndex: u32) -> VertexOutput { var out: VertexOutput; let worldPos4 = model.model * vec4f(in.position, 1.0); out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(in.normal, 0.0)).xyz); let componentCount = max(1u, min(4u, u32(material.scaleSource.x + 0.5))); let stride = max(1u, u32(material.scaleSource.w + 0.5)); let dataOffset = u32(material.scaleDomain.z + 0.5); let base = vertexIndex * stride + dataOffset; var x: f32 = data[base + 0u]; var y: f32 = 0.0; var z: f32 = 0.0; var w: f32 = 0.0; if (componentCount > 1u) { y = data[base + 1u]; } if (componentCount > 2u) { z = data[base + 2u]; } if (componentCount > 3u) { w = data[base + 3u]; } out.dataValue = vec4f(x, y, z, w); return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let componentCount = max(1u, min(4u, u32(material.scaleSource.x + 0.5))); let componentIndex = min(3u, u32(material.scaleSource.y + 0.5)); let valueMode = u32(material.scaleSource.z + 0.5); let v = scale_select_value(in.dataValue, componentCount, componentIndex, valueMode); if (!scale_is_finite(v)) { discard; } let t = scale_apply_transform(v, vec4f(material.scaleDomain.x, material.scaleDomain.y, 0.0, material.scaleDomain.w), material.scaleClamp, material.scaleParams, material.scaleFlags); var cmap = textureSample(colormapTex, colormapSampler, t); let shading = scale_clamp01(material.colorParams.y); if (shading > 0.0) { let N = normalize(in.normal); var lightFactor: f32 = luminance(lighting.ambient.rgb); for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let dist = length(lightDir); L = normalize(lightDir); attenuation = 1.0 / max(1e-6, dist * dist); } let ndotl = max(dot(N, L), 0.0); let lum = luminance(light.color.rgb) * light.color.a; lightFactor += lum * attenuation * ndotl; } let shadedRgb = cmap.rgb * lightFactor; cmap = vec4f(mix(cmap.rgb, shadedRgb, shading), cmap.a); } let opacity = scale_clamp01(material.colorParams.x); let finalA = cmap.a * opacity; let finalRgb = clamp(cmap.rgb, vec3f(0.0), vec3f(1.0)); cmap = vec4f(finalRgb, finalA); return vec4f(srgbFromLinear(cmap.rgb), cmap.a); }";var Hi="struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let worldPos = model.model * vec4f(in.position, 1.0); out.position = camera.viewProjection * worldPos; out.worldPos = worldPos.xyz; out.normal = normalize((model.normalMatrix * vec4f(in.normal, 0.0)).xyz); out.uv = in.uv; return out; }";var Te=20,ft=(n,e,t)=>n<e?e:n>t?t:n,Yn=n=>ft(n,0,1),Ke=(n,e)=>typeof n=="number"&&Number.isFinite(n)?n:e,Qr=(n,e)=>typeof n=="number"&&Number.isInteger(n)?n:e,Ya={linear:0,log:1,symlog:2},Qa={none:0,range:1,percentile:2},Za={component:0,magnitude:1},gr=n=>Ya[n],yr=n=>Qa[n],vr=n=>Za[n],We=n=>({mode:n.mode,clampMode:n.clampMode,valueMode:n.valueMode,componentCount:n.componentCount,componentIndex:n.componentIndex,stride:n.stride,offset:n.offset,domainMin:n.domainMin,domainMax:n.domainMax,clampMin:n.clampMin,clampMax:n.clampMax,percentileLow:n.percentileLow,percentileHigh:n.percentileHigh,logBase:n.logBase,symlogLinThresh:n.symlogLinThresh,gamma:n.gamma,invert:n.invert}),Qn=()=>({mode:"linear",clampMode:"none",valueMode:"component",componentCount:1,componentIndex:0,stride:1,offset:0,domainMin:0,domainMax:1,clampMin:0,clampMax:1,percentileLow:2,percentileHigh:98,logBase:10,symlogLinThresh:1,gamma:1,invert:!1}),ie=n=>{let e=Qn(),t=n.mode??e.mode,r=n.clampMode??e.clampMode,i=n.valueMode??e.valueMode;P(t==="linear"||t==="log"||t==="symlog",`Invalid scale mode: ${String(t)}`),P(r==="none"||r==="range"||r==="percentile",`Invalid scale clamp mode: ${String(r)}`),P(i==="component"||i==="magnitude",`Invalid scale value mode: ${String(i)}`);let o=ft(Qr(n.componentCount,e.componentCount),1,4),a=ft(Qr(n.componentIndex,e.componentIndex),0,3),s=Math.max(o,Qr(n.stride,e.stride)),l=Math.max(0,Qr(n.offset,e.offset)),u=Ke(n.domainMin,e.domainMin),m=Ke(n.domainMax,e.domainMax),c=Ke(n.clampMin,e.clampMin),d=Ke(n.clampMax,e.clampMax),f=ft(Ke(n.percentileLow,e.percentileLow),0,100),p=ft(Ke(n.percentileHigh,e.percentileHigh),0,100);P(p>f,`Scale transform requires percentileHigh > percentileLow (got ${f}, ${p})`);let b=Math.max(1.000001,Ke(n.logBase,e.logBase)),g=Math.max(1e-20,Ke(n.symlogLinThresh,e.symlogLinThresh)),x=Math.max(1e-6,Ke(n.gamma,e.gamma)),M=!!n.invert;return{mode:t,clampMode:r,valueMode:i,componentCount:o,componentIndex:a,stride:s,offset:l,domainMin:u,domainMax:m,clampMin:c,clampMax:d,percentileLow:f,percentileHigh:p,logBase:b,symlogLinThresh:g,gamma:x,invert:M}},Ne=(n,e,t=0)=>{let r=ie(n);e[t+0]=r.componentCount,e[t+1]=r.componentIndex,e[t+2]=vr(r.valueMode),e[t+3]=r.stride,e[t+4]=r.domainMin,e[t+5]=r.domainMax,e[t+6]=r.offset,e[t+7]=yr(r.clampMode),e[t+8]=r.clampMin,e[t+9]=r.clampMax,e[t+10]=r.percentileLow,e[t+11]=r.percentileHigh,e[t+12]=gr(r.mode),e[t+13]=r.logBase,e[t+14]=r.symlogLinThresh,e[t+15]=r.gamma,e[t+16]=r.invert?1:0,e[t+17]=0,e[t+18]=0,e[t+19]=0},qi=(n,e)=>{let t=Math.max(1.000001,e);return Math.log(n)/Math.log(t)},br=(n,e,t,r)=>{if(e==="linear")return n;if(e==="log")return qi(Math.max(n,1e-20),r);let i=Math.max(t,1e-20),o=n>=0?1:-1,a=qi(1+Math.abs(n)/i,r);return o*a},Ja=(n,e,t,r)=>{if(e==="linear")return n;if(e==="log")return Math.pow(Math.max(r,1.000001),n);let i=Math.max(t,1e-20),o=n>=0?1:-1,a=Math.pow(Math.max(r,1.000001),Math.abs(n))-1;return o*(a*i)},Zn=n=>{let e=n.clampMode!=="none"&&n.clampMax>n.clampMin,t=n.domainMin,r=n.domainMax;return r<=t&&e&&(t=n.clampMin,r=n.clampMax),{domainMin:t,domainMax:r,clampMin:n.clampMin,clampMax:n.clampMax,hasClamp:e}},Ki=n=>Zn(ie(n)),Xi=(n,e)=>{let t=ie(e);if(!Number.isFinite(n))return Number.NaN;let r=n,i=Zn(t);i.hasClamp&&(r=ft(r,i.clampMin,i.clampMax));let o=i.domainMin,a=i.domainMax,s=br(o,t.mode,t.symlogLinThresh,t.logBase),l=br(a,t.mode,t.symlogLinThresh,t.logBase),u=br(r,t.mode,t.symlogLinThresh,t.logBase),m=Math.max(1e-20,l-s),c=Yn((u-s)/m);return c=Math.pow(c,t.gamma),t.invert&&(c=1-c),Yn(c)},Zr=(n,e)=>{let t=ie(e),r=Zn(t),i=Yn(n);t.invert&&(i=1-i),i=Math.pow(i,1/Math.max(t.gamma,1e-6));let o=br(r.domainMin,t.mode,t.symlogLinThresh,t.logBase),a=br(r.domainMax,t.mode,t.symlogLinThresh,t.logBase),s=o+(a-o)*i,l=Ja(s,t.mode,t.symlogLinThresh,t.logBase);return r.hasClamp&&(l=ft(l,r.clampMin,r.clampMax)),l};var Dt=(n,e,t)=>n<e?e:n>t?t:n,Qi=n=>n.mapState!==void 0,Jn=n=>Qi(n)?n:n.buffer,es=n=>Qi(n)?Number(n.size):typeof n.byteLength=="number"?n.byteLength:null,Yi=(n,e,t,r,i)=>{if(!Number.isFinite(t)||!Number.isFinite(r)||i<=0)return Number.NaN;if(r<=t)return t;let a=Dt(e,0,100)/100*Math.max(0,i-1),s=(r-t)/n.length,l=0;for(let u=0;u<n.length;u++){let m=n[u]>>>0,c=l+m;if(a<c){let d=t+u*s;if(m===0)return d;let f=(a-l)/m;return d+Dt(f,0,1)*s}l=c}return r},ts=n=>{P(Number.isInteger(n.count)&&n.count>=0,`Scale stats source.count must be an integer >= 0 (got ${n.count})`);let e=typeof n.componentCount=="number"&&Number.isInteger(n.componentCount)?n.componentCount:1,t=Dt(e,1,4),r=typeof n.componentIndex=="number"&&Number.isInteger(n.componentIndex)?n.componentIndex:0,i=Dt(r,0,3),o=typeof n.stride=="number"&&Number.isInteger(n.stride)?n.stride:t,a=Math.max(t,o),s=typeof n.offset=="number"&&Number.isInteger(n.offset)?n.offset:0,l=Math.max(0,s),u=typeof n.revision=="number"&&Number.isInteger(n.revision)?n.revision:0,m=Math.max(0,u),c=n.valueMode??"component";P(c==="component"||c==="magnitude",`Invalid scale value mode: ${String(c)}`);let d=es(n.buffer);if(d!==null){let f=Math.floor(d/4),p=n.count>0?l+(n.count-1)*a+t:0;P(p<=f,`Scale stats source range exceeds source buffer capacity (required ${p} f32, capacity ${f} f32)`)}return{buffer:n.buffer,count:n.count,componentCount:t,componentIndex:i,valueMode:c,stride:a,offset:l,revision:m}},It=class{compute;sourceIds=new WeakMap;cache=new Map;sourceCacheKeys=new Map;nextSourceId=1;constructor(e){this.compute=e}createTransform(e){return ie(e)}invalidate(e){let t=e.buffer?e.buffer:e,r=Jn(t),i=this.sourceIds.get(r);if(i===void 0)return;let o=this.sourceCacheKeys.get(i);if(o){for(let a of o)this.cache.delete(a);this.sourceCacheKeys.delete(i)}}clearCache(){this.cache.clear(),this.sourceCacheKeys.clear()}requestStats(e){let t=ts(e.source),r=Dt(e.percentiles?.low??2,0,100),i=Dt(e.percentiles?.high??98,0,100);P(i>r,`Scale stats requires percentile.high > percentile.low (got ${r}, ${i})`);let o=e.percentiles?.bins??2048,a=Math.max(2,Math.floor(Number.isFinite(o)?o:2048)),s=this.getSourceId(Jn(t.buffer)),l=[s,t.revision,t.count,t.componentCount,t.componentIndex,t.valueMode,t.stride,t.offset,e.percentiles?1:0,r,i,a].join("|"),u=this.cache.get(l);if(u)return u.promise;let m=this.computeStats(t,e.percentiles?{low:r,high:i,bins:a}:null).catch(d=>{this.cache.delete(l);let f=this.sourceCacheKeys.get(s);throw f?.delete(l),f&&f.size===0&&this.sourceCacheKeys.delete(s),d});this.cache.set(l,{promise:m});let c=this.sourceCacheKeys.get(s);return c||(c=new Set,this.sourceCacheKeys.set(s,c)),c.add(l),m}getSourceId(e){let t=this.sourceIds.get(e);if(t!==void 0)return t;let r=this.nextSourceId++;return this.sourceIds.set(e,r),r}async computeStats(e,t){let r=Jn(e.buffer),i=this.compute.kernels.extractScaleValuesF32(r,{count:e.count,componentCount:e.componentCount,componentIndex:e.componentIndex,valueMode:e.valueMode,stride:e.stride,offset:e.offset}),o=this.compute.kernels.compactF32(i.values,i.flags,{count:e.count}),a=await this.compute.readback.readScalarU32(o.count);if(a===0)return i.values.destroy(),i.flags.destroy(),o.output.destroy(),o.count.destroy(),{count:e.count,finiteCount:0,min:Number.NaN,max:Number.NaN,percentileMin:null,percentileMax:null,histogramBins:null};let s=this.compute.kernels.minF32(o.output,{count:a}),l=this.compute.kernels.maxF32(o.output,{count:a}),u=await this.compute.readback.readScalarF32(s),m=await this.compute.readback.readScalarF32(l),c=null,d=null,f=null;if(t){let p=this.compute.kernels.histogramF32(o.output,t.bins,{count:a,minValue:u,maxValue:m,clear:!0}),b=await this.compute.readback.readAs(Uint32Array,p);c=Yi(b,t.low,u,m,a),d=Yi(b,t.high,u,m,a),f=t.bins,p.destroy()}return i.values.destroy(),i.flags.destroy(),o.output.destroy(),o.count.destroy(),s.destroy(),l.destroy(),{count:e.count,finiteCount:a,min:u,max:m,percentileMin:c,percentileMax:d,histogramBins:f}}};var Zi=n=>n<0?0:n>1?1:n,Et=(r=>(r.Opaque="opaque",r.Transparent="transparent",r.Additive="additive",r))(Et||{}),Pr=(r=>(r.None="none",r.Back="back",r.Front="front",r))(Pr||{}),ht=class{blendMode;cullMode;depthWrite;depthTest;pipeline=null;bindGroup=null;bindGroupKey=null;uniformBuffer=null;_uniformDataCache=null;_dirty=!0;constructor(e={}){this.blendMode=e.blendMode??"opaque",this.cullMode=e.cullMode??"back",this.depthWrite=e.depthWrite??!0,this.depthTest=e.depthTest??!0}get dirty(){return this._dirty}markClean(){this._dirty=!1}getUniformDataCache(e){return(!this._uniformDataCache||this._uniformDataCache.length!==e)&&(this._uniformDataCache=new Float32Array(e)),this._uniformDataCache}destroy(){this.uniformBuffer?.destroy(),this.uniformBuffer=null,this.bindGroup=null,this.bindGroupKey=null,this.pipeline=null}},Se=class n extends ht{_color;_opacity;_baseColorTexture;_alphaCutoff;static _cachedBindGroupLayout=null;static _cachedLayoutDevice=null;constructor(e={}){super({...e,blendMode:e.blendMode??((e.opacity??1)<1?"transparent":"opaque")}),this._color=e.color??[1,1,1],this._opacity=e.opacity??1,this._baseColorTexture=e.baseColorTexture??null,this._alphaCutoff=e.alphaCutoff??0}get color(){return this._color}set color(e){this._color=e,this._dirty=!0}get opacity(){return this._opacity}set opacity(e){this._opacity=e,this._dirty=!0}get baseColorTexture(){return this._baseColorTexture}set baseColorTexture(e){this._baseColorTexture=e,this._dirty=!0}get alphaCutoff(){return this._alphaCutoff}set alphaCutoff(e){this._alphaCutoff=e,this._dirty=!0}getUniformBufferSize(){return 32}getUniformData(){let e=this.getUniformDataCache(8);return e[0]=this._color[0],e[1]=this._color[1],e[2]=this._color[2],e[3]=this._opacity,e[4]=this._alphaCutoff,e[5]=0,e[6]=0,e[7]=0,e}createBindGroupLayout(e){if(n._cachedBindGroupLayout&&n._cachedLayoutDevice===e)return n._cachedBindGroupLayout;let t=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]});return n._cachedBindGroupLayout=t,n._cachedLayoutDevice=e,t}getShaderCode(e={}){return e.instanced?Ei:e.skinned8?zi:e.skinned?Oi:Ii}},xe=class n extends ht{_color;_opacity;_metallic;_roughness;_emissive;_emissiveIntensity;_baseColorTexture;_metallicRoughnessTexture;_normalTexture;_occlusionTexture;_emissiveTexture;_normalScale;_occlusionStrength;_alphaCutoff;static _cachedBindGroupLayout=null;static _cachedLayoutDevice=null;constructor(e={}){super({...e,blendMode:e.blendMode??((e.opacity??1)<1?"transparent":"opaque")}),this._color=e.color??[1,1,1],this._opacity=e.opacity??1,this._metallic=e.metallic??0,this._roughness=e.roughness??1,this._emissive=e.emissive??[0,0,0],this._emissiveIntensity=e.emissiveIntensity??0,this._baseColorTexture=e.baseColorTexture??null,this._metallicRoughnessTexture=e.metallicRoughnessTexture??null,this._normalTexture=e.normalTexture??null,this._occlusionTexture=e.occlusionTexture??null,this._emissiveTexture=e.emissiveTexture??null,this._normalScale=e.normalScale??1,this._occlusionStrength=e.occlusionStrength??1,this._alphaCutoff=e.alphaCutoff??0}get color(){return this._color}set color(e){this._color=e,this._dirty=!0}get opacity(){return this._opacity}set opacity(e){this._opacity=e,this._dirty=!0}get metallic(){return this._metallic}set metallic(e){this._metallic=Math.max(0,Math.min(1,e)),this._dirty=!0}get roughness(){return this._roughness}set roughness(e){this._roughness=Math.max(0,Math.min(1,e)),this._dirty=!0}get emissive(){return this._emissive}set emissive(e){this._emissive=e,this._dirty=!0}get emissiveIntensity(){return this._emissiveIntensity}set emissiveIntensity(e){this._emissiveIntensity=e,this._dirty=!0}get baseColorTexture(){return this._baseColorTexture}set baseColorTexture(e){this._baseColorTexture=e}get metallicRoughnessTexture(){return this._metallicRoughnessTexture}set metallicRoughnessTexture(e){this._metallicRoughnessTexture=e}get normalTexture(){return this._normalTexture}set normalTexture(e){this._normalTexture=e}get occlusionTexture(){return this._occlusionTexture}set occlusionTexture(e){this._occlusionTexture=e}get emissiveTexture(){return this._emissiveTexture}set emissiveTexture(e){this._emissiveTexture=e}get normalScale(){return this._normalScale}set normalScale(e){this._normalScale=e,this._dirty=!0}get occlusionStrength(){return this._occlusionStrength}set occlusionStrength(e){this._occlusionStrength=e,this._dirty=!0}get alphaCutoff(){return this._alphaCutoff}set alphaCutoff(e){this._alphaCutoff=e,this._dirty=!0}getUniformBufferSize(){return 64}getUniformData(){let e=this.getUniformDataCache(16);return e[0]=this._color[0],e[1]=this._color[1],e[2]=this._color[2],e[3]=this._opacity,e[4]=this._emissive[0],e[5]=this._emissive[1],e[6]=this._emissive[2],e[7]=this._emissiveIntensity,e[8]=this._metallic,e[9]=this._roughness,e[10]=this._normalScale,e[11]=this._occlusionStrength,e[12]=this._alphaCutoff,e[13]=0,e[14]=0,e[15]=0,e}createBindGroupLayout(e){if(n._cachedBindGroupLayout&&n._cachedLayoutDevice===e)return n._cachedBindGroupLayout;let t=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:3,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:4,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:5,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:6,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:7,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:8,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:9,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:10,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]});return n._cachedBindGroupLayout=t,n._cachedLayoutDevice=e,t}getShaderCode(e={}){return e.instanced?Ni:e.skinned8?ji:e.skinned?Vi:Wi}},Ae=class n extends ht{_CPUData=null;_keepCPUData=!1;_dataDirty=!1;_ownsDataBuffer=!1;dataBuffer=null;_elementCount=0;_scaleTransform;_opacity=1;_shading=0;_colormap="viridis";_scaleRevision=0;_visualChangeListeners=new Set;static _cachedBindGroupLayout=null;static _cachedLayoutDevice=null;constructor(e){if(P(!!e&&!!e.scaleTransform,"DataMaterial: scaleTransform is required."),super({...e,blendMode:e.blendMode??((e.opacity??1)<1?"transparent":"opaque")}),this._scaleTransform=ie(e.scaleTransform),e.keepCPUData!==void 0&&(this._keepCPUData=!!e.keepCPUData),e.opacity!==void 0&&(this._opacity=e.opacity),e.shading!==void 0&&(this._shading=e.shading),e.colormap!==void 0&&(this._colormap=e.colormap),e.data&&this.setData(e.data,{keepCPUData:this._keepCPUData}),e.dataBuffer!==void 0&&e.dataBuffer!==null){let t=e.dataBuffer.buffer?e.dataBuffer.buffer:e.dataBuffer;this.setDataBuffer(t)}}get scaleTransform(){return We(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=ie(e),this._elementCount=this.recomputeElementCount(),this._dirty=!0,this.emitVisualChange("scale")}get opacity(){return this._opacity}set opacity(e){e!==this._opacity&&(this._opacity=e,this._dirty=!0)}get shading(){return this._shading}set shading(e){e!==this._shading&&(this._shading=e,this._dirty=!0)}get colormap(){return this._colormap}set colormap(e){this._colormap=e,this.bindGroupKey=null,this.emitVisualChange("colormap")}onVisualChange(e){return this._visualChangeListeners.add(e),()=>{this._visualChangeListeners.delete(e)}}getColormapKey(){let e=this._colormap;return e instanceof H?`cm:${e.id}`:`cm:${e}`}getColormapForBinding(){let e=this._colormap;return e instanceof H?e:H.builtin(e)}computeElementCountFromFloatLength(e){let t=Math.max(1,Math.floor(this._scaleTransform.stride)),r=Math.max(0,Math.floor(this._scaleTransform.offset));return e<=r?0:Math.max(0,Math.floor((e-r)/t))}recomputeElementCount(){return this._CPUData?this.computeElementCountFromFloatLength(this._CPUData.length):this.dataBuffer?this.computeElementCountFromFloatLength(Math.floor(this.dataBuffer.size/4)):0}setData(e,t={}){P(e.length>0,"DataMaterial: data must be non-empty."),this._CPUData=e,this._dataDirty=!0,this._keepCPUData=t.keepCPUData??this._keepCPUData,this._elementCount=this.computeElementCountFromFloatLength(e.length),this._scaleRevision++,this._dirty=!0,this.bindGroupKey=null}setDataBuffer(e){this._CPUData=null,this.dataBuffer=e,this._ownsDataBuffer=!1,this._dataDirty=!1,this._elementCount=this.computeElementCountFromFloatLength(Math.floor(e.size/4)),this._scaleRevision++,this._dirty=!0,this.bindGroupKey=null}dropCPUData(){this._CPUData=null}getScaleSourceDescriptor(e=this._scaleRevision){return!this.dataBuffer||this._elementCount<=0?null:{buffer:this.dataBuffer,count:this._elementCount,componentCount:this._scaleTransform.componentCount,componentIndex:this._scaleTransform.componentIndex,valueMode:this._scaleTransform.valueMode,stride:this._scaleTransform.stride,offset:this._scaleTransform.offset,revision:e}}upload(e,t){if(!this._dataDirty)return;if(this.dataBuffer&&!this._CPUData){this._dataDirty=!1;return}let r=this._CPUData;if(!r){this._dataDirty=!1;return}let i=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST;if(!this.dataBuffer||!this._ownsDataBuffer)this.dataBuffer=ve(e,r,i),this._ownsDataBuffer=!0;else try{t.writeBuffer(this.dataBuffer,0,r.buffer,r.byteOffset,r.byteLength)}catch{this.dataBuffer.destroy(),this.dataBuffer=ve(e,r,i)}this._elementCount=this.computeElementCountFromFloatLength(r.length),this._keepCPUData||(this._CPUData=null),this._dataDirty=!1,this.bindGroupKey=null}getUniformBufferSize(){return(Te+4)*4}getUniformData(){let e=this.getUniformDataCache(Te+4);return e.fill(0),Ne(this._scaleTransform,e,0),e[Te+0]=Zi(this._opacity),e[Te+1]=Zi(this._shading),e[Te+2]=0,e[Te+3]=0,e}createBindGroupLayout(e){if(n._cachedBindGroupLayout&&n._cachedLayoutDevice===e)return n._cachedBindGroupLayout;let t=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:3,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float",viewDimension:"1d"}}]});return n._cachedBindGroupLayout=t,n._cachedLayoutDevice=e,t}getShaderCode(e={}){return $i}emitVisualChange(e){for(let t of this._visualChangeListeners)try{t(e)}catch{}}destroy(){super.destroy(),this._ownsDataBuffer&&this.dataBuffer?.destroy(),this.dataBuffer=null,this._CPUData=null,this._dataDirty=!1,this._elementCount=0,this._visualChangeListeners.clear()}},xr=class extends ht{_vertexShader;_fragmentShader;_uniforms;_uniformLayout=null;_cachedBindGroupLayout=null;_cachedLayoutDevice=null;constructor(e){super(e),this._vertexShader=e.vertexShader??this.defaultVertexShader(),this._fragmentShader=e.fragmentShader,this._uniforms=e.uniforms??{}}setUniform(e,t){this._uniforms[e]&&(this._uniforms[e].value=t,this._dirty=!0)}getUniform(e){return this._uniforms[e]?.value}getUniformSize(e){switch(e){case"f32":return 4;case"vec2f":return 8;case"vec3f":return 12;case"vec4f":return 16;case"mat4x4f":return 64}}getUniformAlignment(e){switch(e){case"f32":return 4;case"vec2f":return 8;case"vec3f":return 16;case"vec4f":return 16;case"mat4x4f":return 16}}getUniformLayout(){if(this._uniformLayout)return this._uniformLayout;let e=0,t={};for(let[i,o]of Object.entries(this._uniforms)){let a=this.getUniformAlignment(o.type),s=this.getUniformSize(o.type);e=this.alignTo(e,a),t[i]=e,e+=s}let r=Math.ceil(e/16)*16||16;return this._uniformLayout={size:r,offsets:t},this._uniformLayout}alignTo(e,t){return e+t-1&~(t-1)}getUniformBufferSize(){return this.getUniformLayout().size}getUniformData(){let e=this.getUniformLayout(),t=this.getUniformDataCache(e.size/4);t.fill(0);for(let[r,i]of Object.entries(this._uniforms)){let o=e.offsets[r]>>>2;typeof i.value=="number"?t[o]=i.value:t.set(i.value,o)}return t}createBindGroupLayout(e){if(this._cachedBindGroupLayout&&this._cachedLayoutDevice===e)return this._cachedBindGroupLayout;let t=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]});return this._cachedBindGroupLayout=t,this._cachedLayoutDevice=e,t}defaultVertexShader(){return Hi}getShaderCode(e={}){let t=`struct CustomUniforms {
|
|
5
|
-
|
|
13
|
+
[ ${e[12]} ${e[13]} ${e[14]} ${e[15]} ]`)}},Qi={computeVertexNormals:(n,e,t,r,i)=>{C().mesh_compute_vertex_normals(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)}},zn={numel:(n,e)=>C().ndarray_numel(n>>>0,e>>>0)>>>0,stridesRowMajorTo:(n,e,t,r)=>!!C().ndarray_strides_row_major(n>>>0,e>>>0,t>>>0,r>>>0),offsetBytes:(n,e,t,r,i)=>C().ndarray_offset_bytes(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)>>>0},Be={alloc:()=>_.allocF32(4),view:n=>_.f32view(n,4),set:(n,e)=>_.writeF32(n,4,e),abs:(n,e)=>{C().quat_abs(n>>>0,e>>>0)},add:(n,e,t)=>{C().quat_add(n>>>0,e>>>0,t>>>0)},copy:(n,e)=>{C().quat_copy(n>>>0,e>>>0)},dist:(n,e)=>C().quat_dist(n>>>0,e>>>0),distsq:(n,e)=>C().quat_distsq(n>>>0,e>>>0),fromAxisAngle:(n,e,t)=>{C().quat_fromAxisAngle(n>>>0,e>>>0,t)},init:(n,e,t,r,i)=>{C().quat_init(n>>>0,e,t,r,i)},invert:(n,e)=>{C().quat_invert(n>>>0,e>>>0)},isEqual:(n,e)=>Qe(C().quat_isEqual(n>>>0,e>>>0)),isNormalized:n=>Qe(C().quat_isNormalized(n>>>0)),isZero:n=>Qe(C().quat_isZero(n>>>0)),mul:(n,e,t)=>{C().quat_mul(n>>>0,e>>>0,t>>>0)},neg:(n,e)=>{C().quat_neg(n>>>0,e>>>0)},norm:n=>C().quat_norm(n>>>0),normalize:(n,e)=>{C().quat_normalize(n>>>0,e>>>0)},normscl:(n,e,t)=>{C().quat_normscl(n>>>0,e>>>0,t)},normsq:n=>C().quat_normsq(n>>>0),random:n=>{C().quat_random(n>>>0)},randomRange:(n,e,t)=>{C().quat_random_range(n>>>0,e,t)},round:(n,e)=>{C().quat_round(n>>>0,e>>>0)},scl:(n,e,t)=>{C().quat_scl(n>>>0,e>>>0,t)},slerp:(n,e,t,r)=>{C().quat_slerp(n>>>0,e>>>0,t>>>0,r)},sub:(n,e,t)=>{C().quat_sub(n>>>0,e>>>0,t>>>0)},toRotation:(n,e,t)=>{C().quat_toRotation(n>>>0,e>>>0,t>>>0)},print:n=>{let e=_.f32view(n,4);console.log(`[ ${e[0]} ${e[1]} ${e[2]} ${e[3]} ]`)}},At={composeLocalMany:(n,e,t,r,i)=>{C().transform_compose_local_many(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)},updateWorldOrdered:(n,e,t,r,i)=>{C().transform_update_world_ordered(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)},updatePartialOrdered:(n,e,t,r,i,o,a,s,l,u)=>{C().transform_update_partial_ordered(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0,o>>>0,a>>>0,s>>>0,l>>>0,u>>>0)},packModelNormalMat4FromPtrs:(n,e,t)=>{C().transform_pack_model_normal_mat4_from_ptrs(n>>>0,e>>>0,t>>>0)}},qt={alloc:()=>_.allocF32(4),view3:n=>_.f32view(n,3),view4:n=>_.f32view(n,4),set3:(n,e)=>_.writeF32(n,3,e),abs:(n,e)=>{C().vec3_abs(n>>>0,e>>>0)},add:(n,e,t)=>{C().vec3_add(n>>>0,e>>>0,t>>>0)},ang:(n,e)=>{C().vec3_ang(n>>>0,e>>>0)},angBetween:(n,e)=>C().vec3_angBetween(n>>>0,e>>>0),copy:(n,e)=>{C().vec3_copy(n>>>0,e>>>0)},cross:(n,e,t)=>{C().vec3_cross(n>>>0,e>>>0,t>>>0)},dist:(n,e)=>C().vec3_dist(n>>>0,e>>>0),distsq:(n,e)=>C().vec3_distsq(n>>>0,e>>>0),dot:(n,e)=>C().vec3_dot(n>>>0,e>>>0),init:(n,e,t,r)=>{C().vec3_init(n>>>0,e,t,r)},interp:(n,e,t,r,i)=>{C().vec3_interp(n>>>0,e>>>0,t,r,i)},isEqual:(n,e)=>Qe(C().vec3_isEqual(n>>>0,e>>>0)),isNormalized:n=>Qe(C().vec3_isNormalized(n>>>0)),isOrthogonal:(n,e)=>Qe(C().vec3_isOrthogonal(n>>>0,e>>>0)),isParallel:(n,e)=>Qe(C().vec3_isParallel(n>>>0,e>>>0)),isZero:n=>Qe(C().vec3_isZero(n>>>0)),neg:(n,e)=>{C().vec3_neg(n>>>0,e>>>0)},norm:n=>C().vec3_norm(n>>>0),normalize:(n,e)=>{C().vec3_normalize(n>>>0,e>>>0)},normscl:(n,e,t)=>{C().vec3_normscl(n>>>0,e>>>0,t)},normsq:n=>C().vec3_normsq(n>>>0),oproj:(n,e,t)=>{C().vec3_oproj(n>>>0,e>>>0,t>>>0)},proj:(n,e,t)=>{C().vec3_proj(n>>>0,e>>>0,t>>>0)},random:n=>{C().vec3_random(n>>>0)},randomRange:(n,e,t)=>{C().vec3_random_range(n>>>0,e,t)},reflect:(n,e,t)=>{C().vec3_reflect(n>>>0,e>>>0,t>>>0)},refract:(n,e,t,r)=>{C().vec3_refract(n>>>0,e>>>0,t>>>0,r)},round:(n,e)=>{C().vec3_round(n>>>0,e>>>0)},scl:(n,e,t)=>{C().vec3_scl(n>>>0,e>>>0,t)},sub:(n,e,t)=>{C().vec3_sub(n>>>0,e>>>0,t>>>0)},print:n=>{let e=_.f32view(n,3);console.log(`[ ${e[0]} ${e[1]} ${e[2]} ]`)}},st={abs:n=>C().mat4abs(n),add:(n,e)=>C().mat4add(n,e),copy:n=>C().mat4copy(n),det:n=>C().mat4det(n),identity:()=>C().mat4identity(),init:(n,e,t,r,i,o,a,s,l,u,c,m,d,f,p,h)=>C().mat4init(n,e,t,r,i,o,a,s,l,u,c,m,d,f,p,h),invert:n=>C().mat4invert(n),isEqual:(n,e)=>C().mat4isEqual(n,e),isIdentity:n=>C().mat4isIdentity(n),isInverse:(n,e)=>C().mat4isInverse(n,e),isZero:n=>C().mat4isZero(n),lookAt:(n,e,t)=>C().mat4lookAt(n,e,t),mul:(n,e)=>C().mat4mul(n,e),neg:n=>C().mat4neg(n),norm:n=>C().mat4norm(n),normalize:n=>C().mat4normalize(n),normsq:n=>C().mat4normsq(n),perspective:(n,e,t,r)=>C().mat4perspective(n,e,t,r),print:n=>C().mat4print(n),random:(n,e)=>C().mat4random(n,e),rotateX:(n,e)=>C().mat4rotateX(n,e),rotateY:(n,e)=>C().mat4rotateY(n,e),rotateZ:(n,e)=>C().mat4rotateZ(n,e),round:n=>C().mat4round(n),scl:(n,e)=>C().mat4scl(n,e),sub:(n,e)=>C().mat4sub(n,e),trace:n=>C().mat4trace(n),translate:(n,e)=>C().mat4translate(n,e),transpose:n=>C().mat4transpose(n)},Jr={abs:n=>C().quatabs(n),add:(n,e)=>C().quatadd(n,e),copy:n=>C().quatcopy(n),dist:(n,e)=>C().quatdist(n,e),distsq:(n,e)=>C().quatdistsq(n,e),fromAxisAngle:(n,e)=>C().quatfromAxisAngle(n,e),init:(n,e,t,r)=>C().quatinit(n,e,t,r),invert:n=>C().quatinvert(n),isEqual:(n,e)=>C().quatisEqual(n,e),isNormalized:n=>C().quatisNormalized(n),isZero:n=>C().quatisZero(n),mul:(n,e)=>C().quatmul(n,e),neg:n=>C().quatneg(n),norm:n=>C().quatnorm(n),normalize:n=>C().quatnormalize(n),normscl:(n,e)=>C().quatnormscl(n,e),normsq:n=>C().quatnormsq(n),print:n=>C().quatprint(n),random:(n,e)=>C().quatrandom(n,e),round:n=>C().quatround(n),scl:(n,e)=>C().quatscl(n,e),slerp:(n,e,t)=>C().quatslerp(n,e,t),sub:(n,e)=>C().quatsub(n,e),toRotation:(n,e)=>C().quattoRotation(n,e)},Je={abs:n=>C().vec3abs(n),add:(n,e)=>C().vec3add(n,e),ang:n=>C().vec3ang(n),angBetween:(n,e)=>C().vec3angBetween(n,e),copy:n=>C().vec3copy(n),cross:(n,e)=>C().vec3cross(n,e),dist:(n,e)=>C().vec3dist(n,e),distsq:(n,e)=>C().vec3distsq(n,e),dot:(n,e)=>C().vec3dot(n,e),init:(n,e,t)=>C().vec3init(n,e,t),interp:(n,e,t,r)=>C().vec3interp(n,e,t,r),isEqual:(n,e)=>C().vec3isEqual(n,e),isNormalized:n=>C().vec3isNormalized(n),isOrthogonal:(n,e)=>C().vec3isOrthogonal(n,e),isParallel:(n,e)=>C().vec3isParallel(n,e),isZero:n=>C().vec3isZero(n),neg:n=>C().vec3neg(n),norm:n=>C().vec3norm(n),normalize:n=>C().vec3normalize(n),normscl:(n,e)=>C().vec3normscl(n,e),normsq:n=>C().vec3normsq(n),oproj:(n,e)=>C().vec3oproj(n,e),print:n=>C().vec3print(n),proj:(n,e)=>C().vec3proj(n,e),random:(n,e)=>C().vec3random(n,e),reflect:(n,e)=>C().vec3reflect(n,e),refract:(n,e,t)=>C().vec3refract(n,e,t),round:n=>C().vec3round(n),scl:(n,e)=>C().vec3scl(n,e),sub:(n,e)=>C().vec3sub(n,e)};var Il=n=>ArrayBuffer.isView(n),en=(n,e=0,t)=>{if(Il(n)){let o=n.byteOffset+e,a=n.byteLength-e,s=t===void 0?a:Math.min(a,t);return{buffer:n.buffer,offset:o,size:s}}let r=n.byteLength-e,i=t===void 0?r:Math.min(r,t);return{buffer:n,offset:e,size:i}},Dl=(n,e,t,r,i=0,o)=>{y(Number.isInteger(t)&&t>=0,`dstOffsetBytes must be an integer >= 0 (got ${t})`);let a=en(r,i,o);y((t&3)===0,`dstOffsetBytes must be 4-byte aligned (got ${t})`),y((a.offset&3)===0,`srcOffsetBytes must be 4-byte aligned (got ${a.offset})`);let s=he(a.size,4);if(s===a.size){n.writeBuffer(e,t,a.buffer,a.offset,a.size);return}let l=new Uint8Array(s);l.set(new Uint8Array(a.buffer,a.offset,a.size)),n.writeBuffer(e,t,l,0,s)},On=class{device;queue;buffer;byteLength;usage;constructor(e,t,r,i,o){this.device=e,this.queue=t,this.buffer=r,this.byteLength=i,this.usage=o}destroy(){this.buffer.destroy()}write(e,t=0,r=0,i){Dl(this.queue,this.buffer,t,e,r,i)}writeFromArrayBuffer(e,t,r,i=0){this.write(e,i,t,r)}writeFromWasmMemory(e,t,r,i=0){let o=new Uint8Array(e.buffer,t>>>0,r>>>0);this.write(o,i,0,r)}},oe=class extends On{label;constructor(e,t,r){let i=r.data?en(r.data).size:r.byteLength??0;y(Number.isInteger(i)&&i>=0,`StorageBuffer.byteLength must be an integer >= 0 (got ${i})`);let o=he(i,4),a=GPUBufferUsage.STORAGE;r.copyDst!==!1&&(a|=GPUBufferUsage.COPY_DST),r.copySrc&&(a|=GPUBufferUsage.COPY_SRC),r.usage&&(a|=r.usage);let s=e.createBuffer({label:r.label,size:Math.max(4,o),usage:a,mappedAtCreation:!!r.data});if(r.data){let l=en(r.data),u=new Uint8Array(s.getMappedRange());u.fill(0),u.set(new Uint8Array(l.buffer,l.offset,l.size),0),s.unmap()}super(e,t,s,i,a),this.label=r.label??null}get canReadback(){return(this.usage&GPUBufferUsage.COPY_SRC)!==0}async read(e=0,t){y(this.canReadback,"StorageBuffer.read() requires the buffer to be created with copySrc: true"),y(Number.isInteger(e)&&e>=0,`srcOffsetBytes must be an integer >= 0 (got ${e})`);let r=t??this.byteLength-e;y(Number.isInteger(r)&&r>=0,`sizeBytes must be an integer >= 0 (got ${r})`),y(e+r<=this.byteLength,`read range out of bounds (offset ${e}, size ${r}, byteLength ${this.byteLength})`);let i=he(r,4),o=he(e,4);y(o===e,`srcOffsetBytes must be 4-byte aligned for readback (got ${e})`);let a=this.device.createBuffer({size:Math.max(4,i),usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),s=this.device.createCommandEncoder();s.copyBufferToBuffer(this.buffer,e,a,0,i),this.queue.submit([s.finish()]),await a.mapAsync(GPUMapMode.READ,0,i);let u=a.getMappedRange(0,i).slice(0,r);return a.unmap(),a.destroy(),u}async readAs(e,t=0,r){let i=await this.read(t,r),o=e.BYTES_PER_ELEMENT;y(i.byteLength%o===0,`readAs: byteLength (${i.byteLength}) is not divisible by BYTES_PER_ELEMENT (${o})`);let a=i.byteLength/o;return new e(i,0,a)}},xr=class extends On{label;constructor(e,t,r){let i=r.data?en(r.data).size:r.byteLength??0;y(Number.isInteger(i)&&i>=0,`UniformBuffer.byteLength must be an integer >= 0 (got ${i})`);let o=he(i,4),a=GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST;r.usage&&(a|=r.usage);let s=e.createBuffer({label:r.label,size:Math.max(4,o),usage:a,mappedAtCreation:!!r.data});if(r.data){let l=en(r.data),u=new Uint8Array(s.getMappedRange());u.fill(0),u.set(new Uint8Array(l.buffer,l.offset,l.size),0),s.unmap()}super(e,t,s,i,a),this.label=r.label??null}};var Nl={i8:{dtype:"i8",ctor:Int8Array,bytesPerElement:1,wgslScalarType:null},u8:{dtype:"u8",ctor:Uint8Array,bytesPerElement:1,wgslScalarType:null},i16:{dtype:"i16",ctor:Int16Array,bytesPerElement:2,wgslScalarType:null},u16:{dtype:"u16",ctor:Uint16Array,bytesPerElement:2,wgslScalarType:null},i32:{dtype:"i32",ctor:Int32Array,bytesPerElement:4,wgslScalarType:"i32"},u32:{dtype:"u32",ctor:Uint32Array,bytesPerElement:4,wgslScalarType:"u32"},f32:{dtype:"f32",ctor:Float32Array,bytesPerElement:4,wgslScalarType:"f32"},f64:{dtype:"f64",ctor:Float64Array,bytesPerElement:8,wgslScalarType:"f64"}},Ce=n=>{let e=Nl[n];if(!e)throw new Error(`Unknown dtype: ${String(n)}`);return e},Ji=n=>{y(Array.isArray(n),"shape must be an array of dimension sizes");let e=new Array(n.length);for(let t=0;t<n.length;t++){let r=n[t];y(Number.isInteger(r)&&r>=0,`shape[${t}] must be an integer >= 0 (got ${r})`),e[t]=r}return e},Vn=(n,e)=>{let t=n.length,r=new Array(t),i=e;for(let o=t-1;o>=0;o--)y(Number.isInteger(i)&&i>=0,"Stride overflow while computing row-major strides"),y(i<=2147483647,`row-major stride exceeds i32 range (got ${i})`),r[o]=i,i=i*n[o],y(Number.isFinite(i)&&i>=0,"Stride overflow while computing row-major strides"),y(i<=Number.MAX_SAFE_INTEGER,"Stride overflow while computing row-major strides");return r},eo=(n,e,t)=>{y(Array.isArray(n),"stridesBytes must be an array"),y(n.length===e,`stridesBytes length (${n.length}) must equal shape length (${e})`);let r=new Array(e);for(let i=0;i<e;i++){let o=n[i];y(Number.isInteger(o),`stridesBytes[${i}] must be an integer (got ${o})`),y(o>=-2147483648&&o<=2147483647,`stridesBytes[${i}] must fit in i32 (got ${o})`),y(o%t===0,`stridesBytes[${i}] (${o}) must be a multiple of bytesPerElement (${t})`),r[i]=o}return r},to=(n,e)=>{let t=n??0;return y(Number.isInteger(t)&&t>=0,`offsetBytes must be an integer >= 0 (got ${t})`),y(t%e===0,`offsetBytes (${t}) must be a multiple of bytesPerElement (${e})`),t},no=n=>{let e=1;for(let t=0;t<n.length;t++){if(e*=n[t],n[t]===0)return 0;y(Number.isFinite(e),"numel overflow")}return e},ro=(n,e,t,r)=>{if(n.length===0){let s=t+r;return y(s<=4294967295,`required backing bytes exceeds wasm32 address space (got ${s})`),s}if(no(n)===0)return 0;let i=BigInt(t),o=BigInt(t);for(let s=0;s<n.length;s++){let l=n[s],u=BigInt(e[s]),c=BigInt(l-1)*u;c<0n?i+=c:o+=c}y(i>=0n,`layout underflows: minimum byte offset is ${i} (offsetBytes is too small for negative strides)`);let a=o+BigInt(r);return y(a<=BigInt(4294967295),`required backing bytes exceeds wasm32 address space (got ${a})`),Number(a)},zl=(n,e,t,r)=>{if(t!==0)return!1;if(n.length===0||no(n)===0)return!0;let i=Vn(n,r);for(let o=0;o<n.length;o++)if(e[o]!==i[o])return!1;return!0},Ft=class{dtype;shape;stridesBytes;offsetBytes;bytesPerElement;numel;byteLength;constructor(e,t,r,i,o){this.dtype=e,this.shape=t,this.stridesBytes=r,this.offsetBytes=i,this.bytesPerElement=Ce(e).bytesPerElement,this.numel=no(t),this.byteLength=o}get ndim(){return this.shape.length}get wgslScalarType(){return Ce(this.dtype).wgslScalarType}get isContiguousC(){return zl(this.shape,this.stridesBytes,this.offsetBytes,this.bytesPerElement)}layout(){return{shape:this.shape.slice(),stridesBytes:this.stridesBytes.slice(),offsetBytes:this.offsetBytes}}},Ol=4294967295,Kt=class n extends Ft{basePtrBytes;shapePtr;stridesPtr;indicesPtr;_buf=null;_all=null;constructor(e,t,r,i,o,a,s,l,u){super(e,t,r,i,o),this.basePtrBytes=a,this.shapePtr=s,this.stridesPtr=l,this.indicesPtr=u}static empty(e,t){_.memory();let r=Ce(e),i=Ji(t.shape),o=to(t.offsetBytes,r.bytesPerElement),a=t.stridesBytes?eo(t.stridesBytes,i.length,r.bytesPerElement):Vn(i,r.bytesPerElement),s=ro(i,a,o,r.bytesPerElement),l=_.allocU32(i.length>>>0),u=_.allocU32(i.length>>>0),c=_.allocU32(i.length>>>0),m=_.u32view(l,i.length>>>0);for(let p=0;p<i.length;p++)m[p]=i[p]>>>0;let d=_.i32view(u,i.length>>>0);for(let p=0;p<a.length;p++)d[p]=a[p]|0;let f=s>0?_.allocBytes(s>>>0):0;return new n(e,i,a,o,s,f,l,u,c)}static zeros(e,t){let r=n.empty(e,t);return r.zero_(),r}static fromArray(e,t,r){let i=n.empty(e,{shape:t});y(i.isContiguousC,"CPUndarray.fromArray currently requires a contiguous row-major layout"),y(r.length>=i.numel,`source length (${r.length}) must be >= numel (${i.numel})`);let o=i.data();for(let a=0;a<i.numel;a++)o[a]=r[a];return i}get residency(){return"cpu-webassembly"}ensureAllView(){let e=_.memory().buffer;if(this._buf!==e){this._buf=e;let t=Ce(this.dtype).ctor;this._all=new t(e)}return this._all}backingBytes(){return this.byteLength===0?new Uint8Array(_.memory().buffer,0,0):_.u8view(this.basePtrBytes,this.byteLength>>>0)}data(){if(y(this.isContiguousC,"CPUndarray.data() requires a contiguous row-major layout (use backingBytes() for raw backing storage)"),this.numel===0){let e=_.memory().buffer,t=Ce(this.dtype).ctor;return new t(e,0,0)}return new(Ce(this.dtype)).ctor(_.memory().buffer,this.basePtrBytes+this.offsetBytes>>>0,this.numel>>>0)}offsetBytesAt(e){if(y(e.length===this.ndim,`expected ${this.ndim} indices, got ${e.length}`),this.ndim===0)return this.offsetBytes;let t=_.u32view(this.indicesPtr,this.ndim>>>0);for(let i=0;i<this.ndim;i++){let o=e[i];y(Number.isInteger(o)&&o>=0,`index[${i}] must be an integer >= 0 (got ${o})`),t[i]=o>>>0}let r=zn.offsetBytes(this.shapePtr,this.stridesPtr,this.indicesPtr,this.ndim>>>0,this.offsetBytes>>>0);return y(r!==Ol,"index out of bounds (or offset overflow)"),y(r+this.bytesPerElement<=this.byteLength,"computed byte offset is outside backing storage"),r}get(...e){let t=this.offsetBytesAt(e),r=this.basePtrBytes+t>>>0;y(r%this.bytesPerElement===0,"internal error: misaligned element address");let i=r/this.bytesPerElement;return this.ensureAllView()[i]}set(e,...t){let r=this.offsetBytesAt(t),i=this.basePtrBytes+r>>>0;y(i%this.bytesPerElement===0,"internal error: misaligned element address");let o=i/this.bytesPerElement,a=this.ensureAllView();a[o]=e}zero_(){this.byteLength!==0&&this.backingBytes().fill(0)}uploadToGPU(e,t={}){let r=this.backingBytes(),i=new oe(e.device,e.queue,{label:t.label,byteLength:this.byteLength,data:r,copyDst:t.copyDst,copySrc:t.copySrc,usage:t.usage});return new Xt(this.dtype,this.shape.slice(),this.stridesBytes.slice(),this.offsetBytes,this.byteLength,i,0,!0)}},Xt=class n extends Ft{buffer;baseOffsetBytes;owned;constructor(e,t,r,i,o,a,s=0,l=!1){super(e,t,r,i,o),y(Number.isInteger(s)&&s>=0,`baseOffsetBytes must be an integer >= 0 (got ${s})`),y((s&3)===0,`baseOffsetBytes must be 4-byte aligned for storage buffers (got ${s})`),this.buffer=a,this.baseOffsetBytes=s,this.owned=l}static empty(e,t,r,i={}){let o=Ce(t),a=Ji(r.shape),s=to(r.offsetBytes,o.bytesPerElement),l=r.stridesBytes?eo(r.stridesBytes,a.length,o.bytesPerElement):Vn(a,o.bytesPerElement),u=ro(a,l,s,o.bytesPerElement),c=new oe(e.device,e.queue,{label:i.label,byteLength:u,copyDst:i.copyDst,copySrc:i.copySrc,usage:i.usage});return new n(t,a,l,s,u,c,0,!0)}static wrap(e,t,r,i=0){let o=Ce(t),a=Ji(r.shape),s=to(r.offsetBytes,o.bytesPerElement),l=r.stridesBytes?eo(r.stridesBytes,a.length,o.bytesPerElement):Vn(a,o.bytesPerElement),u=ro(a,l,s,o.bytesPerElement);return new n(t,a,l,s,u,e,i,!1)}get residency(){return"gpu-storagebuffer"}bindingResource(){return{buffer:this.buffer,offset:this.baseOffsetBytes,size:he(this.byteLength,4)}}async readbackToCPU(){y(this.buffer.canReadback,"GPUndarray.readbackToCPU() requires the underlying StorageBuffer to be created with copySrc: true");let e=await this.buffer.read(this.baseOffsetBytes,this.byteLength),t=Kt.empty(this.dtype,{shape:this.shape,stridesBytes:this.stridesBytes,offsetBytes:this.offsetBytes});return t.backingBytes().set(new Uint8Array(e),0),t}destroy(){this.owned&&this.buffer.destroy()}};var tn=n=>typeof WebAssembly<"u"&&typeof WebAssembly.Memory<"u"&&n instanceof WebAssembly.Memory,En=n=>typeof WebAssembly<"u"&&typeof WebAssembly.Global<"u"&&n instanceof WebAssembly.Global,vt=(n,e)=>e?`${n} '${e}'`:n,Wn=n=>n||null,bt=(n,e)=>typeof n=="bigint"?(y(n>=0n,`${e} must be >= 0 (got ${n.toString()})`),y(n<=BigInt(Number.MAX_SAFE_INTEGER),`${e} exceeds Number.MAX_SAFE_INTEGER (got ${n.toString()})`),Number(n)):(y(typeof n=="number",`${e} must be a number or bigint (got ${typeof n})`),y(Number.isFinite(n),`${e} must be finite (got ${n})`),y(Number.isInteger(n),`${e} must be an integer (got ${n})`),y(n>=0,`${e} must be >= 0 (got ${n})`),y(Number.isSafeInteger(n),`${e} must be a safe integer (got ${n})`),n),Vl=(n,e)=>(typeof n=="bigint"||(y(typeof n=="number",`${e} must be a number or bigint (got ${typeof n})`),y(Number.isFinite(n),`${e} must be finite (got ${n})`)),n),jn=(n,e)=>{if(n===void 0)return[];if(y(Array.isArray(n),`${e} args must be an array when provided.`),n.length===0)return[];let t=new Array(n.length);for(let r=0;r<n.length;r++)t[r]=Vl(n[r],`${e} args[${r}]`);return t},El=(n,e)=>n===void 0?0:(y(Number.isFinite(n),`${e} byteOffset must be finite (got ${n})`),y(Number.isInteger(n),`${e} byteOffset must be an integer (got ${n})`),y(n>=0,`${e} byteOffset must be >= 0 (got ${n})`),y(Number.isSafeInteger(n),`${e} byteOffset must be a safe integer (got ${n})`),n),ea=(n,e,t)=>{let r=n+e;return y(Number.isSafeInteger(r),`${t} overflowed Number.MAX_SAFE_INTEGER`),r},Wl=(n,e,t)=>{let r=n*e;return y(Number.isSafeInteger(r),`${t} overflowed Number.MAX_SAFE_INTEGER`),r},io=n=>Ce(n).ctor,Yt=class n{exportsObject;defaultMemorySource;name;constructor(e={},t={}){this.exportsObject=e,this.defaultMemorySource=t.memory,this.name=Wn(t.name)}static fromInstance(e,t={}){y(typeof e=="object"&&e!==null,"WasmModule.fromInstance(): instance must be an object with an exports field.");let r=e.exports;return y(typeof r=="object"&&r!==null,"WasmModule.fromInstance(): instance.exports must be an object."),new n(r,t)}static fromExports(e,t={}){return y(typeof e=="object"&&e!==null,"WasmModule.fromExports(): exports must be an object."),new n(e,t)}static fromMemory(e,t={}){return y(tn(e),"WasmModule.fromMemory(): memory must be a WebAssembly.Memory."),new n({},{...t,memory:e})}getExport(e){return y(typeof e=="string"&&e.length>0,"WasmModule.getExport(): name must be a non-empty string."),y(Object.prototype.hasOwnProperty.call(this.exportsObject,e),`${vt("WasmModule export",this.name)} does not contain export '${e}'.`),this.exportsObject[e]}getFunction(e){let t=this.getExport(e);return y(typeof t=="function",`${vt("WasmModule export",this.name)} '${e}' is not a function.`),t}getGlobal(e){let t=this.getExport(e);return y(En(t),`${vt("WasmModule export",this.name)} '${e}' is not a WebAssembly.Global.`),t}memory(e){let t=e!==void 0?e:this.defaultMemorySource;if(tn(t))return t;if(typeof t=="string"){let i=this.getExport(t);return y(tn(i),`${vt("WasmModule export",this.name)} '${t}' is not a WebAssembly.Memory.`),i}if(t!=null)throw new Error(`${vt("WasmModule",this.name)} received an invalid memory source. Expected a WebAssembly.Memory or memory export name.`);let r=this.memoryExportNames();if(r.length===1)return this.memory(r[0]);throw r.length===0?new Error(`${vt("WasmModule",this.name)} could not resolve a WebAssembly.Memory. Pass memory explicitly or export one memory.`):new Error(`${vt("WasmModule",this.name)} has multiple memory exports (${r.join(", ")}). Pass memory explicitly.`)}view(e){return new rn(this,e)}readBytes(e){let t=this._resolveBytes(e);return new Uint8Array(t.memory.buffer,t.ptr>>>0,t.byteLength>>>0)}readUtf8(e,t,r={}){let i=Wn(r.name),o=this._resolveBytes({memory:r.memory,ptr:e,byteLength:t,byteOffset:r.byteOffset,name:i??void 0});return new TextDecoder("utf-8",{fatal:r.fatal??!1,ignoreBOM:r.ignoreBOM??!1}).decode(new Uint8Array(o.memory.buffer,o.ptr>>>0,o.byteLength>>>0))}dataView(e){let t=this._resolveBytes(e);return new DataView(t.memory.buffer,t.ptr>>>0,t.byteLength>>>0)}_resolveView(e){let t=Wn(e.name),r=vt("WasmMemoryView",t),i=e.dtype,o=Ce(i).bytesPerElement>>>0,a=this.resolveValue(e.length,`${r} length`),s=Wl(a,o,`${r} byteLength`),l=this.resolveByteRange(e.memory,e.ptr,e.byteOffset,s,r);return y(l.ptr%o===0,`${r} ptr ${l.ptr} is not aligned for dtype '${i}' (${o} bytes).`),{memory:l.memory,ptr:l.ptr>>>0,length:a>>>0,byteLength:s>>>0,dtype:i,name:t}}_resolveBytes(e){let t=Wn(e.name),r=vt("external WebAssembly memory range",t),i=this.resolveValue(e.byteLength,`${r} byteLength`);return this.resolveByteRange(e.memory,e.ptr,e.byteOffset,i,r)}memoryExportNames(){let e=[];for(let[t,r]of Object.entries(this.exportsObject))tn(r)&&e.push(t);return e}resolveByteRange(e,t,r,i,o){let a=this.memory(e);y(tn(a),`${o} requires a valid WebAssembly.Memory.`);let s=this.resolveValue(t,`${o} ptr`),l=El(r,o),u=ea(s,l,`${o} ptr + byteOffset`),c=ea(u,i,`${o} ptr + byteLength`),m=a.buffer.byteLength>>>0;return y(c<=m,`${o} range [${u}, ${c}) is out of bounds for memory byteLength ${m}.`),{memory:a,ptr:u>>>0,byteLength:i>>>0}}resolveValue(e,t){if(typeof e=="number"||typeof e=="bigint")return bt(e,t);if(typeof e=="string"){let o=this.getExport(e);if(typeof o=="function")return bt(o(),`${t} export '${e}' result`);if(En(o))return bt(o.value,`${t} export '${e}' value`);throw new Error(`${t} export '${e}' must be a function or WebAssembly.Global.`)}if(typeof e=="function")return bt(e(),`${t} callback result`);if(y(typeof e=="object"&&e!==null,`${t} descriptor must be a number, bigint, export name string, callback, or descriptor object.`),Object.prototype.hasOwnProperty.call(e,"function")){let o=e;y(typeof o.function=="function",`${t} function descriptor must contain a callable function.`);let a=jn(o.args,t);return bt(o.function(...a),`${t} function result`)}if(Object.prototype.hasOwnProperty.call(e,"global")){let o=e;return y(En(o.global),`${t} global descriptor must contain a WebAssembly.Global.`),bt(o.global.value,`${t} global value`)}y(Object.prototype.hasOwnProperty.call(e,"export"),`${t} descriptor object requires one of 'function', 'global', or 'export'.`);let r=e;if(y(typeof r.export=="string"&&r.export.length>0,`${t} export descriptor requires a non-empty export name.`),y(r.kind===void 0||r.kind==="function"||r.kind==="global",`${t} export descriptor kind must be 'function' or 'global' when provided.`),r.kind==="global")return bt(this.getGlobal(r.export).value,`${t} export '${r.export}' value`);if(r.kind==="function")return bt(this.getFunction(r.export)(...jn(r.args,t)),`${t} export '${r.export}' result`);let i=this.getExport(r.export);if(typeof i=="function")return bt(i(...jn(r.args,t)),`${t} export '${r.export}' result`);if(En(i))return y(jn(r.args,t).length===0,`${t} export '${r.export}' is a global and does not accept args.`),bt(i.value,`${t} export '${r.export}' value`);throw new Error(`${t} export '${r.export}' must be a function or WebAssembly.Global.`)}},rn=class{moduleRef;descriptor;state;cachedBuffer=null;cachedArray=null;cachedBytes=null;cachedDataView=null;constructor(e,t){this.moduleRef=e,this.descriptor=t,this.state=this.moduleRef._resolveView(this.descriptor)}get memory(){return this.state.memory}get ptr(){return this.state.ptr>>>0}get length(){return this.state.length>>>0}get byteLength(){return this.state.byteLength>>>0}get dtype(){return this.state.dtype}get name(){return this.state.name}refresh(){return this.state=this.moduleRef._resolveView(this.descriptor),this.cachedBuffer=null,this.cachedArray=null,this.cachedBytes=null,this.cachedDataView=null,this}array(){return this.ensureCachedViews(),this.cachedArray}bytes(){return this.ensureCachedViews(),this.cachedBytes}dataView(){return this.ensureCachedViews(),this.cachedDataView}copy(){let e=this.array(),t=io(this.dtype),r=new t(new ArrayBuffer(this.byteLength>>>0),0,this.length>>>0);return r.set(e),r}copyInto(e){let t=vt("WasmMemoryView",this.name);if(y(ArrayBuffer.isView(e)&&!(e instanceof DataView),`${t} copyInto target must be a numeric TypedArray.`),e instanceof Uint8Array||e instanceof Int8Array){y(e.byteLength>>>0>=this.byteLength>>>0,`${t} copyInto target is too small for ${this.byteLength} bytes.`),new Uint8Array(e.buffer,e.byteOffset>>>0,this.byteLength>>>0).set(this.bytes());return}let r=io(this.dtype);y(e.constructor===r,`${t} copyInto target must be dtype-compatible with '${this.dtype}'. Use Uint8Array or Int8Array for raw byte copies.`),y(e.length>>>0>=this.length>>>0,`${t} copyInto target is too small for ${this.length} elements.`),e.set(this.array(),0)}ensureCachedViews(){let e=this.state.memory.buffer;if(this.cachedBuffer===e&&this.cachedArray&&this.cachedBytes&&this.cachedDataView)return;let t=io(this.state.dtype);this.cachedBuffer=e,this.cachedArray=new t(e,this.state.ptr>>>0,this.state.length>>>0),this.cachedBytes=new Uint8Array(e,this.state.ptr>>>0,this.state.byteLength>>>0),this.cachedDataView=new DataView(e,this.state.ptr>>>0,this.state.byteLength>>>0)}},nn={fromInstance:(n,e={})=>Yt.fromInstance(n,e),fromExports:(n,e={})=>Yt.fromExports(n,e),fromMemory:(n,e={})=>Yt.fromMemory(n,e)};var on=4294967295,K=class n{static _global=null;static global(){return n._global||(n._global=new n(16384)),n._global}cap;count=0;posPtr=0;rotPtr=0;sclPtr=0;localPtr=0;worldPtr=0;parentPtr=0;orderPtr=0;tmpAxisPtr=0;tmpQuatPtr=0;dirtyIndicesPtr=0;dirtyIndicesCap=0;_buf=null;_f32=null;_u32=null;_dirty=!0;_orderDirty=!0;_dirtyAll=!0;_dirtyList=[];_dirtyMark=new Uint8Array(0);_nodes=[];_freeList=[];_visited=new Uint8Array(0);_stack=[];constructor(e){this.cap=Math.max(1,e|0),this.allocateArrays(this.cap)}allocateArrays(e){this.posPtr=_.allocF32(e*3),this.rotPtr=_.allocF32(e*4),this.sclPtr=_.allocF32(e*3),this.localPtr=_.allocF32(e*16),this.worldPtr=_.allocF32(e*16),this.parentPtr=_.allocU32(e),this.orderPtr=_.allocU32(e),this.tmpAxisPtr=_.allocF32(4),this.tmpQuatPtr=_.allocF32(4),this.ensureViews();let t=this.u32(),r=this.parentPtr>>>2;for(let i=0;i<e;i++)t[r+i]=on}ensureViews(){let e=_.memory().buffer;this._buf!==e&&(this._buf=e,this._f32=new Float32Array(e),this._u32=new Uint32Array(e))}f32(){return this.ensureViews(),this._f32}u32(){return this.ensureViews(),this._u32}ensureDirtyMarkCapacity(){if(this._dirtyMark.length>=this.cap)return;let e=new Uint8Array(this.cap);for(let t=0;t<this._dirtyList.length;t++)e[this._dirtyList[t]]=1;this._dirtyMark=e}ensureDirtyIndexCapacity(e){if(this.dirtyIndicesCap>=e)return;let t=Math.max(1,this.dirtyIndicesCap|0);for(;t<e;)t*=2;this.dirtyIndicesPtr=_.allocU32(t),this.dirtyIndicesCap=t}clearDirtyList(){for(let e=0;e<this._dirtyList.length;e++)this._dirtyMark[this._dirtyList[e]]=0;this._dirtyList.length=0}markDirty(){this._dirty=!0,this._dirtyAll=!0,this.clearDirtyList()}markOrderDirty(){this._orderDirty=!0,this._dirty=!0,this._dirtyAll=!0,this.clearDirtyList()}markIndexDirty(e){e<0||e>=this.count||(this._dirty=!0,!this._dirtyAll&&(this.ensureDirtyMarkCapacity(),!this._dirtyMark[e]&&(this._dirtyMark[e]=1,this._dirtyList.push(e))))}alloc(e){let t;if(this._freeList.length>0){if(t=this._freeList.pop(),t<0)throw new Error("TransformStore.alloc: corrupted free list (negative index).");if(t>=this.count&&(this.count=t+1),this._nodes[t]!==null&&this._nodes[t]!==void 0)throw new Error(`TransformStore.alloc: free list returned an in-use slot ${t}.`)}else this.count>=this.cap&&this.growTo(this.cap*2),t=this.count++;return this._nodes[t]=e,this.initDefaults(t),this._orderDirty=!0,this._dirty=!0,this._dirtyAll=!0,t}initDefaults(e){this.ensureViews();let t=this.f32(),r=this.u32(),i=(this.posPtr>>>2)+e*3;t[i+0]=0,t[i+1]=0,t[i+2]=0;let o=(this.rotPtr>>>2)+e*4;t[o+0]=0,t[o+1]=0,t[o+2]=0,t[o+3]=1;let a=(this.sclPtr>>>2)+e*3;t[a+0]=1,t[a+1]=1,t[a+2]=1,r[(this.parentPtr>>>2)+e]=on}setParent(e,t){this.ensureViews();let r=this.u32();r[(this.parentPtr>>>2)+e]=t===null?on:t>>>0,this._orderDirty=!0,this._dirty=!0,this._dirtyAll=!0}free(e){if(e<0||e>=this.count)throw new Error(`TransformStore.free: index out of range: ${e} (count=${this.count})`);if(!this._nodes[e])throw new Error(`TransformStore.free: double free or invalid slot: ${e}`);this._nodes[e]=null,this.ensureViews();let r=this.f32(),i=this.u32(),o=(this.posPtr>>>2)+e*3;r[o+0]=0,r[o+1]=0,r[o+2]=0;let a=(this.rotPtr>>>2)+e*4;r[a+0]=0,r[a+1]=0,r[a+2]=0,r[a+3]=1;let s=(this.sclPtr>>>2)+e*3;r[s+0]=1,r[s+1]=1,r[s+2]=1,i[(this.parentPtr>>>2)+e]=on;let l=(this.localPtr>>>2)+e*16,u=(this.worldPtr>>>2)+e*16;for(let c=0;c<16;c++)r[l+c]=0,r[u+c]=0;for(r[l+0]=1,r[l+5]=1,r[l+10]=1,r[l+15]=1,r[u+0]=1,r[u+5]=1,r[u+10]=1,r[u+15]=1,this._freeList.push(e),this._orderDirty=!0,this._dirty=!0,this._dirtyAll=!0;this.count>0;){let c=this.count-1;if(this._nodes[c])break;this.count--}}updateIfNeeded(){this._dirty&&this.update()}update(){let e=this.count|0;if(e===0){this._dirty=!1,this._dirtyAll=!1,this._orderDirty=!1,this.clearDirtyList();return}this.ensureDirtyMarkCapacity();let t=this._dirtyAll?e:this._dirtyList.length|0;if(this._orderDirty||this._dirtyAll||t>e>>>2){this._orderDirty&&this.buildOrder(),At.composeLocalMany(this.localPtr,this.posPtr,this.rotPtr,this.sclPtr,e),At.updateWorldOrdered(this.worldPtr,this.localPtr,this.parentPtr,this.orderPtr,e),this._dirty=!1,this._dirtyAll=!1,this._orderDirty=!1,this.clearDirtyList();return}if(this._dirtyList.length===0){this._dirty=!1;return}this.ensureViews(),this.ensureDirtyIndexCapacity(this._dirtyList.length);let i=this.u32().subarray(this.dirtyIndicesPtr>>>2,(this.dirtyIndicesPtr>>>2)+this._dirtyList.length);for(let o=0;o<this._dirtyList.length;o++)i[o]=this._dirtyList[o]>>>0;At.updatePartialOrdered(this.worldPtr,this.localPtr,this.posPtr,this.rotPtr,this.sclPtr,this.parentPtr,this.orderPtr,this.dirtyIndicesPtr,this._dirtyList.length,e),this._dirty=!1,this.clearDirtyList()}buildOrder(){let e=this.count;this._visited.length<e&&(this._visited=new Uint8Array(e)),this._visited.fill(0,0,e);let t=this.u32(),r=this.parentPtr>>>2,i=this.orderPtr>>>2,o=0,a=this._stack;a.length=0;for(let s=0;s<e;s++)if(!this._visited[s]&&t[r+s]===on)for(a.push(s);a.length;){let l=a.pop();if(this._visited[l])continue;this._visited[l]=1,t[i+o++]=l>>>0;let c=this._nodes[l]?.children??[];for(let m=c.length-1;m>=0;m--)a.push(c[m].index)}for(let s=0;s<e;s++)this._visited[s]||(this._visited[s]=1,t[i+o++]=s>>>0);this._orderDirty=!1}growTo(e){let t=this.cap;for(;t<e;)t*=2;let r=this.count,i=this.posPtr,o=this.rotPtr,a=this.sclPtr,s=this.localPtr,l=this.worldPtr,u=this.parentPtr,c=this.orderPtr;this.cap=t,this.allocateArrays(t),this.ensureViews();let m=this.f32(),d=this.u32();m.set(m.subarray(i>>>2,(i>>>2)+r*3),this.posPtr>>>2),m.set(m.subarray(o>>>2,(o>>>2)+r*4),this.rotPtr>>>2),m.set(m.subarray(a>>>2,(a>>>2)+r*3),this.sclPtr>>>2),m.set(m.subarray(s>>>2,(s>>>2)+r*16),this.localPtr>>>2),m.set(m.subarray(l>>>2,(l>>>2)+r*16),this.worldPtr>>>2),d.set(d.subarray(u>>>2,(u>>>2)+r),this.parentPtr>>>2),d.set(d.subarray(c>>>2,(c>>>2)+r),this.orderPtr>>>2),this._orderDirty=!0,this._dirty=!0,this._dirtyAll=!0}},we=class n{index;_parent=null;_children=[];_position=[0,0,0];_rotation=[0,0,0,1];_scale=[1,1,1];_localMatrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];_worldMatrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];_disposed=!1;constructor(){let e=K.global();this.index=e.alloc(this)}static updateAll(){K.global().updateIfNeeded()}assertAlive(){if(this._disposed)throw new Error("Transform is disposed (use-after-dispose).")}get disposed(){return this._disposed}get parent(){return this._parent}get children(){return this._children}get root(){let e=this;for(;e._parent;)e=e._parent;return e}traverse(e){e(this);for(let t of this._children)t.traverse(e)}readVec3FromStore(e,t){let i=K.global().f32();t[0]=i[e+0],t[1]=i[e+1],t[2]=i[e+2]}readQuatFromStore(e,t){let i=K.global().f32();t[0]=i[e+0],t[1]=i[e+1],t[2]=i[e+2],t[3]=i[e+3]}readMat4FromStore(e,t){let i=K.global().f32();for(let o=0;o<16;o++)t[o]=i[e+o]}get positionPtr(){return this.assertAlive(),K.global().posPtr+this.index*3*4>>>0}get rotationPtr(){return this.assertAlive(),K.global().rotPtr+this.index*4*4>>>0}get scalePtr(){return this.assertAlive(),K.global().sclPtr+this.index*3*4>>>0}get localMatrixPtr(){return this.assertAlive(),K.global().localPtr+this.index*16*4>>>0}get worldMatrixPtr(){return this.assertAlive(),K.global().worldPtr+this.index*16*4>>>0}get position(){return this._position}setPosition(e,t,r){this.assertAlive();let i=K.global(),o=i.f32(),a=(i.posPtr>>>2)+this.index*3;return o[a+0]=e,o[a+1]=t,o[a+2]=r,this._position[0]=e,this._position[1]=t,this._position[2]=r,i.markIndexDirty(this.index),this}translate(e,t,r){return this.assertAlive(),this.setPosition(this._position[0]+e,this._position[1]+t,this._position[2]+r)}get rotation(){return this._rotation}setRotation(e,t,r,i){this.assertAlive();let o=K.global(),a=this.rotationPtr;Be.init(a,e,t,r,i),Be.normalize(a,a);let s=(o.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(s,this._rotation),o.markIndexDirty(this.index),this}setRotationFromAxisAngle(e,t){this.assertAlive();let r=K.global(),i=r.f32(),o=r.tmpAxisPtr>>>2;i[o+0]=e[0],i[o+1]=e[1],i[o+2]=e[2],qt.normalize(r.tmpAxisPtr,r.tmpAxisPtr);let a=this.rotationPtr;Be.fromAxisAngle(a,r.tmpAxisPtr,t),Be.normalize(a,a);let s=(r.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(s,this._rotation),r.markIndexDirty(this.index),this}setRotationFromEuler(e,t,r){this.assertAlive();let i=e*.5,o=t*.5,a=r*.5,s=Math.sin(i),l=Math.cos(i),u=Math.sin(o),c=Math.cos(o),m=Math.sin(a),d=Math.cos(a),f=s*c*d+l*u*m,p=l*u*d-s*c*m,h=l*c*m+s*u*d,g=l*c*d-s*u*m;return this.setRotation(f,p,h,g)}rotateOnAxis(e,t){this.assertAlive();let r=K.global(),i=r.f32(),o=r.tmpAxisPtr>>>2;i[o+0]=e[0],i[o+1]=e[1],i[o+2]=e[2],qt.normalize(r.tmpAxisPtr,r.tmpAxisPtr),Be.fromAxisAngle(r.tmpQuatPtr,r.tmpAxisPtr,t);let a=this.rotationPtr;Be.mul(a,a,r.tmpQuatPtr),Be.normalize(a,a);let s=(r.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(s,this._rotation),r.markIndexDirty(this.index),this}rotateX(e){this.assertAlive();let t=K.global(),r=t.f32(),i=t.tmpAxisPtr>>>2;r[i+0]=1,r[i+1]=0,r[i+2]=0,qt.normalize(t.tmpAxisPtr,t.tmpAxisPtr),Be.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;Be.mul(o,o,t.tmpQuatPtr),Be.normalize(o,o);let a=(t.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(a,this._rotation),t.markIndexDirty(this.index),this}rotateY(e){this.assertAlive();let t=K.global(),r=t.f32(),i=t.tmpAxisPtr>>>2;r[i+0]=0,r[i+1]=1,r[i+2]=0,qt.normalize(t.tmpAxisPtr,t.tmpAxisPtr),Be.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;Be.mul(o,o,t.tmpQuatPtr),Be.normalize(o,o);let a=(t.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(a,this._rotation),t.markIndexDirty(this.index),this}rotateZ(e){this.assertAlive();let t=K.global(),r=t.f32(),i=t.tmpAxisPtr>>>2;r[i+0]=0,r[i+1]=0,r[i+2]=1,qt.normalize(t.tmpAxisPtr,t.tmpAxisPtr),Be.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;Be.mul(o,o,t.tmpQuatPtr),Be.normalize(o,o);let a=(t.rotPtr>>>2)+this.index*4;return this.readQuatFromStore(a,this._rotation),t.markIndexDirty(this.index),this}get scale(){return this._scale}setScale(e,t,r){this.assertAlive();let i=K.global(),o=i.f32(),a=(i.sclPtr>>>2)+this.index*3;return o[a+0]=e,o[a+1]=t,o[a+2]=r,this._scale[0]=e,this._scale[1]=t,this._scale[2]=r,i.markIndexDirty(this.index),this}setUniformScale(e){return this.assertAlive(),this.setScale(e,e,e)}get localMatrix(){this.assertAlive();let e=K.global();e.updateIfNeeded();let t=(e.localPtr>>>2)+this.index*16;return this.readMat4FromStore(t,this._localMatrix),this._localMatrix}get worldMatrix(){this.assertAlive();let e=K.global();e.updateIfNeeded();let t=(e.worldPtr>>>2)+this.index*16;return this.readMat4FromStore(t,this._worldMatrix),this._worldMatrix}get worldPosition(){this.assertAlive();let e=K.global();e.updateIfNeeded();let t=(e.worldPtr>>>2)+this.index*16,r=e.f32();return[r[t+12],r[t+13],r[t+14]]}setParent(e){if(this.assertAlive(),e===this._parent)return this;if(e===this)throw new Error("Transform cannot be parented to itself.");for(let t=e;t;t=t._parent)if(t===this)throw new Error("Transform parenting would create a cycle.");return this.removeFromParent(),this._parent=e,e?(e._children.push(this),K.global().setParent(this.index,e.index)):K.global().setParent(this.index,null),this}addChild(e){return this.assertAlive(),e.setParent(this),this}removeChild(e){return this.assertAlive(),e._parent!==this?this:(e.setParent(null),this)}removeFromParent(){if(this.assertAlive(),!this._parent)return this;let e=this._parent,t=e._children.indexOf(this);return t>=0&&e._children.splice(t,1),this._parent=null,K.global().setParent(this.index,null),this}reset(){return this.assertAlive(),this._parent=null,this._children.length=0,K.global().setParent(this.index,null),this.setPosition(0,0,0),this.setRotation(0,0,0,1),this.setScale(1,1,1),this}copyFrom(e){return this.assertAlive(),this.setPosition(e._position[0],e._position[1],e._position[2]),this.setRotation(e._rotation[0],e._rotation[1],e._rotation[2],e._rotation[3]),this.setScale(e._scale[0],e._scale[1],e._scale[2]),this}clone(){this.assertAlive();let e=new n;return e.copyFrom(this),e}dispose(){if(this._disposed)return;let e=this._children.slice();for(let t of e)t.setParent(null);this._children.length=0,this.removeFromParent(),K.global().free(this.index),this._disposed=!0}};var uo=0,oo=0,Hn=0,$n=0,qn=0,Kn=0,co=0,ao=0,mo=0,so=0,fo=0,lo=0,jl=n=>{oo<n&&(oo=Yr(n),uo=_.allocF32(oo)),Hn===0&&(Hn=_.allocF32(3)),$n===0&&($n=_.allocF32(3)),qn===0&&(qn=_.allocF32(3)),Kn===0&&(Kn=_.allocF32(1))},Hl=(n,e)=>{ao<n&&(ao=Yr(n),co=_.allocF32(ao)),lo<n&&(lo=Yr(n),fo=_.allocF32(lo)),e>0&&so<e&&(so=Yr(e),mo=_.allocU32(so))},po=n=>{let e=n.length/3|0;if(e<=0)return{boxMin:[0,0,0],boxMax:[0,0,0],sphereCenter:[0,0,0],sphereRadius:0};jl(n.length),_.f32view(uo,n.length).set(n),Ht.geometryPositions(Hn,$n,qn,Kn,uo,e);let t=_.f32view(Hn,3),r=_.f32view($n,3),i=_.f32view(qn,3),o=_.f32view(Kn,1);return{boxMin:[t[0],t[1],t[2]],boxMax:[r[0],r[1],r[2]],sphereCenter:[i[0],i[1],i[2]],sphereRadius:o[0]}},Xn=(n,e)=>{let t=n.length/3|0,r=e?e.length|0:0;Hl(n.length,r),_.f32view(co,n.length).set(n);let i=e&&r>0?mo:0;e&&r>0&&_.u32view(mo,r).set(e),Qi.computeVertexNormals(fo,co,t,i,r);let o=new Float32Array(n.length);return o.set(_.f32view(fo,n.length)),o},$l=(n,e,t)=>{let r=n[e+0]??t[0],i=n[e+1]??t[1],o=n[e+2]??t[2],a=Math.hypot(r,i,o);return a<=1e-12?t:(r/=a,i/=a,o/=a,[r,i,o])},ql=(n,e,t)=>{let r=Math.abs(n)<.9?1:0,i=r===1?0:1,o=0,a=i*t-o*e,s=o*n-r*t,l=r*e-i*n,u=Math.hypot(a,s,l);return u<=1e-12?[1,0,0]:(a/=u,s/=u,l/=u,[a,s,l])},ta=(n,e,t,r)=>{let i=n.length/3|0,o=new Float32Array(i*4),a=new Float32Array(i*3),s=new Float32Array(i*3),l=r?r.length:i,u=c=>r?r[c]:c;for(let c=0;c+2<l;c+=3){let m=u(c+0),d=u(c+1),f=u(c+2),p=m*3,h=d*3,g=f*3,b=m*2,P=d*2,v=f*2,x=n[h+0]-n[p+0],T=n[h+1]-n[p+1],w=n[h+2]-n[p+2],M=n[g+0]-n[p+0],B=n[g+1]-n[p+1],S=n[g+2]-n[p+2],R=t[P+0]-t[b+0],G=t[P+1]-t[b+1],L=t[v+0]-t[b+0],U=t[v+1]-t[b+1],F=R*U-L*G;if(Math.abs(F)<=1e-12)continue;let D=1/F,k=(U*x-G*M)*D,A=(U*T-G*B)*D,I=(U*w-G*S)*D,O=(R*M-L*x)*D,N=(R*B-L*T)*D,z=(R*S-L*w)*D,E=m*3;a[E+0]+=k,a[E+1]+=A,a[E+2]+=I,s[E+0]+=O,s[E+1]+=N,s[E+2]+=z;let H=d*3;a[H+0]+=k,a[H+1]+=A,a[H+2]+=I,s[H+0]+=O,s[H+1]+=N,s[H+2]+=z;let j=f*3;a[j+0]+=k,a[j+1]+=A,a[j+2]+=I,s[j+0]+=O,s[j+1]+=N,s[j+2]+=z}for(let c=0;c<i;c++){let m=c*3,d=c*3,f=c*4,[p,h,g]=$l(e,m,[0,1,0]),b=a[d+0],P=a[d+1],v=a[d+2],x=p*b+h*P+g*v;b-=p*x,P-=h*x,v-=g*x;let T=Math.hypot(b,P,v);T<=1e-12?[b,P,v]=ql(p,h,g):(b/=T,P/=T,v/=T);let w=h*v-g*P,M=g*b-p*v,B=p*P-h*b,S=s[d+0],R=s[d+1],G=s[d+2],L=w*S+M*R+B*G<0?-1:1;o[f+0]=b,o[f+1]=P,o[f+2]=v,o[f+3]=L}return o},Kl=n=>{let e=new Float32Array(n*4);for(let t=0;t<n;t++)e[t*4+3]=1;return e},Xl=(n,e,t,r)=>{let i=n.length/4|0,o=t!==null&&r!==null,a=o?48:24,s=new Uint8Array(i*a),l=new DataView(s.buffer);for(let u=0;u<i;u++){let c=u*a,m=u*4;for(let d=0;d<4;d++)l.setUint16(c+d*2,n[m+d]??0,!0);for(let d=0;d<4;d++)l.setFloat32(c+8+d*4,e[m+d]??0,!0);if(o){for(let d=0;d<4;d++)l.setUint16(c+24+d*2,t[m+d]??0,!0);for(let d=0;d<4;d++)l.setFloat32(c+32+d*4,r[m+d]??0,!0)}}return s},ae=class n{positions;normals;tangents;uvs;uvs1;joints;weights;joints1;weights1;_jointsBuffer=null;_weightsBuffer=null;_joints1Buffer=null;_weights1Buffer=null;_skinInfluenceBuffer=null;indices;morphTargets;authoredNormals;vertexCount;indexCount;_boundsMin;_boundsMax;_boundsCenter;_boundsRadius;_positionBuffer=null;_normalBuffer=null;_tangentBuffer=null;_uvBuffer=null;_uv1Buffer=null;_indexBuffer=null;_device=null;_refCount=1;_destroyed=!1;constructor(e){this.positions=e.positions,this.vertexCount=Math.floor(this.positions.length/3),this.positions.length!==this.vertexCount*3&&console.warn(`[Geometry] positions length ${this.positions.length} is not divisible by 3; trailing components ignored.`);let t=this.vertexCount*3,r=e.normals?e.authoredNormals??!0:!1,i=e.normals??new Float32Array(t),o=!e.normals;if(i.length!==t&&(console.warn(`[Geometry] normals length mismatch (got ${i.length}, expected ${t}). Using fallback normals.`),i=new Float32Array(t),r=!1,o=!0),o)for(let b=1;b<i.length;b+=3)i[b]=1;this.authoredNormals=r,this.normals=i;let a=this.vertexCount*4,s=e.tangents??null;s&&s.length!==a&&(console.warn(`[Geometry] tangents length mismatch (got ${s.length}, expected ${a}). Using fallback tangents.`),s=null);let l=this.vertexCount*2,u=e.uvs??new Float32Array(l);u.length!==l&&(console.warn(`[Geometry] uvs length mismatch (got ${u.length}, expected ${l}). TEXCOORD_0 disabled.`),u=new Float32Array(l)),this.uvs=u,this.tangents=s??Kl(this.vertexCount);let c=e.uvs1??new Float32Array(l);c.length!==l&&(console.warn(`[Geometry] uvs1 length mismatch (got ${c.length}, expected ${l}). TEXCOORD_1 disabled.`),c=new Float32Array(l)),this.uvs1=c,this.morphTargets=e.morphTargets??[];let m=e.joints??null,d=e.weights??null,f=this.vertexCount*4;(m&&!d||!m&&d)&&(console.warn("[Geometry] JOINTS_0/WEIGHTS_0 must be provided together. Skinning disabled for this geometry."),m=null,d=null),m&&m.length!==f&&(console.warn(`[Geometry] joints length mismatch (got ${m.length}, expected ${f}). Skinning disabled.`),m=null,d=null),d&&d.length!==f&&(console.warn(`[Geometry] weights length mismatch (got ${d.length}, expected ${f}). Skinning disabled.`),m=null,d=null),this.joints=m,this.weights=d;let p=e.joints1??null,h=e.weights1??null;(p&&!h||!p&&h)&&(console.warn("[Geometry] JOINTS_1/WEIGHTS_1 must be provided together. Ignoring additional influences."),p=null,h=null),(p||h)&&(!m||!d)&&(console.warn("[Geometry] JOINTS_1/WEIGHTS_1 provided without JOINTS_0/WEIGHTS_0. Ignoring additional influences."),p=null,h=null),p&&p.length!==f&&(console.warn(`[Geometry] joints1 length mismatch (got ${p.length}, expected ${f}). Ignoring additional influences.`),p=null,h=null),h&&h.length!==f&&(console.warn(`[Geometry] weights1 length mismatch (got ${h.length}, expected ${f}). Ignoring additional influences.`),p=null,h=null),this.joints1=p,this.weights1=h,this.indices=e.indices??null,this.indexCount=this.indices?.length??this.vertexCount;let g=po(this.positions);this._boundsMin=g.boxMin,this._boundsMax=g.boxMax,this._boundsCenter=g.sphereCenter,this._boundsRadius=g.sphereRadius}assertAlive(e){if(this._destroyed)throw new Error(`Geometry: cannot ${e}; resource has already been released.`)}retain(){return this.assertAlive("retain"),this._refCount++,this}release(){if(this._destroyed)throw new Error("Geometry: release() called after the resource was already released.");if(this._refCount<=0)throw new Error("Geometry: reference count underflow.");this._refCount--,!(this._refCount>0)&&(this._destroyed=!0,this.disposeResources())}upload(e){this.assertAlive("upload"),this._device!==e&&(this._device=e,this._positionBuffer=ne(e,this.positions,GPUBufferUsage.VERTEX),this._normalBuffer=ne(e,this.normals,GPUBufferUsage.VERTEX),this._tangentBuffer=ne(e,this.tangents,GPUBufferUsage.VERTEX),this._uvBuffer=ne(e,this.uvs,GPUBufferUsage.VERTEX),this._uv1Buffer=ne(e,this.uvs1,GPUBufferUsage.VERTEX),this.joints&&(this._jointsBuffer=ne(e,this.joints,GPUBufferUsage.VERTEX)),this.weights&&(this._weightsBuffer=ne(e,this.weights,GPUBufferUsage.VERTEX)),this.joints1&&(this._joints1Buffer=ne(e,this.joints1,GPUBufferUsage.VERTEX)),this.weights1&&(this._weights1Buffer=ne(e,this.weights1,GPUBufferUsage.VERTEX)),this.joints&&this.weights&&(this._skinInfluenceBuffer=ne(e,Xl(this.joints,this.weights,this.joints1,this.weights1),GPUBufferUsage.VERTEX)),this.indices&&(this._indexBuffer=ne(e,this.indices,GPUBufferUsage.INDEX)))}get positionBuffer(){if(this.assertAlive("access positionBuffer"),!this._positionBuffer)throw new Error("Geometry not uploaded. Call upload(device) first.");return this._positionBuffer}get normalBuffer(){if(this.assertAlive("access normalBuffer"),!this._normalBuffer)throw new Error("Geometry not uploaded. Call upload(device) first.");return this._normalBuffer}get tangentBuffer(){if(this.assertAlive("access tangentBuffer"),!this._tangentBuffer)throw new Error("Geometry not uploaded. Call upload(device) first.");return this._tangentBuffer}get uvBuffer(){if(this.assertAlive("access uvBuffer"),!this._uvBuffer)throw new Error("Geometry not uploaded. Call upload(device) first.");return this._uvBuffer}get uv1Buffer(){if(this.assertAlive("access uv1Buffer"),!this._uv1Buffer)throw new Error("Geometry not uploaded. Call upload(device) first.");return this._uv1Buffer}get jointsBuffer(){return this._jointsBuffer}get weightsBuffer(){return this._weightsBuffer}get joints1Buffer(){return this._joints1Buffer}get weights1Buffer(){return this._weights1Buffer}get skinInfluenceBuffer(){return this._skinInfluenceBuffer}get indexBuffer(){return this._indexBuffer}get isIndexed(){return this._indexBuffer!==null}get isSkinned(){return this._jointsBuffer!==null&&this._weightsBuffer!==null}get isSkinned8(){return this._jointsBuffer!==null&&this._weightsBuffer!==null&&this._joints1Buffer!==null&&this._weights1Buffer!==null}get boundsMin(){return this._boundsMin}get boundsMax(){return this._boundsMax}get boundsCenter(){return this._boundsCenter}get boundsRadius(){return this._boundsRadius}destroy(){this.release()}disposeResources(){this._positionBuffer?.destroy(),this._normalBuffer?.destroy(),this._tangentBuffer?.destroy(),this._uvBuffer?.destroy(),this._uv1Buffer?.destroy(),this._jointsBuffer?.destroy(),this._weightsBuffer?.destroy(),this._joints1Buffer?.destroy(),this._weights1Buffer?.destroy(),this._skinInfluenceBuffer?.destroy(),this._jointsBuffer=null,this._weightsBuffer=null,this._joints1Buffer=null,this._weights1Buffer=null,this._skinInfluenceBuffer=null,this._indexBuffer?.destroy(),this._positionBuffer=null,this._normalBuffer=null,this._tangentBuffer=null,this._uvBuffer=null,this._uv1Buffer=null,this._indexBuffer=null,this._device=null}static point(e=1,t="xy",r=!1){return n.rectangle(e,e,t,r)}static line(e=1,t=.01,r="xy",i=!1){return n.rectangle(e,t,r,i)}static plane(e=1,t=1,r=1,i=1){let o=e/2,a=t/2,s=r,l=i,u=s+1,c=l+1,m=e/s,d=t/l,f=[],p=[],h=[],g=[];for(let b=0;b<c;b++){let P=b*d-a;for(let v=0;v<u;v++){let x=v*m-o;f.push(x,0,P),p.push(0,1,0),h.push(v/s,1-b/l)}}for(let b=0;b<l;b++)for(let P=0;P<s;P++){let v=P+u*b,x=P+u*(b+1),T=P+1+u*(b+1),w=P+1+u*b;g.push(v,x,w,x,T,w)}return new n({positions:new Float32Array(f),normals:new Float32Array(p),uvs:new Float32Array(h),indices:new Uint32Array(g)})}static triangle(e=1,t=1,r="xy",i=!1){let o=e/2,a=t/2,s=[],l=[],u=[],c=[],m=r==="xz",d=0,f=0,p=0;switch(r){case"xy":p=1;break;case"xz":f=1;break;case"yz":d=1;break}let h=v=>e!==0?v/e+.5:.5,g=v=>t!==0?-v/t+.5:.5,b=(v,x)=>{switch(r){case"xy":s.push(v,x,0);break;case"xz":s.push(v,0,x);break;case"yz":s.push(0,v,x);break}l.push(d,f,p),u.push(h(v),g(x))};b(-o,-a),b(o,-a),b(0,a),m?c.push(0,2,1):c.push(0,1,2);let P={positions:new Float32Array(s),normals:new Float32Array(l),uvs:new Float32Array(u),indices:new Uint32Array(c)};return new n(i?n._makeDoubleSided(P):P)}static rectangle(e=1,t=1,r="xy",i=!1){let o=e/2,a=t/2,s=[],l=[],u=[],c=[],m=r==="xz",d=0,f=0,p=0;switch(r){case"xy":p=1;break;case"xz":f=1;break;case"yz":d=1;break}let h=(b,P,v,x)=>{switch(r){case"xy":s.push(b,P,0);break;case"xz":s.push(b,0,P);break;case"yz":s.push(0,b,P);break}l.push(d,f,p),u.push(v,x)};h(-o,-a,0,1),h(o,-a,1,1),h(o,a,1,0),h(-o,a,0,0),m?c.push(0,2,1,0,3,2):c.push(0,1,2,0,2,3);let g={positions:new Float32Array(s),normals:new Float32Array(l),uvs:new Float32Array(u),indices:new Uint32Array(c)};return new n(i?n._makeDoubleSided(g):g)}static circle(e=.5,t=64,r="xy",i=!1){let o=Math.max(3,Math.floor(t)),a=[],s=[],l=[],u=[],c=r==="xz",m=0,d=0,f=0;switch(r){case"xy":f=1;break;case"xz":d=1;break;case"yz":m=1;break}let p=e!==0?1/(2*e):0,h=(b,P)=>{switch(r){case"xy":a.push(b,P,0);break;case"xz":a.push(b,0,P);break;case"yz":a.push(0,b,P);break}s.push(m,d,f);let v=e!==0?.5+b*p:.5,x=e!==0?.5-P*p:.5;l.push(v,x)};h(0,0);for(let b=0;b<o;b++){let P=b/o*Math.PI*2,v=Math.cos(P)*e,x=Math.sin(P)*e;h(v,x)}for(let b=0;b<o;b++){let v=1+b,x=1+(b+1)%o;c?u.push(0,x,v):u.push(0,v,x)}let g={positions:new Float32Array(a),normals:new Float32Array(s),uvs:new Float32Array(l),indices:new Uint32Array(u)};return new n(i?n._makeDoubleSided(g):g)}static ellipse(e=.5,t=.5,r=64,i="xy",o=!1){let a=Math.max(3,Math.floor(r)),s=[],l=[],u=[],c=[],m=i==="xz",d=0,f=0,p=0;switch(i){case"xy":p=1;break;case"xz":f=1;break;case"yz":d=1;break}let h=e!==0?1/(2*e):0,g=t!==0?1/(2*t):0,b=(v,x)=>{switch(i){case"xy":s.push(v,x,0);break;case"xz":s.push(v,0,x);break;case"yz":s.push(0,v,x);break}l.push(d,f,p);let T=e!==0?.5+v*h:.5,w=t!==0?.5-x*g:.5;u.push(T,w)};b(0,0);for(let v=0;v<a;v++){let x=v/a*Math.PI*2,T=Math.cos(x)*e,w=Math.sin(x)*t;b(T,w)}for(let v=0;v<a;v++){let T=1+v,w=1+(v+1)%a;m?c.push(0,w,T):c.push(0,T,w)}let P={positions:new Float32Array(s),normals:new Float32Array(l),uvs:new Float32Array(u),indices:new Uint32Array(c)};return new n(o?n._makeDoubleSided(P):P)}static box(e=1,t=1,r=1){let i=e/2,o=t/2,a=r/2,s=new Float32Array([-i,-o,a,i,-o,a,i,o,a,-i,o,a,i,-o,-a,-i,-o,-a,-i,o,-a,i,o,-a,-i,o,a,i,o,a,i,o,-a,-i,o,-a,-i,-o,-a,i,-o,-a,i,-o,a,-i,-o,a,i,-o,a,i,-o,-a,i,o,-a,i,o,a,-i,-o,-a,-i,-o,a,-i,o,a,-i,o,-a]),l=new Float32Array([0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0]),u=new Float32Array([0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0]),c=new Uint32Array([0,1,2,0,2,3,4,5,6,4,6,7,8,9,10,8,10,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23]);return new n({positions:s,normals:l,uvs:u,indices:c})}static sphere(e=.5,t=32,r=16){let i=[],o=[],a=[],s=[];for(let l=0;l<=r;l++){let u=l/r,c=u*Math.PI;for(let m=0;m<=t;m++){let d=m/t,f=d*Math.PI*2,p=-Math.cos(f)*Math.sin(c),h=Math.cos(c),g=Math.sin(f)*Math.sin(c);i.push(e*p,e*h,e*g),o.push(p,h,g),a.push(d,u)}}for(let l=0;l<r;l++)for(let u=0;u<t;u++){let c=u+(t+1)*l,m=u+(t+1)*(l+1),d=u+1+(t+1)*(l+1),f=u+1+(t+1)*l;l!==0&&s.push(c,m,f),l!==r-1&&s.push(m,d,f)}return new n({positions:new Float32Array(i),normals:new Float32Array(o),uvs:new Float32Array(a),indices:new Uint32Array(s)})}static cylinder(e=.5,t=.5,r=1,i=32,o=1,a=!1){let s=[],l=[],u=[],c=[],m=0,d=r/2,f=(t-e)/r;for(let g=0;g<=o;g++){let b=g/o,P=b*r-d,v=b*(e-t)+t;for(let x=0;x<=i;x++){let T=x/i,w=T*Math.PI*2,M=Math.sin(w),B=Math.cos(w);s.push(v*M,P,v*B);let S=Math.sqrt(1+f*f);l.push(M/S,f/S,B/S),u.push(T,1-b)}}for(let g=0;g<o;g++)for(let b=0;b<i;b++){let P=b+(i+1)*g,v=b+(i+1)*(g+1),x=b+1+(i+1)*(g+1),T=b+1+(i+1)*g;c.push(P,T,v,v,T,x)}m=s.length/3;let p=()=>{let g=m;s.push(0,d,0),l.push(0,1,0),u.push(.5,.5),m++;for(let b=0;b<=i;b++){let v=b/i*Math.PI*2,x=e*Math.sin(v),T=e*Math.cos(v);s.push(x,d,T),l.push(0,1,0),u.push(Math.sin(v)*.5+.5,Math.cos(v)*.5+.5),b>0&&c.push(g,m-1,m),m++}},h=()=>{let g=m;s.push(0,-d,0),l.push(0,-1,0),u.push(.5,.5),m++;for(let b=0;b<=i;b++){let v=b/i*Math.PI*2,x=t*Math.sin(v),T=t*Math.cos(v);s.push(x,-d,T),l.push(0,-1,0),u.push(Math.sin(v)*.5+.5,Math.cos(v)*.5+.5),b>0&&c.push(g,m,m-1),m++}};return a||(p(),h()),new n({positions:new Float32Array(s),normals:new Float32Array(l),uvs:new Float32Array(u),indices:new Uint32Array(c)})}static pyramid(e=1,t=1,r=1){let i=e/2,o=t/2,s=[0,r,0],l=[-i,0,-o],u=[i,0,-o],c=[i,0,o],m=[-i,0,o],d=(x,T,w)=>{let M=T[0]-x[0],B=T[1]-x[1],S=T[2]-x[2],R=w[0]-x[0],G=w[1]-x[1],L=w[2]-x[2],U=B*L-S*G,F=S*R-M*L,D=M*G-B*R,k=Math.sqrt(U*U+F*F+D*D);return[U/k,F/k,D/k]},f=[],p=[],h=[],g=[],b=0,P=(x,T,w)=>{let M=d(x,T,w);f.push(...x,...T,...w),p.push(...M,...M,...M),h.push(.5,0,0,1,1,1),g.push(b,b+1,b+2),b+=3};P(s,m,c),P(s,c,u),P(s,u,l),P(s,l,m);let v=[0,-1,0];return f.push(...l,...u,...c,...m),p.push(...v,...v,...v,...v),h.push(0,0,1,0,1,1,0,1),g.push(b,b+1,b+2,b,b+2,b+3),new n({positions:new Float32Array(f),normals:new Float32Array(p),uvs:new Float32Array(h),indices:new Uint32Array(g)})}static torus(e=.5,t=.2,r=32,i=24){let o=[],a=[],s=[],l=[];for(let u=0;u<=r;u++)for(let c=0;c<=i;c++){let m=c/i*Math.PI*2,d=u/r*Math.PI*2,f=(e+t*Math.cos(d))*Math.cos(m),p=t*Math.sin(d),h=(e+t*Math.cos(d))*Math.sin(m);o.push(f,p,h);let g=e*Math.cos(m),b=e*Math.sin(m),P=f-g,v=p,x=h-b,T=Math.sqrt(P*P+v*v+x*x);a.push(P/T,v/T,x/T),s.push(c/i,u/r)}for(let u=0;u<r;u++)for(let c=0;c<i;c++){let m=c+(i+1)*u,d=c+(i+1)*(u+1),f=c+1+(i+1)*(u+1),p=c+1+(i+1)*u;l.push(m,d,p,d,f,p)}return new n({positions:new Float32Array(o),normals:new Float32Array(a),uvs:new Float32Array(s),indices:new Uint32Array(l)})}static prism(e=.5,t=1,r=6){r<3&&(r=3);let i=[],o=[],a=[],s=[],l=t/2,u=0,c=[],m=[];for(let v=0;v<r;v++){let x=v/r*Math.PI*2,T=e*Math.cos(x),w=e*Math.sin(x);c.push([T,l,w]),m.push([T,-l,w])}let d=(v,x,T)=>{let w=x[0]-v[0],M=x[1]-v[1],B=x[2]-v[2],S=T[0]-v[0],R=T[1]-v[1],G=T[2]-v[2],L=M*G-B*R,U=B*S-w*G,F=w*R-M*S,D=Math.sqrt(L*L+U*U+F*F);return[L/D,U/D,F/D]};for(let v=0;v<r;v++){let x=(v+1)%r,T=c[v],w=c[x],M=m[v],B=m[x],S=d(T,w,M);i.push(...T,...M,...B,...w),o.push(...S,...S,...S,...S);let R=v/r,G=(v+1)/r;a.push(R,0,R,1,G,1,G,0),s.push(u,u+2,u+1,u,u+3,u+2),u+=4}let f=[0,l,0],p=[0,1,0],h=u;i.push(...f),o.push(...p),a.push(.5,.5),u++;for(let v=0;v<r;v++){let x=c[v];i.push(...x),o.push(...p);let T=.5+.5*Math.cos(v/r*Math.PI*2),w=.5+.5*Math.sin(v/r*Math.PI*2);a.push(T,w)}for(let v=0;v<r;v++){let x=(v+1)%r;s.push(h,h+1+x,h+1+v)}u+=r;let g=[0,-l,0],b=[0,-1,0],P=u;i.push(...g),o.push(...b),a.push(.5,.5),u++;for(let v=0;v<r;v++){let x=m[v];i.push(...x),o.push(...b);let T=.5+.5*Math.cos(v/r*Math.PI*2),w=.5+.5*Math.sin(v/r*Math.PI*2);a.push(T,w)}for(let v=0;v<r;v++){let x=(v+1)%r;s.push(P,P+1+v,P+1+x)}return new n({positions:new Float32Array(i),normals:new Float32Array(o),uvs:new Float32Array(a),indices:new Uint32Array(s)})}static cartesianCurve(e){let t=e.f,r=e.xMin??-1,i=e.xMax??1,o=Math.max(2,Math.floor(e.segments??256)),a=e.radius??.01,s=Math.max(3,Math.floor(e.radialSegments??8)),l=e.closed??!1,u=e.plane??"xy",c=e.up??[0,0,1],m;switch(u){case"xy":m=c;break;case"xz":m=[c[0],c[2],c[1]];break;case"yz":m=[c[2],c[0],c[1]];break}let d=e.breakOnInvalid??!0,f=[],p=[],h=[],g=[],b=0,P=l?o:o+1,v=[],x=!1,T=M=>{v.length/3>=2&&(b=n._appendTubeSegment(new Float32Array(v),a,s,M,m,f,p,h,g,b)),v=[]},w=i-r;for(let M=0;M<P;M++){let B=o>0?M/o:0,S=r+w*B,R=t(S);if(!Number.isFinite(R)){x=!0,d&&T(!1);continue}let G,L,U;switch(u){case"xy":G=S,L=R,U=0;break;case"xz":G=S,L=0,U=R;break;case"yz":G=0,L=S,U=R;break}v.push(G,L,U)}return T(l&&!x),f.length===0?new n({positions:new Float32Array(0)}):new n({positions:new Float32Array(f),normals:new Float32Array(p),uvs:new Float32Array(h),indices:new Uint32Array(g)})}static cartesianSurface(e){let t=e.f,r=e.xMin??-1,i=e.xMax??1,o=e.zMin??-1,a=e.zMax??1,s=Math.max(1,Math.floor(e.xSegments??128)),l=Math.max(1,Math.floor(e.zSegments??128)),u=e.skipInvalid??!0,c=e.doubleSided??!1,m=e.plane??"xz",d=s,f=l,p=d+1,h=f+1,g=new Float32Array(p*h*3),b=new Float32Array(p*h*3),P=new Float32Array(p*h*2),v=new Uint8Array(p*h),x=i-r,T=a-o;for(let B=0;B<h;B++){let S=f>0?B/f:0,R=o+T*S;for(let G=0;G<p;G++){let L=d>0?G/d:0,U=r+x*L,F=G+p*B,D=t(U,R),k=Number.isFinite(D);v[F]=k?1:0;let A=F*3,I=k?D:0,O,N,z;switch(m){case"xy":O=U,N=R,z=I;break;case"xz":O=U,N=I,z=R;break;case"yz":O=I,N=U,z=R;break}g[A+0]=O,g[A+1]=N,g[A+2]=z;let E=F*2;P[E+0]=L,P[E+1]=1-S}}n._computeGridNormals(g,v,d,f,b);let w=[];for(let B=0;B<f;B++)for(let S=0;S<d;S++){let R=S+p*B,G=S+p*(B+1),L=S+1+p*(B+1),U=S+1+p*B;u&&(!v[R]||!v[G]||!v[L]||!v[U])||w.push(R,G,U,G,L,U)}if(w.length===0)return new n({positions:new Float32Array(0)});let M={positions:g,normals:b,uvs:P,indices:new Uint32Array(w)};return new n(c?n._makeDoubleSided(M):M)}static parametricCurve(e){let t=e.f,r=e.tMin??0,i=e.tMax??1,o=Math.max(2,Math.floor(e.segments??256)),a=e.radius??.01,s=Math.max(3,Math.floor(e.radialSegments??8)),l=e.closed??!1,u=e.breakOnInvalid??!0,c=e.plane??"xy",m=[],d=[],f=[],p=[],h=0,g=l?o:o+1,b=[],P=!1,v=e.up??null,x=null;if(v)switch(c){case"xy":x=v;break;case"xz":x=[v[0],v[2],v[1]];break;case"yz":x=[v[2],v[0],v[1]];break}let T=M=>{if(b.length/3>=2){let S=x??[0,1,0];h=n._appendTubeSegment(new Float32Array(b),a,s,M,S,m,d,f,p,h)}b=[]},w=i-r;for(let M=0;M<g;M++){let B=o>0?M/o:0,S=r+w*B,R=t(S),G,L,U;if(R.length===2){if(G=R[0],L=R[1],U=0,!v)switch(v=[0,0,1],c){case"xy":x=v;break;case"xz":x=[v[0],v[2],v[1]];break;case"yz":x=[v[2],v[0],v[1]];break}}else if(G=R[0],L=R[1],U=R[2],!v)switch(v=[0,1,0],c){case"xy":x=v;break;case"xz":x=[v[0],v[2],v[1]];break;case"yz":x=[v[2],v[0],v[1]];break}if(!Number.isFinite(G)||!Number.isFinite(L)||!Number.isFinite(U)){P=!0,u&&T(!1);continue}let F,D,k;switch(c){case"xy":F=G,D=L,k=U;break;case"xz":F=G,D=U,k=L;break;case"yz":F=U,D=G,k=L;break}b.push(F,D,k)}return T(l&&!P),m.length===0?new n({positions:new Float32Array(0)}):new n({positions:new Float32Array(m),normals:new Float32Array(d),uvs:new Float32Array(f),indices:new Uint32Array(p)})}static parametricSurface(e){let t=e.f,r=e.uMin??0,i=e.uMax??1,o=e.vMin??0,a=e.vMax??1,s=Math.max(1,Math.floor(e.uSegments??128)),l=Math.max(1,Math.floor(e.vSegments??128)),u=e.skipInvalid??!0,c=e.doubleSided??!1,m=e.plane??"xy",d=s,f=l,p=d+1,h=f+1,g=new Float32Array(p*h*3),b=new Float32Array(p*h*3),P=new Float32Array(p*h*2),v=new Uint8Array(p*h),x=i-r,T=a-o;for(let B=0;B<h;B++){let S=f>0?B/f:0,R=o+T*S;for(let G=0;G<p;G++){let L=d>0?G/d:0,U=r+x*L,F=G+p*B,D=t(U,R),k=D[0],A=D[1],I=D[2],O=Number.isFinite(k)&&Number.isFinite(A)&&Number.isFinite(I);v[F]=O?1:0;let N=F*3;if(O){let E,H,j;switch(m){case"xy":E=k,H=A,j=I;break;case"xz":E=k,H=I,j=A;break;case"yz":E=I,H=k,j=A;break}g[N+0]=E,g[N+1]=H,g[N+2]=j}else g[N+0]=0,g[N+1]=0,g[N+2]=0;let z=F*2;P[z+0]=L,P[z+1]=1-S}}n._computeGridNormals(g,v,d,f,b);let w=[];for(let B=0;B<f;B++)for(let S=0;S<d;S++){let R=S+p*B,G=S+p*(B+1),L=S+1+p*(B+1),U=S+1+p*B;u&&(!v[R]||!v[G]||!v[L]||!v[U])||w.push(R,G,U,G,L,U)}if(w.length===0)return new n({positions:new Float32Array(0)});let M={positions:g,normals:b,uvs:P,indices:new Uint32Array(w)};return new n(c?n._makeDoubleSided(M):M)}static _appendTubeSegment(e,t,r,i,o,a,s,l,u,c){let m=e.length/3;if(m<2)return c;let d=new Float32Array(m*3);for(let k=0;k<m;k++){let A=i?(k-1+m)%m:Math.max(k-1,0),I=i?(k+1)%m:Math.min(k+1,m-1),O=e[I*3+0]-e[A*3+0],N=e[I*3+1]-e[A*3+1],z=e[I*3+2]-e[A*3+2],E=Math.sqrt(O*O+N*N+z*z);E>1e-12?(O/=E,N/=E,z/=E):(O=0,N=1,z=0),d[k*3+0]=O,d[k*3+1]=N,d[k*3+2]=z}let f=new Float32Array(m*3),p=new Float32Array(m*3),h=o[0],g=o[1],b=o[2],P=d[0],v=d[1],x=d[2],T=v*b-x*g,w=x*h-P*b,M=P*g-v*h,B=Math.sqrt(T*T+w*w+M*M);B<1e-6&&(Math.abs(P)<.9?(h=1,g=0,b=0):(h=0,g=1,b=0),T=v*b-x*g,w=x*h-P*b,M=P*g-v*h,B=Math.sqrt(T*T+w*w+M*M)),B>1e-12?(T/=B,w/=B,M/=B):(T=1,w=0,M=0),f[0]=T,f[1]=w,f[2]=M;let S=v*M-x*w,R=x*T-P*M,G=P*w-v*T,L=Math.sqrt(S*S+R*R+G*G);L>1e-12&&(S/=L,R/=L,G/=L),p[0]=S,p[1]=R,p[2]=G;for(let k=1;k<m;k++){let A=d[(k-1)*3+0],I=d[(k-1)*3+1],O=d[(k-1)*3+2],N=d[k*3+0],z=d[k*3+1],E=d[k*3+2],H=I*E-O*z,j=O*N-A*E,Z=A*z-I*N,xe=Math.sqrt(H*H+j*j+Z*Z),te=f[(k-1)*3+0],ce=f[(k-1)*3+1],be=f[(k-1)*3+2];if(xe>1e-6){H/=xe,j/=xe,Z/=xe;let Fe=Math.max(-1,Math.min(1,A*N+I*z+O*E)),Fn=Math.acos(Fe),Et=Math.cos(Fn),Ut=Math.sin(Fn),Y=1-Et,wt=j*be-Z*ce,ot=Z*te-H*be,Wt=H*ce-j*te,at=H*te+j*ce+Z*be,Ye=te*Et+wt*Ut+H*at*Y,fr=ce*Et+ot*Ut+j*at*Y,Ki=be*Et+Wt*Ut+Z*at*Y;te=Ye,ce=fr,be=Ki}let Xe=te*N+ce*z+be*E;te-=N*Xe,ce-=z*Xe,be-=E*Xe;let Le=Math.sqrt(te*te+ce*ce+be*be);Le>1e-12?(te/=Le,ce/=Le,be/=Le):(te=f[0],ce=f[1],be=f[2]),f[k*3+0]=te,f[k*3+1]=ce,f[k*3+2]=be;let Re=z*be-E*ce,ft=E*te-N*be,pt=N*ce-z*te,dr=Math.sqrt(Re*Re+ft*ft+pt*pt);dr>1e-12&&(Re/=dr,ft/=dr,pt/=dr),p[k*3+0]=Re,p[k*3+1]=ft,p[k*3+2]=pt}let U=r+1,F=i?m:m-1;for(let k=0;k<m;k++){let A=F>0?k/F:0,I=e[k*3+0],O=e[k*3+1],N=e[k*3+2],z=f[k*3+0],E=f[k*3+1],H=f[k*3+2],j=p[k*3+0],Z=p[k*3+1],xe=p[k*3+2];for(let te=0;te<=r;te++){let ce=r>0?te/r:0,be=ce*Math.PI*2,Xe=Math.cos(be),Le=Math.sin(be),Re=Xe*z+Le*j,ft=Xe*E+Le*Z,pt=Xe*H+Le*xe;a.push(I+t*Re,O+t*ft,N+t*pt),s.push(Re,ft,pt),l.push(A,ce)}}let D=i?m:m-1;for(let k=0;k<D;k++){let A=i?(k+1)%m:k+1;for(let I=0;I<r;I++){let O=c+U*k+I,N=c+U*A+I,z=c+U*A+I+1,E=c+U*k+I+1;u.push(O,E,N,N,E,z)}}return c+U*m}static _computeGridNormals(e,t,r,i,o){let a=r+1,s=i+1;for(let l=0;l<s;l++)for(let u=0;u<a;u++){let c=u+a*l,m=c*3;if(!t[c]){o[m+0]=0,o[m+1]=0,o[m+2]=0;continue}let d=u>0?c-1:c,f=u<r?c+1:c,p=l>0?c-a:c,h=l<i?c+a:c,g=t[d]?e[d*3+0]:e[m+0],b=t[d]?e[d*3+1]:e[m+1],P=t[d]?e[d*3+2]:e[m+2],v=t[f]?e[f*3+0]:e[m+0],x=t[f]?e[f*3+1]:e[m+1],T=t[f]?e[f*3+2]:e[m+2],w=t[p]?e[p*3+0]:e[m+0],M=t[p]?e[p*3+1]:e[m+1],B=t[p]?e[p*3+2]:e[m+2],S=t[h]?e[h*3+0]:e[m+0],R=t[h]?e[h*3+1]:e[m+1],G=t[h]?e[h*3+2]:e[m+2],L=v-g,U=x-b,F=T-P,D=S-w,k=R-M,A=G-B,I=k*F-A*U,O=A*L-D*F,N=D*U-k*L,z=Math.sqrt(I*I+O*O+N*N);z>1e-12?(I/=z,O/=z,N/=z):(I=0,O=1,N=0),o[m+0]=I,o[m+1]=O,o[m+2]=N}}static _makeDoubleSided(e){let t=e.positions,r=e.normals??new Float32Array(t.length/3*3),i=e.tangents??null,o=e.uvs??new Float32Array(t.length/3*2),a=e.uvs1??new Float32Array(t.length/3*2),s=e.indices;if(!s)return e;let l=t.length/3,u=new Float32Array(t.length*2);u.set(t,0),u.set(t,t.length);let c=new Float32Array(r.length*2);c.set(r,0);for(let h=0;h<l;h++){let g=h*3;c[r.length+g+0]=-r[g+0],c[r.length+g+1]=-r[g+1],c[r.length+g+2]=-r[g+2]}let m=new Float32Array(o.length*2);m.set(o,0),m.set(o,o.length);let d=new Float32Array(a.length*2);d.set(a,0),d.set(a,a.length);let f;if(i){f=new Float32Array(i.length*2),f.set(i,0);for(let h=0;h<l;h++){let g=h*4;f[i.length+g+0]=i[g+0],f[i.length+g+1]=i[g+1],f[i.length+g+2]=i[g+2],f[i.length+g+3]=-i[g+3]}}let p=new Uint32Array(s.length*2);p.set(s,0);for(let h=0;h<s.length;h+=3){let g=s[h+0],b=s[h+1],P=s[h+2],v=s.length+h;p[v+0]=l+g,p[v+1]=l+P,p[v+2]=l+b}return{...e,positions:u,normals:c,tangents:f,uvs:m,uvs1:d,indices:p}}};var Bt=n=>[n[0]??0,n[1]??0,n[2]??0],kt=(n=!1)=>({boxMin:[0,0,0],boxMax:[0,0,0],sphereCenter:[0,0,0],sphereRadius:0,empty:!0,partial:n}),an=n=>({boxMin:Bt(n.boxMin),boxMax:Bt(n.boxMax),sphereCenter:Bt(n.sphereCenter),sphereRadius:n.sphereRadius,empty:n.empty,partial:n.partial}),et=(n,e,t=!1)=>{let r=Bt(n),i=Bt(e),o=(r[0]+i[0])*.5,a=(r[1]+i[1])*.5,s=(r[2]+i[2])*.5,l=i[0]-o,u=i[1]-a,c=i[2]-s;return{boxMin:r,boxMax:i,sphereCenter:[o,a,s],sphereRadius:Math.sqrt(l*l+u*u+c*c),empty:!1,partial:t}},yt=(n,e,t=!1)=>{let r=Bt(n),i=Math.max(0,e);return{boxMin:[r[0]-i,r[1]-i,r[2]-i],boxMax:[r[0]+i,r[1]+i,r[2]+i],sphereCenter:r,sphereRadius:i,empty:!1,partial:t}},Zt=(n,e,t,r,i=!1)=>({boxMin:Bt(n),boxMax:Bt(e),sphereCenter:Bt(t),sphereRadius:Math.max(0,r),empty:!1,partial:i}),ho=n=>"getBounds"in n&&typeof n.getBounds=="function"?n.getBounds():n,go=(n,e)=>{if(n.empty){let t=an(e);return t.partial=n.partial||e.partial,t}if(e.empty){let t=an(n);return t.partial=n.partial||e.partial,t}return et([Math.min(n.boxMin[0],e.boxMin[0]),Math.min(n.boxMin[1],e.boxMin[1]),Math.min(n.boxMin[2],e.boxMin[2])],[Math.max(n.boxMax[0],e.boxMax[0]),Math.max(n.boxMax[1],e.boxMax[1]),Math.max(n.boxMax[2],e.boxMax[2])],n.partial||e.partial)},Yn=n=>n.empty?[0,0,0]:[(n.boxMin[0]+n.boxMax[0])*.5,(n.boxMin[1]+n.boxMax[1])*.5,(n.boxMin[2]+n.boxMax[2])*.5],Yl=n=>n.empty?[0,0,0]:[n.boxMax[0]-n.boxMin[0],n.boxMax[1]-n.boxMin[1],n.boxMax[2]-n.boxMin[2]],bo=(n,e)=>{if(n.empty)return an(n);let t=Math.max(1,e),r=Yn(n),i=(n.boxMax[0]-n.boxMin[0])*.5*t,o=(n.boxMax[1]-n.boxMin[1])*.5*t,a=(n.boxMax[2]-n.boxMin[2])*.5*t;return et([r[0]-i,r[1]-o,r[2]-a],[r[0]+i,r[1]+o,r[2]+a],n.partial)},Zn=n=>{if(n.empty)return[];let e=n.boxMin,t=n.boxMax;return[[e[0],e[1],e[2]],[t[0],e[1],e[2]],[e[0],t[1],e[2]],[t[0],t[1],e[2]],[e[0],e[1],t[2]],[t[0],e[1],t[2]],[e[0],t[1],t[2]],[t[0],t[1],t[2]]]},Mt=(n,e)=>{if(n.empty)return an(n);let t=(n.boxMin[0]+n.boxMax[0])*.5,r=(n.boxMin[1]+n.boxMax[1])*.5,i=(n.boxMin[2]+n.boxMax[2])*.5,o=(n.boxMax[0]-n.boxMin[0])*.5,a=(n.boxMax[1]-n.boxMin[1])*.5,s=(n.boxMax[2]-n.boxMin[2])*.5,l=e[0]*t+e[4]*r+e[8]*i+e[12],u=e[1]*t+e[5]*r+e[9]*i+e[13],c=e[2]*t+e[6]*r+e[10]*i+e[14],m=Math.abs(e[0])*o+Math.abs(e[4])*a+Math.abs(e[8])*s,d=Math.abs(e[1])*o+Math.abs(e[5])*a+Math.abs(e[9])*s,f=Math.abs(e[2])*o+Math.abs(e[6])*a+Math.abs(e[10])*s,p=Math.hypot(e[0],e[1],e[2]),h=Math.hypot(e[4],e[5],e[6]),g=Math.hypot(e[8],e[9],e[10]),b=Math.max(p,h,g),P=e[0]*n.sphereCenter[0]+e[4]*n.sphereCenter[1]+e[8]*n.sphereCenter[2]+e[12],v=e[1]*n.sphereCenter[0]+e[5]*n.sphereCenter[1]+e[9]*n.sphereCenter[2]+e[13],x=e[2]*n.sphereCenter[0]+e[6]*n.sphereCenter[1]+e[10]*n.sphereCenter[2]+e[14];return Zt([l-m,u-d,c-f],[l+m,u+d,c+f],[P,v,x],n.sphereRadius*b,n.partial)};var xt=new WeakMap,na=(n,e)=>{let t=new Float32Array(e);if(!n)return t;let r=Math.min(e,n.length|0);for(let i=0;i<r;i++)t[i]=Number(n[i]??0)||0;return t},ia=(n,e)=>{if(!n.dirty)return!1;n.positions.set(e.positions);for(let r=0;r<n.targetCount;r++){let i=n.weights[r]??0;if(i===0)continue;let a=e.morphTargets[r]?.positions;if(a)for(let s=0;s<a.length;s++)n.positions[s]+=a[s]*i}if(n.recomputeNormals)n.normals.set(Xn(n.positions,e.indices));else if(n.hasNormalTargets){n.normals.set(e.normals);for(let r=0;r<n.targetCount;r++){let i=n.weights[r]??0;if(i===0)continue;let a=e.morphTargets[r]?.normals;if(a)for(let s=0;s<a.length;s++)n.normals[s]+=a[s]*i}}else n.normals.set(e.normals);let t=po(n.positions);return n.boundsMin=t.boxMin,n.boundsMax=t.boxMax,n.boundsCenter=t.sphereCenter,n.boundsRadius=t.sphereRadius,n.dirty=!1,n.gpuDirty=!0,!0},oa=n=>{n.positionBuffer?.destroy(),n.normalBuffer?.destroy(),n.positionBuffer=null,n.normalBuffer=null,n.device=null},vo=(n,e)=>{let t=n.geometry.morphTargets.length|0;if(t<=0)return;let r={targetCount:t,weights:na(e,t),positions:new Float32Array(n.geometry.positions),normals:new Float32Array(n.geometry.normals),device:null,positionBuffer:null,normalBuffer:null,dirty:!0,gpuDirty:!0,hasNormalTargets:n.geometry.morphTargets.some(i=>!!i.normals),recomputeNormals:!n.geometry.authoredNormals,boundsMin:n.geometry.boundsMin,boundsMax:n.geometry.boundsMax,boundsCenter:n.geometry.boundsCenter,boundsRadius:n.geometry.boundsRadius};xt.set(n,r)},ra=(n,e)=>{let t=xt.get(n);t&&vo(e,t.weights)},Zl=n=>{let e=xt.get(n);e&&(oa(e),xt.delete(n))},Qn=n=>xt.has(n),aa=(n,e)=>{let t=xt.get(n);if(!t)return;let r=na(e,t.targetCount),i=!1;for(let o=0;o<t.targetCount;o++)if(t.weights[o]!==r[o]){i=!0;break}i&&(t.weights.set(r),t.dirty=!0)},sa=(n,e,t)=>{let r=xt.get(n);if(!r)return;let i=e|0;if(i<0||i>=r.targetCount)return;let o=Number(t)||0;r.weights[i]!==o&&(r.weights[i]=o,r.dirty=!0)};var Jn=n=>{let e=xt.get(n);return e?(ia(e,n.geometry),e):n.geometry},yo=n=>xt.has(n)?n:n.geometry,Qt=(n,e,t)=>{let r=xt.get(n);if(!r)return n.geometry.upload(e),{positionBuffer:n.geometry.positionBuffer,normalBuffer:n.geometry.normalBuffer};let i=ia(r,n.geometry);return r.device!==e||!r.positionBuffer||!r.normalBuffer?(oa(r),r.positionBuffer=ne(e,r.positions,GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST),r.normalBuffer=ne(e,r.normals,GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST),r.device=e,r.gpuDirty=!1):(i||r.gpuDirty)&&(t.writeBuffer(r.positionBuffer,0,r.positions.buffer,r.positions.byteOffset,r.positions.byteLength),t.writeBuffer(r.normalBuffer,0,r.normals.buffer,r.normals.byteOffset,r.normals.byteLength),r.gpuDirty=!1),{positionBuffer:r.positionBuffer,normalBuffer:r.normalBuffer}},tt=class n{geometry;transform;_material;_visible=!0;_castShadow=!0;_receiveShadow=!0;_destroyed=!1;name="";userData={};skin=null;constructor(e,t){this.geometry=e,this._material=t,this.transform=new we}get material(){return this._material}get destroyed(){return this._destroyed}get visible(){return this._visible}set visible(e){this._visible=e}get castShadow(){return this._castShadow}set castShadow(e){this._castShadow=e}get receiveShadow(){return this._receiveShadow}set receiveShadow(e){this._receiveShadow=e}assertAlive(e){if(this._destroyed)throw new Error(`Mesh: cannot ${e}; mesh has already been destroyed.`)}setMaterial(e){if(this.assertAlive("set material"),e===this._material)return this;let t=this._material;return this._material=e,t.release(),this}setParent(e){return this.assertAlive("set parent"),this.transform.setParent(e?.transform??null),this}addChild(e){return this.assertAlive("add child"),this.transform.addChild(e.transform),this}removeChild(e){return this.assertAlive("remove child"),this.transform.removeChild(e.transform),this}get worldMatrix(){return this.assertAlive("access world matrix"),this.transform.worldMatrix}getLocalBounds(){let e=this.getLocalBoundsSource();return Zt(e.boundsMin,e.boundsMax,e.boundsCenter,e.boundsRadius)}getWorldBounds(){return Mt(this.getLocalBounds(),this.transform.worldMatrix)}getBounds(){return this.getWorldBounds()}destroy(){this._destroyed||(this._destroyed=!0,Ql(this),Zl(this),this.skin?.dispose(),this.skin=null,this.transform.dispose(),this.geometry.release(),this._material.release())}clone(){this.assertAlive("clone"),this.geometry.retain(),this.material.retain();let e=new n(this.geometry,this.material);return e.transform.copyFrom(this.transform),e.name=this.name,e.visible=this.visible,e.castShadow=this.castShadow,e.receiveShadow=this.receiveShadow,ra(this,e),e}cloneWithMaterial(e){this.assertAlive("clone with material"),this.geometry.retain();let t=new n(this.geometry,e);return t.transform.copyFrom(this.transform),t.name=this.name,t.visible=this.visible,t.castShadow=this.castShadow,t.receiveShadow=this.receiveShadow,ra(this,t),t}getLocalBoundsSource(){return Jn(this)}},sn=new WeakMap,la=(n,e)=>{let t=sn.get(n);t||(t=new Set,sn.set(n,t)),t.add(e)},xo=(n,e)=>{let t=sn.get(n);t&&(t.delete(e),t.size===0&&sn.delete(n))},Ql=n=>{let e=sn.get(n);if(e)for(let t of[...e])t.remove(n)};var Jt=256,ua={grayscale:"AAAA/wEBAf8CAgL/AwMD/wQEBP8FBQX/BgYG/wcHB/8ICAj/CQkJ/woKCv8LCwv/DAwM/w0NDf8ODg7/Dw8P/xAQEP8RERH/EhIS/xMTE/8UFBT/FRUV/xYWFv8XFxf/GBgY/xkZGf8aGhr/Gxsb/xwcHP8dHR3/Hh4e/x8fH/8gICD/ICAg/yIiIv8jIyP/JCQk/yQkJP8mJib/Jycn/ygoKP8oKCj/Kioq/ysrK/8sLCz/LCws/y4uLv8vLy//MDAw/zAwMP8yMjL/MzMz/zQ0NP80NDT/NjY2/zc3N/84ODj/ODg4/zo6Ov87Ozv/PDw8/zw8PP8+Pj7/Pz8//0BAQP9BQUH/QUFB/0NDQ/9ERET/RUVF/0ZGRv9HR0f/SEhI/0lJSf9JSUn/S0tL/0xMTP9NTU3/Tk5O/09PT/9QUFD/UVFR/1FRUf9TU1P/VFRU/1VVVf9WVlb/V1dX/1hYWP9ZWVn/WVlZ/1tbW/9cXFz/XV1d/15eXv9fX1//YGBg/2FhYf9hYWH/Y2Nj/2RkZP9lZWX/ZmZm/2dnZ/9oaGj/aWlp/2lpaf9ra2v/bGxs/21tbf9ubm7/b29v/3BwcP9xcXH/cXFx/3Nzc/90dHT/dXV1/3Z2dv93d3f/eHh4/3l5ef95eXn/e3t7/3x8fP99fX3/fn5+/39/f/+AgID/gYGB/4KCgv+Dg4P/g4OD/4WFhf+Ghob/h4eH/4iIiP+JiYn/ioqK/4uLi/+MjIz/jY2N/46Ojv+Pj4//kJCQ/5GRkf+SkpL/k5OT/5OTk/+VlZX/lpaW/5eXl/+YmJj/mZmZ/5qamv+bm5v/nJyc/52dnf+enp7/n5+f/6CgoP+hoaH/oqKi/6Ojo/+jo6P/paWl/6ampv+np6f/qKio/6mpqf+qqqr/q6ur/6ysrP+tra3/rq6u/6+vr/+wsLD/sbGx/7Kysv+zs7P/s7Oz/7W1tf+2trb/t7e3/7i4uP+5ubn/urq6/7u7u/+8vLz/vb29/76+vv+/v7//wMDA/8HBwf/CwsL/w8PD/8PDw//FxcX/xsbG/8fHx//IyMj/ycnJ/8rKyv/Ly8v/zMzM/83Nzf/Ozs7/z8/P/9DQ0P/R0dH/0tLS/9PT0//T09P/1dXV/9bW1v/X19f/2NjY/9nZ2f/a2tr/29vb/9zc3P/d3d3/3t7e/9/f3//g4OD/4eHh/+Li4v/j4+P/4+Pj/+Xl5f/m5ub/5+fn/+jo6P/p6en/6urq/+vr6//s7Oz/7e3t/+7u7v/v7+//8PDw//Hx8f/y8vL/8/Pz//Pz8//19fX/9vb2//f39//4+Pj/+fn5//r6+v/7+/v//Pz8//39/f/+/v7//////w==",turbo:"MBI7/zEVQv8yGEr/NBtR/zUeWP82IV//NyNl/zgmbP85KXL/Oix5/zsvf/88MoX/PDWL/z03kf8+Opb/Pz2c/0BAof9AQ6b/QUWr/0FIsP9CS7X/Q066/0NQvv9DU8L/RFbH/0RYy/9FW87/RV7S/0Vg1v9FY9n/Rmbd/0Zo4P9Ga+P/Rm3m/0Zw6P9Gc+v/RnXt/0Z48P9GevL/Rn30/0Z/9v9Ggvj/RYT5/0WH+/9Fifz/RIz9/0OO/f9Ckf7/QZP+/0CW/v8/mP7/Ppv+/zyd/f87oPz/OaL8/zil+/82qPn/NKr4/zOs9v8xr/X/L7Hz/y208f8rtu//Krnt/yi76/8mven/JcDm/yPC5P8hxOH/IMbf/x7J3P8dy9r/HM3X/xvP1P8a0dL/GdPP/xjVzP8Y18r/F9nH/xfaxP8X3ML/F96//xjgvf8Y4br/GeO4/xrktv8b5bT/Heex/x7or/8g6az/Iuup/yTspv8n7aP/Ke6g/yzvnf8v8Jr/MvGX/zXzlP849JH/O/SN/z/1iv9C9of/RveD/0r4gP9N+Xz/Ufl5/1X6dv9Z+3L/Xftv/2H8bP9l/Gj/af1l/239Yv9x/V//dP5c/3j+Wf98/lb/gP5T/4T+UP+H/k3/i/5L/47+SP+S/kb/lf5E/5j+Qv+b/UD/nv0+/6H8Pf+k/Dv/pvs6/6n7Of+s+jf/rvk3/7H4Nv+z+DX/tvc1/7n1NP+79DT/vvM0/8DyM//D8TP/xe8z/8juM//K7TP/zes0/8/qNP/R6DT/1Oc1/9blNf/Y4zX/2uI2/93gNv/f3jb/4dw3/+PaN//l2Dj/59c4/+jVOP/q0zn/7NE5/+3POf/vzTn/8Ms6//LIOv/zxjr/9MQ6//bCOv/3wDn/+L45//m8Of/5ujj/+rc3//u1N//7szb//LA1//yuNP/9qzP//aky//2mMf/9ozD//qEv//6eLv/+my3//pgs//2VK//9kin//Y8o//2MJ//8iSb//IYk//uDI//7gCL/+n0g//p6H//5dx7/+HQc//dxG//3bhr/9msY//VoF//0ZRb/82MV//JgFP/xXRP/71oR/+5YEP/tVQ//7FIO/+pQDf/pTQ3/6EsM/+ZJC//lRgr/40QK/+JCCf/gQAj/3j4I/908B//bOgf/2TgG/9c2Bv/WNAX/1DIF/9IwBf/QLwT/zi0E/8srA//JKQP/xygD/8UmAv/DJAL/wCMC/74hAv+7HwH/uR4B/7YcAf+0GwH/sRkB/64YAf+sFgH/qRUB/6YUAf+jEgH/oBEB/50QAf+aDgH/lw0B/5QMAf+RCwH/jgoB/4sJAf+HCAH/hAcB/4EGAv99BQL/egQC/w==",viridis:"RAFU/0QCVf9EA1f/RQVY/0UGWv9FCFv/Rglc/0YLXv9GDF//Rg5h/0cPYv9HEWP/RxJl/0cUZv9HFWf/RxZp/0cYav9IGWv/SBps/0gcbv9IHW//SB5w/0ggcf9IIXL/SCJz/0gjdP9HJXX/RyZ2/0cnd/9HKHj/Ryp5/0crev9HLHv/Ri18/0YvfP9GMH3/RjF+/0Uyf/9FNH//RTWA/0U2gf9EN4H/RDmC/0M6g/9DO4P/QzyE/0I9hP9CPoX/QkCF/0FBhv9BQob/QEOH/0BEh/8/RYf/P0eI/z5IiP8+SYn/PUqJ/z1Lif89TIn/PE2K/zxOiv87UIr/O1GK/zpSi/86U4v/OVSL/zlVi/84Vov/OFeM/zdYjP83WYz/NlqM/zZbjP81XIz/NV2M/zRejf80X43/M2CN/zNhjf8yYo3/MmON/zFkjf8xZY3/MWaN/zBnjf8waI3/L2mN/y9qjf8ua47/LmyO/y5tjv8tbo7/LW+O/yxwjv8scY7/LHKO/ytzjv8rdI7/KnWO/yp2jv8qd47/KXiO/yl5jv8oeo7/KHqO/yh7jv8nfI7/J32O/yd+jv8mf47/JoCO/yaBjv8lgo7/JYON/ySEjf8khY3/JIaN/yOHjf8jiI3/I4mN/yKJjf8iio3/IouN/yGMjf8hjYz/IY6M/yCPjP8gkIz/IJGM/x+SjP8fk4v/H5SL/x+Vi/8flov/HpeK/x6Yiv8emYr/HpmK/x6aif8em4n/HpyJ/x6diP8enoj/Hp+I/x6gh/8foYf/H6KG/x+jhv8gpIX/IKWF/yGmhf8hp4T/IqeE/yOog/8jqYL/JKqC/yWrgf8mrIH/J62A/yiuf/8pr3//KrB+/yuxff8ssX3/LrJ8/y+ze/8wtHr/MrV6/zO2ef81t3j/Nrh3/zi5dv85uXb/O7p1/z27dP8+vHP/QL1y/0K+cf9EvnD/Rb9v/0fAbv9JwW3/S8Js/03Ca/9Pw2n/UcRo/1PFZ/9Vxmb/V8Zl/1nHZP9byGL/Xslh/2DJYP9iyl//ZMtd/2fMXP9pzFv/a81Z/23OWP9wzlb/cs9V/3TQVP930FL/edFR/3zST/9+0k7/gdNM/4PTS/+G1En/iNVH/4vVRv+N1kT/kNZD/5LXQf+V1z//l9g+/5rYPP+d2Tr/n9k4/6LaN/+l2jX/p9sz/6rbMv+t3DD/r9wu/7LdLP+13Sv/t90p/7reJ/+93ib/v98k/8LfIv/F3yH/x+Af/8rgHv/N4B3/z+Ec/9LhG//U4Rr/1+IZ/9riGP/c4hj/3+MY/+HjGP/k4xj/5+QZ/+nkGf/s5Br/7uUb//HlHP/z5R7/9uYf//jmIf/65iL//eck/w==",magma:"AAAD/wAABP8AAAb/AQAH/wEBCf8BAQv/AgIN/wICD/8DAxH/BAMT/wQEFf8FBBf/BgUZ/wcFG/8IBh3/CQcf/woHIv8LCCT/DAkm/w0KKP8OCir/Dwss/xAML/8RDDH/Eg0z/xQNNf8VDjj/Fg46/xcPPP8YDz//GhBB/xsQRP8cEEb/HhBJ/x8RS/8gEU3/IhFQ/yMRUv8lEVX/JhFX/ygRWf8qEVz/KxFe/y0QYP8vEGL/MBBl/zIQZ/80EGj/NQ9q/zcPbP85D27/Ow9v/zwPcf8+D3L/QA9z/0IPdP9DD3X/RQ92/0cPd/9IEHj/ShB5/0sQef9NEXr/TxF7/1ASe/9SEnz/UxN8/1UTff9XFH3/WBV+/1oVfv9bFn7/XRd+/14Xf/9gGH//YRh//2MZf/9lGoD/ZhqA/2gbgP9pHID/axyA/2wdgP9uHoH/bx6B/3Efgf9zH4H/dCCB/3Yhgf93IYH/eSKB/3oigf98I4H/fiSB/38kgf+BJYH/giWB/4Qmgf+FJoH/hyeB/4kogf+KKIH/jCmA/40pgP+PKoD/kSqA/5IrgP+UK4D/lSyA/5csf/+ZLX//mi1//5wuf/+eLn7/ny9+/6Evfv+jMH7/pDB9/6Yxff+nMX3/qTJ8/6szfP+sM3v/rjR7/7A0e/+xNXr/szV6/7U2ef+2Nnn/uDd4/7k3eP+7OHf/vTl3/745dv/AOnX/wjp1/8M7dP/FPHT/xjxz/8g9cv/KPnL/yz5x/80/cP/OQHD/0EFv/9FCbv/TQm3/1ENt/9ZEbP/XRWv/2UZq/9pHaf/cSGn/3Ulo/95KZ//gS2b/4Uxm/+JNZf/kTmT/5VBj/+ZRYv/nUmL/6FRh/+pVYP/rVmD/7Fhf/+1ZX//uW17/7l1d/+9eXf/wYF3/8WFc//JjXP/zZVz/82db//RoW//1alv/9Wxb//ZuW//2cFv/93Fb//dzXP/4dVz/+Hdc//l5XP/5e13/+X1d//p/Xv/6gF7/+oJf//uEYP/7hmD/+4hh//uKYv/8jGP//I5j//yQZP/8kmX//JNm//2VZ//9l2j//Zlp//2bav/9nWv//Z9s//2hbv/9om///aRw//6mcf/+qHP//qp0//6sdf/+rnb//q94//6xef/+s3v//rV8//63ff/+uX///ruA//68gv/+voP//sCF//7Chv/+xIj//saJ//7Hi//+yY3//suO//3NkP/9z5L//dGT//3Slf/91Jf//daY//3Ymv/92pz//dyd//3dn//936H//eGj//zjpf/85ab//Oao//zoqv/86qz//Oyu//zusP/88LH//PGz//zztf/89bf/+/e5//v5u//7+r3/+/y//w==",plasma:"DAeG/xAHh/8TBon/FQaK/xgGi/8bBoz/HQaN/x8Fjv8hBY//IwWQ/yUFkf8nBZL/KQWT/ysFlP8tBJT/LwSV/zEElv8zBJf/NASY/zYEmP84BJn/OgSa/zsDmv89A5v/PwOc/0ADnP9CA53/RAOe/0UDnv9HAp//SQKf/0oCoP9MAqH/TgKh/08Cov9RAaL/UgGj/1QBo/9WAaP/VwGk/1kBpP9aAKX/XACl/14Apf9fAKb/YQCm/2IApv9kAKf/ZQCn/2cAp/9oAKf/agCn/2wAqP9tAKj/bwCo/3AAqP9yAKj/cwCo/3UAqP92Aaj/eAGo/3kBqP97Aqj/fAKn/34Dp/9/A6f/gQSn/4IEp/+EBab/hQam/4YHpv+IB6X/iQil/4sJpP+MCqT/jgyk/48No/+QDqP/kg+i/5MQof+VEaH/lhKg/5cToP+ZFJ//mhWe/5sXnv+dGJ3/nhmc/58am/+gG5v/ohya/6Mdmf+kHpj/pR+X/6chl/+oIpb/qSOV/6oklP+sJZP/rSaS/64nkf+vKJD/sCqP/7Erj/+yLI7/tC2N/7UujP+2L4v/tzCK/7gyif+5M4j/ujSH/7s1hv+8NoX/vTeE/744g/+/OYL/wDuB/8E8gP/CPYD/wz5//8Q/fv/FQH3/xkF8/8dCe//IRHr/yUV5/8pGeP/LR3f/zEh2/81Jdf/OSnX/z0t0/9BNc//RTnL/0U9x/9JQcP/TUW//1FJu/9VTbf/WVW3/11Zs/9dXa//YWGr/2Vlp/9paaP/bW2f/3F1m/9xeZv/dX2X/3mBk/99hY//fYmL/4GRh/+FlYP/iZmD/42df/+NoXv/kal3/5Wtc/+VsW//mbVr/525a/+hwWf/ocVj/6XJX/+pzVv/qdFX/63ZU/+x3VP/seFP/7XlS/+17Uf/ufFD/731P/+9+Tv/wgE3/8IFN//GCTP/yhEv/8oVK//OGSf/zh0j/9IlH//SKR//1i0b/9Y1F//aORP/2j0P/9pFC//eSQf/3k0H/+JVA//iWP//4mD7/+Zk9//maPP/6nDv/+p06//qfOv/6oDn/+6I4//ujN//7pDb//KY1//ynNf/8qTT//Koz//ysMv/8rTH//a8x//2wMP/9si///bMu//21Lf/9ti3//bgs//25K//9uyv//bwq//2+Kf/9wCn//cEo//3DKP/9xCf//cYm//zHJv/8ySb//Msl//zMJf/8ziX/+9Ak//vRJP/70yT/+tUk//rWJP/62CT/+dkk//nbJP/43ST/+N8k//fgJP/34iX/9uQl//blJf/15yb/9ekm//TqJv/z7Cb/8+4m//LwJv/y8Sb/8fMm//D1Jf/w9iP/7/gh/w==",inferno:"AAAD/wAABP8AAAb/AQAH/wEBCf8BAQv/AgEO/wICEP8DAhL/BAMU/wQDFv8FBBj/BgQb/wcFHf8IBh//CQYh/woHI/8LByb/DQgo/w4IKv8PCS3/EAkv/xIKMv8TCjT/FAs2/xYLOf8XCzv/GQs+/xoLQP8cDEP/HQxF/x8MR/8gDEr/IgtM/yQLTv8mC1D/JwtS/ykLVP8rClb/LQpY/y4KWv8wClz/Mgld/zQJX/81CWD/Nwlh/zkJYv87CWT/PAll/z4JZv9ACWb/QQln/0MKaP9FCmn/Rgpp/0gLav9KC2r/Swxr/00Ma/9PDWz/UA1s/1IObP9TDm3/VQ9t/1cPbf9YEG3/WhFt/1sRbv9dEm7/XxJu/2ATbv9iFG7/YxRu/2UVbv9mFW7/aBZu/2oXbv9rF27/bRhu/24Ybv9wGW7/chlt/3Mabf91G23/dhtt/3gcbf96HG3/ex1s/30dbP9+Hmz/gB9r/4Efa/+DIGv/hSBq/4Yhav+IIWr/iSJp/4siaf+NI2n/jiRo/5AkaP+RJWf/kyVn/5UmZv+WJmb/mCdl/5koZP+bKGT/nClj/54pY/+gKmL/oSth/6MrYf+kLGD/pixf/6ctX/+pLl7/qy5d/6wvXP+uMFv/rzFb/7ExWv+yMln/tDNY/7UzV/+3NFb/uDVW/7o2Vf+7N1T/vTdT/744Uv+/OVH/wTpQ/8I7T//EPE7/xT1N/8c+TP/IPkv/yT9K/8tASf/MQUj/zUJH/89ERv/QRUT/0UZD/9JHQv/USEH/1UlA/9ZKP//XSz7/2U09/9pOO//bTzr/3FA5/91SOP/eUzf/31Q2/+BWNP/iVzP/41gy/+RaMf/lWzD/5lwu/+ZeLf/nXyz/6GEr/+liKv/qZCj/62Un/+xnJv/taCX/7Woj/+5sIv/vbSH/8G8f//BwHv/xch3/8nQc//J1Gv/zdxn/83kY//R6Fv/1fBX/9X4U//aAEv/2gRH/94MQ//eFDv/4hw3/+IgM//iKC//5jAn/+Y4I//mQCP/6kQf/+pMG//qVBv/6lwb/+5kG//ubBv/7nQb/+54H//ugB//7ogj/+6QK//umC//7qA3/+6oO//usEP/7rhL/+7AU//uxFv/7sxj/+7Ua//u3HP/7uR7/+rsh//q9I//6vyX/+sEo//nDKv/5xSz/+ccv//jJMf/4yzT/+M03//fPOv/30Tz/9tM///bVQv/110X/9dlI//TbS//03E//895S//PgVv/z4ln/8uRd//LmYP/x6GT/8elo//HrbP/x7XD/8e50//Hwef/x8n3/8vOB//L0hf/z9on/9PeN//X4kf/2+pX/9/uZ//n8nf/6/aD//P6k/w=="},Po=n=>n<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4),Jl=n=>{if(typeof globalThis.atob=="function"){let t=globalThis.atob(n),r=new Uint8Array(t.length);for(let i=0;i<t.length;i++)r[i]=t.charCodeAt(i)&255;return r}let e=globalThis.Buffer;if(e&&typeof e.from=="function")return Uint8Array.from(e.from(n,"base64"));throw new Error("Colormap: No base64 decoder available (expected atob() or Buffer).")},Pr=n=>{let e=ua,t=e[n];if(t instanceof Uint8Array)return t;let r=Jl(ua[n]);return e[n]=r,r},eu=n=>{y(n.length>=2,"Colormap: expected at least 2 stops.");let e=[],t=0;for(let i of n)Array.isArray(i)?(e.push({t:n.length<=1?0:t/(n.length-1),color:[i[0],i[1],i[2],i[3]]}),t++):e.push({t:i.t,color:[i.color[0],i.color[1],i.color[2],i.color[3]]});e.sort((i,o)=>i.t-o.t);for(let i of e)i.t=le(i.t);e[0].t>0&&e.unshift({t:0,color:e[0].color});let r=e.length-1;return e[r].t<1&&e.push({t:1,color:e[r].color}),e},tu=(n,e)=>{let t=le(e);if(t<=n[0].t)return n[0].color;let r=n.length-1;if(t>=n[r].t)return n[r].color;for(let i=0;i<r;i++){let o=n[i],a=n[i+1];if(t>=o.t&&t<=a.t){let s=a.t-o.t||1e-6,l=(t-o.t)/s;return[Ve(o.color[0],a.color[0],l),Ve(o.color[1],a.color[1],l),Ve(o.color[2],a.color[2],l),Ve(o.color[3],a.color[3],l)]}}return n[r].color},ca=(n,e)=>{let t=new Uint8Array(n.length*4);for(let r=0;r<n.length;r++){let i=le(n[r][0]),o=le(n[r][1]),a=le(n[r][2]),s=le(n[r][3]);e==="srgb"&&(i=Po(i),o=Po(o),a=Po(a)),t[r*4+0]=Math.max(0,Math.min(255,Math.round(i*255))),t[r*4+1]=Math.max(0,Math.min(255,Math.round(o*255))),t[r*4+2]=Math.max(0,Math.min(255,Math.round(a*255))),t[r*4+3]=Math.max(0,Math.min(255,Math.round(s*255)))}return t},ru=(n,e,t)=>{let r=Math.min(e-1,Math.max(0,Math.round(le(t)*(e-1))));return[n[r*4+0]/255,n[r*4+1]/255,n[r*4+2]/255,n[r*4+3]/255]},nu=(n,e,t)=>{let r=le(t)*Math.max(0,e-1),i=Math.min(e-1,Math.max(0,Math.floor(r))),o=Math.min(e-1,i+1),a=r-i,s=i*4,l=o*4;return[Ve(n[s+0]/255,n[l+0]/255,a),Ve(n[s+1]/255,n[l+1]/255,a),Ve(n[s+2]/255,n[l+2]/255,a),Ve(n[s+3]/255,n[l+3]/255,a)]},iu=(n,e,t,r,i)=>{y(r>0,"Colormap: width must be > 0."),y(t.length>>>0===r*4,"Colormap: rgba8 length must be width*4.");let o=n.createTexture({label:i,size:{width:r,height:1,depthOrArrayLayers:1},dimension:"1d",format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST}),a=r*4,s=he(a,256),l=s===a?t:(()=>{let u=new Uint8Array(s);return u.set(t),u})();return e.writeTexture({texture:o},new Uint8Array(l),{bytesPerRow:s,rowsPerImage:1},{width:r,height:1,depthOrArrayLayers:1}),o},ou=(n,e)=>n.createSampler({addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge",addressModeW:"clamp-to-edge",magFilter:e==="linear"?"linear":"nearest",minFilter:e==="linear"?"linear":"nearest",mipmapFilter:"nearest"}),au=1,$=class n{id=au++;_label;_filter;_width;_rgba8Linear;_external;_gpuByDevice=new WeakMap;constructor(e){this._label=e.label,this._width=e.width,this._filter=e.filter,this._rgba8Linear=e.rgba8Linear??null,this._external=e.external??null}static builtin(e){return su[e]}static fromStops(e,t={}){let r=Math.max(2,Math.floor(t.resolution??Jt)),i=t.filter??"linear",o=t.colorSpace??"srgb",a=eu(e),s=new Array(r);for(let u=0;u<r;u++){let c=r===1?0:u/(r-1);s[u]=tu(a,c)}let l=ca(s,o);return new n({label:"Colormap.customStops",width:r,filter:i,rgba8Linear:l})}static fromPalette(e,t={}){y(e.length>=1,"Colormap.fromPalette: expected at least 1 color.");let r=t.filter??"nearest",i=t.colorSpace??"srgb",o=ca(e,i);return new n({label:"Colormap.palette",width:e.length,filter:r,rgba8Linear:o})}static fromGPUTextureView(e,t,r,i,o="linear"){return y(i>0,"Colormap.fromGPUTextureView: width must be > 0."),new n({label:"Colormap.external",width:i,filter:o,external:{device:e,view:t,sampler:r,width:i,filter:o}})}get width(){return this._width}get filter(){return this._filter}get canSampleCPU(){return this._rgba8Linear!==null}getRGBA8LinearLUT(){if(!this._rgba8Linear)throw new Error("Colormap: CPU sampling is unavailable for external GPU-only colormaps.");return this._rgba8Linear.slice()}sampleCPU(e){let t=this._rgba8Linear;if(!t)throw new Error("Colormap: CPU sampling is unavailable for external GPU-only colormaps.");return this._filter==="nearest"?ru(t,this._width,e):nu(t,this._width,e)}getGPUResources(e,t){if(this._external)return y(this._external.device===e,"Colormap: external texture was created with a different GPUDevice."),{texture:null,view:this._external.view,sampler:this._external.sampler,width:this._external.width,filter:this._external.filter};let r=this._gpuByDevice.get(e);if(r)return r;let i=this._rgba8Linear??(()=>{throw new Error("Colormap: no LUT data to upload.")})(),o=iu(e,t,i,this._width,this._label),a=o.createView({dimension:"1d"}),s=ou(e,this._filter),l={texture:o,view:a,sampler:s,width:this._width,filter:this._filter};return this._gpuByDevice.set(e,l),l}toUniformStops(e=8,t="linear"){let r=Math.max(2,Math.min(8,Math.floor(e))),i=this._rgba8Linear;if(!i)return[[0,0,0,1],[1,1,1,1]];let o=new Array(r);for(let a=0;a<r;a++){let s=r===1?0:a/(r-1),l=Math.min(this._width-1,Math.max(0,Math.round(s*(this._width-1)))),u=i[l*4+0]/255,c=i[l*4+1]/255,m=i[l*4+2]/255,d=i[l*4+3]/255;if(t==="linear")o[a]=[u,c,m,d];else{let f=p=>p<=.0031308?12.92*p:1.055*Math.pow(p,.4166666666666667)-.055;o[a]=[f(u),f(c),f(m),d]}}return o}},su={grayscale:new $({label:"Colormap.grayscale",width:Jt,filter:"linear",rgba8Linear:Pr("grayscale")}),turbo:new $({label:"Colormap.turbo",width:Jt,filter:"linear",rgba8Linear:Pr("turbo")}),viridis:new $({label:"Colormap.viridis",width:Jt,filter:"linear",rgba8Linear:Pr("viridis")}),magma:new $({label:"Colormap.magma",width:Jt,filter:"linear",rgba8Linear:Pr("magma")}),plasma:new $({label:"Colormap.plasma",width:Jt,filter:"linear",rgba8Linear:Pr("plasma")}),inferno:new $({label:"Colormap.inferno",width:Jt,filter:"linear",rgba8Linear:Pr("inferno")})};var ma="struct MaterialUniforms { color: vec4f, params: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseSampler: sampler; @group(1) @binding(2) var baseTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) normal: vec3f, @location(1) uv: vec2f, @location(2) uv1: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; fn linearToSrgb(c: vec3f) -> vec3f { return pow(c, vec3f(1.0 / 2.2)); } @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; out.position = camera.viewProjection * model.model * vec4f(in.position, 1.0); out.normal = (model.normalMatrix * vec4f(in.normal, 0.0)).xyz; out.uv = in.uv; out.uv1 = in.uv1; return out; } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let texColor = textureSample(baseTex, baseSampler, baseUv); var outColor = material.color * texColor; let alphaCutoff = material.params.x; if (alphaCutoff > 0.0 && outColor.a < alphaCutoff) { discard; } return vec4f(linearToSrgb(outColor.rgb), outColor.a); }";var da="struct MaterialUniforms { color: vec4f, params: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseSampler: sampler; @group(1) @binding(2) var baseTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(3) m0: vec4f, @location(4) m1: vec4f, @location(5) m2: vec4f, @location(6) m3: vec4f, @location(7) n0: vec4f, @location(8) n1: vec4f, @location(9) n2: vec4f, @location(10) n3: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) normal: vec3f, @location(1) uv: vec2f, @location(2) uv1: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; fn linearToSrgb(c: vec3f) -> vec3f { return pow(c, vec3f(1.0 / 2.2)); } @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let modelM = mat4x4f(in.m0, in.m1, in.m2, in.m3); let normalM = mat4x4f(in.n0, in.n1, in.n2, in.n3); out.position = camera.viewProjection * modelM * vec4f(in.position, 1.0); out.normal = (normalM * vec4f(in.normal, 0.0)).xyz; out.uv = in.uv; out.uv1 = in.uv1; return out; } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let texColor = textureSample(baseTex, baseSampler, baseUv); var outColor = material.color * texColor; let alphaCutoff = material.params.x; if (alphaCutoff > 0.0 && outColor.a < alphaCutoff) { discard; } return vec4f(linearToSrgb(outColor.rgb), outColor.a); }";var fa="struct MaterialUniforms { color: vec4f, params: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTexture: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(3) joints: vec4u, @location(4) weights: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) uv: vec2f, @location(1) uv1: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec4f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; struct SkinBuffer { joints: array<mat4x4f>, }; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let j = in.joints; let w = in.weights; let m = skin.joints[j.x] * w.x + skin.joints[j.y] * w.y + skin.joints[j.z] * w.z + skin.joints[j.w] * w.w; let localPos = m * vec4f(in.position, 1.0); out.position = camera.viewProjection * model.model * localPos; out.uv = in.uv; out.uv1 = in.uv1; return out; } fn linearToSrgb(c: vec3f) -> vec3f { return pow(c, vec3f(1.0 / 2.2)); } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let baseColorSample = textureSample(baseColorTexture, baseColorSampler, baseUv); var outColor = material.color * baseColorSample; let alphaCutoff = material.params.x; if (alphaCutoff > 0.0 && outColor.a < alphaCutoff) { discard; } return vec4f(linearToSrgb(outColor.rgb), outColor.a); }";var pa="struct MaterialUniforms { color: vec4f, params: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTexture: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(3) joints0: vec4u, @location(4) weights0: vec4f, @location(5) joints1: vec4u, @location(6) weights1: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) uv: vec2f, @location(1) uv1: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec4f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; struct SkinBuffer { joints: array<mat4x4f>, }; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let j0 = in.joints0; let w0 = in.weights0; let j1 = in.joints1; let w1 = in.weights1; let m = skin.joints[j0.x] * w0.x + skin.joints[j0.y] * w0.y + skin.joints[j0.z] * w0.z + skin.joints[j0.w] * w0.w + skin.joints[j1.x] * w1.x + skin.joints[j1.y] * w1.y + skin.joints[j1.z] * w1.z + skin.joints[j1.w] * w1.w; let localPos = m * vec4f(in.position, 1.0); out.position = camera.viewProjection * model.model * localPos; out.uv = in.uv; out.uv1 = in.uv1; return out; } fn linearToSrgb(c: vec3f) -> vec3f { return pow(c, vec3f(1.0 / 2.2)); } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let baseColorSample = textureSample(baseColorTexture, baseColorSampler, baseUv); var outColor = material.color * baseColorSample; let alphaCutoff = material.params.x; if (alphaCutoff > 0.0 && outColor.a < alphaCutoff) { discard; } return vec4f(linearToSrgb(outColor.rgb), outColor.a); }";var ha="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f, metallicRoughnessTransform0: vec4f, metallicRoughnessTransform1: vec4f, normalTransform0: vec4f, normalTransform1: vec4f, occlusionTransform0: vec4f, occlusionTransform1: vec4f, emissiveTransform0: vec4f, emissiveTransform1: vec4f, clearcoatParams: vec4f, specularParams: vec4f, extensionParams: vec4f, clearcoatTransform0: vec4f, clearcoatTransform1: vec4f, clearcoatRoughnessTransform0: vec4f, clearcoatRoughnessTransform1: vec4f, clearcoatNormalTransform0: vec4f, clearcoatNormalTransform1: vec4f, specularTransform0: vec4f, specularTransform1: vec4f, specularColorTransform0: vec4f, specularColorTransform1: vec4f, sheenParams: vec4f, iridescenceParams: vec4f, anisotropyParams: vec4f, sheenColorTransform0: vec4f, sheenColorTransform1: vec4f, sheenRoughnessTransform0: vec4f, sheenRoughnessTransform1: vec4f, iridescenceTransform0: vec4f, iridescenceTransform1: vec4f, iridescenceThicknessTransform0: vec4f, iridescenceThicknessTransform1: vec4f, anisotropyTransform0: vec4f, anisotropyTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; @group(1) @binding(11) var clearcoatSampler: sampler; @group(1) @binding(12) var clearcoatTex: texture_2d<f32>; @group(1) @binding(13) var clearcoatRoughnessSampler: sampler; @group(1) @binding(14) var clearcoatRoughnessTex: texture_2d<f32>; @group(1) @binding(15) var clearcoatNormalSampler: sampler; @group(1) @binding(16) var clearcoatNormalTex: texture_2d<f32>; @group(1) @binding(17) var specularSampler: sampler; @group(1) @binding(18) var specularTex: texture_2d<f32>; @group(1) @binding(19) var specularColorSampler: sampler; @group(1) @binding(20) var specularColorTex: texture_2d<f32>; @group(1) @binding(21) var sheenColorSampler: sampler; @group(1) @binding(22) var sheenColorTex: texture_2d<f32>; @group(1) @binding(23) var sheenRoughnessSampler: sampler; @group(1) @binding(24) var sheenRoughnessTex: texture_2d<f32>; @group(1) @binding(25) var iridescenceSampler: sampler; @group(1) @binding(26) var iridescenceTex: texture_2d<f32>; @group(1) @binding(27) var iridescenceThicknessSampler: sampler; @group(1) @binding(28) var iridescenceThicknessTex: texture_2d<f32>; @group(1) @binding(29) var anisotropySampler: sampler; @group(1) @binding(30) var anisotropyTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(12) tangent: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) uv1: vec2f, @location(4) tangent: vec4f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, direction: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let worldPos4 = model.model * vec4f(in.position, 1.0); out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(in.normal, 0.0)).xyz); out.tangent = vec4f((model.normalMatrix * vec4f(in.tangent.xyz, 0.0)).xyz, in.tangent.w); out.uv = in.uv; out.uv1 = in.uv1; return out; } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } fn fresnelSchlick(cosTheta: f32, F0: vec3f, F90: vec3f) -> vec3f { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (F90 - F0) * pow(oneMinusCos, 5.0); } fn maxComponent(v: vec3f) -> f32 { return max(max(v.x, v.y), v.z); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } struct TangentFrame { t: vec3f, b: vec3f, n: vec3f }; fn fallbackTangentFrame(N: vec3f) -> TangentFrame { let n = normalize(N); let axis = select(vec3f(0.0, 1.0, 0.0), vec3f(1.0, 0.0, 0.0), abs(n.x) < 0.9); let t = normalize(cross(axis, n)); let b = cross(n, t); return TangentFrame(t, b, n); } fn derivativeTangentFrame(N: vec3f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let dp2perp = cross(dp2, n); let dp1perp = cross(n, dp1); let T = (dp2perp * duv1.x) + (dp1perp * duv2.x); let B = (dp2perp * duv1.y) + (dp1perp * duv2.y); let frameLength2 = max(dot(T, T), dot(B, B)); if (frameLength2 <= 1e-20) { return fallbackTangentFrame(n); } let frameScale = 1.0 / sqrt(frameLength2); return TangentFrame(T * frameScale, B * frameScale, n); } fn buildTangentFrame(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let derivativeFrame = derivativeTangentFrame(n, worldPos, uv); var t = tangent.xyz - n * dot(n, tangent.xyz); let tLen2 = dot(t, t); if (tLen2 <= 1e-20) { return derivativeFrame; } t = t * inverseSqrt(tLen2); let b = normalize(cross(n, t)) * select(-1.0, 1.0, tangent.w >= 0.0); return TangentFrame(t, b, n); } fn applyNormalMap(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { if (normalScale == 0.0) { return normalize(N); } let frame = buildTangentFrame(N, tangent, worldPos, uv); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(frame.t * ns.x + frame.b * ns.y + frame.n * ns.z); } fn sqr(v: f32) -> f32 { return v * v; } fn iorToFresnel0(transmittedIor: f32, incidentIor: f32) -> f32 { let r = (transmittedIor - incidentIor) / (transmittedIor + incidentIor); return r * r; } fn iorToFresnel0Vec(transmittedIor: vec3f, incidentIor: f32) -> vec3f { let r = (transmittedIor - vec3f(incidentIor)) / (transmittedIor + vec3f(incidentIor)); return r * r; } fn fresnel0ToIor(F0: vec3f) -> vec3f { let sqrtF0 = sqrt(clamp(F0, vec3f(0.0), vec3f(0.9999))); return (vec3f(1.0) + sqrtF0) / max(vec3f(1.0) - sqrtF0, vec3f(1e-4)); } fn fresnelSchlickScalar(cosTheta: f32, F0: f32) -> f32 { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (1.0 - F0) * pow(oneMinusCos, 5.0); } fn sanitizeReflectance(value: vec3f, fallback: vec3f) -> vec3f { var result = clamp(fallback, vec3f(0.0), vec3f(1.0)); if (value.x == value.x && abs(value.x) < 1.0e6) { result.x = clamp(value.x, 0.0, 1.0); } if (value.y == value.y && abs(value.y) < 1.0e6) { result.y = clamp(value.y, 0.0, 1.0); } if (value.z == value.z && abs(value.z) < 1.0e6) { result.z = clamp(value.z, 0.0, 1.0); } return result; } fn evalIridescenceSensitivity(OPD: f32, shift: vec3f) -> vec3f { let phase = 2.0 * PI * OPD * 1.0e-9; let phase2 = phase * phase; let val = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13); let pos = vec3f(1.6810e+06, 1.7953e+06, 2.2084e+06); let variance = vec3f(4.3278e+09, 9.3046e+09, 6.6121e+09); var xyz = val * sqrt(2.0 * PI * variance) * cos(pos * phase + shift) * exp(-phase2 * variance); xyz.x += 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift.x) * exp(-4.5282e+09 * phase2); xyz /= 1.0685e-7; return vec3f( 3.2404542 * xyz.x - 1.5371385 * xyz.y - 0.4985314 * xyz.z, -0.9692660 * xyz.x + 1.8760108 * xyz.y + 0.0415560 * xyz.z, 0.0556434 * xyz.x - 0.2040259 * xyz.y + 1.0572252 * xyz.z ); } fn iridescentFresnel(outsideIor: f32, iridescenceIor: f32, baseF0: vec3f, thickness: f32, cosTheta1: f32) -> vec3f { let safeCosTheta1 = clamp(cosTheta1, 0.0, 1.0); let thinFilmIor = mix(outsideIor, iridescenceIor, smoothstep(0.0, 0.03, thickness)); let R0 = iorToFresnel0(thinFilmIor, outsideIor); let R12 = fresnelSchlickScalar(safeCosTheta1, R0); let T121 = 1.0 - R12; let baseIor = fresnel0ToIor(baseF0); let R1 = iorToFresnel0Vec(baseIor, thinFilmIor); let eta = outsideIor / thinFilmIor; let sinTheta2Sq = eta * eta * (1.0 - safeCosTheta1 * safeCosTheta1); let cosTheta2Sq = 1.0 - sinTheta2Sq; if (cosTheta2Sq < 0.0) { return vec3f(1.0); } let cosTheta2 = sqrt(cosTheta2Sq); let R23 = fresnelSchlick(cosTheta2, R1, vec3f(1.0)); let phi12 = select(0.0, PI, thinFilmIor < outsideIor); let phi21 = PI - phi12; let phi23 = vec3f( select(0.0, PI, baseIor.x < thinFilmIor), select(0.0, PI, baseIor.y < thinFilmIor), select(0.0, PI, baseIor.z < thinFilmIor) ); let phi = vec3f(phi21) + phi23; let OPD = 2.0 * thinFilmIor * thickness * cosTheta2; let R123 = clamp(vec3f(R12) * R23, vec3f(1e-5), vec3f(0.9999)); let r123 = sqrt(R123); let Rs = sqr(T121) * R23 / (vec3f(1.0) - R123); var I = vec3f(R12) + Rs; var Cm = Rs - vec3f(T121); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(OPD, phi); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(2.0 * OPD, 2.0 * phi); return sanitizeReflectance(I, baseF0); } fn distributionGGXAnisotropic(NdotH: f32, TdotH: f32, BdotH: f32, at: f32, ab: f32) -> f32 { let a2 = at * ab; let f = vec3f(ab * TdotH, at * BdotH, a2 * NdotH); let w2 = a2 / max(dot(f, f), 1e-8); return a2 * w2 * w2 / PI; } fn visibilityGGXAnisotropic(NdotL: f32, NdotV: f32, BdotV: f32, TdotV: f32, TdotL: f32, BdotL: f32, at: f32, ab: f32) -> f32 { let GGXV = NdotL * length(vec3f(at * TdotV, ab * BdotV, NdotV)); let GGXL = NdotV * length(vec3f(at * TdotL, ab * BdotL, NdotL)); return clamp(0.5 / max(GGXV + GGXL, 1e-8), 0.0, 1.0); } fn sheenDistribution(NdotH: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let invR = 1.0 / alphaG; let sin2h = max(1.0 - NdotH * NdotH, 0.0); return (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * PI); } fn sheenL(cosTheta: f32, alphaG: f32) -> f32 { let oneMinusAlphaSq = sqr(1.0 - alphaG); let a = mix(21.5473, 25.3245, oneMinusAlphaSq); let b = mix(3.82987, 3.32435, oneMinusAlphaSq); let c = mix(0.19823, 0.16801, oneMinusAlphaSq); let d = mix(-1.97760, -1.27393, oneMinusAlphaSq); let e = mix(-4.32054, -4.85967, oneMinusAlphaSq); return a / (1.0 + b * pow(cosTheta, c)) + d * cosTheta + e; } fn sheenLambda(cosTheta: f32, alphaG: f32) -> f32 { let safeCosTheta = clamp(cosTheta, 1e-4, 1.0); if (safeCosTheta < 0.5) { return exp(sheenL(safeCosTheta, alphaG)); } return exp(2.0 * sheenL(0.5, alphaG) - sheenL(1.0 - safeCosTheta, alphaG)); } fn sheenVisibility(NdotL: f32, NdotV: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let visibility = 1.0 + sheenLambda(NdotV, alphaG) + sheenLambda(NdotL, alphaG); return clamp(1.0 / max(visibility * 4.0 * NdotV * NdotL, 1e-6), 0.0, 1.0); } fn dielectricF0FromIor(ior: f32) -> f32 { if (ior == 0.0) { return 1.0; } let safeIor = max(ior, 1.0); let r = (safeIor - 1.0) / (safeIor + 1.0); return r * r; } fn computeRangeAttenuation(distance: f32, range: f32) -> f32 { let invSq = 1.0 / max(distance * distance, 0.0001); if (range <= 0.0) { return invSq; } let fade = clamp(1.0 - distance / range, 0.0, 1.0); return invSq * fade * fade; } fn computeSpotFactor(L: vec3f, direction: vec3f, cosInner: f32, cosOuter: f32) -> f32 { let angleCos = dot(-L, normalize(direction)); if (cosInner <= cosOuter) { return select(0.0, 1.0, angleCos >= cosOuter); } return clamp((angleCos - cosOuter) / max(cosInner - cosOuter, 1e-4), 0.0, 1.0); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let mrUv = applyTextureTransform(in.uv, in.uv1, material.metallicRoughnessTransform0, material.metallicRoughnessTransform1); let normalUv = applyTextureTransform(in.uv, in.uv1, material.normalTransform0, material.normalTransform1); let occlusionUv = applyTextureTransform(in.uv, in.uv1, material.occlusionTransform0, material.occlusionTransform1); let emissiveUv = applyTextureTransform(in.uv, in.uv1, material.emissiveTransform0, material.emissiveTransform1); let clearcoatUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatTransform0, material.clearcoatTransform1); let clearcoatRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatRoughnessTransform0, material.clearcoatRoughnessTransform1); let clearcoatNormalUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatNormalTransform0, material.clearcoatNormalTransform1); let specularUv = applyTextureTransform(in.uv, in.uv1, material.specularTransform0, material.specularTransform1); let specularColorUv = applyTextureTransform(in.uv, in.uv1, material.specularColorTransform0, material.specularColorTransform1); let sheenColorUv = applyTextureTransform(in.uv, in.uv1, material.sheenColorTransform0, material.sheenColorTransform1); let sheenRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.sheenRoughnessTransform0, material.sheenRoughnessTransform1); let iridescenceUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceTransform0, material.iridescenceTransform1); let iridescenceThicknessUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceThicknessTransform0, material.iridescenceThicknessTransform1); let anisotropyUv = applyTextureTransform(in.uv, in.uv1, material.anisotropyTransform0, material.anisotropyTransform1); let baseSample = textureSample(baseColorTex, baseColorSampler, baseUv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, mrUv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, normalUv).xyz; let N = applyNormalMap(in.normal, in.tangent, in.worldPos, normalUv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, occlusionUv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, emissiveUv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a * material.extensionParams.y; let clearcoat = clamp(material.clearcoatParams.x * textureSample(clearcoatTex, clearcoatSampler, clearcoatUv).r, 0.0, 1.0); let clearcoatRoughness = clamp(material.clearcoatParams.y * textureSample(clearcoatRoughnessTex, clearcoatRoughnessSampler, clearcoatRoughnessUv).g, 0.04, 1.0); let clearcoatNormalSample = textureSample(clearcoatNormalTex, clearcoatNormalSampler, clearcoatNormalUv).xyz; let clearcoatNormal = applyNormalMap(in.normal, in.tangent, in.worldPos, clearcoatNormalUv, clearcoatNormalSample, material.clearcoatParams.z); let specularStrength = clamp(material.specularParams.x * textureSample(specularTex, specularSampler, specularUv).a, 0.0, 1.0); let specularColor = material.specularParams.yzw * textureSample(specularColorTex, specularColorSampler, specularColorUv).rgb; let sheenColor = material.sheenParams.rgb * textureSample(sheenColorTex, sheenColorSampler, sheenColorUv).rgb; let sheenRoughness = clamp(material.sheenParams.w * textureSample(sheenRoughnessTex, sheenRoughnessSampler, sheenRoughnessUv).a, 0.0, 1.0); let iridescence = clamp(material.iridescenceParams.x * textureSample(iridescenceTex, iridescenceSampler, iridescenceUv).r, 0.0, 1.0); let iridescenceThicknessSample = textureSample(iridescenceThicknessTex, iridescenceThicknessSampler, iridescenceThicknessUv).g; let iridescenceThickness = mix(material.iridescenceParams.z, material.iridescenceParams.w, iridescenceThicknessSample); let anisotropySample = textureSample(anisotropyTex, anisotropySampler, anisotropyUv).rgb; let anisotropyStrength = clamp(material.anisotropyParams.x * anisotropySample.b, 0.0, 1.0); var anisotropyDirection = anisotropySample.rg * 2.0 - vec2f(1.0); let anisotropyDirectionLength2 = dot(anisotropyDirection, anisotropyDirection); anisotropyDirection = select(vec2f(1.0, 0.0), anisotropyDirection * inverseSqrt(max(anisotropyDirectionLength2, 1e-8)), anisotropyDirectionLength2 > 1e-8); anisotropyDirection = vec2f( material.anisotropyParams.y * anisotropyDirection.x - material.anisotropyParams.z * anisotropyDirection.y, material.anisotropyParams.z * anisotropyDirection.x + material.anisotropyParams.y * anisotropyDirection.y ); let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let dielectricF0 = dielectricF0FromIor(material.extensionParams.x); let dielectricF0Color = min(vec3f(dielectricF0) * specularColor, vec3f(1.0)) * specularStrength; let F0 = mix(dielectricF0Color, albedo, metallic); let F90 = mix(vec3f(specularStrength), vec3f(1.0), metallic); let viewNdotV = max(dot(N, V), 0.0); var iridescenceFresnelColor = F0; if (iridescence > 1e-5 && iridescenceThickness > 0.0) { iridescenceFresnelColor = iridescentFresnel(1.0, material.iridescenceParams.y, F0, iridescenceThickness, viewNdotV); } let geometricN = normalize(in.normal); let anisotropyFrame = buildTangentFrame(geometricN, in.tangent, in.worldPos, anisotropyUv); let clearcoatViewFresnel = clamp(clearcoat * fresnelSchlickScalar(abs(dot(V, clearcoatNormal)), 0.04), 0.0, 1.0); var Lo = lighting.ambient.rgb * albedo * ao; for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); if (distance <= 1e-5) { continue; } L = lightDir / distance; attenuation = computeRangeAttenuation(distance, light.params.x); if (light.position.w == 2.0) { attenuation = attenuation * computeSpotFactor(L, light.direction.xyz, light.params.y, light.params.z); } } if (attenuation <= 0.0) { continue; } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NdotL = max(dot(N, L), 0.0); let NdotV = viewNdotV; let NdotH = max(dot(N, H), 0.0); let VdotH = max(dot(V, H), 0.0); let baseF = fresnelSchlick(VdotH, F0, F90); var F = baseF; if (iridescence > 1e-5) { F = mix(baseF, iridescenceFresnelColor, iridescence); } var specularBrdf: vec3f; if (anisotropyStrength > 1e-5) { let anisotropicT = normalize(anisotropyFrame.t * anisotropyDirection.x + anisotropyFrame.b * anisotropyDirection.y); let anisotropicB = normalize(cross(geometricN, anisotropicT)); let TdotV = dot(anisotropicT, V); let BdotV = dot(anisotropicB, V); let TdotL = dot(anisotropicT, L); let BdotL = dot(anisotropicB, L); let TdotH = dot(anisotropicT, H); let BdotH = dot(anisotropicB, H); let alphaRoughness = max(roughness * roughness, 0.001); let at = mix(alphaRoughness, 1.0, anisotropyStrength * anisotropyStrength); let ab = alphaRoughness; let D = distributionGGXAnisotropic(NdotH, TdotH, BdotH, at, ab); let Vg = visibilityGGXAnisotropic(NdotL, NdotV, BdotV, TdotV, TdotL, BdotL, at, ab); specularBrdf = F * D * Vg; } else { let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let numerator = NDF * G * F; let denominator = 4.0 * NdotV * NdotL + 0.0001; specularBrdf = numerator / denominator; } let sheenD = sheenDistribution(NdotH, sheenRoughness); let sheenV = sheenVisibility(NdotL, NdotV, sheenRoughness); let sheenBrdf = sheenColor * sheenD * sheenV; let diffuseEnergy = max(1.0 - maxComponent(F), 0.0); let kD = vec3f(diffuseEnergy) * (1.0 - metallic); let baseContribution = (kD * albedo / PI + specularBrdf + sheenBrdf) * radiance * NdotL; let clearcoatNdotL = max(dot(clearcoatNormal, L), 0.0); let clearcoatNdotV = max(dot(clearcoatNormal, V), 0.0); let clearcoatNDF = distributionGGX(clearcoatNormal, H, clearcoatRoughness); let clearcoatG = geometrySmith(clearcoatNormal, V, L, clearcoatRoughness); let clearcoatBrdf = clearcoatNDF * clearcoatG / (4.0 * clearcoatNdotV * clearcoatNdotL + 0.0001); let clearcoatContribution = vec3f(clearcoatBrdf) * radiance * clearcoatNdotL; Lo += mix(baseContribution, clearcoatContribution, clearcoatViewFresnel); } Lo += emissive * (1.0 - clearcoatViewFresnel); Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var ga="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f, metallicRoughnessTransform0: vec4f, metallicRoughnessTransform1: vec4f, normalTransform0: vec4f, normalTransform1: vec4f, occlusionTransform0: vec4f, occlusionTransform1: vec4f, emissiveTransform0: vec4f, emissiveTransform1: vec4f, clearcoatParams: vec4f, specularParams: vec4f, extensionParams: vec4f, clearcoatTransform0: vec4f, clearcoatTransform1: vec4f, clearcoatRoughnessTransform0: vec4f, clearcoatRoughnessTransform1: vec4f, clearcoatNormalTransform0: vec4f, clearcoatNormalTransform1: vec4f, specularTransform0: vec4f, specularTransform1: vec4f, specularColorTransform0: vec4f, specularColorTransform1: vec4f, sheenParams: vec4f, iridescenceParams: vec4f, anisotropyParams: vec4f, sheenColorTransform0: vec4f, sheenColorTransform1: vec4f, sheenRoughnessTransform0: vec4f, sheenRoughnessTransform1: vec4f, iridescenceTransform0: vec4f, iridescenceTransform1: vec4f, iridescenceThicknessTransform0: vec4f, iridescenceThicknessTransform1: vec4f, anisotropyTransform0: vec4f, anisotropyTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; @group(1) @binding(11) var clearcoatSampler: sampler; @group(1) @binding(12) var clearcoatTex: texture_2d<f32>; @group(1) @binding(13) var clearcoatRoughnessSampler: sampler; @group(1) @binding(14) var clearcoatRoughnessTex: texture_2d<f32>; @group(1) @binding(15) var clearcoatNormalSampler: sampler; @group(1) @binding(16) var clearcoatNormalTex: texture_2d<f32>; @group(1) @binding(17) var specularSampler: sampler; @group(1) @binding(18) var specularTex: texture_2d<f32>; @group(1) @binding(19) var specularColorSampler: sampler; @group(1) @binding(20) var specularColorTex: texture_2d<f32>; @group(1) @binding(21) var sheenColorSampler: sampler; @group(1) @binding(22) var sheenColorTex: texture_2d<f32>; @group(1) @binding(23) var sheenRoughnessSampler: sampler; @group(1) @binding(24) var sheenRoughnessTex: texture_2d<f32>; @group(1) @binding(25) var iridescenceSampler: sampler; @group(1) @binding(26) var iridescenceTex: texture_2d<f32>; @group(1) @binding(27) var iridescenceThicknessSampler: sampler; @group(1) @binding(28) var iridescenceThicknessTex: texture_2d<f32>; @group(1) @binding(29) var anisotropySampler: sampler; @group(1) @binding(30) var anisotropyTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(12) tangent: vec4f, @location(3) m0: vec4f, @location(4) m1: vec4f, @location(5) m2: vec4f, @location(6) m3: vec4f, @location(7) n0: vec4f, @location(8) n1: vec4f, @location(9) n2: vec4f, @location(10) n3: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) uv1: vec2f, @location(4) tangent: vec4f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct Light { position: vec4f, color: vec4f, direction: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let modelM = mat4x4f(in.m0, in.m1, in.m2, in.m3); let normalM = mat4x4f(in.n0, in.n1, in.n2, in.n3); let worldPos4 = modelM * vec4f(in.position, 1.0); out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((normalM * vec4f(in.normal, 0.0)).xyz); out.tangent = vec4f((normalM * vec4f(in.tangent.xyz, 0.0)).xyz, in.tangent.w); out.uv = in.uv; out.uv1 = in.uv1; return out; } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } fn fresnelSchlick(cosTheta: f32, F0: vec3f, F90: vec3f) -> vec3f { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (F90 - F0) * pow(oneMinusCos, 5.0); } fn maxComponent(v: vec3f) -> f32 { return max(max(v.x, v.y), v.z); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } struct TangentFrame { t: vec3f, b: vec3f, n: vec3f }; fn fallbackTangentFrame(N: vec3f) -> TangentFrame { let n = normalize(N); let axis = select(vec3f(0.0, 1.0, 0.0), vec3f(1.0, 0.0, 0.0), abs(n.x) < 0.9); let t = normalize(cross(axis, n)); let b = cross(n, t); return TangentFrame(t, b, n); } fn derivativeTangentFrame(N: vec3f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let dp2perp = cross(dp2, n); let dp1perp = cross(n, dp1); let T = (dp2perp * duv1.x) + (dp1perp * duv2.x); let B = (dp2perp * duv1.y) + (dp1perp * duv2.y); let frameLength2 = max(dot(T, T), dot(B, B)); if (frameLength2 <= 1e-20) { return fallbackTangentFrame(n); } let frameScale = 1.0 / sqrt(frameLength2); return TangentFrame(T * frameScale, B * frameScale, n); } fn buildTangentFrame(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let derivativeFrame = derivativeTangentFrame(n, worldPos, uv); var t = tangent.xyz - n * dot(n, tangent.xyz); let tLen2 = dot(t, t); if (tLen2 <= 1e-20) { return derivativeFrame; } t = t * inverseSqrt(tLen2); let b = normalize(cross(n, t)) * select(-1.0, 1.0, tangent.w >= 0.0); return TangentFrame(t, b, n); } fn applyNormalMap(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { if (normalScale == 0.0) { return normalize(N); } let frame = buildTangentFrame(N, tangent, worldPos, uv); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(frame.t * ns.x + frame.b * ns.y + frame.n * ns.z); } fn sqr(v: f32) -> f32 { return v * v; } fn iorToFresnel0(transmittedIor: f32, incidentIor: f32) -> f32 { let r = (transmittedIor - incidentIor) / (transmittedIor + incidentIor); return r * r; } fn iorToFresnel0Vec(transmittedIor: vec3f, incidentIor: f32) -> vec3f { let r = (transmittedIor - vec3f(incidentIor)) / (transmittedIor + vec3f(incidentIor)); return r * r; } fn fresnel0ToIor(F0: vec3f) -> vec3f { let sqrtF0 = sqrt(clamp(F0, vec3f(0.0), vec3f(0.9999))); return (vec3f(1.0) + sqrtF0) / max(vec3f(1.0) - sqrtF0, vec3f(1e-4)); } fn fresnelSchlickScalar(cosTheta: f32, F0: f32) -> f32 { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (1.0 - F0) * pow(oneMinusCos, 5.0); } fn sanitizeReflectance(value: vec3f, fallback: vec3f) -> vec3f { var result = clamp(fallback, vec3f(0.0), vec3f(1.0)); if (value.x == value.x && abs(value.x) < 1.0e6) { result.x = clamp(value.x, 0.0, 1.0); } if (value.y == value.y && abs(value.y) < 1.0e6) { result.y = clamp(value.y, 0.0, 1.0); } if (value.z == value.z && abs(value.z) < 1.0e6) { result.z = clamp(value.z, 0.0, 1.0); } return result; } fn evalIridescenceSensitivity(OPD: f32, shift: vec3f) -> vec3f { let phase = 2.0 * PI * OPD * 1.0e-9; let phase2 = phase * phase; let val = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13); let pos = vec3f(1.6810e+06, 1.7953e+06, 2.2084e+06); let variance = vec3f(4.3278e+09, 9.3046e+09, 6.6121e+09); var xyz = val * sqrt(2.0 * PI * variance) * cos(pos * phase + shift) * exp(-phase2 * variance); xyz.x += 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift.x) * exp(-4.5282e+09 * phase2); xyz /= 1.0685e-7; return vec3f( 3.2404542 * xyz.x - 1.5371385 * xyz.y - 0.4985314 * xyz.z, -0.9692660 * xyz.x + 1.8760108 * xyz.y + 0.0415560 * xyz.z, 0.0556434 * xyz.x - 0.2040259 * xyz.y + 1.0572252 * xyz.z ); } fn iridescentFresnel(outsideIor: f32, iridescenceIor: f32, baseF0: vec3f, thickness: f32, cosTheta1: f32) -> vec3f { let safeCosTheta1 = clamp(cosTheta1, 0.0, 1.0); let thinFilmIor = mix(outsideIor, iridescenceIor, smoothstep(0.0, 0.03, thickness)); let R0 = iorToFresnel0(thinFilmIor, outsideIor); let R12 = fresnelSchlickScalar(safeCosTheta1, R0); let T121 = 1.0 - R12; let baseIor = fresnel0ToIor(baseF0); let R1 = iorToFresnel0Vec(baseIor, thinFilmIor); let eta = outsideIor / thinFilmIor; let sinTheta2Sq = eta * eta * (1.0 - safeCosTheta1 * safeCosTheta1); let cosTheta2Sq = 1.0 - sinTheta2Sq; if (cosTheta2Sq < 0.0) { return vec3f(1.0); } let cosTheta2 = sqrt(cosTheta2Sq); let R23 = fresnelSchlick(cosTheta2, R1, vec3f(1.0)); let phi12 = select(0.0, PI, thinFilmIor < outsideIor); let phi21 = PI - phi12; let phi23 = vec3f( select(0.0, PI, baseIor.x < thinFilmIor), select(0.0, PI, baseIor.y < thinFilmIor), select(0.0, PI, baseIor.z < thinFilmIor) ); let phi = vec3f(phi21) + phi23; let OPD = 2.0 * thinFilmIor * thickness * cosTheta2; let R123 = clamp(vec3f(R12) * R23, vec3f(1e-5), vec3f(0.9999)); let r123 = sqrt(R123); let Rs = sqr(T121) * R23 / (vec3f(1.0) - R123); var I = vec3f(R12) + Rs; var Cm = Rs - vec3f(T121); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(OPD, phi); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(2.0 * OPD, 2.0 * phi); return sanitizeReflectance(I, baseF0); } fn distributionGGXAnisotropic(NdotH: f32, TdotH: f32, BdotH: f32, at: f32, ab: f32) -> f32 { let a2 = at * ab; let f = vec3f(ab * TdotH, at * BdotH, a2 * NdotH); let w2 = a2 / max(dot(f, f), 1e-8); return a2 * w2 * w2 / PI; } fn visibilityGGXAnisotropic(NdotL: f32, NdotV: f32, BdotV: f32, TdotV: f32, TdotL: f32, BdotL: f32, at: f32, ab: f32) -> f32 { let GGXV = NdotL * length(vec3f(at * TdotV, ab * BdotV, NdotV)); let GGXL = NdotV * length(vec3f(at * TdotL, ab * BdotL, NdotL)); return clamp(0.5 / max(GGXV + GGXL, 1e-8), 0.0, 1.0); } fn sheenDistribution(NdotH: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let invR = 1.0 / alphaG; let sin2h = max(1.0 - NdotH * NdotH, 0.0); return (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * PI); } fn sheenL(cosTheta: f32, alphaG: f32) -> f32 { let oneMinusAlphaSq = sqr(1.0 - alphaG); let a = mix(21.5473, 25.3245, oneMinusAlphaSq); let b = mix(3.82987, 3.32435, oneMinusAlphaSq); let c = mix(0.19823, 0.16801, oneMinusAlphaSq); let d = mix(-1.97760, -1.27393, oneMinusAlphaSq); let e = mix(-4.32054, -4.85967, oneMinusAlphaSq); return a / (1.0 + b * pow(cosTheta, c)) + d * cosTheta + e; } fn sheenLambda(cosTheta: f32, alphaG: f32) -> f32 { let safeCosTheta = clamp(cosTheta, 1e-4, 1.0); if (safeCosTheta < 0.5) { return exp(sheenL(safeCosTheta, alphaG)); } return exp(2.0 * sheenL(0.5, alphaG) - sheenL(1.0 - safeCosTheta, alphaG)); } fn sheenVisibility(NdotL: f32, NdotV: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let visibility = 1.0 + sheenLambda(NdotV, alphaG) + sheenLambda(NdotL, alphaG); return clamp(1.0 / max(visibility * 4.0 * NdotV * NdotL, 1e-6), 0.0, 1.0); } fn dielectricF0FromIor(ior: f32) -> f32 { if (ior == 0.0) { return 1.0; } let safeIor = max(ior, 1.0); let r = (safeIor - 1.0) / (safeIor + 1.0); return r * r; } fn computeRangeAttenuation(distance: f32, range: f32) -> f32 { let invSq = 1.0 / max(distance * distance, 0.0001); if (range <= 0.0) { return invSq; } let fade = clamp(1.0 - distance / range, 0.0, 1.0); return invSq * fade * fade; } fn computeSpotFactor(L: vec3f, direction: vec3f, cosInner: f32, cosOuter: f32) -> f32 { let angleCos = dot(-L, normalize(direction)); if (cosInner <= cosOuter) { return select(0.0, 1.0, angleCos >= cosOuter); } return clamp((angleCos - cosOuter) / max(cosInner - cosOuter, 1e-4), 0.0, 1.0); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let mrUv = applyTextureTransform(in.uv, in.uv1, material.metallicRoughnessTransform0, material.metallicRoughnessTransform1); let normalUv = applyTextureTransform(in.uv, in.uv1, material.normalTransform0, material.normalTransform1); let occlusionUv = applyTextureTransform(in.uv, in.uv1, material.occlusionTransform0, material.occlusionTransform1); let emissiveUv = applyTextureTransform(in.uv, in.uv1, material.emissiveTransform0, material.emissiveTransform1); let clearcoatUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatTransform0, material.clearcoatTransform1); let clearcoatRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatRoughnessTransform0, material.clearcoatRoughnessTransform1); let clearcoatNormalUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatNormalTransform0, material.clearcoatNormalTransform1); let specularUv = applyTextureTransform(in.uv, in.uv1, material.specularTransform0, material.specularTransform1); let specularColorUv = applyTextureTransform(in.uv, in.uv1, material.specularColorTransform0, material.specularColorTransform1); let sheenColorUv = applyTextureTransform(in.uv, in.uv1, material.sheenColorTransform0, material.sheenColorTransform1); let sheenRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.sheenRoughnessTransform0, material.sheenRoughnessTransform1); let iridescenceUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceTransform0, material.iridescenceTransform1); let iridescenceThicknessUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceThicknessTransform0, material.iridescenceThicknessTransform1); let anisotropyUv = applyTextureTransform(in.uv, in.uv1, material.anisotropyTransform0, material.anisotropyTransform1); let baseSample = textureSample(baseColorTex, baseColorSampler, baseUv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, mrUv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, normalUv).xyz; let N = applyNormalMap(in.normal, in.tangent, in.worldPos, normalUv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, occlusionUv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, emissiveUv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a * material.extensionParams.y; let clearcoat = clamp(material.clearcoatParams.x * textureSample(clearcoatTex, clearcoatSampler, clearcoatUv).r, 0.0, 1.0); let clearcoatRoughness = clamp(material.clearcoatParams.y * textureSample(clearcoatRoughnessTex, clearcoatRoughnessSampler, clearcoatRoughnessUv).g, 0.04, 1.0); let clearcoatNormalSample = textureSample(clearcoatNormalTex, clearcoatNormalSampler, clearcoatNormalUv).xyz; let clearcoatNormal = applyNormalMap(in.normal, in.tangent, in.worldPos, clearcoatNormalUv, clearcoatNormalSample, material.clearcoatParams.z); let specularStrength = clamp(material.specularParams.x * textureSample(specularTex, specularSampler, specularUv).a, 0.0, 1.0); let specularColor = material.specularParams.yzw * textureSample(specularColorTex, specularColorSampler, specularColorUv).rgb; let sheenColor = material.sheenParams.rgb * textureSample(sheenColorTex, sheenColorSampler, sheenColorUv).rgb; let sheenRoughness = clamp(material.sheenParams.w * textureSample(sheenRoughnessTex, sheenRoughnessSampler, sheenRoughnessUv).a, 0.0, 1.0); let iridescence = clamp(material.iridescenceParams.x * textureSample(iridescenceTex, iridescenceSampler, iridescenceUv).r, 0.0, 1.0); let iridescenceThicknessSample = textureSample(iridescenceThicknessTex, iridescenceThicknessSampler, iridescenceThicknessUv).g; let iridescenceThickness = mix(material.iridescenceParams.z, material.iridescenceParams.w, iridescenceThicknessSample); let anisotropySample = textureSample(anisotropyTex, anisotropySampler, anisotropyUv).rgb; let anisotropyStrength = clamp(material.anisotropyParams.x * anisotropySample.b, 0.0, 1.0); var anisotropyDirection = anisotropySample.rg * 2.0 - vec2f(1.0); let anisotropyDirectionLength2 = dot(anisotropyDirection, anisotropyDirection); anisotropyDirection = select(vec2f(1.0, 0.0), anisotropyDirection * inverseSqrt(max(anisotropyDirectionLength2, 1e-8)), anisotropyDirectionLength2 > 1e-8); anisotropyDirection = vec2f( material.anisotropyParams.y * anisotropyDirection.x - material.anisotropyParams.z * anisotropyDirection.y, material.anisotropyParams.z * anisotropyDirection.x + material.anisotropyParams.y * anisotropyDirection.y ); let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let dielectricF0 = dielectricF0FromIor(material.extensionParams.x); let dielectricF0Color = min(vec3f(dielectricF0) * specularColor, vec3f(1.0)) * specularStrength; let F0 = mix(dielectricF0Color, albedo, metallic); let F90 = mix(vec3f(specularStrength), vec3f(1.0), metallic); let viewNdotV = max(dot(N, V), 0.0); var iridescenceFresnelColor = F0; if (iridescence > 1e-5 && iridescenceThickness > 0.0) { iridescenceFresnelColor = iridescentFresnel(1.0, material.iridescenceParams.y, F0, iridescenceThickness, viewNdotV); } let geometricN = normalize(in.normal); let anisotropyFrame = buildTangentFrame(geometricN, in.tangent, in.worldPos, anisotropyUv); let clearcoatViewFresnel = clamp(clearcoat * fresnelSchlickScalar(abs(dot(V, clearcoatNormal)), 0.04), 0.0, 1.0); var Lo = lighting.ambient.rgb * albedo * ao; for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); if (distance <= 1e-5) { continue; } L = lightDir / distance; attenuation = computeRangeAttenuation(distance, light.params.x); if (light.position.w == 2.0) { attenuation = attenuation * computeSpotFactor(L, light.direction.xyz, light.params.y, light.params.z); } } if (attenuation <= 0.0) { continue; } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NdotL = max(dot(N, L), 0.0); let NdotV = viewNdotV; let NdotH = max(dot(N, H), 0.0); let VdotH = max(dot(V, H), 0.0); let baseF = fresnelSchlick(VdotH, F0, F90); var F = baseF; if (iridescence > 1e-5) { F = mix(baseF, iridescenceFresnelColor, iridescence); } var specularBrdf: vec3f; if (anisotropyStrength > 1e-5) { let anisotropicT = normalize(anisotropyFrame.t * anisotropyDirection.x + anisotropyFrame.b * anisotropyDirection.y); let anisotropicB = normalize(cross(geometricN, anisotropicT)); let TdotV = dot(anisotropicT, V); let BdotV = dot(anisotropicB, V); let TdotL = dot(anisotropicT, L); let BdotL = dot(anisotropicB, L); let TdotH = dot(anisotropicT, H); let BdotH = dot(anisotropicB, H); let alphaRoughness = max(roughness * roughness, 0.001); let at = mix(alphaRoughness, 1.0, anisotropyStrength * anisotropyStrength); let ab = alphaRoughness; let D = distributionGGXAnisotropic(NdotH, TdotH, BdotH, at, ab); let Vg = visibilityGGXAnisotropic(NdotL, NdotV, BdotV, TdotV, TdotL, BdotL, at, ab); specularBrdf = F * D * Vg; } else { let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let numerator = NDF * G * F; let denominator = 4.0 * NdotV * NdotL + 0.0001; specularBrdf = numerator / denominator; } let sheenD = sheenDistribution(NdotH, sheenRoughness); let sheenV = sheenVisibility(NdotL, NdotV, sheenRoughness); let sheenBrdf = sheenColor * sheenD * sheenV; let diffuseEnergy = max(1.0 - maxComponent(F), 0.0); let kD = vec3f(diffuseEnergy) * (1.0 - metallic); let baseContribution = (kD * albedo / PI + specularBrdf + sheenBrdf) * radiance * NdotL; let clearcoatNdotL = max(dot(clearcoatNormal, L), 0.0); let clearcoatNdotV = max(dot(clearcoatNormal, V), 0.0); let clearcoatNDF = distributionGGX(clearcoatNormal, H, clearcoatRoughness); let clearcoatG = geometrySmith(clearcoatNormal, V, L, clearcoatRoughness); let clearcoatBrdf = clearcoatNDF * clearcoatG / (4.0 * clearcoatNdotV * clearcoatNdotL + 0.0001); let clearcoatContribution = vec3f(clearcoatBrdf) * radiance * clearcoatNdotL; Lo += mix(baseContribution, clearcoatContribution, clearcoatViewFresnel); } Lo += emissive * (1.0 - clearcoatViewFresnel); Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var ba="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f, metallicRoughnessTransform0: vec4f, metallicRoughnessTransform1: vec4f, normalTransform0: vec4f, normalTransform1: vec4f, occlusionTransform0: vec4f, occlusionTransform1: vec4f, emissiveTransform0: vec4f, emissiveTransform1: vec4f, clearcoatParams: vec4f, specularParams: vec4f, extensionParams: vec4f, clearcoatTransform0: vec4f, clearcoatTransform1: vec4f, clearcoatRoughnessTransform0: vec4f, clearcoatRoughnessTransform1: vec4f, clearcoatNormalTransform0: vec4f, clearcoatNormalTransform1: vec4f, specularTransform0: vec4f, specularTransform1: vec4f, specularColorTransform0: vec4f, specularColorTransform1: vec4f, sheenParams: vec4f, iridescenceParams: vec4f, anisotropyParams: vec4f, sheenColorTransform0: vec4f, sheenColorTransform1: vec4f, sheenRoughnessTransform0: vec4f, sheenRoughnessTransform1: vec4f, iridescenceTransform0: vec4f, iridescenceTransform1: vec4f, iridescenceThicknessTransform0: vec4f, iridescenceThicknessTransform1: vec4f, anisotropyTransform0: vec4f, anisotropyTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; @group(1) @binding(11) var clearcoatSampler: sampler; @group(1) @binding(12) var clearcoatTex: texture_2d<f32>; @group(1) @binding(13) var clearcoatRoughnessSampler: sampler; @group(1) @binding(14) var clearcoatRoughnessTex: texture_2d<f32>; @group(1) @binding(15) var clearcoatNormalSampler: sampler; @group(1) @binding(16) var clearcoatNormalTex: texture_2d<f32>; @group(1) @binding(17) var specularSampler: sampler; @group(1) @binding(18) var specularTex: texture_2d<f32>; @group(1) @binding(19) var specularColorSampler: sampler; @group(1) @binding(20) var specularColorTex: texture_2d<f32>; @group(1) @binding(21) var sheenColorSampler: sampler; @group(1) @binding(22) var sheenColorTex: texture_2d<f32>; @group(1) @binding(23) var sheenRoughnessSampler: sampler; @group(1) @binding(24) var sheenRoughnessTex: texture_2d<f32>; @group(1) @binding(25) var iridescenceSampler: sampler; @group(1) @binding(26) var iridescenceTex: texture_2d<f32>; @group(1) @binding(27) var iridescenceThicknessSampler: sampler; @group(1) @binding(28) var iridescenceThicknessTex: texture_2d<f32>; @group(1) @binding(29) var anisotropySampler: sampler; @group(1) @binding(30) var anisotropyTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(12) tangent: vec4f, @location(3) joints: vec4u, @location(4) weights: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) uv1: vec2f, @location(4) tangent: vec4f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, direction: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; struct SkinBuffer { joints: array<mat4x4f> }; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let j = in.joints; let w = in.weights; let skinMatrix = skin.joints[j.x] * w.x + skin.joints[j.y] * w.y + skin.joints[j.z] * w.z + skin.joints[j.w] * w.w; let localPos = skinMatrix * vec4f(in.position, 1.0); let localNormal = (skinMatrix * vec4f(in.normal, 0.0)).xyz; let localTangent = (skinMatrix * vec4f(in.tangent.xyz, 0.0)).xyz; let worldPos4 = model.model * localPos; out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(localNormal, 0.0)).xyz); out.tangent = vec4f((model.normalMatrix * vec4f(localTangent, 0.0)).xyz, in.tangent.w); out.uv = in.uv; out.uv1 = in.uv1; return out; } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } fn fresnelSchlick(cosTheta: f32, F0: vec3f, F90: vec3f) -> vec3f { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (F90 - F0) * pow(oneMinusCos, 5.0); } fn maxComponent(v: vec3f) -> f32 { return max(max(v.x, v.y), v.z); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } struct TangentFrame { t: vec3f, b: vec3f, n: vec3f }; fn fallbackTangentFrame(N: vec3f) -> TangentFrame { let n = normalize(N); let axis = select(vec3f(0.0, 1.0, 0.0), vec3f(1.0, 0.0, 0.0), abs(n.x) < 0.9); let t = normalize(cross(axis, n)); let b = cross(n, t); return TangentFrame(t, b, n); } fn derivativeTangentFrame(N: vec3f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let dp2perp = cross(dp2, n); let dp1perp = cross(n, dp1); let T = (dp2perp * duv1.x) + (dp1perp * duv2.x); let B = (dp2perp * duv1.y) + (dp1perp * duv2.y); let frameLength2 = max(dot(T, T), dot(B, B)); if (frameLength2 <= 1e-20) { return fallbackTangentFrame(n); } let frameScale = 1.0 / sqrt(frameLength2); return TangentFrame(T * frameScale, B * frameScale, n); } fn buildTangentFrame(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let derivativeFrame = derivativeTangentFrame(n, worldPos, uv); var t = tangent.xyz - n * dot(n, tangent.xyz); let tLen2 = dot(t, t); if (tLen2 <= 1e-20) { return derivativeFrame; } t = t * inverseSqrt(tLen2); let b = normalize(cross(n, t)) * select(-1.0, 1.0, tangent.w >= 0.0); return TangentFrame(t, b, n); } fn applyNormalMap(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { if (normalScale == 0.0) { return normalize(N); } let frame = buildTangentFrame(N, tangent, worldPos, uv); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(frame.t * ns.x + frame.b * ns.y + frame.n * ns.z); } fn sqr(v: f32) -> f32 { return v * v; } fn iorToFresnel0(transmittedIor: f32, incidentIor: f32) -> f32 { let r = (transmittedIor - incidentIor) / (transmittedIor + incidentIor); return r * r; } fn iorToFresnel0Vec(transmittedIor: vec3f, incidentIor: f32) -> vec3f { let r = (transmittedIor - vec3f(incidentIor)) / (transmittedIor + vec3f(incidentIor)); return r * r; } fn fresnel0ToIor(F0: vec3f) -> vec3f { let sqrtF0 = sqrt(clamp(F0, vec3f(0.0), vec3f(0.9999))); return (vec3f(1.0) + sqrtF0) / max(vec3f(1.0) - sqrtF0, vec3f(1e-4)); } fn fresnelSchlickScalar(cosTheta: f32, F0: f32) -> f32 { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (1.0 - F0) * pow(oneMinusCos, 5.0); } fn sanitizeReflectance(value: vec3f, fallback: vec3f) -> vec3f { var result = clamp(fallback, vec3f(0.0), vec3f(1.0)); if (value.x == value.x && abs(value.x) < 1.0e6) { result.x = clamp(value.x, 0.0, 1.0); } if (value.y == value.y && abs(value.y) < 1.0e6) { result.y = clamp(value.y, 0.0, 1.0); } if (value.z == value.z && abs(value.z) < 1.0e6) { result.z = clamp(value.z, 0.0, 1.0); } return result; } fn evalIridescenceSensitivity(OPD: f32, shift: vec3f) -> vec3f { let phase = 2.0 * PI * OPD * 1.0e-9; let phase2 = phase * phase; let val = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13); let pos = vec3f(1.6810e+06, 1.7953e+06, 2.2084e+06); let variance = vec3f(4.3278e+09, 9.3046e+09, 6.6121e+09); var xyz = val * sqrt(2.0 * PI * variance) * cos(pos * phase + shift) * exp(-phase2 * variance); xyz.x += 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift.x) * exp(-4.5282e+09 * phase2); xyz /= 1.0685e-7; return vec3f( 3.2404542 * xyz.x - 1.5371385 * xyz.y - 0.4985314 * xyz.z, -0.9692660 * xyz.x + 1.8760108 * xyz.y + 0.0415560 * xyz.z, 0.0556434 * xyz.x - 0.2040259 * xyz.y + 1.0572252 * xyz.z ); } fn iridescentFresnel(outsideIor: f32, iridescenceIor: f32, baseF0: vec3f, thickness: f32, cosTheta1: f32) -> vec3f { let safeCosTheta1 = clamp(cosTheta1, 0.0, 1.0); let thinFilmIor = mix(outsideIor, iridescenceIor, smoothstep(0.0, 0.03, thickness)); let R0 = iorToFresnel0(thinFilmIor, outsideIor); let R12 = fresnelSchlickScalar(safeCosTheta1, R0); let T121 = 1.0 - R12; let baseIor = fresnel0ToIor(baseF0); let R1 = iorToFresnel0Vec(baseIor, thinFilmIor); let eta = outsideIor / thinFilmIor; let sinTheta2Sq = eta * eta * (1.0 - safeCosTheta1 * safeCosTheta1); let cosTheta2Sq = 1.0 - sinTheta2Sq; if (cosTheta2Sq < 0.0) { return vec3f(1.0); } let cosTheta2 = sqrt(cosTheta2Sq); let R23 = fresnelSchlick(cosTheta2, R1, vec3f(1.0)); let phi12 = select(0.0, PI, thinFilmIor < outsideIor); let phi21 = PI - phi12; let phi23 = vec3f( select(0.0, PI, baseIor.x < thinFilmIor), select(0.0, PI, baseIor.y < thinFilmIor), select(0.0, PI, baseIor.z < thinFilmIor) ); let phi = vec3f(phi21) + phi23; let OPD = 2.0 * thinFilmIor * thickness * cosTheta2; let R123 = clamp(vec3f(R12) * R23, vec3f(1e-5), vec3f(0.9999)); let r123 = sqrt(R123); let Rs = sqr(T121) * R23 / (vec3f(1.0) - R123); var I = vec3f(R12) + Rs; var Cm = Rs - vec3f(T121); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(OPD, phi); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(2.0 * OPD, 2.0 * phi); return sanitizeReflectance(I, baseF0); } fn distributionGGXAnisotropic(NdotH: f32, TdotH: f32, BdotH: f32, at: f32, ab: f32) -> f32 { let a2 = at * ab; let f = vec3f(ab * TdotH, at * BdotH, a2 * NdotH); let w2 = a2 / max(dot(f, f), 1e-8); return a2 * w2 * w2 / PI; } fn visibilityGGXAnisotropic(NdotL: f32, NdotV: f32, BdotV: f32, TdotV: f32, TdotL: f32, BdotL: f32, at: f32, ab: f32) -> f32 { let GGXV = NdotL * length(vec3f(at * TdotV, ab * BdotV, NdotV)); let GGXL = NdotV * length(vec3f(at * TdotL, ab * BdotL, NdotL)); return clamp(0.5 / max(GGXV + GGXL, 1e-8), 0.0, 1.0); } fn sheenDistribution(NdotH: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let invR = 1.0 / alphaG; let sin2h = max(1.0 - NdotH * NdotH, 0.0); return (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * PI); } fn sheenL(cosTheta: f32, alphaG: f32) -> f32 { let oneMinusAlphaSq = sqr(1.0 - alphaG); let a = mix(21.5473, 25.3245, oneMinusAlphaSq); let b = mix(3.82987, 3.32435, oneMinusAlphaSq); let c = mix(0.19823, 0.16801, oneMinusAlphaSq); let d = mix(-1.97760, -1.27393, oneMinusAlphaSq); let e = mix(-4.32054, -4.85967, oneMinusAlphaSq); return a / (1.0 + b * pow(cosTheta, c)) + d * cosTheta + e; } fn sheenLambda(cosTheta: f32, alphaG: f32) -> f32 { let safeCosTheta = clamp(cosTheta, 1e-4, 1.0); if (safeCosTheta < 0.5) { return exp(sheenL(safeCosTheta, alphaG)); } return exp(2.0 * sheenL(0.5, alphaG) - sheenL(1.0 - safeCosTheta, alphaG)); } fn sheenVisibility(NdotL: f32, NdotV: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let visibility = 1.0 + sheenLambda(NdotV, alphaG) + sheenLambda(NdotL, alphaG); return clamp(1.0 / max(visibility * 4.0 * NdotV * NdotL, 1e-6), 0.0, 1.0); } fn dielectricF0FromIor(ior: f32) -> f32 { if (ior == 0.0) { return 1.0; } let safeIor = max(ior, 1.0); let r = (safeIor - 1.0) / (safeIor + 1.0); return r * r; } fn computeRangeAttenuation(distance: f32, range: f32) -> f32 { let invSq = 1.0 / max(distance * distance, 0.0001); if (range <= 0.0) { return invSq; } let fade = clamp(1.0 - distance / range, 0.0, 1.0); return invSq * fade * fade; } fn computeSpotFactor(L: vec3f, direction: vec3f, cosInner: f32, cosOuter: f32) -> f32 { let angleCos = dot(-L, normalize(direction)); if (cosInner <= cosOuter) { return select(0.0, 1.0, angleCos >= cosOuter); } return clamp((angleCos - cosOuter) / max(cosInner - cosOuter, 1e-4), 0.0, 1.0); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let mrUv = applyTextureTransform(in.uv, in.uv1, material.metallicRoughnessTransform0, material.metallicRoughnessTransform1); let normalUv = applyTextureTransform(in.uv, in.uv1, material.normalTransform0, material.normalTransform1); let occlusionUv = applyTextureTransform(in.uv, in.uv1, material.occlusionTransform0, material.occlusionTransform1); let emissiveUv = applyTextureTransform(in.uv, in.uv1, material.emissiveTransform0, material.emissiveTransform1); let clearcoatUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatTransform0, material.clearcoatTransform1); let clearcoatRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatRoughnessTransform0, material.clearcoatRoughnessTransform1); let clearcoatNormalUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatNormalTransform0, material.clearcoatNormalTransform1); let specularUv = applyTextureTransform(in.uv, in.uv1, material.specularTransform0, material.specularTransform1); let specularColorUv = applyTextureTransform(in.uv, in.uv1, material.specularColorTransform0, material.specularColorTransform1); let sheenColorUv = applyTextureTransform(in.uv, in.uv1, material.sheenColorTransform0, material.sheenColorTransform1); let sheenRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.sheenRoughnessTransform0, material.sheenRoughnessTransform1); let iridescenceUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceTransform0, material.iridescenceTransform1); let iridescenceThicknessUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceThicknessTransform0, material.iridescenceThicknessTransform1); let anisotropyUv = applyTextureTransform(in.uv, in.uv1, material.anisotropyTransform0, material.anisotropyTransform1); let baseSample = textureSample(baseColorTex, baseColorSampler, baseUv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, mrUv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, normalUv).xyz; let N = applyNormalMap(in.normal, in.tangent, in.worldPos, normalUv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, occlusionUv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, emissiveUv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a * material.extensionParams.y; let clearcoat = clamp(material.clearcoatParams.x * textureSample(clearcoatTex, clearcoatSampler, clearcoatUv).r, 0.0, 1.0); let clearcoatRoughness = clamp(material.clearcoatParams.y * textureSample(clearcoatRoughnessTex, clearcoatRoughnessSampler, clearcoatRoughnessUv).g, 0.04, 1.0); let clearcoatNormalSample = textureSample(clearcoatNormalTex, clearcoatNormalSampler, clearcoatNormalUv).xyz; let clearcoatNormal = applyNormalMap(in.normal, in.tangent, in.worldPos, clearcoatNormalUv, clearcoatNormalSample, material.clearcoatParams.z); let specularStrength = clamp(material.specularParams.x * textureSample(specularTex, specularSampler, specularUv).a, 0.0, 1.0); let specularColor = material.specularParams.yzw * textureSample(specularColorTex, specularColorSampler, specularColorUv).rgb; let sheenColor = material.sheenParams.rgb * textureSample(sheenColorTex, sheenColorSampler, sheenColorUv).rgb; let sheenRoughness = clamp(material.sheenParams.w * textureSample(sheenRoughnessTex, sheenRoughnessSampler, sheenRoughnessUv).a, 0.0, 1.0); let iridescence = clamp(material.iridescenceParams.x * textureSample(iridescenceTex, iridescenceSampler, iridescenceUv).r, 0.0, 1.0); let iridescenceThicknessSample = textureSample(iridescenceThicknessTex, iridescenceThicknessSampler, iridescenceThicknessUv).g; let iridescenceThickness = mix(material.iridescenceParams.z, material.iridescenceParams.w, iridescenceThicknessSample); let anisotropySample = textureSample(anisotropyTex, anisotropySampler, anisotropyUv).rgb; let anisotropyStrength = clamp(material.anisotropyParams.x * anisotropySample.b, 0.0, 1.0); var anisotropyDirection = anisotropySample.rg * 2.0 - vec2f(1.0); let anisotropyDirectionLength2 = dot(anisotropyDirection, anisotropyDirection); anisotropyDirection = select(vec2f(1.0, 0.0), anisotropyDirection * inverseSqrt(max(anisotropyDirectionLength2, 1e-8)), anisotropyDirectionLength2 > 1e-8); anisotropyDirection = vec2f( material.anisotropyParams.y * anisotropyDirection.x - material.anisotropyParams.z * anisotropyDirection.y, material.anisotropyParams.z * anisotropyDirection.x + material.anisotropyParams.y * anisotropyDirection.y ); let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let dielectricF0 = dielectricF0FromIor(material.extensionParams.x); let dielectricF0Color = min(vec3f(dielectricF0) * specularColor, vec3f(1.0)) * specularStrength; let F0 = mix(dielectricF0Color, albedo, metallic); let F90 = mix(vec3f(specularStrength), vec3f(1.0), metallic); let viewNdotV = max(dot(N, V), 0.0); var iridescenceFresnelColor = F0; if (iridescence > 1e-5 && iridescenceThickness > 0.0) { iridescenceFresnelColor = iridescentFresnel(1.0, material.iridescenceParams.y, F0, iridescenceThickness, viewNdotV); } let geometricN = normalize(in.normal); let anisotropyFrame = buildTangentFrame(geometricN, in.tangent, in.worldPos, anisotropyUv); let clearcoatViewFresnel = clamp(clearcoat * fresnelSchlickScalar(abs(dot(V, clearcoatNormal)), 0.04), 0.0, 1.0); var Lo = lighting.ambient.rgb * albedo * ao; for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); if (distance <= 1e-5) { continue; } L = lightDir / distance; attenuation = computeRangeAttenuation(distance, light.params.x); if (light.position.w == 2.0) { attenuation = attenuation * computeSpotFactor(L, light.direction.xyz, light.params.y, light.params.z); } } if (attenuation <= 0.0) { continue; } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NdotL = max(dot(N, L), 0.0); let NdotV = viewNdotV; let NdotH = max(dot(N, H), 0.0); let VdotH = max(dot(V, H), 0.0); let baseF = fresnelSchlick(VdotH, F0, F90); var F = baseF; if (iridescence > 1e-5) { F = mix(baseF, iridescenceFresnelColor, iridescence); } var specularBrdf: vec3f; if (anisotropyStrength > 1e-5) { let anisotropicT = normalize(anisotropyFrame.t * anisotropyDirection.x + anisotropyFrame.b * anisotropyDirection.y); let anisotropicB = normalize(cross(geometricN, anisotropicT)); let TdotV = dot(anisotropicT, V); let BdotV = dot(anisotropicB, V); let TdotL = dot(anisotropicT, L); let BdotL = dot(anisotropicB, L); let TdotH = dot(anisotropicT, H); let BdotH = dot(anisotropicB, H); let alphaRoughness = max(roughness * roughness, 0.001); let at = mix(alphaRoughness, 1.0, anisotropyStrength * anisotropyStrength); let ab = alphaRoughness; let D = distributionGGXAnisotropic(NdotH, TdotH, BdotH, at, ab); let Vg = visibilityGGXAnisotropic(NdotL, NdotV, BdotV, TdotV, TdotL, BdotL, at, ab); specularBrdf = F * D * Vg; } else { let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let numerator = NDF * G * F; let denominator = 4.0 * NdotV * NdotL + 0.0001; specularBrdf = numerator / denominator; } let sheenD = sheenDistribution(NdotH, sheenRoughness); let sheenV = sheenVisibility(NdotL, NdotV, sheenRoughness); let sheenBrdf = sheenColor * sheenD * sheenV; let diffuseEnergy = max(1.0 - maxComponent(F), 0.0); let kD = vec3f(diffuseEnergy) * (1.0 - metallic); let baseContribution = (kD * albedo / PI + specularBrdf + sheenBrdf) * radiance * NdotL; let clearcoatNdotL = max(dot(clearcoatNormal, L), 0.0); let clearcoatNdotV = max(dot(clearcoatNormal, V), 0.0); let clearcoatNDF = distributionGGX(clearcoatNormal, H, clearcoatRoughness); let clearcoatG = geometrySmith(clearcoatNormal, V, L, clearcoatRoughness); let clearcoatBrdf = clearcoatNDF * clearcoatG / (4.0 * clearcoatNdotV * clearcoatNdotL + 0.0001); let clearcoatContribution = vec3f(clearcoatBrdf) * radiance * clearcoatNdotL; Lo += mix(baseContribution, clearcoatContribution, clearcoatViewFresnel); } Lo += emissive * (1.0 - clearcoatViewFresnel); Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var va="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f, metallicRoughnessTransform0: vec4f, metallicRoughnessTransform1: vec4f, normalTransform0: vec4f, normalTransform1: vec4f, occlusionTransform0: vec4f, occlusionTransform1: vec4f, emissiveTransform0: vec4f, emissiveTransform1: vec4f, clearcoatParams: vec4f, specularParams: vec4f, extensionParams: vec4f, clearcoatTransform0: vec4f, clearcoatTransform1: vec4f, clearcoatRoughnessTransform0: vec4f, clearcoatRoughnessTransform1: vec4f, clearcoatNormalTransform0: vec4f, clearcoatNormalTransform1: vec4f, specularTransform0: vec4f, specularTransform1: vec4f, specularColorTransform0: vec4f, specularColorTransform1: vec4f, sheenParams: vec4f, iridescenceParams: vec4f, anisotropyParams: vec4f, sheenColorTransform0: vec4f, sheenColorTransform1: vec4f, sheenRoughnessTransform0: vec4f, sheenRoughnessTransform1: vec4f, iridescenceTransform0: vec4f, iridescenceTransform1: vec4f, iridescenceThicknessTransform0: vec4f, iridescenceThicknessTransform1: vec4f, anisotropyTransform0: vec4f, anisotropyTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; @group(1) @binding(11) var clearcoatSampler: sampler; @group(1) @binding(12) var clearcoatTex: texture_2d<f32>; @group(1) @binding(13) var clearcoatRoughnessSampler: sampler; @group(1) @binding(14) var clearcoatRoughnessTex: texture_2d<f32>; @group(1) @binding(15) var clearcoatNormalSampler: sampler; @group(1) @binding(16) var clearcoatNormalTex: texture_2d<f32>; @group(1) @binding(17) var specularSampler: sampler; @group(1) @binding(18) var specularTex: texture_2d<f32>; @group(1) @binding(19) var specularColorSampler: sampler; @group(1) @binding(20) var specularColorTex: texture_2d<f32>; @group(1) @binding(21) var sheenColorSampler: sampler; @group(1) @binding(22) var sheenColorTex: texture_2d<f32>; @group(1) @binding(23) var sheenRoughnessSampler: sampler; @group(1) @binding(24) var sheenRoughnessTex: texture_2d<f32>; @group(1) @binding(25) var iridescenceSampler: sampler; @group(1) @binding(26) var iridescenceTex: texture_2d<f32>; @group(1) @binding(27) var iridescenceThicknessSampler: sampler; @group(1) @binding(28) var iridescenceThicknessTex: texture_2d<f32>; @group(1) @binding(29) var anisotropySampler: sampler; @group(1) @binding(30) var anisotropyTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(12) tangent: vec4f, @location(3) joints0: vec4u, @location(4) weights0: vec4f, @location(5) joints1: vec4u, @location(6) weights1: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) uv1: vec2f, @location(4) tangent: vec4f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, direction: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; struct SkinBuffer { joints: array<mat4x4f> }; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let j0 = in.joints0; let w0 = in.weights0; let j1 = in.joints1; let w1 = in.weights1; let skinMatrix = skin.joints[j0.x] * w0.x + skin.joints[j0.y] * w0.y + skin.joints[j0.z] * w0.z + skin.joints[j0.w] * w0.w + skin.joints[j1.x] * w1.x + skin.joints[j1.y] * w1.y + skin.joints[j1.z] * w1.z + skin.joints[j1.w] * w1.w; let localPos = skinMatrix * vec4f(in.position, 1.0); let localNormal = (skinMatrix * vec4f(in.normal, 0.0)).xyz; let localTangent = (skinMatrix * vec4f(in.tangent.xyz, 0.0)).xyz; let worldPos4 = model.model * localPos; out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(localNormal, 0.0)).xyz); out.tangent = vec4f((model.normalMatrix * vec4f(localTangent, 0.0)).xyz, in.tangent.w); out.uv = in.uv; out.uv1 = in.uv1; return out; } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } fn fresnelSchlick(cosTheta: f32, F0: vec3f, F90: vec3f) -> vec3f { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (F90 - F0) * pow(oneMinusCos, 5.0); } fn maxComponent(v: vec3f) -> f32 { return max(max(v.x, v.y), v.z); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } struct TangentFrame { t: vec3f, b: vec3f, n: vec3f }; fn fallbackTangentFrame(N: vec3f) -> TangentFrame { let n = normalize(N); let axis = select(vec3f(0.0, 1.0, 0.0), vec3f(1.0, 0.0, 0.0), abs(n.x) < 0.9); let t = normalize(cross(axis, n)); let b = cross(n, t); return TangentFrame(t, b, n); } fn derivativeTangentFrame(N: vec3f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let dp2perp = cross(dp2, n); let dp1perp = cross(n, dp1); let T = (dp2perp * duv1.x) + (dp1perp * duv2.x); let B = (dp2perp * duv1.y) + (dp1perp * duv2.y); let frameLength2 = max(dot(T, T), dot(B, B)); if (frameLength2 <= 1e-20) { return fallbackTangentFrame(n); } let frameScale = 1.0 / sqrt(frameLength2); return TangentFrame(T * frameScale, B * frameScale, n); } fn buildTangentFrame(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let derivativeFrame = derivativeTangentFrame(n, worldPos, uv); var t = tangent.xyz - n * dot(n, tangent.xyz); let tLen2 = dot(t, t); if (tLen2 <= 1e-20) { return derivativeFrame; } t = t * inverseSqrt(tLen2); let b = normalize(cross(n, t)) * select(-1.0, 1.0, tangent.w >= 0.0); return TangentFrame(t, b, n); } fn applyNormalMap(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { if (normalScale == 0.0) { return normalize(N); } let frame = buildTangentFrame(N, tangent, worldPos, uv); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(frame.t * ns.x + frame.b * ns.y + frame.n * ns.z); } fn sqr(v: f32) -> f32 { return v * v; } fn iorToFresnel0(transmittedIor: f32, incidentIor: f32) -> f32 { let r = (transmittedIor - incidentIor) / (transmittedIor + incidentIor); return r * r; } fn iorToFresnel0Vec(transmittedIor: vec3f, incidentIor: f32) -> vec3f { let r = (transmittedIor - vec3f(incidentIor)) / (transmittedIor + vec3f(incidentIor)); return r * r; } fn fresnel0ToIor(F0: vec3f) -> vec3f { let sqrtF0 = sqrt(clamp(F0, vec3f(0.0), vec3f(0.9999))); return (vec3f(1.0) + sqrtF0) / max(vec3f(1.0) - sqrtF0, vec3f(1e-4)); } fn fresnelSchlickScalar(cosTheta: f32, F0: f32) -> f32 { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (1.0 - F0) * pow(oneMinusCos, 5.0); } fn sanitizeReflectance(value: vec3f, fallback: vec3f) -> vec3f { var result = clamp(fallback, vec3f(0.0), vec3f(1.0)); if (value.x == value.x && abs(value.x) < 1.0e6) { result.x = clamp(value.x, 0.0, 1.0); } if (value.y == value.y && abs(value.y) < 1.0e6) { result.y = clamp(value.y, 0.0, 1.0); } if (value.z == value.z && abs(value.z) < 1.0e6) { result.z = clamp(value.z, 0.0, 1.0); } return result; } fn evalIridescenceSensitivity(OPD: f32, shift: vec3f) -> vec3f { let phase = 2.0 * PI * OPD * 1.0e-9; let phase2 = phase * phase; let val = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13); let pos = vec3f(1.6810e+06, 1.7953e+06, 2.2084e+06); let variance = vec3f(4.3278e+09, 9.3046e+09, 6.6121e+09); var xyz = val * sqrt(2.0 * PI * variance) * cos(pos * phase + shift) * exp(-phase2 * variance); xyz.x += 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift.x) * exp(-4.5282e+09 * phase2); xyz /= 1.0685e-7; return vec3f( 3.2404542 * xyz.x - 1.5371385 * xyz.y - 0.4985314 * xyz.z, -0.9692660 * xyz.x + 1.8760108 * xyz.y + 0.0415560 * xyz.z, 0.0556434 * xyz.x - 0.2040259 * xyz.y + 1.0572252 * xyz.z ); } fn iridescentFresnel(outsideIor: f32, iridescenceIor: f32, baseF0: vec3f, thickness: f32, cosTheta1: f32) -> vec3f { let safeCosTheta1 = clamp(cosTheta1, 0.0, 1.0); let thinFilmIor = mix(outsideIor, iridescenceIor, smoothstep(0.0, 0.03, thickness)); let R0 = iorToFresnel0(thinFilmIor, outsideIor); let R12 = fresnelSchlickScalar(safeCosTheta1, R0); let T121 = 1.0 - R12; let baseIor = fresnel0ToIor(baseF0); let R1 = iorToFresnel0Vec(baseIor, thinFilmIor); let eta = outsideIor / thinFilmIor; let sinTheta2Sq = eta * eta * (1.0 - safeCosTheta1 * safeCosTheta1); let cosTheta2Sq = 1.0 - sinTheta2Sq; if (cosTheta2Sq < 0.0) { return vec3f(1.0); } let cosTheta2 = sqrt(cosTheta2Sq); let R23 = fresnelSchlick(cosTheta2, R1, vec3f(1.0)); let phi12 = select(0.0, PI, thinFilmIor < outsideIor); let phi21 = PI - phi12; let phi23 = vec3f( select(0.0, PI, baseIor.x < thinFilmIor), select(0.0, PI, baseIor.y < thinFilmIor), select(0.0, PI, baseIor.z < thinFilmIor) ); let phi = vec3f(phi21) + phi23; let OPD = 2.0 * thinFilmIor * thickness * cosTheta2; let R123 = clamp(vec3f(R12) * R23, vec3f(1e-5), vec3f(0.9999)); let r123 = sqrt(R123); let Rs = sqr(T121) * R23 / (vec3f(1.0) - R123); var I = vec3f(R12) + Rs; var Cm = Rs - vec3f(T121); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(OPD, phi); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(2.0 * OPD, 2.0 * phi); return sanitizeReflectance(I, baseF0); } fn distributionGGXAnisotropic(NdotH: f32, TdotH: f32, BdotH: f32, at: f32, ab: f32) -> f32 { let a2 = at * ab; let f = vec3f(ab * TdotH, at * BdotH, a2 * NdotH); let w2 = a2 / max(dot(f, f), 1e-8); return a2 * w2 * w2 / PI; } fn visibilityGGXAnisotropic(NdotL: f32, NdotV: f32, BdotV: f32, TdotV: f32, TdotL: f32, BdotL: f32, at: f32, ab: f32) -> f32 { let GGXV = NdotL * length(vec3f(at * TdotV, ab * BdotV, NdotV)); let GGXL = NdotV * length(vec3f(at * TdotL, ab * BdotL, NdotL)); return clamp(0.5 / max(GGXV + GGXL, 1e-8), 0.0, 1.0); } fn sheenDistribution(NdotH: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let invR = 1.0 / alphaG; let sin2h = max(1.0 - NdotH * NdotH, 0.0); return (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * PI); } fn sheenL(cosTheta: f32, alphaG: f32) -> f32 { let oneMinusAlphaSq = sqr(1.0 - alphaG); let a = mix(21.5473, 25.3245, oneMinusAlphaSq); let b = mix(3.82987, 3.32435, oneMinusAlphaSq); let c = mix(0.19823, 0.16801, oneMinusAlphaSq); let d = mix(-1.97760, -1.27393, oneMinusAlphaSq); let e = mix(-4.32054, -4.85967, oneMinusAlphaSq); return a / (1.0 + b * pow(cosTheta, c)) + d * cosTheta + e; } fn sheenLambda(cosTheta: f32, alphaG: f32) -> f32 { let safeCosTheta = clamp(cosTheta, 1e-4, 1.0); if (safeCosTheta < 0.5) { return exp(sheenL(safeCosTheta, alphaG)); } return exp(2.0 * sheenL(0.5, alphaG) - sheenL(1.0 - safeCosTheta, alphaG)); } fn sheenVisibility(NdotL: f32, NdotV: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let visibility = 1.0 + sheenLambda(NdotV, alphaG) + sheenLambda(NdotL, alphaG); return clamp(1.0 / max(visibility * 4.0 * NdotV * NdotL, 1e-6), 0.0, 1.0); } fn dielectricF0FromIor(ior: f32) -> f32 { if (ior == 0.0) { return 1.0; } let safeIor = max(ior, 1.0); let r = (safeIor - 1.0) / (safeIor + 1.0); return r * r; } fn computeRangeAttenuation(distance: f32, range: f32) -> f32 { let invSq = 1.0 / max(distance * distance, 0.0001); if (range <= 0.0) { return invSq; } let fade = clamp(1.0 - distance / range, 0.0, 1.0); return invSq * fade * fade; } fn computeSpotFactor(L: vec3f, direction: vec3f, cosInner: f32, cosOuter: f32) -> f32 { let angleCos = dot(-L, normalize(direction)); if (cosInner <= cosOuter) { return select(0.0, 1.0, angleCos >= cosOuter); } return clamp((angleCos - cosOuter) / max(cosInner - cosOuter, 1e-4), 0.0, 1.0); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let mrUv = applyTextureTransform(in.uv, in.uv1, material.metallicRoughnessTransform0, material.metallicRoughnessTransform1); let normalUv = applyTextureTransform(in.uv, in.uv1, material.normalTransform0, material.normalTransform1); let occlusionUv = applyTextureTransform(in.uv, in.uv1, material.occlusionTransform0, material.occlusionTransform1); let emissiveUv = applyTextureTransform(in.uv, in.uv1, material.emissiveTransform0, material.emissiveTransform1); let clearcoatUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatTransform0, material.clearcoatTransform1); let clearcoatRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatRoughnessTransform0, material.clearcoatRoughnessTransform1); let clearcoatNormalUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatNormalTransform0, material.clearcoatNormalTransform1); let specularUv = applyTextureTransform(in.uv, in.uv1, material.specularTransform0, material.specularTransform1); let specularColorUv = applyTextureTransform(in.uv, in.uv1, material.specularColorTransform0, material.specularColorTransform1); let sheenColorUv = applyTextureTransform(in.uv, in.uv1, material.sheenColorTransform0, material.sheenColorTransform1); let sheenRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.sheenRoughnessTransform0, material.sheenRoughnessTransform1); let iridescenceUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceTransform0, material.iridescenceTransform1); let iridescenceThicknessUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceThicknessTransform0, material.iridescenceThicknessTransform1); let anisotropyUv = applyTextureTransform(in.uv, in.uv1, material.anisotropyTransform0, material.anisotropyTransform1); let baseSample = textureSample(baseColorTex, baseColorSampler, baseUv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, mrUv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, normalUv).xyz; let N = applyNormalMap(in.normal, in.tangent, in.worldPos, normalUv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, occlusionUv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, emissiveUv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a * material.extensionParams.y; let clearcoat = clamp(material.clearcoatParams.x * textureSample(clearcoatTex, clearcoatSampler, clearcoatUv).r, 0.0, 1.0); let clearcoatRoughness = clamp(material.clearcoatParams.y * textureSample(clearcoatRoughnessTex, clearcoatRoughnessSampler, clearcoatRoughnessUv).g, 0.04, 1.0); let clearcoatNormalSample = textureSample(clearcoatNormalTex, clearcoatNormalSampler, clearcoatNormalUv).xyz; let clearcoatNormal = applyNormalMap(in.normal, in.tangent, in.worldPos, clearcoatNormalUv, clearcoatNormalSample, material.clearcoatParams.z); let specularStrength = clamp(material.specularParams.x * textureSample(specularTex, specularSampler, specularUv).a, 0.0, 1.0); let specularColor = material.specularParams.yzw * textureSample(specularColorTex, specularColorSampler, specularColorUv).rgb; let sheenColor = material.sheenParams.rgb * textureSample(sheenColorTex, sheenColorSampler, sheenColorUv).rgb; let sheenRoughness = clamp(material.sheenParams.w * textureSample(sheenRoughnessTex, sheenRoughnessSampler, sheenRoughnessUv).a, 0.0, 1.0); let iridescence = clamp(material.iridescenceParams.x * textureSample(iridescenceTex, iridescenceSampler, iridescenceUv).r, 0.0, 1.0); let iridescenceThicknessSample = textureSample(iridescenceThicknessTex, iridescenceThicknessSampler, iridescenceThicknessUv).g; let iridescenceThickness = mix(material.iridescenceParams.z, material.iridescenceParams.w, iridescenceThicknessSample); let anisotropySample = textureSample(anisotropyTex, anisotropySampler, anisotropyUv).rgb; let anisotropyStrength = clamp(material.anisotropyParams.x * anisotropySample.b, 0.0, 1.0); var anisotropyDirection = anisotropySample.rg * 2.0 - vec2f(1.0); let anisotropyDirectionLength2 = dot(anisotropyDirection, anisotropyDirection); anisotropyDirection = select(vec2f(1.0, 0.0), anisotropyDirection * inverseSqrt(max(anisotropyDirectionLength2, 1e-8)), anisotropyDirectionLength2 > 1e-8); anisotropyDirection = vec2f( material.anisotropyParams.y * anisotropyDirection.x - material.anisotropyParams.z * anisotropyDirection.y, material.anisotropyParams.z * anisotropyDirection.x + material.anisotropyParams.y * anisotropyDirection.y ); let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let dielectricF0 = dielectricF0FromIor(material.extensionParams.x); let dielectricF0Color = min(vec3f(dielectricF0) * specularColor, vec3f(1.0)) * specularStrength; let F0 = mix(dielectricF0Color, albedo, metallic); let F90 = mix(vec3f(specularStrength), vec3f(1.0), metallic); let viewNdotV = max(dot(N, V), 0.0); var iridescenceFresnelColor = F0; if (iridescence > 1e-5 && iridescenceThickness > 0.0) { iridescenceFresnelColor = iridescentFresnel(1.0, material.iridescenceParams.y, F0, iridescenceThickness, viewNdotV); } let geometricN = normalize(in.normal); let anisotropyFrame = buildTangentFrame(geometricN, in.tangent, in.worldPos, anisotropyUv); let clearcoatViewFresnel = clamp(clearcoat * fresnelSchlickScalar(abs(dot(V, clearcoatNormal)), 0.04), 0.0, 1.0); var Lo = lighting.ambient.rgb * albedo * ao; for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); if (distance <= 1e-5) { continue; } L = lightDir / distance; attenuation = computeRangeAttenuation(distance, light.params.x); if (light.position.w == 2.0) { attenuation = attenuation * computeSpotFactor(L, light.direction.xyz, light.params.y, light.params.z); } } if (attenuation <= 0.0) { continue; } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NdotL = max(dot(N, L), 0.0); let NdotV = viewNdotV; let NdotH = max(dot(N, H), 0.0); let VdotH = max(dot(V, H), 0.0); let baseF = fresnelSchlick(VdotH, F0, F90); var F = baseF; if (iridescence > 1e-5) { F = mix(baseF, iridescenceFresnelColor, iridescence); } var specularBrdf: vec3f; if (anisotropyStrength > 1e-5) { let anisotropicT = normalize(anisotropyFrame.t * anisotropyDirection.x + anisotropyFrame.b * anisotropyDirection.y); let anisotropicB = normalize(cross(geometricN, anisotropicT)); let TdotV = dot(anisotropicT, V); let BdotV = dot(anisotropicB, V); let TdotL = dot(anisotropicT, L); let BdotL = dot(anisotropicB, L); let TdotH = dot(anisotropicT, H); let BdotH = dot(anisotropicB, H); let alphaRoughness = max(roughness * roughness, 0.001); let at = mix(alphaRoughness, 1.0, anisotropyStrength * anisotropyStrength); let ab = alphaRoughness; let D = distributionGGXAnisotropic(NdotH, TdotH, BdotH, at, ab); let Vg = visibilityGGXAnisotropic(NdotL, NdotV, BdotV, TdotV, TdotL, BdotL, at, ab); specularBrdf = F * D * Vg; } else { let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let numerator = NDF * G * F; let denominator = 4.0 * NdotV * NdotL + 0.0001; specularBrdf = numerator / denominator; } let sheenD = sheenDistribution(NdotH, sheenRoughness); let sheenV = sheenVisibility(NdotL, NdotV, sheenRoughness); let sheenBrdf = sheenColor * sheenD * sheenV; let diffuseEnergy = max(1.0 - maxComponent(F), 0.0); let kD = vec3f(diffuseEnergy) * (1.0 - metallic); let baseContribution = (kD * albedo / PI + specularBrdf + sheenBrdf) * radiance * NdotL; let clearcoatNdotL = max(dot(clearcoatNormal, L), 0.0); let clearcoatNdotV = max(dot(clearcoatNormal, V), 0.0); let clearcoatNDF = distributionGGX(clearcoatNormal, H, clearcoatRoughness); let clearcoatG = geometrySmith(clearcoatNormal, V, L, clearcoatRoughness); let clearcoatBrdf = clearcoatNDF * clearcoatG / (4.0 * clearcoatNdotV * clearcoatNdotL + 0.0001); let clearcoatContribution = vec3f(clearcoatBrdf) * radiance * clearcoatNdotL; Lo += mix(baseContribution, clearcoatContribution, clearcoatViewFresnel); } Lo += emissive * (1.0 - clearcoatViewFresnel); Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var ya="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f, metallicRoughnessTransform0: vec4f, metallicRoughnessTransform1: vec4f, normalTransform0: vec4f, normalTransform1: vec4f, occlusionTransform0: vec4f, occlusionTransform1: vec4f, emissiveTransform0: vec4f, emissiveTransform1: vec4f, clearcoatParams: vec4f, specularParams: vec4f, extensionParams: vec4f, clearcoatTransform0: vec4f, clearcoatTransform1: vec4f, clearcoatRoughnessTransform0: vec4f, clearcoatRoughnessTransform1: vec4f, clearcoatNormalTransform0: vec4f, clearcoatNormalTransform1: vec4f, specularTransform0: vec4f, specularTransform1: vec4f, specularColorTransform0: vec4f, specularColorTransform1: vec4f, sheenParams: vec4f, iridescenceParams: vec4f, anisotropyParams: vec4f, sheenColorTransform0: vec4f, sheenColorTransform1: vec4f, sheenRoughnessTransform0: vec4f, sheenRoughnessTransform1: vec4f, iridescenceTransform0: vec4f, iridescenceTransform1: vec4f, iridescenceThicknessTransform0: vec4f, iridescenceThicknessTransform1: vec4f, anisotropyTransform0: vec4f, anisotropyTransform1: vec4f, transmissionParams: vec4f, diffuseTransmissionColor: vec4f, volumeAttenuation: vec4f, transmissionTransform0: vec4f, transmissionTransform1: vec4f, volumeThicknessTransform0: vec4f, volumeThicknessTransform1: vec4f, diffuseTransmissionTransform0: vec4f, diffuseTransmissionTransform1: vec4f, diffuseTransmissionColorTransform0: vec4f, diffuseTransmissionColorTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; @group(1) @binding(11) var clearcoatSampler: sampler; @group(1) @binding(12) var clearcoatTex: texture_2d<f32>; @group(1) @binding(13) var clearcoatRoughnessSampler: sampler; @group(1) @binding(14) var clearcoatRoughnessTex: texture_2d<f32>; @group(1) @binding(15) var clearcoatNormalSampler: sampler; @group(1) @binding(16) var clearcoatNormalTex: texture_2d<f32>; @group(1) @binding(17) var specularSampler: sampler; @group(1) @binding(18) var specularTex: texture_2d<f32>; @group(1) @binding(19) var specularColorSampler: sampler; @group(1) @binding(20) var specularColorTex: texture_2d<f32>; @group(1) @binding(21) var transmissionSampler: sampler; @group(1) @binding(22) var transmissionTex: texture_2d<f32>; @group(1) @binding(23) var volumeThicknessSampler: sampler; @group(1) @binding(24) var volumeThicknessTex: texture_2d<f32>; @group(1) @binding(25) var diffuseTransmissionSampler: sampler; @group(1) @binding(26) var diffuseTransmissionTex: texture_2d<f32>; @group(1) @binding(27) var diffuseTransmissionColorSampler: sampler; @group(1) @binding(28) var diffuseTransmissionColorTex: texture_2d<f32>; @group(1) @binding(29) var transmissionSourceSampler: sampler; @group(1) @binding(30) var transmissionSourceTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(12) tangent: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) uv1: vec2f, @location(4) tangent: vec4f, @location(5) modelScale: vec3f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, direction: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let worldPos4 = model.model * vec4f(in.position, 1.0); out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(in.normal, 0.0)).xyz); out.tangent = vec4f((model.normalMatrix * vec4f(in.tangent.xyz, 0.0)).xyz, in.tangent.w); out.modelScale = vec3f(length(model.model[0].xyz), length(model.model[1].xyz), length(model.model[2].xyz)); out.uv = in.uv; out.uv1 = in.uv1; return out; } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } fn fresnelSchlick(cosTheta: f32, F0: vec3f, F90: vec3f) -> vec3f { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (F90 - F0) * pow(oneMinusCos, 5.0); } fn maxComponent(v: vec3f) -> f32 { return max(max(v.x, v.y), v.z); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } struct TangentFrame { t: vec3f, b: vec3f, n: vec3f }; fn fallbackTangentFrame(N: vec3f) -> TangentFrame { let n = normalize(N); let axis = select(vec3f(0.0, 1.0, 0.0), vec3f(1.0, 0.0, 0.0), abs(n.x) < 0.9); let t = normalize(cross(axis, n)); let b = cross(n, t); return TangentFrame(t, b, n); } fn derivativeTangentFrame(N: vec3f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let dp2perp = cross(dp2, n); let dp1perp = cross(n, dp1); let T = (dp2perp * duv1.x) + (dp1perp * duv2.x); let B = (dp2perp * duv1.y) + (dp1perp * duv2.y); let frameLength2 = max(dot(T, T), dot(B, B)); if (frameLength2 <= 1e-20) { return fallbackTangentFrame(n); } let frameScale = 1.0 / sqrt(frameLength2); return TangentFrame(T * frameScale, B * frameScale, n); } fn buildTangentFrame(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let derivativeFrame = derivativeTangentFrame(n, worldPos, uv); var t = tangent.xyz - n * dot(n, tangent.xyz); let tLen2 = dot(t, t); if (tLen2 <= 1e-20) { return derivativeFrame; } t = t * inverseSqrt(tLen2); let b = normalize(cross(n, t)) * select(-1.0, 1.0, tangent.w >= 0.0); return TangentFrame(t, b, n); } fn applyNormalMap(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { if (normalScale == 0.0) { return normalize(N); } let frame = buildTangentFrame(N, tangent, worldPos, uv); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(frame.t * ns.x + frame.b * ns.y + frame.n * ns.z); } fn sqr(v: f32) -> f32 { return v * v; } fn iorToFresnel0(transmittedIor: f32, incidentIor: f32) -> f32 { let r = (transmittedIor - incidentIor) / (transmittedIor + incidentIor); return r * r; } fn iorToFresnel0Vec(transmittedIor: vec3f, incidentIor: f32) -> vec3f { let r = (transmittedIor - vec3f(incidentIor)) / (transmittedIor + vec3f(incidentIor)); return r * r; } fn fresnel0ToIor(F0: vec3f) -> vec3f { let sqrtF0 = sqrt(clamp(F0, vec3f(0.0), vec3f(0.9999))); return (vec3f(1.0) + sqrtF0) / max(vec3f(1.0) - sqrtF0, vec3f(1e-4)); } fn fresnelSchlickScalar(cosTheta: f32, F0: f32) -> f32 { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (1.0 - F0) * pow(oneMinusCos, 5.0); } fn sanitizeReflectance(value: vec3f, fallback: vec3f) -> vec3f { var result = clamp(fallback, vec3f(0.0), vec3f(1.0)); if (value.x == value.x && abs(value.x) < 1.0e6) { result.x = clamp(value.x, 0.0, 1.0); } if (value.y == value.y && abs(value.y) < 1.0e6) { result.y = clamp(value.y, 0.0, 1.0); } if (value.z == value.z && abs(value.z) < 1.0e6) { result.z = clamp(value.z, 0.0, 1.0); } return result; } fn evalIridescenceSensitivity(OPD: f32, shift: vec3f) -> vec3f { let phase = 2.0 * PI * OPD * 1.0e-9; let phase2 = phase * phase; let val = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13); let pos = vec3f(1.6810e+06, 1.7953e+06, 2.2084e+06); let variance = vec3f(4.3278e+09, 9.3046e+09, 6.6121e+09); var xyz = val * sqrt(2.0 * PI * variance) * cos(pos * phase + shift) * exp(-phase2 * variance); xyz.x += 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift.x) * exp(-4.5282e+09 * phase2); xyz /= 1.0685e-7; return vec3f( 3.2404542 * xyz.x - 1.5371385 * xyz.y - 0.4985314 * xyz.z, -0.9692660 * xyz.x + 1.8760108 * xyz.y + 0.0415560 * xyz.z, 0.0556434 * xyz.x - 0.2040259 * xyz.y + 1.0572252 * xyz.z ); } fn iridescentFresnel(outsideIor: f32, iridescenceIor: f32, baseF0: vec3f, thickness: f32, cosTheta1: f32) -> vec3f { let safeCosTheta1 = clamp(cosTheta1, 0.0, 1.0); let thinFilmIor = mix(outsideIor, iridescenceIor, smoothstep(0.0, 0.03, thickness)); let R0 = iorToFresnel0(thinFilmIor, outsideIor); let R12 = fresnelSchlickScalar(safeCosTheta1, R0); let T121 = 1.0 - R12; let baseIor = fresnel0ToIor(baseF0); let R1 = iorToFresnel0Vec(baseIor, thinFilmIor); let eta = outsideIor / thinFilmIor; let sinTheta2Sq = eta * eta * (1.0 - safeCosTheta1 * safeCosTheta1); let cosTheta2Sq = 1.0 - sinTheta2Sq; if (cosTheta2Sq < 0.0) { return vec3f(1.0); } let cosTheta2 = sqrt(cosTheta2Sq); let R23 = fresnelSchlick(cosTheta2, R1, vec3f(1.0)); let phi12 = select(0.0, PI, thinFilmIor < outsideIor); let phi21 = PI - phi12; let phi23 = vec3f( select(0.0, PI, baseIor.x < thinFilmIor), select(0.0, PI, baseIor.y < thinFilmIor), select(0.0, PI, baseIor.z < thinFilmIor) ); let phi = vec3f(phi21) + phi23; let OPD = 2.0 * thinFilmIor * thickness * cosTheta2; let R123 = clamp(vec3f(R12) * R23, vec3f(1e-5), vec3f(0.9999)); let r123 = sqrt(R123); let Rs = sqr(T121) * R23 / (vec3f(1.0) - R123); var I = vec3f(R12) + Rs; var Cm = Rs - vec3f(T121); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(OPD, phi); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(2.0 * OPD, 2.0 * phi); return sanitizeReflectance(I, baseF0); } fn distributionGGXAnisotropic(NdotH: f32, TdotH: f32, BdotH: f32, at: f32, ab: f32) -> f32 { let a2 = at * ab; let f = vec3f(ab * TdotH, at * BdotH, a2 * NdotH); let w2 = a2 / max(dot(f, f), 1e-8); return a2 * w2 * w2 / PI; } fn visibilityGGXAnisotropic(NdotL: f32, NdotV: f32, BdotV: f32, TdotV: f32, TdotL: f32, BdotL: f32, at: f32, ab: f32) -> f32 { let GGXV = NdotL * length(vec3f(at * TdotV, ab * BdotV, NdotV)); let GGXL = NdotV * length(vec3f(at * TdotL, ab * BdotL, NdotL)); return clamp(0.5 / max(GGXV + GGXL, 1e-8), 0.0, 1.0); } fn sheenDistribution(NdotH: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let invR = 1.0 / alphaG; let sin2h = max(1.0 - NdotH * NdotH, 0.0); return (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * PI); } fn sheenL(cosTheta: f32, alphaG: f32) -> f32 { let oneMinusAlphaSq = sqr(1.0 - alphaG); let a = mix(21.5473, 25.3245, oneMinusAlphaSq); let b = mix(3.82987, 3.32435, oneMinusAlphaSq); let c = mix(0.19823, 0.16801, oneMinusAlphaSq); let d = mix(-1.97760, -1.27393, oneMinusAlphaSq); let e = mix(-4.32054, -4.85967, oneMinusAlphaSq); return a / (1.0 + b * pow(cosTheta, c)) + d * cosTheta + e; } fn sheenLambda(cosTheta: f32, alphaG: f32) -> f32 { let safeCosTheta = clamp(cosTheta, 1e-4, 1.0); if (safeCosTheta < 0.5) { return exp(sheenL(safeCosTheta, alphaG)); } return exp(2.0 * sheenL(0.5, alphaG) - sheenL(1.0 - safeCosTheta, alphaG)); } fn sheenVisibility(NdotL: f32, NdotV: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let visibility = 1.0 + sheenLambda(NdotV, alphaG) + sheenLambda(NdotL, alphaG); return clamp(1.0 / max(visibility * 4.0 * NdotV * NdotL, 1e-6), 0.0, 1.0); } fn dielectricF0FromIor(ior: f32) -> f32 { if (ior == 0.0) { return 1.0; } let safeIor = max(ior, 1.0); let r = (safeIor - 1.0) / (safeIor + 1.0); return r * r; } fn computeRangeAttenuation(distance: f32, range: f32) -> f32 { let invSq = 1.0 / max(distance * distance, 0.0001); if (range <= 0.0) { return invSq; } let fade = clamp(1.0 - distance / range, 0.0, 1.0); return invSq * fade * fade; } fn computeSpotFactor(L: vec3f, direction: vec3f, cosInner: f32, cosOuter: f32) -> f32 { let angleCos = dot(-L, normalize(direction)); if (cosInner <= cosOuter) { return select(0.0, 1.0, angleCos >= cosOuter); } return clamp((angleCos - cosOuter) / max(cosInner - cosOuter, 1e-4), 0.0, 1.0); } fn screenUvFromFragment(position: vec4f) -> vec2f { let dims = vec2f(textureDimensions(transmissionSourceTex, 0)); return clamp(position.xy / max(dims, vec2f(1.0)), vec2f(0.0), vec2f(1.0)); } fn projectWorldToScreenUv(worldPos: vec3f) -> vec2f { let clip = camera.viewProjection * vec4f(worldPos, 1.0); let invW = 1.0 / max(abs(clip.w), 1e-5); let ndc = clip.xy * invW * select(-1.0, 1.0, clip.w >= 0.0); return clamp(vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5), vec2f(0.0), vec2f(1.0)); } fn transmissionScreenUv(position: vec4f, worldPos: vec3f, N: vec3f, V: vec3f, ior: f32, thickness: f32, modelScale: vec3f) -> vec2f { let baseUv = screenUvFromFragment(position); if (thickness <= 1e-5) { return baseUv; } let eta = 1.0 / max(ior, 1.0001); var ray = refract(-V, N, eta); let rayLength2 = dot(ray, ray); if (rayLength2 <= 1e-8) { ray = -V; } else { ray = ray * inverseSqrt(rayLength2); } let transmissionRay = ray * max(thickness, 0.0) * max(modelScale, vec3f(1e-4)); return projectWorldToScreenUv(worldPos + transmissionRay); } fn transmissionSourceToLinear(color: vec3f) -> vec3f { return pow(clamp(color, vec3f(0.0), vec3f(1.0)), vec3f(2.2)); } fn sampleTransmissionSourceAt(uv: vec2f) -> vec3f { let sourceColor = textureSampleLevel(transmissionSourceTex, transmissionSourceSampler, clamp(uv, vec2f(0.0), vec2f(1.0)), 0.0).rgb; return transmissionSourceToLinear(sourceColor); } fn dispersionIors(ior: f32, dispersion: f32) -> vec3f { let halfSpread = max(ior - 1.0, 0.0) * 0.025 * max(dispersion, 0.0); return max(vec3f(ior - halfSpread, ior, ior + halfSpread), vec3f(1.0)); } fn sampleTransmissionSource(position: vec4f, worldPos: vec3f, N: vec3f, V: vec3f, ior: f32, dispersion: f32, thickness: f32, modelScale: vec3f) -> vec3f { if (dispersion <= 1e-5 || thickness <= 1e-5) { return sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, ior, thickness, modelScale)); } let iors = dispersionIors(ior, dispersion); let r = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.r, thickness, modelScale)).r; let g = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.g, thickness, modelScale)).g; let b = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.b, thickness, modelScale)).b; return vec3f(r, g, b); } fn volumeTransmissionAttenuation(thickness: f32, attenuationDistance: f32, attenuationColor: vec3f) -> vec3f { if (thickness <= 1e-5 || attenuationDistance <= 1e-5) { return vec3f(1.0); } return pow(max(attenuationColor, vec3f(1e-4)), vec3f(thickness / attenuationDistance)); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let mrUv = applyTextureTransform(in.uv, in.uv1, material.metallicRoughnessTransform0, material.metallicRoughnessTransform1); let normalUv = applyTextureTransform(in.uv, in.uv1, material.normalTransform0, material.normalTransform1); let occlusionUv = applyTextureTransform(in.uv, in.uv1, material.occlusionTransform0, material.occlusionTransform1); let emissiveUv = applyTextureTransform(in.uv, in.uv1, material.emissiveTransform0, material.emissiveTransform1); let clearcoatUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatTransform0, material.clearcoatTransform1); let clearcoatRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatRoughnessTransform0, material.clearcoatRoughnessTransform1); let clearcoatNormalUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatNormalTransform0, material.clearcoatNormalTransform1); let specularUv = applyTextureTransform(in.uv, in.uv1, material.specularTransform0, material.specularTransform1); let specularColorUv = applyTextureTransform(in.uv, in.uv1, material.specularColorTransform0, material.specularColorTransform1); let sheenColorUv = applyTextureTransform(in.uv, in.uv1, material.sheenColorTransform0, material.sheenColorTransform1); let sheenRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.sheenRoughnessTransform0, material.sheenRoughnessTransform1); let iridescenceUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceTransform0, material.iridescenceTransform1); let iridescenceThicknessUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceThicknessTransform0, material.iridescenceThicknessTransform1); let anisotropyUv = applyTextureTransform(in.uv, in.uv1, material.anisotropyTransform0, material.anisotropyTransform1); let transmissionUv = applyTextureTransform(in.uv, in.uv1, material.transmissionTransform0, material.transmissionTransform1); let volumeThicknessUv = applyTextureTransform(in.uv, in.uv1, material.volumeThicknessTransform0, material.volumeThicknessTransform1); let diffuseTransmissionUv = applyTextureTransform(in.uv, in.uv1, material.diffuseTransmissionTransform0, material.diffuseTransmissionTransform1); let diffuseTransmissionColorUv = applyTextureTransform(in.uv, in.uv1, material.diffuseTransmissionColorTransform0, material.diffuseTransmissionColorTransform1); let baseSample = textureSample(baseColorTex, baseColorSampler, baseUv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, mrUv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, normalUv).xyz; let N = applyNormalMap(in.normal, in.tangent, in.worldPos, normalUv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, occlusionUv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, emissiveUv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a * material.extensionParams.y; let clearcoat = clamp(material.clearcoatParams.x * textureSample(clearcoatTex, clearcoatSampler, clearcoatUv).r, 0.0, 1.0); let clearcoatRoughness = clamp(material.clearcoatParams.y * textureSample(clearcoatRoughnessTex, clearcoatRoughnessSampler, clearcoatRoughnessUv).g, 0.04, 1.0); let clearcoatNormalSample = textureSample(clearcoatNormalTex, clearcoatNormalSampler, clearcoatNormalUv).xyz; let clearcoatNormal = applyNormalMap(in.normal, in.tangent, in.worldPos, clearcoatNormalUv, clearcoatNormalSample, material.clearcoatParams.z); let specularStrength = clamp(material.specularParams.x * textureSample(specularTex, specularSampler, specularUv).a, 0.0, 1.0); let specularColor = material.specularParams.yzw * textureSample(specularColorTex, specularColorSampler, specularColorUv).rgb; let sheenColor = material.sheenParams.rgb; let sheenRoughness = clamp(material.sheenParams.w, 0.0, 1.0); let iridescence = clamp(material.iridescenceParams.x, 0.0, 1.0); let iridescenceThickness = material.iridescenceParams.w; let anisotropySample = vec3f(1.0, 0.5, 1.0); let transmission = clamp(material.transmissionParams.x * textureSample(transmissionTex, transmissionSampler, transmissionUv).r, 0.0, 1.0); let diffuseTransmission = clamp(material.transmissionParams.y * textureSample(diffuseTransmissionTex, diffuseTransmissionSampler, diffuseTransmissionUv).a, 0.0, 1.0); let volumeThickness = max(material.transmissionParams.z * textureSample(volumeThicknessTex, volumeThicknessSampler, volumeThicknessUv).g, 0.0); let dispersion = max(material.transmissionParams.w, 0.0); let diffuseTransmissionColor = material.diffuseTransmissionColor.rgb * textureSample(diffuseTransmissionColorTex, diffuseTransmissionColorSampler, diffuseTransmissionColorUv).rgb; let volumeAttenuation = volumeTransmissionAttenuation(volumeThickness, material.diffuseTransmissionColor.w, material.volumeAttenuation.rgb); let anisotropyStrength = clamp(material.anisotropyParams.x * anisotropySample.b, 0.0, 1.0); var anisotropyDirection = anisotropySample.rg * 2.0 - vec2f(1.0); let anisotropyDirectionLength2 = dot(anisotropyDirection, anisotropyDirection); anisotropyDirection = select(vec2f(1.0, 0.0), anisotropyDirection * inverseSqrt(max(anisotropyDirectionLength2, 1e-8)), anisotropyDirectionLength2 > 1e-8); anisotropyDirection = vec2f( material.anisotropyParams.y * anisotropyDirection.x - material.anisotropyParams.z * anisotropyDirection.y, material.anisotropyParams.z * anisotropyDirection.x + material.anisotropyParams.y * anisotropyDirection.y ); let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let dielectricF0 = dielectricF0FromIor(material.extensionParams.x); let dielectricF0Color = min(vec3f(dielectricF0) * specularColor, vec3f(1.0)) * specularStrength; let F0 = mix(dielectricF0Color, albedo, metallic); let F90 = mix(vec3f(specularStrength), vec3f(1.0), metallic); let viewNdotV = max(dot(N, V), 0.0); var iridescenceFresnelColor = F0; if (iridescence > 1e-5 && iridescenceThickness > 0.0) { iridescenceFresnelColor = iridescentFresnel(1.0, material.iridescenceParams.y, F0, iridescenceThickness, viewNdotV); } var viewFresnel = fresnelSchlick(viewNdotV, F0, F90); if (iridescence > 1e-5) { viewFresnel = mix(viewFresnel, iridescenceFresnelColor, iridescence); } let transmissionWeight = transmission * (1.0 - metallic) * max(1.0 - maxComponent(viewFresnel), 0.0); let geometricN = normalize(in.normal); let anisotropyFrame = buildTangentFrame(geometricN, in.tangent, in.worldPos, anisotropyUv); let clearcoatViewFresnel = clamp(clearcoat * fresnelSchlickScalar(abs(dot(V, clearcoatNormal)), 0.04), 0.0, 1.0); var Lo = lighting.ambient.rgb * albedo * ao * (1.0 - transmission); for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); if (distance <= 1e-5) { continue; } L = lightDir / distance; attenuation = computeRangeAttenuation(distance, light.params.x); if (light.position.w == 2.0) { attenuation = attenuation * computeSpotFactor(L, light.direction.xyz, light.params.y, light.params.z); } } if (attenuation <= 0.0) { continue; } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NdotL = max(dot(N, L), 0.0); let NdotV = viewNdotV; let NdotH = max(dot(N, H), 0.0); let VdotH = max(dot(V, H), 0.0); let baseF = fresnelSchlick(VdotH, F0, F90); var F = baseF; if (iridescence > 1e-5) { F = mix(baseF, iridescenceFresnelColor, iridescence); } var specularBrdf: vec3f; if (anisotropyStrength > 1e-5) { let anisotropicT = normalize(anisotropyFrame.t * anisotropyDirection.x + anisotropyFrame.b * anisotropyDirection.y); let anisotropicB = normalize(cross(geometricN, anisotropicT)); let TdotV = dot(anisotropicT, V); let BdotV = dot(anisotropicB, V); let TdotL = dot(anisotropicT, L); let BdotL = dot(anisotropicB, L); let TdotH = dot(anisotropicT, H); let BdotH = dot(anisotropicB, H); let alphaRoughness = max(roughness * roughness, 0.001); let at = mix(alphaRoughness, 1.0, anisotropyStrength * anisotropyStrength); let ab = alphaRoughness; let D = distributionGGXAnisotropic(NdotH, TdotH, BdotH, at, ab); let Vg = visibilityGGXAnisotropic(NdotL, NdotV, BdotV, TdotV, TdotL, BdotL, at, ab); specularBrdf = F * D * Vg; } else { let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let numerator = NDF * G * F; let denominator = 4.0 * NdotV * NdotL + 0.0001; specularBrdf = numerator / denominator; } let sheenD = sheenDistribution(NdotH, sheenRoughness); let sheenV = sheenVisibility(NdotL, NdotV, sheenRoughness); let sheenBrdf = sheenColor * sheenD * sheenV; let diffuseEnergy = max(1.0 - maxComponent(F), 0.0); let kD = vec3f(diffuseEnergy) * (1.0 - metallic); let frontDiffuse = (1.0 - diffuseTransmission) * kD * albedo * radiance * NdotL / PI; let backDiffuse = diffuseTransmission * kD * diffuseTransmissionColor * radiance * max(dot(-N, L), 0.0) / PI; let diffuseContribution = (frontDiffuse + backDiffuse) * (1.0 - transmission); let specularContribution = (specularBrdf + sheenBrdf) * radiance * NdotL; let baseContribution = diffuseContribution + specularContribution; let clearcoatNdotL = max(dot(clearcoatNormal, L), 0.0); let clearcoatNdotV = max(dot(clearcoatNormal, V), 0.0); let clearcoatNDF = distributionGGX(clearcoatNormal, H, clearcoatRoughness); let clearcoatG = geometrySmith(clearcoatNormal, V, L, clearcoatRoughness); let clearcoatBrdf = clearcoatNDF * clearcoatG / (4.0 * clearcoatNdotV * clearcoatNdotL + 0.0001); let clearcoatContribution = vec3f(clearcoatBrdf) * radiance * clearcoatNdotL; Lo += mix(baseContribution, clearcoatContribution, clearcoatViewFresnel); } if (transmissionWeight > 1e-5) { let transmittedSource = sampleTransmissionSource(in.position, in.worldPos, N, V, material.extensionParams.x, dispersion, volumeThickness, in.modelScale); Lo += transmittedSource * albedo * volumeAttenuation * transmissionWeight * (1.0 - clearcoatViewFresnel); } Lo += emissive * (1.0 - clearcoatViewFresnel); Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var xa="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f, metallicRoughnessTransform0: vec4f, metallicRoughnessTransform1: vec4f, normalTransform0: vec4f, normalTransform1: vec4f, occlusionTransform0: vec4f, occlusionTransform1: vec4f, emissiveTransform0: vec4f, emissiveTransform1: vec4f, clearcoatParams: vec4f, specularParams: vec4f, extensionParams: vec4f, clearcoatTransform0: vec4f, clearcoatTransform1: vec4f, clearcoatRoughnessTransform0: vec4f, clearcoatRoughnessTransform1: vec4f, clearcoatNormalTransform0: vec4f, clearcoatNormalTransform1: vec4f, specularTransform0: vec4f, specularTransform1: vec4f, specularColorTransform0: vec4f, specularColorTransform1: vec4f, sheenParams: vec4f, iridescenceParams: vec4f, anisotropyParams: vec4f, sheenColorTransform0: vec4f, sheenColorTransform1: vec4f, sheenRoughnessTransform0: vec4f, sheenRoughnessTransform1: vec4f, iridescenceTransform0: vec4f, iridescenceTransform1: vec4f, iridescenceThicknessTransform0: vec4f, iridescenceThicknessTransform1: vec4f, anisotropyTransform0: vec4f, anisotropyTransform1: vec4f, transmissionParams: vec4f, diffuseTransmissionColor: vec4f, volumeAttenuation: vec4f, transmissionTransform0: vec4f, transmissionTransform1: vec4f, volumeThicknessTransform0: vec4f, volumeThicknessTransform1: vec4f, diffuseTransmissionTransform0: vec4f, diffuseTransmissionTransform1: vec4f, diffuseTransmissionColorTransform0: vec4f, diffuseTransmissionColorTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; @group(1) @binding(11) var clearcoatSampler: sampler; @group(1) @binding(12) var clearcoatTex: texture_2d<f32>; @group(1) @binding(13) var clearcoatRoughnessSampler: sampler; @group(1) @binding(14) var clearcoatRoughnessTex: texture_2d<f32>; @group(1) @binding(15) var clearcoatNormalSampler: sampler; @group(1) @binding(16) var clearcoatNormalTex: texture_2d<f32>; @group(1) @binding(17) var specularSampler: sampler; @group(1) @binding(18) var specularTex: texture_2d<f32>; @group(1) @binding(19) var specularColorSampler: sampler; @group(1) @binding(20) var specularColorTex: texture_2d<f32>; @group(1) @binding(21) var transmissionSampler: sampler; @group(1) @binding(22) var transmissionTex: texture_2d<f32>; @group(1) @binding(23) var volumeThicknessSampler: sampler; @group(1) @binding(24) var volumeThicknessTex: texture_2d<f32>; @group(1) @binding(25) var diffuseTransmissionSampler: sampler; @group(1) @binding(26) var diffuseTransmissionTex: texture_2d<f32>; @group(1) @binding(27) var diffuseTransmissionColorSampler: sampler; @group(1) @binding(28) var diffuseTransmissionColorTex: texture_2d<f32>; @group(1) @binding(29) var transmissionSourceSampler: sampler; @group(1) @binding(30) var transmissionSourceTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(12) tangent: vec4f, @location(3) m0: vec4f, @location(4) m1: vec4f, @location(5) m2: vec4f, @location(6) m3: vec4f, @location(7) n0: vec4f, @location(8) n1: vec4f, @location(9) n2: vec4f, @location(10) n3: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) uv1: vec2f, @location(4) tangent: vec4f, @location(5) modelScale: vec3f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct Light { position: vec4f, color: vec4f, direction: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let modelM = mat4x4f(in.m0, in.m1, in.m2, in.m3); let normalM = mat4x4f(in.n0, in.n1, in.n2, in.n3); let worldPos4 = modelM * vec4f(in.position, 1.0); out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((normalM * vec4f(in.normal, 0.0)).xyz); out.tangent = vec4f((normalM * vec4f(in.tangent.xyz, 0.0)).xyz, in.tangent.w); out.modelScale = vec3f(length(modelM[0].xyz), length(modelM[1].xyz), length(modelM[2].xyz)); out.uv = in.uv; out.uv1 = in.uv1; return out; } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } fn fresnelSchlick(cosTheta: f32, F0: vec3f, F90: vec3f) -> vec3f { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (F90 - F0) * pow(oneMinusCos, 5.0); } fn maxComponent(v: vec3f) -> f32 { return max(max(v.x, v.y), v.z); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } struct TangentFrame { t: vec3f, b: vec3f, n: vec3f }; fn fallbackTangentFrame(N: vec3f) -> TangentFrame { let n = normalize(N); let axis = select(vec3f(0.0, 1.0, 0.0), vec3f(1.0, 0.0, 0.0), abs(n.x) < 0.9); let t = normalize(cross(axis, n)); let b = cross(n, t); return TangentFrame(t, b, n); } fn derivativeTangentFrame(N: vec3f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let dp2perp = cross(dp2, n); let dp1perp = cross(n, dp1); let T = (dp2perp * duv1.x) + (dp1perp * duv2.x); let B = (dp2perp * duv1.y) + (dp1perp * duv2.y); let frameLength2 = max(dot(T, T), dot(B, B)); if (frameLength2 <= 1e-20) { return fallbackTangentFrame(n); } let frameScale = 1.0 / sqrt(frameLength2); return TangentFrame(T * frameScale, B * frameScale, n); } fn buildTangentFrame(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let derivativeFrame = derivativeTangentFrame(n, worldPos, uv); var t = tangent.xyz - n * dot(n, tangent.xyz); let tLen2 = dot(t, t); if (tLen2 <= 1e-20) { return derivativeFrame; } t = t * inverseSqrt(tLen2); let b = normalize(cross(n, t)) * select(-1.0, 1.0, tangent.w >= 0.0); return TangentFrame(t, b, n); } fn applyNormalMap(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { if (normalScale == 0.0) { return normalize(N); } let frame = buildTangentFrame(N, tangent, worldPos, uv); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(frame.t * ns.x + frame.b * ns.y + frame.n * ns.z); } fn sqr(v: f32) -> f32 { return v * v; } fn iorToFresnel0(transmittedIor: f32, incidentIor: f32) -> f32 { let r = (transmittedIor - incidentIor) / (transmittedIor + incidentIor); return r * r; } fn iorToFresnel0Vec(transmittedIor: vec3f, incidentIor: f32) -> vec3f { let r = (transmittedIor - vec3f(incidentIor)) / (transmittedIor + vec3f(incidentIor)); return r * r; } fn fresnel0ToIor(F0: vec3f) -> vec3f { let sqrtF0 = sqrt(clamp(F0, vec3f(0.0), vec3f(0.9999))); return (vec3f(1.0) + sqrtF0) / max(vec3f(1.0) - sqrtF0, vec3f(1e-4)); } fn fresnelSchlickScalar(cosTheta: f32, F0: f32) -> f32 { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (1.0 - F0) * pow(oneMinusCos, 5.0); } fn sanitizeReflectance(value: vec3f, fallback: vec3f) -> vec3f { var result = clamp(fallback, vec3f(0.0), vec3f(1.0)); if (value.x == value.x && abs(value.x) < 1.0e6) { result.x = clamp(value.x, 0.0, 1.0); } if (value.y == value.y && abs(value.y) < 1.0e6) { result.y = clamp(value.y, 0.0, 1.0); } if (value.z == value.z && abs(value.z) < 1.0e6) { result.z = clamp(value.z, 0.0, 1.0); } return result; } fn evalIridescenceSensitivity(OPD: f32, shift: vec3f) -> vec3f { let phase = 2.0 * PI * OPD * 1.0e-9; let phase2 = phase * phase; let val = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13); let pos = vec3f(1.6810e+06, 1.7953e+06, 2.2084e+06); let variance = vec3f(4.3278e+09, 9.3046e+09, 6.6121e+09); var xyz = val * sqrt(2.0 * PI * variance) * cos(pos * phase + shift) * exp(-phase2 * variance); xyz.x += 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift.x) * exp(-4.5282e+09 * phase2); xyz /= 1.0685e-7; return vec3f( 3.2404542 * xyz.x - 1.5371385 * xyz.y - 0.4985314 * xyz.z, -0.9692660 * xyz.x + 1.8760108 * xyz.y + 0.0415560 * xyz.z, 0.0556434 * xyz.x - 0.2040259 * xyz.y + 1.0572252 * xyz.z ); } fn iridescentFresnel(outsideIor: f32, iridescenceIor: f32, baseF0: vec3f, thickness: f32, cosTheta1: f32) -> vec3f { let safeCosTheta1 = clamp(cosTheta1, 0.0, 1.0); let thinFilmIor = mix(outsideIor, iridescenceIor, smoothstep(0.0, 0.03, thickness)); let R0 = iorToFresnel0(thinFilmIor, outsideIor); let R12 = fresnelSchlickScalar(safeCosTheta1, R0); let T121 = 1.0 - R12; let baseIor = fresnel0ToIor(baseF0); let R1 = iorToFresnel0Vec(baseIor, thinFilmIor); let eta = outsideIor / thinFilmIor; let sinTheta2Sq = eta * eta * (1.0 - safeCosTheta1 * safeCosTheta1); let cosTheta2Sq = 1.0 - sinTheta2Sq; if (cosTheta2Sq < 0.0) { return vec3f(1.0); } let cosTheta2 = sqrt(cosTheta2Sq); let R23 = fresnelSchlick(cosTheta2, R1, vec3f(1.0)); let phi12 = select(0.0, PI, thinFilmIor < outsideIor); let phi21 = PI - phi12; let phi23 = vec3f( select(0.0, PI, baseIor.x < thinFilmIor), select(0.0, PI, baseIor.y < thinFilmIor), select(0.0, PI, baseIor.z < thinFilmIor) ); let phi = vec3f(phi21) + phi23; let OPD = 2.0 * thinFilmIor * thickness * cosTheta2; let R123 = clamp(vec3f(R12) * R23, vec3f(1e-5), vec3f(0.9999)); let r123 = sqrt(R123); let Rs = sqr(T121) * R23 / (vec3f(1.0) - R123); var I = vec3f(R12) + Rs; var Cm = Rs - vec3f(T121); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(OPD, phi); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(2.0 * OPD, 2.0 * phi); return sanitizeReflectance(I, baseF0); } fn distributionGGXAnisotropic(NdotH: f32, TdotH: f32, BdotH: f32, at: f32, ab: f32) -> f32 { let a2 = at * ab; let f = vec3f(ab * TdotH, at * BdotH, a2 * NdotH); let w2 = a2 / max(dot(f, f), 1e-8); return a2 * w2 * w2 / PI; } fn visibilityGGXAnisotropic(NdotL: f32, NdotV: f32, BdotV: f32, TdotV: f32, TdotL: f32, BdotL: f32, at: f32, ab: f32) -> f32 { let GGXV = NdotL * length(vec3f(at * TdotV, ab * BdotV, NdotV)); let GGXL = NdotV * length(vec3f(at * TdotL, ab * BdotL, NdotL)); return clamp(0.5 / max(GGXV + GGXL, 1e-8), 0.0, 1.0); } fn sheenDistribution(NdotH: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let invR = 1.0 / alphaG; let sin2h = max(1.0 - NdotH * NdotH, 0.0); return (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * PI); } fn sheenL(cosTheta: f32, alphaG: f32) -> f32 { let oneMinusAlphaSq = sqr(1.0 - alphaG); let a = mix(21.5473, 25.3245, oneMinusAlphaSq); let b = mix(3.82987, 3.32435, oneMinusAlphaSq); let c = mix(0.19823, 0.16801, oneMinusAlphaSq); let d = mix(-1.97760, -1.27393, oneMinusAlphaSq); let e = mix(-4.32054, -4.85967, oneMinusAlphaSq); return a / (1.0 + b * pow(cosTheta, c)) + d * cosTheta + e; } fn sheenLambda(cosTheta: f32, alphaG: f32) -> f32 { let safeCosTheta = clamp(cosTheta, 1e-4, 1.0); if (safeCosTheta < 0.5) { return exp(sheenL(safeCosTheta, alphaG)); } return exp(2.0 * sheenL(0.5, alphaG) - sheenL(1.0 - safeCosTheta, alphaG)); } fn sheenVisibility(NdotL: f32, NdotV: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let visibility = 1.0 + sheenLambda(NdotV, alphaG) + sheenLambda(NdotL, alphaG); return clamp(1.0 / max(visibility * 4.0 * NdotV * NdotL, 1e-6), 0.0, 1.0); } fn dielectricF0FromIor(ior: f32) -> f32 { if (ior == 0.0) { return 1.0; } let safeIor = max(ior, 1.0); let r = (safeIor - 1.0) / (safeIor + 1.0); return r * r; } fn computeRangeAttenuation(distance: f32, range: f32) -> f32 { let invSq = 1.0 / max(distance * distance, 0.0001); if (range <= 0.0) { return invSq; } let fade = clamp(1.0 - distance / range, 0.0, 1.0); return invSq * fade * fade; } fn computeSpotFactor(L: vec3f, direction: vec3f, cosInner: f32, cosOuter: f32) -> f32 { let angleCos = dot(-L, normalize(direction)); if (cosInner <= cosOuter) { return select(0.0, 1.0, angleCos >= cosOuter); } return clamp((angleCos - cosOuter) / max(cosInner - cosOuter, 1e-4), 0.0, 1.0); } fn screenUvFromFragment(position: vec4f) -> vec2f { let dims = vec2f(textureDimensions(transmissionSourceTex, 0)); return clamp(position.xy / max(dims, vec2f(1.0)), vec2f(0.0), vec2f(1.0)); } fn projectWorldToScreenUv(worldPos: vec3f) -> vec2f { let clip = camera.viewProjection * vec4f(worldPos, 1.0); let invW = 1.0 / max(abs(clip.w), 1e-5); let ndc = clip.xy * invW * select(-1.0, 1.0, clip.w >= 0.0); return clamp(vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5), vec2f(0.0), vec2f(1.0)); } fn transmissionScreenUv(position: vec4f, worldPos: vec3f, N: vec3f, V: vec3f, ior: f32, thickness: f32, modelScale: vec3f) -> vec2f { let baseUv = screenUvFromFragment(position); if (thickness <= 1e-5) { return baseUv; } let eta = 1.0 / max(ior, 1.0001); var ray = refract(-V, N, eta); let rayLength2 = dot(ray, ray); if (rayLength2 <= 1e-8) { ray = -V; } else { ray = ray * inverseSqrt(rayLength2); } let transmissionRay = ray * max(thickness, 0.0) * max(modelScale, vec3f(1e-4)); return projectWorldToScreenUv(worldPos + transmissionRay); } fn transmissionSourceToLinear(color: vec3f) -> vec3f { return pow(clamp(color, vec3f(0.0), vec3f(1.0)), vec3f(2.2)); } fn sampleTransmissionSourceAt(uv: vec2f) -> vec3f { let sourceColor = textureSampleLevel(transmissionSourceTex, transmissionSourceSampler, clamp(uv, vec2f(0.0), vec2f(1.0)), 0.0).rgb; return transmissionSourceToLinear(sourceColor); } fn dispersionIors(ior: f32, dispersion: f32) -> vec3f { let halfSpread = max(ior - 1.0, 0.0) * 0.025 * max(dispersion, 0.0); return max(vec3f(ior - halfSpread, ior, ior + halfSpread), vec3f(1.0)); } fn sampleTransmissionSource(position: vec4f, worldPos: vec3f, N: vec3f, V: vec3f, ior: f32, dispersion: f32, thickness: f32, modelScale: vec3f) -> vec3f { if (dispersion <= 1e-5 || thickness <= 1e-5) { return sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, ior, thickness, modelScale)); } let iors = dispersionIors(ior, dispersion); let r = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.r, thickness, modelScale)).r; let g = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.g, thickness, modelScale)).g; let b = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.b, thickness, modelScale)).b; return vec3f(r, g, b); } fn volumeTransmissionAttenuation(thickness: f32, attenuationDistance: f32, attenuationColor: vec3f) -> vec3f { if (thickness <= 1e-5 || attenuationDistance <= 1e-5) { return vec3f(1.0); } return pow(max(attenuationColor, vec3f(1e-4)), vec3f(thickness / attenuationDistance)); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let mrUv = applyTextureTransform(in.uv, in.uv1, material.metallicRoughnessTransform0, material.metallicRoughnessTransform1); let normalUv = applyTextureTransform(in.uv, in.uv1, material.normalTransform0, material.normalTransform1); let occlusionUv = applyTextureTransform(in.uv, in.uv1, material.occlusionTransform0, material.occlusionTransform1); let emissiveUv = applyTextureTransform(in.uv, in.uv1, material.emissiveTransform0, material.emissiveTransform1); let clearcoatUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatTransform0, material.clearcoatTransform1); let clearcoatRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatRoughnessTransform0, material.clearcoatRoughnessTransform1); let clearcoatNormalUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatNormalTransform0, material.clearcoatNormalTransform1); let specularUv = applyTextureTransform(in.uv, in.uv1, material.specularTransform0, material.specularTransform1); let specularColorUv = applyTextureTransform(in.uv, in.uv1, material.specularColorTransform0, material.specularColorTransform1); let sheenColorUv = applyTextureTransform(in.uv, in.uv1, material.sheenColorTransform0, material.sheenColorTransform1); let sheenRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.sheenRoughnessTransform0, material.sheenRoughnessTransform1); let iridescenceUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceTransform0, material.iridescenceTransform1); let iridescenceThicknessUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceThicknessTransform0, material.iridescenceThicknessTransform1); let anisotropyUv = applyTextureTransform(in.uv, in.uv1, material.anisotropyTransform0, material.anisotropyTransform1); let transmissionUv = applyTextureTransform(in.uv, in.uv1, material.transmissionTransform0, material.transmissionTransform1); let volumeThicknessUv = applyTextureTransform(in.uv, in.uv1, material.volumeThicknessTransform0, material.volumeThicknessTransform1); let diffuseTransmissionUv = applyTextureTransform(in.uv, in.uv1, material.diffuseTransmissionTransform0, material.diffuseTransmissionTransform1); let diffuseTransmissionColorUv = applyTextureTransform(in.uv, in.uv1, material.diffuseTransmissionColorTransform0, material.diffuseTransmissionColorTransform1); let baseSample = textureSample(baseColorTex, baseColorSampler, baseUv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, mrUv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, normalUv).xyz; let N = applyNormalMap(in.normal, in.tangent, in.worldPos, normalUv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, occlusionUv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, emissiveUv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a * material.extensionParams.y; let clearcoat = clamp(material.clearcoatParams.x * textureSample(clearcoatTex, clearcoatSampler, clearcoatUv).r, 0.0, 1.0); let clearcoatRoughness = clamp(material.clearcoatParams.y * textureSample(clearcoatRoughnessTex, clearcoatRoughnessSampler, clearcoatRoughnessUv).g, 0.04, 1.0); let clearcoatNormalSample = textureSample(clearcoatNormalTex, clearcoatNormalSampler, clearcoatNormalUv).xyz; let clearcoatNormal = applyNormalMap(in.normal, in.tangent, in.worldPos, clearcoatNormalUv, clearcoatNormalSample, material.clearcoatParams.z); let specularStrength = clamp(material.specularParams.x * textureSample(specularTex, specularSampler, specularUv).a, 0.0, 1.0); let specularColor = material.specularParams.yzw * textureSample(specularColorTex, specularColorSampler, specularColorUv).rgb; let sheenColor = material.sheenParams.rgb; let sheenRoughness = clamp(material.sheenParams.w, 0.0, 1.0); let iridescence = clamp(material.iridescenceParams.x, 0.0, 1.0); let iridescenceThickness = material.iridescenceParams.w; let anisotropySample = vec3f(1.0, 0.5, 1.0); let transmission = clamp(material.transmissionParams.x * textureSample(transmissionTex, transmissionSampler, transmissionUv).r, 0.0, 1.0); let diffuseTransmission = clamp(material.transmissionParams.y * textureSample(diffuseTransmissionTex, diffuseTransmissionSampler, diffuseTransmissionUv).a, 0.0, 1.0); let volumeThickness = max(material.transmissionParams.z * textureSample(volumeThicknessTex, volumeThicknessSampler, volumeThicknessUv).g, 0.0); let dispersion = max(material.transmissionParams.w, 0.0); let diffuseTransmissionColor = material.diffuseTransmissionColor.rgb * textureSample(diffuseTransmissionColorTex, diffuseTransmissionColorSampler, diffuseTransmissionColorUv).rgb; let volumeAttenuation = volumeTransmissionAttenuation(volumeThickness, material.diffuseTransmissionColor.w, material.volumeAttenuation.rgb); let anisotropyStrength = clamp(material.anisotropyParams.x * anisotropySample.b, 0.0, 1.0); var anisotropyDirection = anisotropySample.rg * 2.0 - vec2f(1.0); let anisotropyDirectionLength2 = dot(anisotropyDirection, anisotropyDirection); anisotropyDirection = select(vec2f(1.0, 0.0), anisotropyDirection * inverseSqrt(max(anisotropyDirectionLength2, 1e-8)), anisotropyDirectionLength2 > 1e-8); anisotropyDirection = vec2f( material.anisotropyParams.y * anisotropyDirection.x - material.anisotropyParams.z * anisotropyDirection.y, material.anisotropyParams.z * anisotropyDirection.x + material.anisotropyParams.y * anisotropyDirection.y ); let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let dielectricF0 = dielectricF0FromIor(material.extensionParams.x); let dielectricF0Color = min(vec3f(dielectricF0) * specularColor, vec3f(1.0)) * specularStrength; let F0 = mix(dielectricF0Color, albedo, metallic); let F90 = mix(vec3f(specularStrength), vec3f(1.0), metallic); let viewNdotV = max(dot(N, V), 0.0); var iridescenceFresnelColor = F0; if (iridescence > 1e-5 && iridescenceThickness > 0.0) { iridescenceFresnelColor = iridescentFresnel(1.0, material.iridescenceParams.y, F0, iridescenceThickness, viewNdotV); } var viewFresnel = fresnelSchlick(viewNdotV, F0, F90); if (iridescence > 1e-5) { viewFresnel = mix(viewFresnel, iridescenceFresnelColor, iridescence); } let transmissionWeight = transmission * (1.0 - metallic) * max(1.0 - maxComponent(viewFresnel), 0.0); let geometricN = normalize(in.normal); let anisotropyFrame = buildTangentFrame(geometricN, in.tangent, in.worldPos, anisotropyUv); let clearcoatViewFresnel = clamp(clearcoat * fresnelSchlickScalar(abs(dot(V, clearcoatNormal)), 0.04), 0.0, 1.0); var Lo = lighting.ambient.rgb * albedo * ao * (1.0 - transmission); for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); if (distance <= 1e-5) { continue; } L = lightDir / distance; attenuation = computeRangeAttenuation(distance, light.params.x); if (light.position.w == 2.0) { attenuation = attenuation * computeSpotFactor(L, light.direction.xyz, light.params.y, light.params.z); } } if (attenuation <= 0.0) { continue; } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NdotL = max(dot(N, L), 0.0); let NdotV = viewNdotV; let NdotH = max(dot(N, H), 0.0); let VdotH = max(dot(V, H), 0.0); let baseF = fresnelSchlick(VdotH, F0, F90); var F = baseF; if (iridescence > 1e-5) { F = mix(baseF, iridescenceFresnelColor, iridescence); } var specularBrdf: vec3f; if (anisotropyStrength > 1e-5) { let anisotropicT = normalize(anisotropyFrame.t * anisotropyDirection.x + anisotropyFrame.b * anisotropyDirection.y); let anisotropicB = normalize(cross(geometricN, anisotropicT)); let TdotV = dot(anisotropicT, V); let BdotV = dot(anisotropicB, V); let TdotL = dot(anisotropicT, L); let BdotL = dot(anisotropicB, L); let TdotH = dot(anisotropicT, H); let BdotH = dot(anisotropicB, H); let alphaRoughness = max(roughness * roughness, 0.001); let at = mix(alphaRoughness, 1.0, anisotropyStrength * anisotropyStrength); let ab = alphaRoughness; let D = distributionGGXAnisotropic(NdotH, TdotH, BdotH, at, ab); let Vg = visibilityGGXAnisotropic(NdotL, NdotV, BdotV, TdotV, TdotL, BdotL, at, ab); specularBrdf = F * D * Vg; } else { let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let numerator = NDF * G * F; let denominator = 4.0 * NdotV * NdotL + 0.0001; specularBrdf = numerator / denominator; } let sheenD = sheenDistribution(NdotH, sheenRoughness); let sheenV = sheenVisibility(NdotL, NdotV, sheenRoughness); let sheenBrdf = sheenColor * sheenD * sheenV; let diffuseEnergy = max(1.0 - maxComponent(F), 0.0); let kD = vec3f(diffuseEnergy) * (1.0 - metallic); let frontDiffuse = (1.0 - diffuseTransmission) * kD * albedo * radiance * NdotL / PI; let backDiffuse = diffuseTransmission * kD * diffuseTransmissionColor * radiance * max(dot(-N, L), 0.0) / PI; let diffuseContribution = (frontDiffuse + backDiffuse) * (1.0 - transmission); let specularContribution = (specularBrdf + sheenBrdf) * radiance * NdotL; let baseContribution = diffuseContribution + specularContribution; let clearcoatNdotL = max(dot(clearcoatNormal, L), 0.0); let clearcoatNdotV = max(dot(clearcoatNormal, V), 0.0); let clearcoatNDF = distributionGGX(clearcoatNormal, H, clearcoatRoughness); let clearcoatG = geometrySmith(clearcoatNormal, V, L, clearcoatRoughness); let clearcoatBrdf = clearcoatNDF * clearcoatG / (4.0 * clearcoatNdotV * clearcoatNdotL + 0.0001); let clearcoatContribution = vec3f(clearcoatBrdf) * radiance * clearcoatNdotL; Lo += mix(baseContribution, clearcoatContribution, clearcoatViewFresnel); } if (transmissionWeight > 1e-5) { let transmittedSource = sampleTransmissionSource(in.position, in.worldPos, N, V, material.extensionParams.x, dispersion, volumeThickness, in.modelScale); Lo += transmittedSource * albedo * volumeAttenuation * transmissionWeight * (1.0 - clearcoatViewFresnel); } Lo += emissive * (1.0 - clearcoatViewFresnel); Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var Pa="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f, metallicRoughnessTransform0: vec4f, metallicRoughnessTransform1: vec4f, normalTransform0: vec4f, normalTransform1: vec4f, occlusionTransform0: vec4f, occlusionTransform1: vec4f, emissiveTransform0: vec4f, emissiveTransform1: vec4f, clearcoatParams: vec4f, specularParams: vec4f, extensionParams: vec4f, clearcoatTransform0: vec4f, clearcoatTransform1: vec4f, clearcoatRoughnessTransform0: vec4f, clearcoatRoughnessTransform1: vec4f, clearcoatNormalTransform0: vec4f, clearcoatNormalTransform1: vec4f, specularTransform0: vec4f, specularTransform1: vec4f, specularColorTransform0: vec4f, specularColorTransform1: vec4f, sheenParams: vec4f, iridescenceParams: vec4f, anisotropyParams: vec4f, sheenColorTransform0: vec4f, sheenColorTransform1: vec4f, sheenRoughnessTransform0: vec4f, sheenRoughnessTransform1: vec4f, iridescenceTransform0: vec4f, iridescenceTransform1: vec4f, iridescenceThicknessTransform0: vec4f, iridescenceThicknessTransform1: vec4f, anisotropyTransform0: vec4f, anisotropyTransform1: vec4f, transmissionParams: vec4f, diffuseTransmissionColor: vec4f, volumeAttenuation: vec4f, transmissionTransform0: vec4f, transmissionTransform1: vec4f, volumeThicknessTransform0: vec4f, volumeThicknessTransform1: vec4f, diffuseTransmissionTransform0: vec4f, diffuseTransmissionTransform1: vec4f, diffuseTransmissionColorTransform0: vec4f, diffuseTransmissionColorTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; @group(1) @binding(11) var clearcoatSampler: sampler; @group(1) @binding(12) var clearcoatTex: texture_2d<f32>; @group(1) @binding(13) var clearcoatRoughnessSampler: sampler; @group(1) @binding(14) var clearcoatRoughnessTex: texture_2d<f32>; @group(1) @binding(15) var clearcoatNormalSampler: sampler; @group(1) @binding(16) var clearcoatNormalTex: texture_2d<f32>; @group(1) @binding(17) var specularSampler: sampler; @group(1) @binding(18) var specularTex: texture_2d<f32>; @group(1) @binding(19) var specularColorSampler: sampler; @group(1) @binding(20) var specularColorTex: texture_2d<f32>; @group(1) @binding(21) var transmissionSampler: sampler; @group(1) @binding(22) var transmissionTex: texture_2d<f32>; @group(1) @binding(23) var volumeThicknessSampler: sampler; @group(1) @binding(24) var volumeThicknessTex: texture_2d<f32>; @group(1) @binding(25) var diffuseTransmissionSampler: sampler; @group(1) @binding(26) var diffuseTransmissionTex: texture_2d<f32>; @group(1) @binding(27) var diffuseTransmissionColorSampler: sampler; @group(1) @binding(28) var diffuseTransmissionColorTex: texture_2d<f32>; @group(1) @binding(29) var transmissionSourceSampler: sampler; @group(1) @binding(30) var transmissionSourceTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(12) tangent: vec4f, @location(3) joints: vec4u, @location(4) weights: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) uv1: vec2f, @location(4) tangent: vec4f, @location(5) modelScale: vec3f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, direction: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; struct SkinBuffer { joints: array<mat4x4f> }; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let j = in.joints; let w = in.weights; let skinMatrix = skin.joints[j.x] * w.x + skin.joints[j.y] * w.y + skin.joints[j.z] * w.z + skin.joints[j.w] * w.w; let localPos = skinMatrix * vec4f(in.position, 1.0); let localNormal = (skinMatrix * vec4f(in.normal, 0.0)).xyz; let localTangent = (skinMatrix * vec4f(in.tangent.xyz, 0.0)).xyz; let worldPos4 = model.model * localPos; out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(localNormal, 0.0)).xyz); out.tangent = vec4f((model.normalMatrix * vec4f(localTangent, 0.0)).xyz, in.tangent.w); out.modelScale = vec3f(length(model.model[0].xyz), length(model.model[1].xyz), length(model.model[2].xyz)); out.uv = in.uv; out.uv1 = in.uv1; return out; } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } fn fresnelSchlick(cosTheta: f32, F0: vec3f, F90: vec3f) -> vec3f { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (F90 - F0) * pow(oneMinusCos, 5.0); } fn maxComponent(v: vec3f) -> f32 { return max(max(v.x, v.y), v.z); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } struct TangentFrame { t: vec3f, b: vec3f, n: vec3f }; fn fallbackTangentFrame(N: vec3f) -> TangentFrame { let n = normalize(N); let axis = select(vec3f(0.0, 1.0, 0.0), vec3f(1.0, 0.0, 0.0), abs(n.x) < 0.9); let t = normalize(cross(axis, n)); let b = cross(n, t); return TangentFrame(t, b, n); } fn derivativeTangentFrame(N: vec3f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let dp2perp = cross(dp2, n); let dp1perp = cross(n, dp1); let T = (dp2perp * duv1.x) + (dp1perp * duv2.x); let B = (dp2perp * duv1.y) + (dp1perp * duv2.y); let frameLength2 = max(dot(T, T), dot(B, B)); if (frameLength2 <= 1e-20) { return fallbackTangentFrame(n); } let frameScale = 1.0 / sqrt(frameLength2); return TangentFrame(T * frameScale, B * frameScale, n); } fn buildTangentFrame(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let derivativeFrame = derivativeTangentFrame(n, worldPos, uv); var t = tangent.xyz - n * dot(n, tangent.xyz); let tLen2 = dot(t, t); if (tLen2 <= 1e-20) { return derivativeFrame; } t = t * inverseSqrt(tLen2); let b = normalize(cross(n, t)) * select(-1.0, 1.0, tangent.w >= 0.0); return TangentFrame(t, b, n); } fn applyNormalMap(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { if (normalScale == 0.0) { return normalize(N); } let frame = buildTangentFrame(N, tangent, worldPos, uv); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(frame.t * ns.x + frame.b * ns.y + frame.n * ns.z); } fn sqr(v: f32) -> f32 { return v * v; } fn iorToFresnel0(transmittedIor: f32, incidentIor: f32) -> f32 { let r = (transmittedIor - incidentIor) / (transmittedIor + incidentIor); return r * r; } fn iorToFresnel0Vec(transmittedIor: vec3f, incidentIor: f32) -> vec3f { let r = (transmittedIor - vec3f(incidentIor)) / (transmittedIor + vec3f(incidentIor)); return r * r; } fn fresnel0ToIor(F0: vec3f) -> vec3f { let sqrtF0 = sqrt(clamp(F0, vec3f(0.0), vec3f(0.9999))); return (vec3f(1.0) + sqrtF0) / max(vec3f(1.0) - sqrtF0, vec3f(1e-4)); } fn fresnelSchlickScalar(cosTheta: f32, F0: f32) -> f32 { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (1.0 - F0) * pow(oneMinusCos, 5.0); } fn sanitizeReflectance(value: vec3f, fallback: vec3f) -> vec3f { var result = clamp(fallback, vec3f(0.0), vec3f(1.0)); if (value.x == value.x && abs(value.x) < 1.0e6) { result.x = clamp(value.x, 0.0, 1.0); } if (value.y == value.y && abs(value.y) < 1.0e6) { result.y = clamp(value.y, 0.0, 1.0); } if (value.z == value.z && abs(value.z) < 1.0e6) { result.z = clamp(value.z, 0.0, 1.0); } return result; } fn evalIridescenceSensitivity(OPD: f32, shift: vec3f) -> vec3f { let phase = 2.0 * PI * OPD * 1.0e-9; let phase2 = phase * phase; let val = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13); let pos = vec3f(1.6810e+06, 1.7953e+06, 2.2084e+06); let variance = vec3f(4.3278e+09, 9.3046e+09, 6.6121e+09); var xyz = val * sqrt(2.0 * PI * variance) * cos(pos * phase + shift) * exp(-phase2 * variance); xyz.x += 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift.x) * exp(-4.5282e+09 * phase2); xyz /= 1.0685e-7; return vec3f( 3.2404542 * xyz.x - 1.5371385 * xyz.y - 0.4985314 * xyz.z, -0.9692660 * xyz.x + 1.8760108 * xyz.y + 0.0415560 * xyz.z, 0.0556434 * xyz.x - 0.2040259 * xyz.y + 1.0572252 * xyz.z ); } fn iridescentFresnel(outsideIor: f32, iridescenceIor: f32, baseF0: vec3f, thickness: f32, cosTheta1: f32) -> vec3f { let safeCosTheta1 = clamp(cosTheta1, 0.0, 1.0); let thinFilmIor = mix(outsideIor, iridescenceIor, smoothstep(0.0, 0.03, thickness)); let R0 = iorToFresnel0(thinFilmIor, outsideIor); let R12 = fresnelSchlickScalar(safeCosTheta1, R0); let T121 = 1.0 - R12; let baseIor = fresnel0ToIor(baseF0); let R1 = iorToFresnel0Vec(baseIor, thinFilmIor); let eta = outsideIor / thinFilmIor; let sinTheta2Sq = eta * eta * (1.0 - safeCosTheta1 * safeCosTheta1); let cosTheta2Sq = 1.0 - sinTheta2Sq; if (cosTheta2Sq < 0.0) { return vec3f(1.0); } let cosTheta2 = sqrt(cosTheta2Sq); let R23 = fresnelSchlick(cosTheta2, R1, vec3f(1.0)); let phi12 = select(0.0, PI, thinFilmIor < outsideIor); let phi21 = PI - phi12; let phi23 = vec3f( select(0.0, PI, baseIor.x < thinFilmIor), select(0.0, PI, baseIor.y < thinFilmIor), select(0.0, PI, baseIor.z < thinFilmIor) ); let phi = vec3f(phi21) + phi23; let OPD = 2.0 * thinFilmIor * thickness * cosTheta2; let R123 = clamp(vec3f(R12) * R23, vec3f(1e-5), vec3f(0.9999)); let r123 = sqrt(R123); let Rs = sqr(T121) * R23 / (vec3f(1.0) - R123); var I = vec3f(R12) + Rs; var Cm = Rs - vec3f(T121); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(OPD, phi); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(2.0 * OPD, 2.0 * phi); return sanitizeReflectance(I, baseF0); } fn distributionGGXAnisotropic(NdotH: f32, TdotH: f32, BdotH: f32, at: f32, ab: f32) -> f32 { let a2 = at * ab; let f = vec3f(ab * TdotH, at * BdotH, a2 * NdotH); let w2 = a2 / max(dot(f, f), 1e-8); return a2 * w2 * w2 / PI; } fn visibilityGGXAnisotropic(NdotL: f32, NdotV: f32, BdotV: f32, TdotV: f32, TdotL: f32, BdotL: f32, at: f32, ab: f32) -> f32 { let GGXV = NdotL * length(vec3f(at * TdotV, ab * BdotV, NdotV)); let GGXL = NdotV * length(vec3f(at * TdotL, ab * BdotL, NdotL)); return clamp(0.5 / max(GGXV + GGXL, 1e-8), 0.0, 1.0); } fn sheenDistribution(NdotH: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let invR = 1.0 / alphaG; let sin2h = max(1.0 - NdotH * NdotH, 0.0); return (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * PI); } fn sheenL(cosTheta: f32, alphaG: f32) -> f32 { let oneMinusAlphaSq = sqr(1.0 - alphaG); let a = mix(21.5473, 25.3245, oneMinusAlphaSq); let b = mix(3.82987, 3.32435, oneMinusAlphaSq); let c = mix(0.19823, 0.16801, oneMinusAlphaSq); let d = mix(-1.97760, -1.27393, oneMinusAlphaSq); let e = mix(-4.32054, -4.85967, oneMinusAlphaSq); return a / (1.0 + b * pow(cosTheta, c)) + d * cosTheta + e; } fn sheenLambda(cosTheta: f32, alphaG: f32) -> f32 { let safeCosTheta = clamp(cosTheta, 1e-4, 1.0); if (safeCosTheta < 0.5) { return exp(sheenL(safeCosTheta, alphaG)); } return exp(2.0 * sheenL(0.5, alphaG) - sheenL(1.0 - safeCosTheta, alphaG)); } fn sheenVisibility(NdotL: f32, NdotV: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let visibility = 1.0 + sheenLambda(NdotV, alphaG) + sheenLambda(NdotL, alphaG); return clamp(1.0 / max(visibility * 4.0 * NdotV * NdotL, 1e-6), 0.0, 1.0); } fn dielectricF0FromIor(ior: f32) -> f32 { if (ior == 0.0) { return 1.0; } let safeIor = max(ior, 1.0); let r = (safeIor - 1.0) / (safeIor + 1.0); return r * r; } fn computeRangeAttenuation(distance: f32, range: f32) -> f32 { let invSq = 1.0 / max(distance * distance, 0.0001); if (range <= 0.0) { return invSq; } let fade = clamp(1.0 - distance / range, 0.0, 1.0); return invSq * fade * fade; } fn computeSpotFactor(L: vec3f, direction: vec3f, cosInner: f32, cosOuter: f32) -> f32 { let angleCos = dot(-L, normalize(direction)); if (cosInner <= cosOuter) { return select(0.0, 1.0, angleCos >= cosOuter); } return clamp((angleCos - cosOuter) / max(cosInner - cosOuter, 1e-4), 0.0, 1.0); } fn screenUvFromFragment(position: vec4f) -> vec2f { let dims = vec2f(textureDimensions(transmissionSourceTex, 0)); return clamp(position.xy / max(dims, vec2f(1.0)), vec2f(0.0), vec2f(1.0)); } fn projectWorldToScreenUv(worldPos: vec3f) -> vec2f { let clip = camera.viewProjection * vec4f(worldPos, 1.0); let invW = 1.0 / max(abs(clip.w), 1e-5); let ndc = clip.xy * invW * select(-1.0, 1.0, clip.w >= 0.0); return clamp(vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5), vec2f(0.0), vec2f(1.0)); } fn transmissionScreenUv(position: vec4f, worldPos: vec3f, N: vec3f, V: vec3f, ior: f32, thickness: f32, modelScale: vec3f) -> vec2f { let baseUv = screenUvFromFragment(position); if (thickness <= 1e-5) { return baseUv; } let eta = 1.0 / max(ior, 1.0001); var ray = refract(-V, N, eta); let rayLength2 = dot(ray, ray); if (rayLength2 <= 1e-8) { ray = -V; } else { ray = ray * inverseSqrt(rayLength2); } let transmissionRay = ray * max(thickness, 0.0) * max(modelScale, vec3f(1e-4)); return projectWorldToScreenUv(worldPos + transmissionRay); } fn transmissionSourceToLinear(color: vec3f) -> vec3f { return pow(clamp(color, vec3f(0.0), vec3f(1.0)), vec3f(2.2)); } fn sampleTransmissionSourceAt(uv: vec2f) -> vec3f { let sourceColor = textureSampleLevel(transmissionSourceTex, transmissionSourceSampler, clamp(uv, vec2f(0.0), vec2f(1.0)), 0.0).rgb; return transmissionSourceToLinear(sourceColor); } fn dispersionIors(ior: f32, dispersion: f32) -> vec3f { let halfSpread = max(ior - 1.0, 0.0) * 0.025 * max(dispersion, 0.0); return max(vec3f(ior - halfSpread, ior, ior + halfSpread), vec3f(1.0)); } fn sampleTransmissionSource(position: vec4f, worldPos: vec3f, N: vec3f, V: vec3f, ior: f32, dispersion: f32, thickness: f32, modelScale: vec3f) -> vec3f { if (dispersion <= 1e-5 || thickness <= 1e-5) { return sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, ior, thickness, modelScale)); } let iors = dispersionIors(ior, dispersion); let r = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.r, thickness, modelScale)).r; let g = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.g, thickness, modelScale)).g; let b = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.b, thickness, modelScale)).b; return vec3f(r, g, b); } fn volumeTransmissionAttenuation(thickness: f32, attenuationDistance: f32, attenuationColor: vec3f) -> vec3f { if (thickness <= 1e-5 || attenuationDistance <= 1e-5) { return vec3f(1.0); } return pow(max(attenuationColor, vec3f(1e-4)), vec3f(thickness / attenuationDistance)); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let mrUv = applyTextureTransform(in.uv, in.uv1, material.metallicRoughnessTransform0, material.metallicRoughnessTransform1); let normalUv = applyTextureTransform(in.uv, in.uv1, material.normalTransform0, material.normalTransform1); let occlusionUv = applyTextureTransform(in.uv, in.uv1, material.occlusionTransform0, material.occlusionTransform1); let emissiveUv = applyTextureTransform(in.uv, in.uv1, material.emissiveTransform0, material.emissiveTransform1); let clearcoatUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatTransform0, material.clearcoatTransform1); let clearcoatRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatRoughnessTransform0, material.clearcoatRoughnessTransform1); let clearcoatNormalUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatNormalTransform0, material.clearcoatNormalTransform1); let specularUv = applyTextureTransform(in.uv, in.uv1, material.specularTransform0, material.specularTransform1); let specularColorUv = applyTextureTransform(in.uv, in.uv1, material.specularColorTransform0, material.specularColorTransform1); let sheenColorUv = applyTextureTransform(in.uv, in.uv1, material.sheenColorTransform0, material.sheenColorTransform1); let sheenRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.sheenRoughnessTransform0, material.sheenRoughnessTransform1); let iridescenceUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceTransform0, material.iridescenceTransform1); let iridescenceThicknessUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceThicknessTransform0, material.iridescenceThicknessTransform1); let anisotropyUv = applyTextureTransform(in.uv, in.uv1, material.anisotropyTransform0, material.anisotropyTransform1); let transmissionUv = applyTextureTransform(in.uv, in.uv1, material.transmissionTransform0, material.transmissionTransform1); let volumeThicknessUv = applyTextureTransform(in.uv, in.uv1, material.volumeThicknessTransform0, material.volumeThicknessTransform1); let diffuseTransmissionUv = applyTextureTransform(in.uv, in.uv1, material.diffuseTransmissionTransform0, material.diffuseTransmissionTransform1); let diffuseTransmissionColorUv = applyTextureTransform(in.uv, in.uv1, material.diffuseTransmissionColorTransform0, material.diffuseTransmissionColorTransform1); let baseSample = textureSample(baseColorTex, baseColorSampler, baseUv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, mrUv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, normalUv).xyz; let N = applyNormalMap(in.normal, in.tangent, in.worldPos, normalUv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, occlusionUv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, emissiveUv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a * material.extensionParams.y; let clearcoat = clamp(material.clearcoatParams.x * textureSample(clearcoatTex, clearcoatSampler, clearcoatUv).r, 0.0, 1.0); let clearcoatRoughness = clamp(material.clearcoatParams.y * textureSample(clearcoatRoughnessTex, clearcoatRoughnessSampler, clearcoatRoughnessUv).g, 0.04, 1.0); let clearcoatNormalSample = textureSample(clearcoatNormalTex, clearcoatNormalSampler, clearcoatNormalUv).xyz; let clearcoatNormal = applyNormalMap(in.normal, in.tangent, in.worldPos, clearcoatNormalUv, clearcoatNormalSample, material.clearcoatParams.z); let specularStrength = clamp(material.specularParams.x * textureSample(specularTex, specularSampler, specularUv).a, 0.0, 1.0); let specularColor = material.specularParams.yzw * textureSample(specularColorTex, specularColorSampler, specularColorUv).rgb; let sheenColor = material.sheenParams.rgb; let sheenRoughness = clamp(material.sheenParams.w, 0.0, 1.0); let iridescence = clamp(material.iridescenceParams.x, 0.0, 1.0); let iridescenceThickness = material.iridescenceParams.w; let anisotropySample = vec3f(1.0, 0.5, 1.0); let transmission = clamp(material.transmissionParams.x * textureSample(transmissionTex, transmissionSampler, transmissionUv).r, 0.0, 1.0); let diffuseTransmission = clamp(material.transmissionParams.y * textureSample(diffuseTransmissionTex, diffuseTransmissionSampler, diffuseTransmissionUv).a, 0.0, 1.0); let volumeThickness = max(material.transmissionParams.z * textureSample(volumeThicknessTex, volumeThicknessSampler, volumeThicknessUv).g, 0.0); let dispersion = max(material.transmissionParams.w, 0.0); let diffuseTransmissionColor = material.diffuseTransmissionColor.rgb * textureSample(diffuseTransmissionColorTex, diffuseTransmissionColorSampler, diffuseTransmissionColorUv).rgb; let volumeAttenuation = volumeTransmissionAttenuation(volumeThickness, material.diffuseTransmissionColor.w, material.volumeAttenuation.rgb); let anisotropyStrength = clamp(material.anisotropyParams.x * anisotropySample.b, 0.0, 1.0); var anisotropyDirection = anisotropySample.rg * 2.0 - vec2f(1.0); let anisotropyDirectionLength2 = dot(anisotropyDirection, anisotropyDirection); anisotropyDirection = select(vec2f(1.0, 0.0), anisotropyDirection * inverseSqrt(max(anisotropyDirectionLength2, 1e-8)), anisotropyDirectionLength2 > 1e-8); anisotropyDirection = vec2f( material.anisotropyParams.y * anisotropyDirection.x - material.anisotropyParams.z * anisotropyDirection.y, material.anisotropyParams.z * anisotropyDirection.x + material.anisotropyParams.y * anisotropyDirection.y ); let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let dielectricF0 = dielectricF0FromIor(material.extensionParams.x); let dielectricF0Color = min(vec3f(dielectricF0) * specularColor, vec3f(1.0)) * specularStrength; let F0 = mix(dielectricF0Color, albedo, metallic); let F90 = mix(vec3f(specularStrength), vec3f(1.0), metallic); let viewNdotV = max(dot(N, V), 0.0); var iridescenceFresnelColor = F0; if (iridescence > 1e-5 && iridescenceThickness > 0.0) { iridescenceFresnelColor = iridescentFresnel(1.0, material.iridescenceParams.y, F0, iridescenceThickness, viewNdotV); } var viewFresnel = fresnelSchlick(viewNdotV, F0, F90); if (iridescence > 1e-5) { viewFresnel = mix(viewFresnel, iridescenceFresnelColor, iridescence); } let transmissionWeight = transmission * (1.0 - metallic) * max(1.0 - maxComponent(viewFresnel), 0.0); let geometricN = normalize(in.normal); let anisotropyFrame = buildTangentFrame(geometricN, in.tangent, in.worldPos, anisotropyUv); let clearcoatViewFresnel = clamp(clearcoat * fresnelSchlickScalar(abs(dot(V, clearcoatNormal)), 0.04), 0.0, 1.0); var Lo = lighting.ambient.rgb * albedo * ao * (1.0 - transmission); for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); if (distance <= 1e-5) { continue; } L = lightDir / distance; attenuation = computeRangeAttenuation(distance, light.params.x); if (light.position.w == 2.0) { attenuation = attenuation * computeSpotFactor(L, light.direction.xyz, light.params.y, light.params.z); } } if (attenuation <= 0.0) { continue; } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NdotL = max(dot(N, L), 0.0); let NdotV = viewNdotV; let NdotH = max(dot(N, H), 0.0); let VdotH = max(dot(V, H), 0.0); let baseF = fresnelSchlick(VdotH, F0, F90); var F = baseF; if (iridescence > 1e-5) { F = mix(baseF, iridescenceFresnelColor, iridescence); } var specularBrdf: vec3f; if (anisotropyStrength > 1e-5) { let anisotropicT = normalize(anisotropyFrame.t * anisotropyDirection.x + anisotropyFrame.b * anisotropyDirection.y); let anisotropicB = normalize(cross(geometricN, anisotropicT)); let TdotV = dot(anisotropicT, V); let BdotV = dot(anisotropicB, V); let TdotL = dot(anisotropicT, L); let BdotL = dot(anisotropicB, L); let TdotH = dot(anisotropicT, H); let BdotH = dot(anisotropicB, H); let alphaRoughness = max(roughness * roughness, 0.001); let at = mix(alphaRoughness, 1.0, anisotropyStrength * anisotropyStrength); let ab = alphaRoughness; let D = distributionGGXAnisotropic(NdotH, TdotH, BdotH, at, ab); let Vg = visibilityGGXAnisotropic(NdotL, NdotV, BdotV, TdotV, TdotL, BdotL, at, ab); specularBrdf = F * D * Vg; } else { let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let numerator = NDF * G * F; let denominator = 4.0 * NdotV * NdotL + 0.0001; specularBrdf = numerator / denominator; } let sheenD = sheenDistribution(NdotH, sheenRoughness); let sheenV = sheenVisibility(NdotL, NdotV, sheenRoughness); let sheenBrdf = sheenColor * sheenD * sheenV; let diffuseEnergy = max(1.0 - maxComponent(F), 0.0); let kD = vec3f(diffuseEnergy) * (1.0 - metallic); let frontDiffuse = (1.0 - diffuseTransmission) * kD * albedo * radiance * NdotL / PI; let backDiffuse = diffuseTransmission * kD * diffuseTransmissionColor * radiance * max(dot(-N, L), 0.0) / PI; let diffuseContribution = (frontDiffuse + backDiffuse) * (1.0 - transmission); let specularContribution = (specularBrdf + sheenBrdf) * radiance * NdotL; let baseContribution = diffuseContribution + specularContribution; let clearcoatNdotL = max(dot(clearcoatNormal, L), 0.0); let clearcoatNdotV = max(dot(clearcoatNormal, V), 0.0); let clearcoatNDF = distributionGGX(clearcoatNormal, H, clearcoatRoughness); let clearcoatG = geometrySmith(clearcoatNormal, V, L, clearcoatRoughness); let clearcoatBrdf = clearcoatNDF * clearcoatG / (4.0 * clearcoatNdotV * clearcoatNdotL + 0.0001); let clearcoatContribution = vec3f(clearcoatBrdf) * radiance * clearcoatNdotL; Lo += mix(baseContribution, clearcoatContribution, clearcoatViewFresnel); } if (transmissionWeight > 1e-5) { let transmittedSource = sampleTransmissionSource(in.position, in.worldPos, N, V, material.extensionParams.x, dispersion, volumeThickness, in.modelScale); Lo += transmittedSource * albedo * volumeAttenuation * transmissionWeight * (1.0 - clearcoatViewFresnel); } Lo += emissive * (1.0 - clearcoatViewFresnel); Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var Ta="struct MaterialUniforms { color: vec4f, emissive: vec4f, params: vec4f, params2: vec4f, baseColorTransform0: vec4f, baseColorTransform1: vec4f, metallicRoughnessTransform0: vec4f, metallicRoughnessTransform1: vec4f, normalTransform0: vec4f, normalTransform1: vec4f, occlusionTransform0: vec4f, occlusionTransform1: vec4f, emissiveTransform0: vec4f, emissiveTransform1: vec4f, clearcoatParams: vec4f, specularParams: vec4f, extensionParams: vec4f, clearcoatTransform0: vec4f, clearcoatTransform1: vec4f, clearcoatRoughnessTransform0: vec4f, clearcoatRoughnessTransform1: vec4f, clearcoatNormalTransform0: vec4f, clearcoatNormalTransform1: vec4f, specularTransform0: vec4f, specularTransform1: vec4f, specularColorTransform0: vec4f, specularColorTransform1: vec4f, sheenParams: vec4f, iridescenceParams: vec4f, anisotropyParams: vec4f, sheenColorTransform0: vec4f, sheenColorTransform1: vec4f, sheenRoughnessTransform0: vec4f, sheenRoughnessTransform1: vec4f, iridescenceTransform0: vec4f, iridescenceTransform1: vec4f, iridescenceThicknessTransform0: vec4f, iridescenceThicknessTransform1: vec4f, anisotropyTransform0: vec4f, anisotropyTransform1: vec4f, transmissionParams: vec4f, diffuseTransmissionColor: vec4f, volumeAttenuation: vec4f, transmissionTransform0: vec4f, transmissionTransform1: vec4f, volumeThicknessTransform0: vec4f, volumeThicknessTransform1: vec4f, diffuseTransmissionTransform0: vec4f, diffuseTransmissionTransform1: vec4f, diffuseTransmissionColorTransform0: vec4f, diffuseTransmissionColorTransform1: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var baseColorSampler: sampler; @group(1) @binding(2) var baseColorTex: texture_2d<f32>; @group(1) @binding(3) var metallicRoughnessSampler: sampler; @group(1) @binding(4) var metallicRoughnessTex: texture_2d<f32>; @group(1) @binding(5) var normalSampler: sampler; @group(1) @binding(6) var normalTex: texture_2d<f32>; @group(1) @binding(7) var occlusionSampler: sampler; @group(1) @binding(8) var occlusionTex: texture_2d<f32>; @group(1) @binding(9) var emissiveSampler: sampler; @group(1) @binding(10) var emissiveTex: texture_2d<f32>; @group(1) @binding(11) var clearcoatSampler: sampler; @group(1) @binding(12) var clearcoatTex: texture_2d<f32>; @group(1) @binding(13) var clearcoatRoughnessSampler: sampler; @group(1) @binding(14) var clearcoatRoughnessTex: texture_2d<f32>; @group(1) @binding(15) var clearcoatNormalSampler: sampler; @group(1) @binding(16) var clearcoatNormalTex: texture_2d<f32>; @group(1) @binding(17) var specularSampler: sampler; @group(1) @binding(18) var specularTex: texture_2d<f32>; @group(1) @binding(19) var specularColorSampler: sampler; @group(1) @binding(20) var specularColorTex: texture_2d<f32>; @group(1) @binding(21) var transmissionSampler: sampler; @group(1) @binding(22) var transmissionTex: texture_2d<f32>; @group(1) @binding(23) var volumeThicknessSampler: sampler; @group(1) @binding(24) var volumeThicknessTex: texture_2d<f32>; @group(1) @binding(25) var diffuseTransmissionSampler: sampler; @group(1) @binding(26) var diffuseTransmissionTex: texture_2d<f32>; @group(1) @binding(27) var diffuseTransmissionColorSampler: sampler; @group(1) @binding(28) var diffuseTransmissionColorTex: texture_2d<f32>; @group(1) @binding(29) var transmissionSourceSampler: sampler; @group(1) @binding(30) var transmissionSourceTex: texture_2d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(11) uv1: vec2f, @location(12) tangent: vec4f, @location(3) joints0: vec4u, @location(4) weights0: vec4f, @location(5) joints1: vec4u, @location(6) weights1: vec4f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f, @location(3) uv1: vec2f, @location(4) tangent: vec4f, @location(5) modelScale: vec3f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, direction: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; struct SkinBuffer { joints: array<mat4x4f> }; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; const PI: f32 = 3.14159265359; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let j0 = in.joints0; let w0 = in.weights0; let j1 = in.joints1; let w1 = in.weights1; let skinMatrix = skin.joints[j0.x] * w0.x + skin.joints[j0.y] * w0.y + skin.joints[j0.z] * w0.z + skin.joints[j0.w] * w0.w + skin.joints[j1.x] * w1.x + skin.joints[j1.y] * w1.y + skin.joints[j1.z] * w1.z + skin.joints[j1.w] * w1.w; let localPos = skinMatrix * vec4f(in.position, 1.0); let localNormal = (skinMatrix * vec4f(in.normal, 0.0)).xyz; let localTangent = (skinMatrix * vec4f(in.tangent.xyz, 0.0)).xyz; let worldPos4 = model.model * localPos; out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(localNormal, 0.0)).xyz); out.tangent = vec4f((model.normalMatrix * vec4f(localTangent, 0.0)).xyz, in.tangent.w); out.modelScale = vec3f(length(model.model[0].xyz), length(model.model[1].xyz), length(model.model[2].xyz)); out.uv = in.uv; out.uv1 = in.uv1; return out; } fn applyTextureTransform(uv0: vec2f, uv1: vec2f, transform0: vec4f, transform1: vec4f) -> vec2f { let uv = select(uv0, uv1, transform1.z >= 0.5); let scaled = uv * transform1.xy; let rotated = vec2f( transform0.z * scaled.x + transform0.w * scaled.y, -transform0.w * scaled.x + transform0.z * scaled.y ); return rotated + transform0.xy; } fn fresnelSchlick(cosTheta: f32, F0: vec3f, F90: vec3f) -> vec3f { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (F90 - F0) * pow(oneMinusCos, 5.0); } fn maxComponent(v: vec3f) -> f32 { return max(max(v.x, v.y), v.z); } fn distributionGGX(N: vec3f, H: vec3f, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let NdotH2 = NdotH * NdotH; let denom = NdotH2 * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 { let r = roughness + 1.0; let k = (r * r) / 8.0; return NdotV / (NdotV * (1.0 - k) + k); } fn geometrySmith(N: vec3f, V: vec3f, L: vec3f, roughness: f32) -> f32 { let NdotV = max(dot(N, V), 0.0); let NdotL = max(dot(N, L), 0.0); return geometrySchlickGGX(NdotV, roughness) * geometrySchlickGGX(NdotL, roughness); } struct TangentFrame { t: vec3f, b: vec3f, n: vec3f }; fn fallbackTangentFrame(N: vec3f) -> TangentFrame { let n = normalize(N); let axis = select(vec3f(0.0, 1.0, 0.0), vec3f(1.0, 0.0, 0.0), abs(n.x) < 0.9); let t = normalize(cross(axis, n)); let b = cross(n, t); return TangentFrame(t, b, n); } fn derivativeTangentFrame(N: vec3f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let dp1 = dpdx(worldPos); let dp2 = dpdy(worldPos); let duv1 = dpdx(uv); let duv2 = dpdy(uv); let dp2perp = cross(dp2, n); let dp1perp = cross(n, dp1); let T = (dp2perp * duv1.x) + (dp1perp * duv2.x); let B = (dp2perp * duv1.y) + (dp1perp * duv2.y); let frameLength2 = max(dot(T, T), dot(B, B)); if (frameLength2 <= 1e-20) { return fallbackTangentFrame(n); } let frameScale = 1.0 / sqrt(frameLength2); return TangentFrame(T * frameScale, B * frameScale, n); } fn buildTangentFrame(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f) -> TangentFrame { let n = normalize(N); let derivativeFrame = derivativeTangentFrame(n, worldPos, uv); var t = tangent.xyz - n * dot(n, tangent.xyz); let tLen2 = dot(t, t); if (tLen2 <= 1e-20) { return derivativeFrame; } t = t * inverseSqrt(tLen2); let b = normalize(cross(n, t)) * select(-1.0, 1.0, tangent.w >= 0.0); return TangentFrame(t, b, n); } fn applyNormalMap(N: vec3f, tangent: vec4f, worldPos: vec3f, uv: vec2f, normalSample: vec3f, normalScale: f32) -> vec3f { if (normalScale == 0.0) { return normalize(N); } let frame = buildTangentFrame(N, tangent, worldPos, uv); var ns = normalSample * 2.0 - vec3f(1.0); ns = vec3f(ns.x * normalScale, ns.y * normalScale, ns.z); return normalize(frame.t * ns.x + frame.b * ns.y + frame.n * ns.z); } fn sqr(v: f32) -> f32 { return v * v; } fn iorToFresnel0(transmittedIor: f32, incidentIor: f32) -> f32 { let r = (transmittedIor - incidentIor) / (transmittedIor + incidentIor); return r * r; } fn iorToFresnel0Vec(transmittedIor: vec3f, incidentIor: f32) -> vec3f { let r = (transmittedIor - vec3f(incidentIor)) / (transmittedIor + vec3f(incidentIor)); return r * r; } fn fresnel0ToIor(F0: vec3f) -> vec3f { let sqrtF0 = sqrt(clamp(F0, vec3f(0.0), vec3f(0.9999))); return (vec3f(1.0) + sqrtF0) / max(vec3f(1.0) - sqrtF0, vec3f(1e-4)); } fn fresnelSchlickScalar(cosTheta: f32, F0: f32) -> f32 { let oneMinusCos = 1.0 - clamp(cosTheta, 0.0, 1.0); return F0 + (1.0 - F0) * pow(oneMinusCos, 5.0); } fn sanitizeReflectance(value: vec3f, fallback: vec3f) -> vec3f { var result = clamp(fallback, vec3f(0.0), vec3f(1.0)); if (value.x == value.x && abs(value.x) < 1.0e6) { result.x = clamp(value.x, 0.0, 1.0); } if (value.y == value.y && abs(value.y) < 1.0e6) { result.y = clamp(value.y, 0.0, 1.0); } if (value.z == value.z && abs(value.z) < 1.0e6) { result.z = clamp(value.z, 0.0, 1.0); } return result; } fn evalIridescenceSensitivity(OPD: f32, shift: vec3f) -> vec3f { let phase = 2.0 * PI * OPD * 1.0e-9; let phase2 = phase * phase; let val = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13); let pos = vec3f(1.6810e+06, 1.7953e+06, 2.2084e+06); let variance = vec3f(4.3278e+09, 9.3046e+09, 6.6121e+09); var xyz = val * sqrt(2.0 * PI * variance) * cos(pos * phase + shift) * exp(-phase2 * variance); xyz.x += 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift.x) * exp(-4.5282e+09 * phase2); xyz /= 1.0685e-7; return vec3f( 3.2404542 * xyz.x - 1.5371385 * xyz.y - 0.4985314 * xyz.z, -0.9692660 * xyz.x + 1.8760108 * xyz.y + 0.0415560 * xyz.z, 0.0556434 * xyz.x - 0.2040259 * xyz.y + 1.0572252 * xyz.z ); } fn iridescentFresnel(outsideIor: f32, iridescenceIor: f32, baseF0: vec3f, thickness: f32, cosTheta1: f32) -> vec3f { let safeCosTheta1 = clamp(cosTheta1, 0.0, 1.0); let thinFilmIor = mix(outsideIor, iridescenceIor, smoothstep(0.0, 0.03, thickness)); let R0 = iorToFresnel0(thinFilmIor, outsideIor); let R12 = fresnelSchlickScalar(safeCosTheta1, R0); let T121 = 1.0 - R12; let baseIor = fresnel0ToIor(baseF0); let R1 = iorToFresnel0Vec(baseIor, thinFilmIor); let eta = outsideIor / thinFilmIor; let sinTheta2Sq = eta * eta * (1.0 - safeCosTheta1 * safeCosTheta1); let cosTheta2Sq = 1.0 - sinTheta2Sq; if (cosTheta2Sq < 0.0) { return vec3f(1.0); } let cosTheta2 = sqrt(cosTheta2Sq); let R23 = fresnelSchlick(cosTheta2, R1, vec3f(1.0)); let phi12 = select(0.0, PI, thinFilmIor < outsideIor); let phi21 = PI - phi12; let phi23 = vec3f( select(0.0, PI, baseIor.x < thinFilmIor), select(0.0, PI, baseIor.y < thinFilmIor), select(0.0, PI, baseIor.z < thinFilmIor) ); let phi = vec3f(phi21) + phi23; let OPD = 2.0 * thinFilmIor * thickness * cosTheta2; let R123 = clamp(vec3f(R12) * R23, vec3f(1e-5), vec3f(0.9999)); let r123 = sqrt(R123); let Rs = sqr(T121) * R23 / (vec3f(1.0) - R123); var I = vec3f(R12) + Rs; var Cm = Rs - vec3f(T121); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(OPD, phi); Cm *= r123; I += Cm * 2.0 * evalIridescenceSensitivity(2.0 * OPD, 2.0 * phi); return sanitizeReflectance(I, baseF0); } fn distributionGGXAnisotropic(NdotH: f32, TdotH: f32, BdotH: f32, at: f32, ab: f32) -> f32 { let a2 = at * ab; let f = vec3f(ab * TdotH, at * BdotH, a2 * NdotH); let w2 = a2 / max(dot(f, f), 1e-8); return a2 * w2 * w2 / PI; } fn visibilityGGXAnisotropic(NdotL: f32, NdotV: f32, BdotV: f32, TdotV: f32, TdotL: f32, BdotL: f32, at: f32, ab: f32) -> f32 { let GGXV = NdotL * length(vec3f(at * TdotV, ab * BdotV, NdotV)); let GGXL = NdotV * length(vec3f(at * TdotL, ab * BdotL, NdotL)); return clamp(0.5 / max(GGXV + GGXL, 1e-8), 0.0, 1.0); } fn sheenDistribution(NdotH: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let invR = 1.0 / alphaG; let sin2h = max(1.0 - NdotH * NdotH, 0.0); return (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * PI); } fn sheenL(cosTheta: f32, alphaG: f32) -> f32 { let oneMinusAlphaSq = sqr(1.0 - alphaG); let a = mix(21.5473, 25.3245, oneMinusAlphaSq); let b = mix(3.82987, 3.32435, oneMinusAlphaSq); let c = mix(0.19823, 0.16801, oneMinusAlphaSq); let d = mix(-1.97760, -1.27393, oneMinusAlphaSq); let e = mix(-4.32054, -4.85967, oneMinusAlphaSq); return a / (1.0 + b * pow(cosTheta, c)) + d * cosTheta + e; } fn sheenLambda(cosTheta: f32, alphaG: f32) -> f32 { let safeCosTheta = clamp(cosTheta, 1e-4, 1.0); if (safeCosTheta < 0.5) { return exp(sheenL(safeCosTheta, alphaG)); } return exp(2.0 * sheenL(0.5, alphaG) - sheenL(1.0 - safeCosTheta, alphaG)); } fn sheenVisibility(NdotL: f32, NdotV: f32, sheenRoughness: f32) -> f32 { let alphaG = max(sheenRoughness * sheenRoughness, 1e-4); let visibility = 1.0 + sheenLambda(NdotV, alphaG) + sheenLambda(NdotL, alphaG); return clamp(1.0 / max(visibility * 4.0 * NdotV * NdotL, 1e-6), 0.0, 1.0); } fn dielectricF0FromIor(ior: f32) -> f32 { if (ior == 0.0) { return 1.0; } let safeIor = max(ior, 1.0); let r = (safeIor - 1.0) / (safeIor + 1.0); return r * r; } fn computeRangeAttenuation(distance: f32, range: f32) -> f32 { let invSq = 1.0 / max(distance * distance, 0.0001); if (range <= 0.0) { return invSq; } let fade = clamp(1.0 - distance / range, 0.0, 1.0); return invSq * fade * fade; } fn computeSpotFactor(L: vec3f, direction: vec3f, cosInner: f32, cosOuter: f32) -> f32 { let angleCos = dot(-L, normalize(direction)); if (cosInner <= cosOuter) { return select(0.0, 1.0, angleCos >= cosOuter); } return clamp((angleCos - cosOuter) / max(cosInner - cosOuter, 1e-4), 0.0, 1.0); } fn screenUvFromFragment(position: vec4f) -> vec2f { let dims = vec2f(textureDimensions(transmissionSourceTex, 0)); return clamp(position.xy / max(dims, vec2f(1.0)), vec2f(0.0), vec2f(1.0)); } fn projectWorldToScreenUv(worldPos: vec3f) -> vec2f { let clip = camera.viewProjection * vec4f(worldPos, 1.0); let invW = 1.0 / max(abs(clip.w), 1e-5); let ndc = clip.xy * invW * select(-1.0, 1.0, clip.w >= 0.0); return clamp(vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5), vec2f(0.0), vec2f(1.0)); } fn transmissionScreenUv(position: vec4f, worldPos: vec3f, N: vec3f, V: vec3f, ior: f32, thickness: f32, modelScale: vec3f) -> vec2f { let baseUv = screenUvFromFragment(position); if (thickness <= 1e-5) { return baseUv; } let eta = 1.0 / max(ior, 1.0001); var ray = refract(-V, N, eta); let rayLength2 = dot(ray, ray); if (rayLength2 <= 1e-8) { ray = -V; } else { ray = ray * inverseSqrt(rayLength2); } let transmissionRay = ray * max(thickness, 0.0) * max(modelScale, vec3f(1e-4)); return projectWorldToScreenUv(worldPos + transmissionRay); } fn transmissionSourceToLinear(color: vec3f) -> vec3f { return pow(clamp(color, vec3f(0.0), vec3f(1.0)), vec3f(2.2)); } fn sampleTransmissionSourceAt(uv: vec2f) -> vec3f { let sourceColor = textureSampleLevel(transmissionSourceTex, transmissionSourceSampler, clamp(uv, vec2f(0.0), vec2f(1.0)), 0.0).rgb; return transmissionSourceToLinear(sourceColor); } fn dispersionIors(ior: f32, dispersion: f32) -> vec3f { let halfSpread = max(ior - 1.0, 0.0) * 0.025 * max(dispersion, 0.0); return max(vec3f(ior - halfSpread, ior, ior + halfSpread), vec3f(1.0)); } fn sampleTransmissionSource(position: vec4f, worldPos: vec3f, N: vec3f, V: vec3f, ior: f32, dispersion: f32, thickness: f32, modelScale: vec3f) -> vec3f { if (dispersion <= 1e-5 || thickness <= 1e-5) { return sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, ior, thickness, modelScale)); } let iors = dispersionIors(ior, dispersion); let r = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.r, thickness, modelScale)).r; let g = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.g, thickness, modelScale)).g; let b = sampleTransmissionSourceAt(transmissionScreenUv(position, worldPos, N, V, iors.b, thickness, modelScale)).b; return vec3f(r, g, b); } fn volumeTransmissionAttenuation(thickness: f32, attenuationDistance: f32, attenuationColor: vec3f) -> vec3f { if (thickness <= 1e-5 || attenuationDistance <= 1e-5) { return vec3f(1.0); } return pow(max(attenuationColor, vec3f(1e-4)), vec3f(thickness / attenuationDistance)); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let baseUv = applyTextureTransform(in.uv, in.uv1, material.baseColorTransform0, material.baseColorTransform1); let mrUv = applyTextureTransform(in.uv, in.uv1, material.metallicRoughnessTransform0, material.metallicRoughnessTransform1); let normalUv = applyTextureTransform(in.uv, in.uv1, material.normalTransform0, material.normalTransform1); let occlusionUv = applyTextureTransform(in.uv, in.uv1, material.occlusionTransform0, material.occlusionTransform1); let emissiveUv = applyTextureTransform(in.uv, in.uv1, material.emissiveTransform0, material.emissiveTransform1); let clearcoatUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatTransform0, material.clearcoatTransform1); let clearcoatRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatRoughnessTransform0, material.clearcoatRoughnessTransform1); let clearcoatNormalUv = applyTextureTransform(in.uv, in.uv1, material.clearcoatNormalTransform0, material.clearcoatNormalTransform1); let specularUv = applyTextureTransform(in.uv, in.uv1, material.specularTransform0, material.specularTransform1); let specularColorUv = applyTextureTransform(in.uv, in.uv1, material.specularColorTransform0, material.specularColorTransform1); let sheenColorUv = applyTextureTransform(in.uv, in.uv1, material.sheenColorTransform0, material.sheenColorTransform1); let sheenRoughnessUv = applyTextureTransform(in.uv, in.uv1, material.sheenRoughnessTransform0, material.sheenRoughnessTransform1); let iridescenceUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceTransform0, material.iridescenceTransform1); let iridescenceThicknessUv = applyTextureTransform(in.uv, in.uv1, material.iridescenceThicknessTransform0, material.iridescenceThicknessTransform1); let anisotropyUv = applyTextureTransform(in.uv, in.uv1, material.anisotropyTransform0, material.anisotropyTransform1); let transmissionUv = applyTextureTransform(in.uv, in.uv1, material.transmissionTransform0, material.transmissionTransform1); let volumeThicknessUv = applyTextureTransform(in.uv, in.uv1, material.volumeThicknessTransform0, material.volumeThicknessTransform1); let diffuseTransmissionUv = applyTextureTransform(in.uv, in.uv1, material.diffuseTransmissionTransform0, material.diffuseTransmissionTransform1); let diffuseTransmissionColorUv = applyTextureTransform(in.uv, in.uv1, material.diffuseTransmissionColorTransform0, material.diffuseTransmissionColorTransform1); let baseSample = textureSample(baseColorTex, baseColorSampler, baseUv); let baseColor = material.color * baseSample; let alphaCutoff = material.params2.x; if (alphaCutoff > 0.0 && baseColor.a < alphaCutoff) { discard; } let mrSample = textureSample(metallicRoughnessTex, metallicRoughnessSampler, mrUv); let metallic = clamp(material.params.x * mrSample.b, 0.0, 1.0); let roughness = clamp(material.params.y * mrSample.g, 0.04, 1.0); let normalSample = textureSample(normalTex, normalSampler, normalUv).xyz; let N = applyNormalMap(in.normal, in.tangent, in.worldPos, normalUv, normalSample, material.params.z); let occlSample = textureSample(occlusionTex, occlusionSampler, occlusionUv).r; let ao = 1.0 + material.params.w * (occlSample - 1.0); let emissiveSample = textureSample(emissiveTex, emissiveSampler, emissiveUv).rgb; let emissive = emissiveSample * material.emissive.rgb * material.emissive.a * material.extensionParams.y; let clearcoat = clamp(material.clearcoatParams.x * textureSample(clearcoatTex, clearcoatSampler, clearcoatUv).r, 0.0, 1.0); let clearcoatRoughness = clamp(material.clearcoatParams.y * textureSample(clearcoatRoughnessTex, clearcoatRoughnessSampler, clearcoatRoughnessUv).g, 0.04, 1.0); let clearcoatNormalSample = textureSample(clearcoatNormalTex, clearcoatNormalSampler, clearcoatNormalUv).xyz; let clearcoatNormal = applyNormalMap(in.normal, in.tangent, in.worldPos, clearcoatNormalUv, clearcoatNormalSample, material.clearcoatParams.z); let specularStrength = clamp(material.specularParams.x * textureSample(specularTex, specularSampler, specularUv).a, 0.0, 1.0); let specularColor = material.specularParams.yzw * textureSample(specularColorTex, specularColorSampler, specularColorUv).rgb; let sheenColor = material.sheenParams.rgb; let sheenRoughness = clamp(material.sheenParams.w, 0.0, 1.0); let iridescence = clamp(material.iridescenceParams.x, 0.0, 1.0); let iridescenceThickness = material.iridescenceParams.w; let anisotropySample = vec3f(1.0, 0.5, 1.0); let transmission = clamp(material.transmissionParams.x * textureSample(transmissionTex, transmissionSampler, transmissionUv).r, 0.0, 1.0); let diffuseTransmission = clamp(material.transmissionParams.y * textureSample(diffuseTransmissionTex, diffuseTransmissionSampler, diffuseTransmissionUv).a, 0.0, 1.0); let volumeThickness = max(material.transmissionParams.z * textureSample(volumeThicknessTex, volumeThicknessSampler, volumeThicknessUv).g, 0.0); let dispersion = max(material.transmissionParams.w, 0.0); let diffuseTransmissionColor = material.diffuseTransmissionColor.rgb * textureSample(diffuseTransmissionColorTex, diffuseTransmissionColorSampler, diffuseTransmissionColorUv).rgb; let volumeAttenuation = volumeTransmissionAttenuation(volumeThickness, material.diffuseTransmissionColor.w, material.volumeAttenuation.rgb); let anisotropyStrength = clamp(material.anisotropyParams.x * anisotropySample.b, 0.0, 1.0); var anisotropyDirection = anisotropySample.rg * 2.0 - vec2f(1.0); let anisotropyDirectionLength2 = dot(anisotropyDirection, anisotropyDirection); anisotropyDirection = select(vec2f(1.0, 0.0), anisotropyDirection * inverseSqrt(max(anisotropyDirectionLength2, 1e-8)), anisotropyDirectionLength2 > 1e-8); anisotropyDirection = vec2f( material.anisotropyParams.y * anisotropyDirection.x - material.anisotropyParams.z * anisotropyDirection.y, material.anisotropyParams.z * anisotropyDirection.x + material.anisotropyParams.y * anisotropyDirection.y ); let albedo = baseColor.rgb; let V = normalize(camera.position - in.worldPos); let dielectricF0 = dielectricF0FromIor(material.extensionParams.x); let dielectricF0Color = min(vec3f(dielectricF0) * specularColor, vec3f(1.0)) * specularStrength; let F0 = mix(dielectricF0Color, albedo, metallic); let F90 = mix(vec3f(specularStrength), vec3f(1.0), metallic); let viewNdotV = max(dot(N, V), 0.0); var iridescenceFresnelColor = F0; if (iridescence > 1e-5 && iridescenceThickness > 0.0) { iridescenceFresnelColor = iridescentFresnel(1.0, material.iridescenceParams.y, F0, iridescenceThickness, viewNdotV); } var viewFresnel = fresnelSchlick(viewNdotV, F0, F90); if (iridescence > 1e-5) { viewFresnel = mix(viewFresnel, iridescenceFresnelColor, iridescence); } let transmissionWeight = transmission * (1.0 - metallic) * max(1.0 - maxComponent(viewFresnel), 0.0); let geometricN = normalize(in.normal); let anisotropyFrame = buildTangentFrame(geometricN, in.tangent, in.worldPos, anisotropyUv); let clearcoatViewFresnel = clamp(clearcoat * fresnelSchlickScalar(abs(dot(V, clearcoatNormal)), 0.04), 0.0, 1.0); var Lo = lighting.ambient.rgb * albedo * ao * (1.0 - transmission); for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let distance = length(lightDir); if (distance <= 1e-5) { continue; } L = lightDir / distance; attenuation = computeRangeAttenuation(distance, light.params.x); if (light.position.w == 2.0) { attenuation = attenuation * computeSpotFactor(L, light.direction.xyz, light.params.y, light.params.z); } } if (attenuation <= 0.0) { continue; } let H = normalize(V + L); let radiance = light.color.rgb * light.color.a * attenuation; let NdotL = max(dot(N, L), 0.0); let NdotV = viewNdotV; let NdotH = max(dot(N, H), 0.0); let VdotH = max(dot(V, H), 0.0); let baseF = fresnelSchlick(VdotH, F0, F90); var F = baseF; if (iridescence > 1e-5) { F = mix(baseF, iridescenceFresnelColor, iridescence); } var specularBrdf: vec3f; if (anisotropyStrength > 1e-5) { let anisotropicT = normalize(anisotropyFrame.t * anisotropyDirection.x + anisotropyFrame.b * anisotropyDirection.y); let anisotropicB = normalize(cross(geometricN, anisotropicT)); let TdotV = dot(anisotropicT, V); let BdotV = dot(anisotropicB, V); let TdotL = dot(anisotropicT, L); let BdotL = dot(anisotropicB, L); let TdotH = dot(anisotropicT, H); let BdotH = dot(anisotropicB, H); let alphaRoughness = max(roughness * roughness, 0.001); let at = mix(alphaRoughness, 1.0, anisotropyStrength * anisotropyStrength); let ab = alphaRoughness; let D = distributionGGXAnisotropic(NdotH, TdotH, BdotH, at, ab); let Vg = visibilityGGXAnisotropic(NdotL, NdotV, BdotV, TdotV, TdotL, BdotL, at, ab); specularBrdf = F * D * Vg; } else { let NDF = distributionGGX(N, H, roughness); let G = geometrySmith(N, V, L, roughness); let numerator = NDF * G * F; let denominator = 4.0 * NdotV * NdotL + 0.0001; specularBrdf = numerator / denominator; } let sheenD = sheenDistribution(NdotH, sheenRoughness); let sheenV = sheenVisibility(NdotL, NdotV, sheenRoughness); let sheenBrdf = sheenColor * sheenD * sheenV; let diffuseEnergy = max(1.0 - maxComponent(F), 0.0); let kD = vec3f(diffuseEnergy) * (1.0 - metallic); let frontDiffuse = (1.0 - diffuseTransmission) * kD * albedo * radiance * NdotL / PI; let backDiffuse = diffuseTransmission * kD * diffuseTransmissionColor * radiance * max(dot(-N, L), 0.0) / PI; let diffuseContribution = (frontDiffuse + backDiffuse) * (1.0 - transmission); let specularContribution = (specularBrdf + sheenBrdf) * radiance * NdotL; let baseContribution = diffuseContribution + specularContribution; let clearcoatNdotL = max(dot(clearcoatNormal, L), 0.0); let clearcoatNdotV = max(dot(clearcoatNormal, V), 0.0); let clearcoatNDF = distributionGGX(clearcoatNormal, H, clearcoatRoughness); let clearcoatG = geometrySmith(clearcoatNormal, V, L, clearcoatRoughness); let clearcoatBrdf = clearcoatNDF * clearcoatG / (4.0 * clearcoatNdotV * clearcoatNdotL + 0.0001); let clearcoatContribution = vec3f(clearcoatBrdf) * radiance * clearcoatNdotL; Lo += mix(baseContribution, clearcoatContribution, clearcoatViewFresnel); } if (transmissionWeight > 1e-5) { let transmittedSource = sampleTransmissionSource(in.position, in.worldPos, N, V, material.extensionParams.x, dispersion, volumeThickness, in.modelScale); Lo += transmittedSource * albedo * volumeAttenuation * transmissionWeight * (1.0 - clearcoatViewFresnel); } Lo += emissive * (1.0 - clearcoatViewFresnel); Lo = Lo / (Lo + vec3f(1.0)); Lo = pow(Lo, vec3f(1.0 / 2.2)); return vec4f(Lo, baseColor.a); }";var Sa="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct MaterialUniforms { scaleSource: vec4f, scaleDomain: vec4f, scaleClamp: vec4f, scaleParams: vec4f, scaleFlags: vec4f, colorParams: vec4f }; @group(1) @binding(0) var<uniform> material: MaterialUniforms; @group(1) @binding(1) var<storage, read> data: array<f32>; @group(1) @binding(2) var colormapSampler: sampler; @group(1) @binding(3) var colormapTex: texture_1d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) dataValue: vec4f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; struct Light { position: vec4f, color: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; fn srgbFromLinear(c: vec3f) -> vec3f { let a = vec3f(0.055); return select(12.92 * c, (1.0 + a) * pow(c, vec3f(1.0 / 2.4)) - a, c > vec3f(0.0031308)); } fn luminance(rgb: vec3f) -> f32 { return dot(rgb, vec3f(0.2126, 0.7152, 0.0722)); } @vertex fn vs_main(in: VertexInput, @builtin(vertex_index) vertexIndex: u32) -> VertexOutput { var out: VertexOutput; let worldPos4 = model.model * vec4f(in.position, 1.0); out.position = camera.viewProjection * worldPos4; out.worldPos = worldPos4.xyz; out.normal = normalize((model.normalMatrix * vec4f(in.normal, 0.0)).xyz); let componentCount = max(1u, min(4u, u32(material.scaleSource.x + 0.5))); let stride = max(1u, u32(material.scaleSource.w + 0.5)); let dataOffset = u32(material.scaleDomain.z + 0.5); let base = vertexIndex * stride + dataOffset; var x: f32 = data[base + 0u]; var y: f32 = 0.0; var z: f32 = 0.0; var w: f32 = 0.0; if (componentCount > 1u) { y = data[base + 1u]; } if (componentCount > 2u) { z = data[base + 2u]; } if (componentCount > 3u) { w = data[base + 3u]; } out.dataValue = vec4f(x, y, z, w); return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let componentCount = max(1u, min(4u, u32(material.scaleSource.x + 0.5))); let componentIndex = min(3u, u32(material.scaleSource.y + 0.5)); let valueMode = u32(material.scaleSource.z + 0.5); let v = scale_select_value(in.dataValue, componentCount, componentIndex, valueMode); if (!scale_is_finite(v)) { discard; } let t = scale_apply_transform(v, vec4f(material.scaleDomain.x, material.scaleDomain.y, 0.0, material.scaleDomain.w), material.scaleClamp, material.scaleParams, material.scaleFlags); var cmap = textureSample(colormapTex, colormapSampler, t); let shading = scale_clamp01(material.colorParams.y); if (shading > 0.0) { let N = normalize(in.normal); var lightFactor: f32 = luminance(lighting.ambient.rgb); for (var i = 0u; i < lighting.lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - in.worldPos; let dist = length(lightDir); L = normalize(lightDir); attenuation = 1.0 / max(1e-6, dist * dist); } let ndotl = max(dot(N, L), 0.0); let lum = luminance(light.color.rgb) * light.color.a; lightFactor += lum * attenuation * ndotl; } let shadedRgb = cmap.rgb * lightFactor; cmap = vec4f(mix(cmap.rgb, shadedRgb, shading), cmap.a); } let opacity = scale_clamp01(material.colorParams.x); let finalA = cmap.a * opacity; let finalRgb = clamp(cmap.rgb, vec3f(0.0), vec3f(1.0)); cmap = vec4f(finalRgb, finalA); return vec4f(srgbFromLinear(cmap.rgb), cmap.a); }";var Ca="struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) uv: vec2f }; struct CameraUniforms { viewProjection: mat4x4f, position: vec3f }; struct ModelUniforms { model: mat4x4f, normalMatrix: mat4x4f }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let worldPos = model.model * vec4f(in.position, 1.0); out.position = camera.viewProjection * worldPos; out.worldPos = worldPos.xyz; out.normal = normalize((model.normalMatrix * vec4f(in.normal, 0.0)).xyz); out.uv = in.uv; return out; }";var lt=20,Tu={linear:0,log:1,symlog:2},Su={none:0,range:1,percentile:2},Cu={component:0,magnitude:1},un=n=>Tu[n],cn=n=>Su[n],mn=n=>Cu[n],Ie=n=>({mode:n.mode,clampMode:n.clampMode,valueMode:n.valueMode,componentCount:n.componentCount,componentIndex:n.componentIndex,stride:n.stride,offset:n.offset,domainMin:n.domainMin,domainMax:n.domainMax,clampMin:n.clampMin,clampMax:n.clampMax,percentileLow:n.percentileLow,percentileHigh:n.percentileHigh,logBase:n.logBase,symlogLinThresh:n.symlogLinThresh,gamma:n.gamma,invert:n.invert}),To=()=>({mode:"linear",clampMode:"none",valueMode:"component",componentCount:1,componentIndex:0,stride:1,offset:0,domainMin:0,domainMax:1,clampMin:0,clampMax:1,percentileLow:2,percentileHigh:98,logBase:10,symlogLinThresh:1,gamma:1,invert:!1}),fe=n=>{let e=To(),t=n.mode??e.mode,r=n.clampMode??e.clampMode,i=n.valueMode??e.valueMode;y(t==="linear"||t==="log"||t==="symlog",`Invalid scale mode: ${String(t)}`),y(r==="none"||r==="range"||r==="percentile",`Invalid scale clamp mode: ${String(r)}`),y(i==="component"||i==="magnitude",`Invalid scale value mode: ${String(i)}`);let o=se(Xr(n.componentCount,e.componentCount),1,4),a=se(Xr(n.componentIndex,e.componentIndex),0,3),s=Math.max(o,Xr(n.stride,e.stride)),l=Math.max(0,Xr(n.offset,e.offset)),u=gt(n.domainMin,e.domainMin),c=gt(n.domainMax,e.domainMax),m=gt(n.clampMin,e.clampMin),d=gt(n.clampMax,e.clampMax),f=se(gt(n.percentileLow,e.percentileLow),0,100),p=se(gt(n.percentileHigh,e.percentileHigh),0,100);y(p>f,`Scale transform requires percentileHigh > percentileLow (got ${f}, ${p})`);let h=Math.max(1.000001,gt(n.logBase,e.logBase)),g=Math.max(1e-20,gt(n.symlogLinThresh,e.symlogLinThresh)),b=Math.max(1e-6,gt(n.gamma,e.gamma)),P=!!n.invert;return{mode:t,clampMode:r,valueMode:i,componentCount:o,componentIndex:a,stride:s,offset:l,domainMin:u,domainMax:c,clampMin:m,clampMax:d,percentileLow:f,percentileHigh:p,logBase:h,symlogLinThresh:g,gamma:b,invert:P}},je=(n,e,t=0)=>{let r=fe(n);e[t+0]=r.componentCount,e[t+1]=r.componentIndex,e[t+2]=mn(r.valueMode),e[t+3]=r.stride,e[t+4]=r.domainMin,e[t+5]=r.domainMax,e[t+6]=r.offset,e[t+7]=cn(r.clampMode),e[t+8]=r.clampMin,e[t+9]=r.clampMax,e[t+10]=r.percentileLow,e[t+11]=r.percentileHigh,e[t+12]=un(r.mode),e[t+13]=r.logBase,e[t+14]=r.symlogLinThresh,e[t+15]=r.gamma,e[t+16]=r.invert?1:0,e[t+17]=0,e[t+18]=0,e[t+19]=0},wa=(n,e)=>{let t=Math.max(1.000001,e);return Math.log(n)/Math.log(t)},ln=(n,e,t,r)=>{if(e==="linear")return n;if(e==="log")return wa(Math.max(n,1e-20),r);let i=Math.max(t,1e-20),o=n>=0?1:-1,a=wa(1+Math.abs(n)/i,r);return o*a},wu=(n,e,t,r)=>{if(e==="linear")return n;if(e==="log")return Math.pow(Math.max(r,1.000001),n);let i=Math.max(t,1e-20),o=n>=0?1:-1,a=Math.pow(Math.max(r,1.000001),Math.abs(n))-1;return o*(a*i)},So=n=>{let e=n.clampMode!=="none"&&n.clampMax>n.clampMin,t=n.domainMin,r=n.domainMax;return r<=t&&e&&(t=n.clampMin,r=n.clampMax),{domainMin:t,domainMax:r,clampMin:n.clampMin,clampMax:n.clampMax,hasClamp:e}},_a=n=>So(fe(n)),Ba=(n,e)=>{let t=fe(e);if(!Number.isFinite(n))return Number.NaN;let r=n,i=So(t);i.hasClamp&&(r=se(r,i.clampMin,i.clampMax));let o=i.domainMin,a=i.domainMax,s=ln(o,t.mode,t.symlogLinThresh,t.logBase),l=ln(a,t.mode,t.symlogLinThresh,t.logBase),u=ln(r,t.mode,t.symlogLinThresh,t.logBase),c=Math.max(1e-20,l-s),m=le((u-s)/c);return m=Math.pow(m,t.gamma),t.invert&&(m=1-m),le(m)},ei=(n,e)=>{let t=fe(e),r=So(t),i=le(n);t.invert&&(i=1-i),i=Math.pow(i,1/Math.max(t.gamma,1e-6));let o=ln(r.domainMin,t.mode,t.symlogLinThresh,t.logBase),a=ln(r.domainMax,t.mode,t.symlogLinThresh,t.logBase),s=o+(a-o)*i,l=wu(s,t.mode,t.symlogLinThresh,t.logBase);return r.hasClamp&&(l=se(l,r.clampMin,r.clampMax)),l};var Co=n=>gr(n)?n:n.buffer,_u=n=>gr(n)?Number(n.size):typeof n.byteLength=="number"?n.byteLength:null,ka=(n,e,t,r,i)=>{if(!Number.isFinite(t)||!Number.isFinite(r)||i<=0)return Number.NaN;if(r<=t)return t;let a=se(e,0,100)/100*Math.max(0,i-1),s=(r-t)/n.length,l=0;for(let u=0;u<n.length;u++){let c=n[u]>>>0,m=l+c;if(a<m){let d=t+u*s;if(c===0)return d;let f=(a-l)/c;return d+se(f,0,1)*s}l=m}return r},Bu=n=>{y(Number.isInteger(n.count)&&n.count>=0,`Scale stats source.count must be an integer >= 0 (got ${n.count})`);let e=typeof n.componentCount=="number"&&Number.isInteger(n.componentCount)?n.componentCount:1,t=se(e,1,4),r=typeof n.componentIndex=="number"&&Number.isInteger(n.componentIndex)?n.componentIndex:0,i=se(r,0,3),o=typeof n.stride=="number"&&Number.isInteger(n.stride)?n.stride:t,a=Math.max(t,o),s=typeof n.offset=="number"&&Number.isInteger(n.offset)?n.offset:0,l=Math.max(0,s),u=typeof n.revision=="number"&&Number.isInteger(n.revision)?n.revision:0,c=Math.max(0,u),m=n.valueMode??"component";y(m==="component"||m==="magnitude",`Invalid scale value mode: ${String(m)}`);let d=_u(n.buffer);if(d!==null){let f=Math.floor(d/4),p=n.count>0?l+(n.count-1)*a+t:0;y(p<=f,`Scale stats source range exceeds source buffer capacity (required ${p} f32, capacity ${f} f32)`)}return{buffer:n.buffer,count:n.count,componentCount:t,componentIndex:i,valueMode:m,stride:a,offset:l,revision:c}},Tr=class{compute;sourceIds=new WeakMap;cache=new Map;sourceCacheKeys=new Map;nextSourceId=1;constructor(e){this.compute=e}createTransform(e){return fe(e)}invalidate(e){let t=e.buffer?e.buffer:e,r=Co(t),i=this.sourceIds.get(r);if(i===void 0)return;let o=this.sourceCacheKeys.get(i);if(o){for(let a of o)this.cache.delete(a);this.sourceCacheKeys.delete(i)}}clearCache(){this.cache.clear(),this.sourceCacheKeys.clear()}requestStats(e){let t=Bu(e.source),r=se(e.percentiles?.low??2,0,100),i=se(e.percentiles?.high??98,0,100);y(i>r,`Scale stats requires percentile.high > percentile.low (got ${r}, ${i})`);let o=e.percentiles?.bins??2048,a=Math.max(2,Math.floor(Number.isFinite(o)?o:2048)),s=this.getSourceId(Co(t.buffer)),l=[s,t.revision,t.count,t.componentCount,t.componentIndex,t.valueMode,t.stride,t.offset,e.percentiles?1:0,r,i,a].join("|"),u=this.cache.get(l);if(u)return u.promise;let c=this.computeStats(t,e.percentiles?{low:r,high:i,bins:a}:null).catch(d=>{this.cache.delete(l);let f=this.sourceCacheKeys.get(s);throw f?.delete(l),f&&f.size===0&&this.sourceCacheKeys.delete(s),d});this.cache.set(l,{promise:c});let m=this.sourceCacheKeys.get(s);return m||(m=new Set,this.sourceCacheKeys.set(s,m)),m.add(l),c}getSourceId(e){let t=this.sourceIds.get(e);if(t!==void 0)return t;let r=this.nextSourceId++;return this.sourceIds.set(e,r),r}async computeStats(e,t){let r=Co(e.buffer),i=this.compute.kernels.extractScaleValuesF32(r,{count:e.count,componentCount:e.componentCount,componentIndex:e.componentIndex,valueMode:e.valueMode,stride:e.stride,offset:e.offset}),o=this.compute.kernels.compactF32(i.values,i.flags,{count:e.count}),a=await this.compute.readback.readScalarU32(o.count);if(a===0)return i.values.destroy(),i.flags.destroy(),o.output.destroy(),o.count.destroy(),{count:e.count,finiteCount:0,min:Number.NaN,max:Number.NaN,percentileMin:null,percentileMax:null,histogramBins:null};let s=this.compute.kernels.minF32(o.output,{count:a}),l=this.compute.kernels.maxF32(o.output,{count:a}),u=await this.compute.readback.readScalarF32(s),c=await this.compute.readback.readScalarF32(l),m=null,d=null,f=null;if(t){let p=this.compute.kernels.histogramF32(o.output,t.bins,{count:a,minValue:u,maxValue:c,clear:!0}),h=await this.compute.readback.readAs(Uint32Array,p);m=ka(h,t.low,u,c,a),d=ka(h,t.high,u,c,a),f=t.bins,p.destroy()}return i.values.destroy(),i.flags.destroy(),o.output.destroy(),o.count.destroy(),s.destroy(),l.destroy(),{count:e.count,finiteCount:a,min:u,max:c,percentileMin:m,percentileMax:d,histogramBins:f}}};var me=n=>{let e=n?.texCoord===1?1:0;return{offset:[n?.offset?.[0]??0,n?.offset?.[1]??0],rotation:n?.rotation??0,scale:[n?.scale?.[0]??1,n?.scale?.[1]??1],texCoord:e}},Sr=n=>({offset:[n.offset[0],n.offset[1]],rotation:n.rotation,scale:[n.scale[0],n.scale[1]],texCoord:n.texCoord}),Ne=me(null),Pe=(n,e,t)=>{let r=Math.cos(t.rotation),i=Math.sin(t.rotation);n[e+0]=t.offset[0],n[e+1]=t.offset[1],n[e+2]=r,n[e+3]=i,n[e+4]=t.scale[0],n[e+5]=t.scale[1],n[e+6]=t.texCoord,n[e+7]=0},rr=(r=>(r.Opaque="opaque",r.Transparent="transparent",r.Additive="additive",r))(rr||{}),Cr=(r=>(r.None="none",r.Back="back",r.Front="front",r))(Cr||{}),er=class{blendMode;cullMode;depthWrite;depthTest;pipeline=null;bindGroup=null;bindGroupKey=null;uniformBuffer=null;_uniformDataCache=null;_dirty=!0;_refCount=1;_destroyed=!1;constructor(e={}){this.blendMode=e.blendMode??"opaque",this.cullMode=e.cullMode??"back",this.depthWrite=e.depthWrite??!0,this.depthTest=e.depthTest??!0}get dirty(){return this._dirty}assertAlive(e){if(this._destroyed)throw new Error(`Material: cannot ${e}; resource has already been released.`)}retain(){return this.assertAlive("retain"),this._refCount++,this}release(){if(this._destroyed)throw new Error("Material: release() called after the resource was already released.");if(this._refCount<=0)throw new Error("Material: reference count underflow.");this._refCount--,!(this._refCount>0)&&(this._destroyed=!0,this.disposeResources())}markClean(){this.assertAlive("markClean"),this._dirty=!1}getUniformDataCache(e){return this.assertAlive("build uniform data"),(!this._uniformDataCache||this._uniformDataCache.length!==e)&&(this._uniformDataCache=new Float32Array(e)),this._uniformDataCache}destroy(){this.release()}disposeResources(){this.uniformBuffer?.destroy(),this.uniformBuffer=null,this.bindGroup=null,this.bindGroupKey=null,this.pipeline=null,this._uniformDataCache=null,this._dirty=!0}},ke=class n extends er{_color;_opacity;_baseColorTexture;_baseColorTextureTransform;_alphaCutoff;static _cachedBindGroupLayout=null;static _cachedLayoutDevice=null;constructor(e={}){super({...e,blendMode:e.blendMode??((e.opacity??1)<1?"transparent":"opaque")}),this._color=e.color??[1,1,1],this._opacity=e.opacity??1,this._baseColorTexture=e.baseColorTexture??null,this._baseColorTextureTransform=me(e.baseColorTextureTransform),this._alphaCutoff=e.alphaCutoff??0}get color(){return this._color}set color(e){this._color=e,this._dirty=!0}get opacity(){return this._opacity}set opacity(e){this._opacity=e,this._dirty=!0}get baseColorTexture(){return this._baseColorTexture}set baseColorTexture(e){this._baseColorTexture=e,this._dirty=!0}get baseColorTextureTransform(){return Sr(this._baseColorTextureTransform)}set baseColorTextureTransform(e){this._baseColorTextureTransform=me(e),this._dirty=!0}get alphaCutoff(){return this._alphaCutoff}set alphaCutoff(e){this._alphaCutoff=e,this._dirty=!0}getUniformBufferSize(){return 64}getUniformData(){let e=this.getUniformDataCache(16);return e[0]=this._color[0],e[1]=this._color[1],e[2]=this._color[2],e[3]=this._opacity,e[4]=this._alphaCutoff,e[5]=0,e[6]=0,e[7]=0,Pe(e,8,this._baseColorTextureTransform),e}createBindGroupLayout(e){if(n._cachedBindGroupLayout&&n._cachedLayoutDevice===e)return n._cachedBindGroupLayout;let t=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]});return n._cachedBindGroupLayout=t,n._cachedLayoutDevice=e,t}getShaderCode(e={}){return e.instanced?da:e.skinned8?pa:e.skinned?fa:ma}};var ti=(n,e)=>[n?.[0]??e[0],n?.[1]??e[1],n?.[2]??e[2]],wo=n=>({clearcoat:n?.clearcoat?{factor:n.clearcoat.factor??0,texture:n.clearcoat.texture??null,textureTransform:me(n.clearcoat.textureTransform),roughness:n.clearcoat.roughness??0,roughnessTexture:n.clearcoat.roughnessTexture??null,roughnessTextureTransform:me(n.clearcoat.roughnessTextureTransform),normalTexture:n.clearcoat.normalTexture??null,normalTextureTransform:me(n.clearcoat.normalTextureTransform),normalScale:n.clearcoat.normalScale??1}:null,transmission:n?.transmission?{factor:n.transmission.factor??0,texture:n.transmission.texture??null,textureTransform:me(n.transmission.textureTransform)}:null,volume:n?.volume?{thicknessFactor:n.volume.thicknessFactor??0,thicknessTexture:n.volume.thicknessTexture??null,thicknessTextureTransform:me(n.volume.thicknessTextureTransform),attenuationDistance:n.volume.attenuationDistance??1/0,attenuationColor:ti(n.volume.attenuationColor,[1,1,1])}:null,specular:n?.specular?{factor:n.specular.factor??1,texture:n.specular.texture??null,textureTransform:me(n.specular.textureTransform),color:ti(n.specular.color,[1,1,1]),colorTexture:n.specular.colorTexture??null,colorTextureTransform:me(n.specular.colorTextureTransform)}:null,sheen:n?.sheen?{color:ti(n.sheen.color,[0,0,0]),colorTexture:n.sheen.colorTexture??null,colorTextureTransform:me(n.sheen.colorTextureTransform),roughness:n.sheen.roughness??0,roughnessTexture:n.sheen.roughnessTexture??null,roughnessTextureTransform:me(n.sheen.roughnessTextureTransform)}:null,iridescence:n?.iridescence?{factor:n.iridescence.factor??0,texture:n.iridescence.texture??null,textureTransform:me(n.iridescence.textureTransform),ior:n.iridescence.ior??1.3,thicknessMinimum:n.iridescence.thicknessMinimum??100,thicknessMaximum:n.iridescence.thicknessMaximum??400,thicknessTexture:n.iridescence.thicknessTexture??null,thicknessTextureTransform:me(n.iridescence.thicknessTextureTransform)}:null,anisotropy:n?.anisotropy?{strength:n.anisotropy.strength??0,rotation:n.anisotropy.rotation??0,texture:n.anisotropy.texture??null,textureTransform:me(n.anisotropy.textureTransform)}:null,diffuseTransmission:n?.diffuseTransmission?{factor:n.diffuseTransmission.factor??0,texture:n.diffuseTransmission.texture??null,textureTransform:me(n.diffuseTransmission.textureTransform),color:ti(n.diffuseTransmission.color,[1,1,1]),colorTexture:n.diffuseTransmission.colorTexture??null,colorTextureTransform:me(n.diffuseTransmission.colorTextureTransform)}:null,dispersion:n?.dispersion?{dispersion:n.dispersion.dispersion??0}:null,ior:n?.ior?{ior:n.ior.ior??1.5}:null,emissiveStrength:n?.emissiveStrength?{strength:n.emissiveStrength.strength??1}:null}),ku=n=>wo(n),J=class n extends er{_color;_opacity;_metallic;_roughness;_emissive;_emissiveIntensity;_baseColorTexture;_metallicRoughnessTexture;_normalTexture;_occlusionTexture;_emissiveTexture;_baseColorTextureTransform;_metallicRoughnessTextureTransform;_normalTextureTransform;_occlusionTextureTransform;_emissiveTextureTransform;_normalScale;_occlusionStrength;_alphaCutoff;_extensions;static _cachedBindGroupLayout=null;static _cachedLayoutDevice=null;static UNIFORM_FLOAT_COUNT=204;static TEXTURE_BINDING_COUNT=15;constructor(e={}){super({...e,blendMode:e.blendMode??((e.opacity??1)<1?"transparent":"opaque")}),this._color=e.color??[1,1,1],this._opacity=e.opacity??1,this._metallic=e.metallic??0,this._roughness=e.roughness??1,this._emissive=e.emissive??[0,0,0],this._emissiveIntensity=e.emissiveIntensity??0,this._baseColorTexture=e.baseColorTexture??null,this._metallicRoughnessTexture=e.metallicRoughnessTexture??null,this._normalTexture=e.normalTexture??null,this._occlusionTexture=e.occlusionTexture??null,this._emissiveTexture=e.emissiveTexture??null,this._baseColorTextureTransform=me(e.baseColorTextureTransform),this._metallicRoughnessTextureTransform=me(e.metallicRoughnessTextureTransform),this._normalTextureTransform=me(e.normalTextureTransform),this._occlusionTextureTransform=me(e.occlusionTextureTransform),this._emissiveTextureTransform=me(e.emissiveTextureTransform),this._normalScale=e.normalScale??1,this._occlusionStrength=e.occlusionStrength??1,this._alphaCutoff=e.alphaCutoff??0,this._extensions=wo(e.extensions)}invalidateBindings(){this.bindGroupKey=null,this._dirty=!0}get color(){return this._color}set color(e){this._color=e,this._dirty=!0}get opacity(){return this._opacity}set opacity(e){this._opacity=e,this._dirty=!0}get metallic(){return this._metallic}set metallic(e){this._metallic=Math.max(0,Math.min(1,e)),this._dirty=!0}get roughness(){return this._roughness}set roughness(e){this._roughness=Math.max(0,Math.min(1,e)),this._dirty=!0}get emissive(){return this._emissive}set emissive(e){this._emissive=e,this._dirty=!0}get emissiveIntensity(){return this._emissiveIntensity}set emissiveIntensity(e){this._emissiveIntensity=e,this._dirty=!0}get baseColorTexture(){return this._baseColorTexture}set baseColorTexture(e){this._baseColorTexture=e,this.invalidateBindings()}get metallicRoughnessTexture(){return this._metallicRoughnessTexture}set metallicRoughnessTexture(e){this._metallicRoughnessTexture=e,this.invalidateBindings()}get normalTexture(){return this._normalTexture}set normalTexture(e){this._normalTexture=e,this.invalidateBindings()}get occlusionTexture(){return this._occlusionTexture}set occlusionTexture(e){this._occlusionTexture=e,this.invalidateBindings()}get emissiveTexture(){return this._emissiveTexture}set emissiveTexture(e){this._emissiveTexture=e,this.invalidateBindings()}get baseColorTextureTransform(){return Sr(this._baseColorTextureTransform)}set baseColorTextureTransform(e){this._baseColorTextureTransform=me(e),this._dirty=!0}get metallicRoughnessTextureTransform(){return Sr(this._metallicRoughnessTextureTransform)}set metallicRoughnessTextureTransform(e){this._metallicRoughnessTextureTransform=me(e),this._dirty=!0}get normalTextureTransform(){return Sr(this._normalTextureTransform)}set normalTextureTransform(e){this._normalTextureTransform=me(e),this._dirty=!0}get occlusionTextureTransform(){return Sr(this._occlusionTextureTransform)}set occlusionTextureTransform(e){this._occlusionTextureTransform=me(e),this._dirty=!0}get emissiveTextureTransform(){return Sr(this._emissiveTextureTransform)}set emissiveTextureTransform(e){this._emissiveTextureTransform=me(e),this._dirty=!0}get normalScale(){return this._normalScale}set normalScale(e){this._normalScale=e,this._dirty=!0}get occlusionStrength(){return this._occlusionStrength}set occlusionStrength(e){this._occlusionStrength=e,this._dirty=!0}get alphaCutoff(){return this._alphaCutoff}set alphaCutoff(e){this._alphaCutoff=e,this._dirty=!0}get extensions(){return ku(this._extensions)}setExtensions(e){return this._extensions=wo(e),this.invalidateBindings(),this}getFeatureMask(){let e=0;this._baseColorTexture&&(e|=1),this._metallicRoughnessTexture&&(e|=2),this._normalTexture&&(e|=4),this._occlusionTexture&&(e|=8),this._emissiveTexture&&(e|=16);let t=this._extensions.clearcoat;t&&(e|=32,t.texture&&(e|=64),t.roughnessTexture&&(e|=128),t.normalTexture&&(e|=256));let r=this._extensions.transmission;r&&(e|=512,r.texture&&(e|=1024));let i=this._extensions.volume;i&&(e|=2048,i.thicknessTexture&&(e|=4096));let o=this._extensions.specular;o&&(e|=8192,o.texture&&(e|=16384),o.colorTexture&&(e|=32768));let a=this._extensions.sheen;a&&(e|=65536,a.colorTexture&&(e|=131072),a.roughnessTexture&&(e|=262144));let s=this._extensions.iridescence;s&&(e|=524288,s.texture&&(e|=1048576),s.thicknessTexture&&(e|=2097152));let l=this._extensions.anisotropy;l&&(e|=4194304,l.texture&&(e|=8388608));let u=this._extensions.diffuseTransmission;return u&&(e|=67108864,u.texture&&(e|=134217728),u.colorTexture&&(e|=268435456)),this._extensions.dispersion&&(e|=536870912),this._extensions.ior&&(e|=16777216),this._extensions.emissiveStrength&&(e|=33554432),e>>>0}getUniformBufferSize(){return n.UNIFORM_FLOAT_COUNT*4}getUniformData(){let e=this.getUniformDataCache(n.UNIFORM_FLOAT_COUNT);e[0]=this._color[0],e[1]=this._color[1],e[2]=this._color[2],e[3]=this._opacity,e[4]=this._emissive[0],e[5]=this._emissive[1],e[6]=this._emissive[2],e[7]=this._emissiveIntensity,e[8]=this._metallic,e[9]=this._roughness,e[10]=this._normalTexture?this._normalScale:0,e[11]=this._occlusionStrength,e[12]=this._alphaCutoff,e[13]=0,e[14]=0,e[15]=0,Pe(e,16,this._baseColorTextureTransform),Pe(e,24,this._metallicRoughnessTextureTransform),Pe(e,32,this._normalTextureTransform),Pe(e,40,this._occlusionTextureTransform),Pe(e,48,this._emissiveTextureTransform);let t=this._extensions.clearcoat,r=this._extensions.specular,i=this._extensions.sheen,o=this._extensions.iridescence,a=this._extensions.anisotropy,s=this._extensions.transmission,l=this._extensions.volume,u=this._extensions.diffuseTransmission,c=this._extensions.dispersion,m=this._extensions.ior,d=this._extensions.emissiveStrength;return e[56]=t?.factor??0,e[57]=t?.roughness??0,e[58]=t?.normalTexture?t.normalScale??1:0,e[59]=0,e[60]=r?.factor??1,e[61]=r?.color[0]??1,e[62]=r?.color[1]??1,e[63]=r?.color[2]??1,e[64]=m?.ior??1.5,e[65]=d?.strength??1,e[66]=0,e[67]=0,Pe(e,68,t?.textureTransform??Ne),Pe(e,76,t?.roughnessTextureTransform??Ne),Pe(e,84,t?.normalTextureTransform??Ne),Pe(e,92,r?.textureTransform??Ne),Pe(e,100,r?.colorTextureTransform??Ne),e[108]=i?.color[0]??0,e[109]=i?.color[1]??0,e[110]=i?.color[2]??0,e[111]=i?.roughness??0,e[112]=o?.factor??0,e[113]=o?.ior??1.3,e[114]=o?.thicknessMinimum??100,e[115]=o?.thicknessMaximum??400,e[116]=a?.strength??0,e[117]=Math.cos(a?.rotation??0),e[118]=Math.sin(a?.rotation??0),e[119]=0,Pe(e,120,i?.colorTextureTransform??Ne),Pe(e,128,i?.roughnessTextureTransform??Ne),Pe(e,136,o?.textureTransform??Ne),Pe(e,144,o?.thicknessTextureTransform??Ne),Pe(e,152,a?.textureTransform??Ne),e[160]=s?.factor??0,e[161]=u?.factor??0,e[162]=l?.thicknessFactor??0,e[163]=c?.dispersion??0,e[164]=u?.color[0]??1,e[165]=u?.color[1]??1,e[166]=u?.color[2]??1,e[167]=Number.isFinite(l?.attenuationDistance??1/0)?l?.attenuationDistance??0:0,e[168]=l?.attenuationColor[0]??1,e[169]=l?.attenuationColor[1]??1,e[170]=l?.attenuationColor[2]??1,e[171]=0,Pe(e,172,s?.textureTransform??Ne),Pe(e,180,l?.thicknessTextureTransform??Ne),Pe(e,188,u?.textureTransform??Ne),Pe(e,196,u?.colorTextureTransform??Ne),e}createBindGroupLayout(e){if(n._cachedBindGroupLayout&&n._cachedLayoutDevice===e)return n._cachedBindGroupLayout;let t=[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}];for(let i=0;i<n.TEXTURE_BINDING_COUNT;i++){let o=1+i*2;t.push({binding:o,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}}),t.push({binding:o+1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}})}let r=e.createBindGroupLayout({entries:t});return n._cachedBindGroupLayout=r,n._cachedLayoutDevice=e,r}usesTransmissionLayout(){let e=this._extensions.transmission?.factor??0,t=this._extensions.diffuseTransmission?.factor??0;return e>0||t>0}getShaderCode(e={}){return e.transmission?e.instanced?xa:e.skinned8?Ta:e.skinned?Pa:ya:e.instanced?ga:e.skinned8?va:e.skinned?ba:ha}},He=class n extends er{_CPUData=null;_keepCPUData=!1;_dataDirty=!1;_ownsDataBuffer=!1;dataBuffer=null;_elementCount=0;_scaleTransform;_opacity=1;_shading=0;_colormap="viridis";_scaleRevision=0;_visualChangeListeners=new Set;static _cachedBindGroupLayout=null;static _cachedLayoutDevice=null;constructor(e){y(!!e&&!!e.scaleTransform,"DataMaterial: scaleTransform is required."),super({...e,blendMode:e.blendMode??((e.opacity??1)<1?"transparent":"opaque")}),this._scaleTransform=fe(e.scaleTransform),e.keepCPUData!==void 0&&(this._keepCPUData=!!e.keepCPUData),e.opacity!==void 0&&(this._opacity=e.opacity),e.shading!==void 0&&(this._shading=e.shading),e.colormap!==void 0&&(this._colormap=e.colormap),e.data&&this.setData(e.data,{keepCPUData:this._keepCPUData}),e.dataBuffer!==void 0&&e.dataBuffer!==null&&this.setDataBuffer(re(e.dataBuffer))}get scaleTransform(){return Ie(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=fe(e),this._elementCount=this.recomputeElementCount(),this._dirty=!0,this.emitVisualChange("scale")}get opacity(){return this._opacity}set opacity(e){e!==this._opacity&&(this._opacity=e,this._dirty=!0)}get shading(){return this._shading}set shading(e){e!==this._shading&&(this._shading=e,this._dirty=!0)}get colormap(){return this._colormap}set colormap(e){this._colormap=e,this.bindGroupKey=null,this.emitVisualChange("colormap")}onVisualChange(e){return this._visualChangeListeners.add(e),()=>{this._visualChangeListeners.delete(e)}}getColormapKey(){let e=this._colormap;return e instanceof $?`cm:${e.id}`:`cm:${e}`}getColormapForBinding(){let e=this._colormap;return e instanceof $?e:$.builtin(e)}computeElementCountFromFloatLength(e){let t=Math.max(1,Math.floor(this._scaleTransform.stride)),r=Math.max(0,Math.floor(this._scaleTransform.offset));return e<=r?0:Math.max(0,Math.floor((e-r)/t))}recomputeElementCount(){return this._CPUData?this.computeElementCountFromFloatLength(this._CPUData.length):this.dataBuffer?this.computeElementCountFromFloatLength(Math.floor(this.dataBuffer.size/4)):0}setData(e,t={}){y(e.length>0,"DataMaterial: data must be non-empty."),this._CPUData=e,this._dataDirty=!0,this._keepCPUData=t.keepCPUData??this._keepCPUData,this._elementCount=this.computeElementCountFromFloatLength(e.length),this._scaleRevision++,this._dirty=!0,this.bindGroupKey=null}setDataBuffer(e){this._CPUData=null,this.dataBuffer=e,this._ownsDataBuffer=!1,this._dataDirty=!1,this._elementCount=this.computeElementCountFromFloatLength(Math.floor(e.size/4)),this._scaleRevision++,this._dirty=!0,this.bindGroupKey=null}dropCPUData(){this._CPUData=null}getScaleSourceDescriptor(e=this._scaleRevision){return!this.dataBuffer||this._elementCount<=0?null:{buffer:this.dataBuffer,count:this._elementCount,componentCount:this._scaleTransform.componentCount,componentIndex:this._scaleTransform.componentIndex,valueMode:this._scaleTransform.valueMode,stride:this._scaleTransform.stride,offset:this._scaleTransform.offset,revision:e}}upload(e,t){if(this.assertAlive("upload"),!this._dataDirty)return;if(this.dataBuffer&&!this._CPUData){this._dataDirty=!1;return}let r=this._CPUData;if(!r){this._dataDirty=!1;return}let i=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST;if(!this.dataBuffer||!this._ownsDataBuffer)this.dataBuffer=ne(e,r,i),this._ownsDataBuffer=!0;else try{t.writeBuffer(this.dataBuffer,0,r.buffer,r.byteOffset,r.byteLength)}catch{this.dataBuffer.destroy(),this.dataBuffer=ne(e,r,i)}this._elementCount=this.computeElementCountFromFloatLength(r.length),this._keepCPUData||(this._CPUData=null),this._dataDirty=!1,this.bindGroupKey=null}getUniformBufferSize(){return(lt+4)*4}getUniformData(){let e=this.getUniformDataCache(lt+4);return e.fill(0),je(this._scaleTransform,e,0),e[lt+0]=le(this._opacity),e[lt+1]=le(this._shading),e[lt+2]=0,e[lt+3]=0,e}createBindGroupLayout(e){if(n._cachedBindGroupLayout&&n._cachedLayoutDevice===e)return n._cachedBindGroupLayout;let t=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:3,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float",viewDimension:"1d"}}]});return n._cachedBindGroupLayout=t,n._cachedLayoutDevice=e,t}getShaderCode(e={}){return Sa}emitVisualChange(e){for(let t of this._visualChangeListeners)try{t(e)}catch{}}disposeResources(){super.disposeResources(),this._ownsDataBuffer&&this.dataBuffer?.destroy(),this.dataBuffer=null,this._CPUData=null,this._dataDirty=!1,this._elementCount=0,this._visualChangeListeners.clear()}},tr=class extends er{_vertexShader;_fragmentShader;_uniforms;_uniformLayout=null;_cachedBindGroupLayout=null;_cachedLayoutDevice=null;constructor(e){super(e),this._vertexShader=e.vertexShader??this.defaultVertexShader(),this._fragmentShader=e.fragmentShader,this._uniforms=e.uniforms??{}}setUniform(e,t){this._uniforms[e]&&(this._uniforms[e].value=t,this._dirty=!0)}getUniform(e){return this._uniforms[e]?.value}getUniformSize(e){switch(e){case"f32":return 4;case"vec2f":return 8;case"vec3f":return 12;case"vec4f":return 16;case"mat4x4f":return 64}}getUniformAlignment(e){switch(e){case"f32":return 4;case"vec2f":return 8;case"vec3f":return 16;case"vec4f":return 16;case"mat4x4f":return 16}}getUniformLayout(){if(this._uniformLayout)return this._uniformLayout;let e=0,t={};for(let[i,o]of Object.entries(this._uniforms)){let a=this.getUniformAlignment(o.type),s=this.getUniformSize(o.type);e=this.alignTo(e,a),t[i]=e,e+=s}let r=Math.ceil(e/16)*16||16;return this._uniformLayout={size:r,offsets:t},this._uniformLayout}alignTo(e,t){return e+t-1&~(t-1)}getUniformBufferSize(){return this.getUniformLayout().size}getUniformData(){let e=this.getUniformLayout(),t=this.getUniformDataCache(e.size/4);t.fill(0);for(let[r,i]of Object.entries(this._uniforms)){let o=e.offsets[r]>>>2;typeof i.value=="number"?t[o]=i.value:t.set(i.value,o)}return t}createBindGroupLayout(e){if(this._cachedBindGroupLayout&&this._cachedLayoutDevice===e)return this._cachedBindGroupLayout;let t=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]});return this._cachedBindGroupLayout=t,this._cachedLayoutDevice=e,t}defaultVertexShader(){return Ca}getShaderCode(e={}){let t=`struct CustomUniforms {
|
|
14
|
+
`,r=Object.entries(this._uniforms);if(r.length===0)t+=` _pad: f32
|
|
15
|
+
`;else for(let[i,o]of r)t+=` ${i}: ${o.type},
|
|
6
16
|
`;return t+=`};
|
|
7
17
|
|
|
8
18
|
@group(1) @binding(0) var<uniform> custom: CustomUniforms;
|
|
9
19
|
|
|
10
20
|
`,this._vertexShader+`
|
|
11
|
-
`+t+this._fragmentShader}};var to=4+Te+4+32,rs=to*4,Ji=n=>n<0?0:n>1?1:n,ns=n=>{if(!n)return null;let e=[];for(let t=0;t<n.length;t++){let r=n[t];P(Number.isInteger(r)&&r>0,`PointCloud: ndShape[${t}] must be an integer > 0.`),e.push(r|0)}return e.length>0?e:null},is=(n,e)=>{if(!n||n.length===0||!Number.isInteger(e)||e<0)return null;let t=e|0,r=new Array(n.length);for(let i=n.length-1;i>=0;i--){let o=n[i];r[i]=t%o,t=Math.floor(t/o)}return t===0?r:null},eo=n=>{if(!n||n.length===0)return[[0,0,0,1],[1,1,1,1]];let e=[],t=Math.min(8,n.length);for(let r=0;r<t;r++){let i=n[r];e.push([i[0],i[1],i[2],i[3]])}return e},ei=n=>ie({componentCount:4,componentIndex:3,stride:4,...n}),Ue=class{transform=new pe;name=null;visible=!0;boundsMin=[0,0,0];boundsMax=[0,0,0];boundsCenter=[0,0,0];boundsRadius=0;blendMode="additive";depthWrite=!1;depthTest=!0;_basePointSize=2;_minPointSize=1;_maxPointSize=16;_sizeAttenuation=1;_opacity=1;_colormap="viridis";_colormapStops=[[.267,.00487,.32942,1],[.99325,.90616,.14394,1]];_softness=.15;_scaleTransform;_CPUData=null;_keepCPUData=!1;_ndShape=null;_boundsSource="none";_scaleRevision=0;_visualChangeListeners=new Set;pointsBuffer=null;uniformBuffer=null;bindGroup=null;bindGroupKey=null;_pointCount=0;_uniformDirty=!0;_pointsDirty=!0;constructor(e){if(P(!!e&&!!e.scaleTransform,"PointCloud: scaleTransform is required."),this._scaleTransform=ei(e.scaleTransform),e.name!==void 0&&(this.name=e.name),e.visible!==void 0&&(this.visible=!!e.visible),e.blendMode!==void 0&&(this.blendMode=e.blendMode),e.depthWrite!==void 0&&(this.depthWrite=!!e.depthWrite),e.depthTest!==void 0&&(this.depthTest=!!e.depthTest),e.basePointSize!==void 0&&(this._basePointSize=e.basePointSize),e.minPointSize!==void 0&&(this._minPointSize=e.minPointSize),e.maxPointSize!==void 0&&(this._maxPointSize=e.maxPointSize),e.sizeAttenuation!==void 0&&(this._sizeAttenuation=e.sizeAttenuation),e.opacity!==void 0&&(this._opacity=e.opacity),e.colormap!==void 0&&(this._colormap=e.colormap),e.colormapStops!==void 0&&(this._colormapStops=eo(e.colormapStops)),e.softness!==void 0&&(this._softness=e.softness),e.keepCPUData!==void 0&&(this._keepCPUData=!!e.keepCPUData),e.ndShape!==void 0&&(this.ndShape=e.ndShape),this.applyExplicitBounds(e),e.data)this.setData(e.data,{keepCPUData:this._keepCPUData});else if(e.pointsBuffer){let t=e.pointsBuffer.buffer?e.pointsBuffer.buffer:e.pointsBuffer,r=e.pointCount??0;P(r>0,"PointCloud: pointCount is required when using pointsBuffer."),this.setPointsBuffer(t,r)}else e.pointCount!==void 0&&(this._pointCount=e.pointCount,this._pointsDirty=!1)}applyExplicitBounds(e){if(e.boundsMin&&e.boundsMax){let t=qe(e.boundsMin,e.boundsMax);this.setBounds(t,"explicit"),e.boundsCenter&&(this.boundsCenter=[e.boundsCenter[0],e.boundsCenter[1],e.boundsCenter[2]]),e.boundsRadius!==void 0&&(this.boundsRadius=Math.max(0,e.boundsRadius));return}if(e.boundsCenter||e.boundsRadius!==void 0){let t=e.boundsCenter??[0,0,0],r=e.boundsRadius??0;this.setBounds(ct(t,r),"explicit")}}setBounds(e,t){this.boundsMin=[e.boxMin[0],e.boxMin[1],e.boxMin[2]],this.boundsMax=[e.boxMax[0],e.boxMax[1],e.boxMax[2]],this.boundsCenter=[e.sphereCenter[0],e.sphereCenter[1],e.sphereCenter[2]],this.boundsRadius=e.sphereRadius,this._boundsSource=t}clearComputedBoundsIfNeeded(){this._boundsSource==="computed"&&(this._boundsSource="none",this.boundsMin=[0,0,0],this.boundsMax=[0,0,0],this.boundsCenter=[0,0,0],this.boundsRadius=0)}get pointCount(){return this._pointCount}get ndShape(){return this._ndShape?this._ndShape.slice():null}set ndShape(e){this._ndShape=ns(e)}get scaleTransform(){return We(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=ei(e),this._uniformDirty=!0,this.emitVisualChange("scale")}applyScaleStats(e){let t=We(this._scaleTransform);Number.isFinite(e.min)&&(t.domainMin=e.min),Number.isFinite(e.max)&&(t.domainMax=e.max),e.percentileMin!==null&&e.percentileMax!==null&&(t.clampMin=e.percentileMin,t.clampMax=e.percentileMax),this._scaleTransform=ei(t),this._uniformDirty=!0,this.emitVisualChange("scale")}onVisualChange(e){return this._visualChangeListeners.add(e),()=>this._visualChangeListeners.delete(e)}getScaleSourceDescriptor(e=this._scaleRevision){return!this.pointsBuffer||this._pointCount<=0?null:{buffer:this.pointsBuffer,count:this._pointCount,componentCount:this._scaleTransform.componentCount,componentIndex:this._scaleTransform.componentIndex,valueMode:this._scaleTransform.valueMode,stride:this._scaleTransform.stride,offset:this._scaleTransform.offset,revision:e}}get basePointSize(){return this._basePointSize}set basePointSize(e){e!==this._basePointSize&&(this._basePointSize=e,this._uniformDirty=!0)}get minPointSize(){return this._minPointSize}set minPointSize(e){e!==this._minPointSize&&(this._minPointSize=e,this._uniformDirty=!0)}get maxPointSize(){return this._maxPointSize}set maxPointSize(e){e!==this._maxPointSize&&(this._maxPointSize=e,this._uniformDirty=!0)}get sizeAttenuation(){return this._sizeAttenuation}set sizeAttenuation(e){e!==this._sizeAttenuation&&(this._sizeAttenuation=e,this._uniformDirty=!0)}get opacity(){return this._opacity}set opacity(e){e!==this._opacity&&(this._opacity=e,this._uniformDirty=!0)}get colormap(){return this._colormap}set colormap(e){this._colormap=e,this._uniformDirty=!0,this.bindGroupKey=null,this.emitVisualChange("colormap")}get colormapStops(){return this._colormapStops}set colormapStops(e){this._colormapStops=eo(e),this._uniformDirty=!0,this.emitVisualChange("colormap")}getColormapKey(){let e=this._colormap;return e instanceof H?`cm:${e.id}`:`cm:${e}`}getColormapForBinding(){let e=this._colormap;return e instanceof H?e:e==="custom"?H.builtin("grayscale"):H.builtin(e)}get softness(){return this._softness}set softness(e){e!==this._softness&&(this._softness=e,this._uniformDirty=!0)}setData(e,t={}){P(e.length%4===0,"PointCloud: data length must be a multiple of 4 (x,y,z,scalar per point)."),this._CPUData=e,this._pointCount=e.length/4,this._pointsDirty=!0,this._keepCPUData=t.keepCPUData??this._keepCPUData,this._scaleRevision++,this.clearComputedBoundsIfNeeded()}setPointsBuffer(e,t){P(t>0,"PointCloud: pointCount must be > 0."),this._CPUData=null,this._pointCount=t,this.pointsBuffer=e,this._pointsDirty=!1,this._scaleRevision++,this.bindGroupKey=null,this.clearComputedBoundsIfNeeded()}dropCPUData(){this._CPUData=null}getPointRecord(e){let t=this._CPUData;if(!t||!Number.isInteger(e)||e<0||e>=this._pointCount)return null;let r=e*4;return{position:[t[r+0],t[r+1],t[r+2]],scalar:t[r+3],packed:[t[r+0],t[r+1],t[r+2],t[r+3]]}}mapLinearIndexToNd(e){return is(this._ndShape,e)}computeBoundsFromCPUData(){let e=this._CPUData;if(!e||e.length<4)return;let t=this._pointCount|0;if(t<=0)return;let r=_.allocF32(e.length),i=_.allocF32(3),o=_.allocF32(3),a=_.allocF32(3),s=_.allocF32(1);try{_.f32view(r,e.length).set(e),Tt.pointcloudXYZS(i,o,a,s,r,t,4);let l=_.f32view(i,3),u=_.f32view(o,3),m=_.f32view(a,3),c=_.f32view(s,1)[0];this.setBounds(mt([l[0],l[1],l[2]],[u[0],u[1],u[2]],[m[0],m[1],m[2]],c),"computed")}finally{_.freeF32(s,1),_.freeF32(a,3),_.freeF32(o,3),_.freeF32(i,3),_.freeF32(r,e.length)}}getLocalBounds(){return this._boundsSource==="none"&&this._CPUData&&this.computeBoundsFromCPUData(),this._boundsSource==="none"?ut(this._pointCount>0):mt(this.boundsMin,this.boundsMax,this.boundsCenter,this.boundsRadius)}getWorldBounds(){return dt(this.getLocalBounds(),this.transform.worldMatrix)}getBounds(){return this.getWorldBounds()}upload(e,t){if(!this._pointsDirty)return;if(this.pointsBuffer&&!this._CPUData){this._pointsDirty=!1;return}let r=this._CPUData;if(!r){this._pointsDirty=!1;return}let i=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST;if(!this.pointsBuffer)this.pointsBuffer=ve(e,r,i);else try{t.writeBuffer(this.pointsBuffer,0,r.buffer,r.byteOffset,r.byteLength)}catch{this.pointsBuffer.destroy(),this.pointsBuffer=ve(e,r,i)}this._keepCPUData||(this._CPUData=null),this._pointsDirty=!1,this.bindGroupKey=null}getUniformBufferSize(){return rs}getUniformData(){let e=new Float32Array(to),t=Math.max(0,this._basePointSize),r=Math.max(0,this._minPointSize),i=Math.max(r,this._maxPointSize),o=Math.max(0,this._sizeAttenuation);e[0]=t,e[1]=r,e[2]=i,e[3]=o,Ne(this._scaleTransform,e,4),e[24]=Ji(this._opacity),e[25]=Ji(this._softness),e[26]=typeof this._colormap=="string"&&this._colormap==="custom"?Math.min(8,Math.max(2,this._colormapStops.length)):0,e[27]=0;let a=this._colormapStops,s=Math.min(8,Math.max(2,a.length));for(let l=0;l<8;l++){let u=a[Math.min(l,s-1)],m=28+l*4;e[m+0]=u[0],e[m+1]=u[1],e[m+2]=u[2],e[m+3]=u[3]}return e}get dirtyUniforms(){return this._uniformDirty}markUniformsClean(){this._uniformDirty=!1}emitVisualChange(e){for(let t of this._visualChangeListeners)try{t(e)}catch{}}destroy(){this.pointsBuffer?.destroy(),this.uniformBuffer?.destroy(),this.pointsBuffer=null,this.uniformBuffer=null,this.bindGroup=null,this.bindGroupKey=null,this._CPUData=null,this._ndShape=null,this._pointCount=0,this._visualChangeListeners.clear(),this.transform.dispose()}};var Xe=class n{_meshes=[];_pointClouds=[];_glyphFields=[];_lights=[];_background;static MAX_LIGHTS=8;constructor(e={}){this._background=e.background??[0,0,0]}get background(){return this._background}set background(e){this._background=e}get meshes(){return this._meshes}get pointClouds(){return this._pointClouds}get glyphFields(){return this._glyphFields}add(e){return e instanceof Me?this._meshes.includes(e)||this._meshes.push(e):e instanceof Ue?this._pointClouds.includes(e)||this._pointClouds.push(e):this._glyphFields.includes(e)||this._glyphFields.push(e),this}remove(e){if(e instanceof Me){let t=this._meshes.indexOf(e);t!==-1&&this._meshes.splice(t,1)}else if(e instanceof Ue){let t=this._pointClouds.indexOf(e);t!==-1&&this._pointClouds.splice(t,1)}else{let t=this._glyphFields.indexOf(e);t!==-1&&this._glyphFields.splice(t,1)}return this}clear(){return this._meshes=[],this._pointClouds=[],this._glyphFields=[],this}clearPointClouds(){return this._pointClouds=[],this}clearGlyphFields(){return this._glyphFields=[],this}get lights(){return this._lights}addLight(e){return this._lights.includes(e)||(this._lights.length>=n.MAX_LIGHTS&&e.type!=="ambient"&&console.warn(`Scene: Maximum of ${n.MAX_LIGHTS} non-ambient lights supported.`),this._lights.push(e)),this}removeLight(e){let t=this._lights.indexOf(e);return t!==-1&&this._lights.splice(t,1),this}clearLights(){return this._lights=[],this}findByName(e){return this._meshes.find(t=>t.name===e)}findAllByName(e){return this._meshes.filter(t=>t.name===e)}findPointCloudByName(e){return this._pointClouds.find(t=>t.name===e)}findAllPointCloudsByName(e){return this._pointClouds.filter(t=>t.name===e)}findGlyphFieldByName(e){return this._glyphFields.find(t=>t.name===e)}findAllGlyphFieldsByName(e){return this._glyphFields.filter(t=>t.name===e)}get visibleMeshes(){return this._meshes.filter(e=>e.visible)}get visiblePointClouds(){return this._pointClouds.filter(e=>e.visible)}get visibleGlyphFields(){return this._glyphFields.filter(e=>e.visible)}get enabledLights(){return this._lights.filter(e=>e.enabled)}getAmbientColor(){let e=this._lights.find(t=>t.type==="ambient"&&t.enabled);return e?[e.color[0]*e.intensity,e.color[1]*e.intensity,e.color[2]*e.intensity]:[0,0,0]}getLightingData(){let e=this.getAmbientColor(),t=this.enabledLights.filter(r=>r.type!=="ambient").slice(0,n.MAX_LIGHTS);return{ambient:e,lights:t}}getBounds(e={}){let t=e.visibleOnly??!0,r=ut(!1),i=l=>{if(l.empty){l.partial&&(r.partial=!0);return}r=Hn(r,l)},o=t?this.visibleMeshes:this._meshes,a=t?this.visiblePointClouds:this._pointClouds,s=t?this.visibleGlyphFields:this._glyphFields;for(let l of o)i(l.getWorldBounds());for(let l of a)i(l.getWorldBounds());for(let l of s)i(l.getWorldBounds());return r}traverse(e){for(let t of this._meshes)e(t)}traverseVisible(e){for(let t of this._meshes)t.visible&&e(t)}traversePointClouds(e){for(let t of this._pointClouds)e(t)}traverseVisiblePointClouds(e){for(let t of this._pointClouds)t.visible&&e(t)}traverseGlyphFields(e){for(let t of this._glyphFields)e(t)}traverseVisibleGlyphFields(e){for(let t of this._glyphFields)t.visible&&e(t)}destroy(){for(let e of this._meshes)e.destroy();for(let e of this._pointClouds)e.destroy();for(let e of this._glyphFields)e.destroy();this._meshes=[],this._pointClouds=[],this._glyphFields=[],this._lights=[]}};var Ot=class{type;_color=[1,1,1];_intensity=1;_enabled=!0;constructor(e){this.type=e}get color(){return this._color}set color(e){this._color=e}get intensity(){return this._intensity}set intensity(e){this._intensity=e}get enabled(){return this._enabled}set enabled(e){this._enabled=e}},wr=class extends Ot{constructor(e={}){super("ambient"),this._color=e.color??[1,1,1],this._intensity=e.intensity??.1}},Ye=class extends Ot{_direction;constructor(e={}){super("directional"),this._direction=e.direction??[0,-1,0],this._color=e.color??[1,1,1],this._intensity=e.intensity??1}get direction(){return this._direction}set direction(e){let t=Math.sqrt(e[0]**2+e[1]**2+e[2]**2);t>0&&(this._direction=[e[0]/t,e[1]/t,e[2]/t])}},Ve=class extends Ot{_position;_range;constructor(e={}){super("point"),this._position=e.position??[0,0,0],this._color=e.color??[1,1,1],this._intensity=e.intensity??1,this._range=e.range??10}get position(){return this._position}set position(e){this._position=e}get range(){return this._range}set range(e){this._range=e}};var X=class n{positions;normals;uvs;joints;weights;joints1;weights1;_jointsBuffer=null;_weightsBuffer=null;_joints1Buffer=null;_weights1Buffer=null;indices;vertexCount;indexCount;_boundsMin;_boundsMax;_boundsCenter;_boundsRadius;_positionBuffer=null;_normalBuffer=null;_uvBuffer=null;_indexBuffer=null;_device=null;constructor(e){if(this.positions=e.positions,this.vertexCount=this.positions.length/3,this.normals=e.normals??new Float32Array(this.vertexCount*3).fill(0),!e.normals)for(let s=1;s<this.normals.length;s+=3)this.normals[s]=1;this.uvs=e.uvs??new Float32Array(this.vertexCount*2);let t=e.joints??null,r=e.weights??null,i=this.vertexCount*4;(t&&!r||!t&&r)&&(console.warn("[Geometry] JOINTS_0/WEIGHTS_0 must be provided together. Skinning disabled for this geometry."),t=null,r=null),t&&t.length!==i&&(console.warn(`[Geometry] joints length mismatch (got ${t.length}, expected ${i}). Skinning disabled.`),t=null,r=null),r&&r.length!==i&&(console.warn(`[Geometry] weights length mismatch (got ${r.length}, expected ${i}). Skinning disabled.`),t=null,r=null),this.joints=t,this.weights=r;let o=e.joints1??null,a=e.weights1??null;if((o&&!a||!o&&a)&&(console.warn("[Geometry] JOINTS_1/WEIGHTS_1 must be provided together. Ignoring additional influences."),o=null,a=null),(o||a)&&(!t||!r)&&(console.warn("[Geometry] JOINTS_1/WEIGHTS_1 provided without JOINTS_0/WEIGHTS_0. Ignoring additional influences."),o=null,a=null),o&&o.length!==i&&(console.warn(`[Geometry] joints1 length mismatch (got ${o.length}, expected ${i}). Ignoring additional influences.`),o=null,a=null),a&&a.length!==i&&(console.warn(`[Geometry] weights1 length mismatch (got ${a.length}, expected ${i}). Ignoring additional influences.`),o=null,a=null),this.joints1=o,this.weights1=a,this.indices=e.indices??null,this.indexCount=this.indices?.length??this.vertexCount,this.vertexCount>0){let s=_.allocF32(this.positions.length),l=_.allocF32(3),u=_.allocF32(3),m=_.allocF32(3),c=_.allocF32(1);try{_.f32view(s,this.positions.length).set(this.positions),Tt.geometryPositions(l,u,m,c,s,this.vertexCount);let d=_.f32view(l,3),f=_.f32view(u,3),p=_.f32view(m,3),b=_.f32view(c,1);this._boundsMin=[d[0],d[1],d[2]],this._boundsMax=[f[0],f[1],f[2]],this._boundsCenter=[p[0],p[1],p[2]],this._boundsRadius=b[0]}finally{_.freeF32(c,1),_.freeF32(m,3),_.freeF32(u,3),_.freeF32(l,3),_.freeF32(s,this.positions.length)}}else this._boundsMin=[0,0,0],this._boundsMax=[0,0,0],this._boundsCenter=[0,0,0],this._boundsRadius=0}upload(e){this._device!==e&&(this._device=e,this._positionBuffer=ve(e,this.positions,GPUBufferUsage.VERTEX),this._normalBuffer=ve(e,this.normals,GPUBufferUsage.VERTEX),this._uvBuffer=ve(e,this.uvs,GPUBufferUsage.VERTEX),this.joints&&(this._jointsBuffer=ve(e,this.joints,GPUBufferUsage.VERTEX)),this.weights&&(this._weightsBuffer=ve(e,this.weights,GPUBufferUsage.VERTEX)),this.joints1&&(this._joints1Buffer=ve(e,this.joints1,GPUBufferUsage.VERTEX)),this.weights1&&(this._weights1Buffer=ve(e,this.weights1,GPUBufferUsage.VERTEX)),this.indices&&(this._indexBuffer=ve(e,this.indices,GPUBufferUsage.INDEX)))}get positionBuffer(){if(!this._positionBuffer)throw new Error("Geometry not uploaded. Call upload(device) first.");return this._positionBuffer}get normalBuffer(){if(!this._normalBuffer)throw new Error("Geometry not uploaded. Call upload(device) first.");return this._normalBuffer}get uvBuffer(){if(!this._uvBuffer)throw new Error("Geometry not uploaded. Call upload(device) first.");return this._uvBuffer}get jointsBuffer(){return this._jointsBuffer}get weightsBuffer(){return this._weightsBuffer}get joints1Buffer(){return this._joints1Buffer}get weights1Buffer(){return this._weights1Buffer}get indexBuffer(){return this._indexBuffer}get isIndexed(){return this._indexBuffer!==null}get isSkinned(){return this._jointsBuffer!==null&&this._weightsBuffer!==null}get isSkinned8(){return this._jointsBuffer!==null&&this._weightsBuffer!==null&&this._joints1Buffer!==null&&this._weights1Buffer!==null}get boundsMin(){return this._boundsMin}get boundsMax(){return this._boundsMax}get boundsCenter(){return this._boundsCenter}get boundsRadius(){return this._boundsRadius}destroy(){this._positionBuffer?.destroy(),this._normalBuffer?.destroy(),this._uvBuffer?.destroy(),this._jointsBuffer?.destroy(),this._weightsBuffer?.destroy(),this._joints1Buffer?.destroy(),this._weights1Buffer?.destroy(),this._jointsBuffer=null,this._weightsBuffer=null,this._joints1Buffer=null,this._weights1Buffer=null,this._indexBuffer?.destroy(),this._positionBuffer=null,this._normalBuffer=null,this._uvBuffer=null,this._indexBuffer=null,this._device=null}static point(e=1,t="xy",r=!1){return n.rectangle(e,e,t,r)}static line(e=1,t=.01,r="xy",i=!1){return n.rectangle(e,t,r,i)}static plane(e=1,t=1,r=1,i=1){let o=e/2,a=t/2,s=r,l=i,u=s+1,m=l+1,c=e/s,d=t/l,f=[],p=[],b=[],g=[];for(let x=0;x<m;x++){let M=x*d-a;for(let h=0;h<u;h++){let w=h*c-o;f.push(w,0,M),p.push(0,1,0),b.push(h/s,1-x/l)}}for(let x=0;x<l;x++)for(let M=0;M<s;M++){let h=M+u*x,w=M+u*(x+1),S=M+1+u*(x+1),B=M+1+u*x;g.push(h,w,B,w,S,B)}return new n({positions:new Float32Array(f),normals:new Float32Array(p),uvs:new Float32Array(b),indices:new Uint32Array(g)})}static triangle(e=1,t=1,r="xy",i=!1){let o=e/2,a=t/2,s=[],l=[],u=[],m=[],c=r==="xz",d=0,f=0,p=0;switch(r){case"xy":p=1;break;case"xz":f=1;break;case"yz":d=1;break}let b=h=>e!==0?h/e+.5:.5,g=h=>t!==0?-h/t+.5:.5,x=(h,w)=>{switch(r){case"xy":s.push(h,w,0);break;case"xz":s.push(h,0,w);break;case"yz":s.push(0,h,w);break}l.push(d,f,p),u.push(b(h),g(w))};x(-o,-a),x(o,-a),x(0,a),c?m.push(0,2,1):m.push(0,1,2);let M={positions:new Float32Array(s),normals:new Float32Array(l),uvs:new Float32Array(u),indices:new Uint32Array(m)};return new n(i?n._makeDoubleSided(M):M)}static rectangle(e=1,t=1,r="xy",i=!1){let o=e/2,a=t/2,s=[],l=[],u=[],m=[],c=r==="xz",d=0,f=0,p=0;switch(r){case"xy":p=1;break;case"xz":f=1;break;case"yz":d=1;break}let b=(x,M,h,w)=>{switch(r){case"xy":s.push(x,M,0);break;case"xz":s.push(x,0,M);break;case"yz":s.push(0,x,M);break}l.push(d,f,p),u.push(h,w)};b(-o,-a,0,1),b(o,-a,1,1),b(o,a,1,0),b(-o,a,0,0),c?m.push(0,2,1,0,3,2):m.push(0,1,2,0,2,3);let g={positions:new Float32Array(s),normals:new Float32Array(l),uvs:new Float32Array(u),indices:new Uint32Array(m)};return new n(i?n._makeDoubleSided(g):g)}static circle(e=.5,t=64,r="xy",i=!1){let o=Math.max(3,Math.floor(t)),a=[],s=[],l=[],u=[],m=r==="xz",c=0,d=0,f=0;switch(r){case"xy":f=1;break;case"xz":d=1;break;case"yz":c=1;break}let p=e!==0?1/(2*e):0,b=(x,M)=>{switch(r){case"xy":a.push(x,M,0);break;case"xz":a.push(x,0,M);break;case"yz":a.push(0,x,M);break}s.push(c,d,f);let h=e!==0?.5+x*p:.5,w=e!==0?.5-M*p:.5;l.push(h,w)};b(0,0);for(let x=0;x<o;x++){let M=x/o*Math.PI*2,h=Math.cos(M)*e,w=Math.sin(M)*e;b(h,w)}for(let x=0;x<o;x++){let h=1+x,w=1+(x+1)%o;m?u.push(0,w,h):u.push(0,h,w)}let g={positions:new Float32Array(a),normals:new Float32Array(s),uvs:new Float32Array(l),indices:new Uint32Array(u)};return new n(i?n._makeDoubleSided(g):g)}static ellipse(e=.5,t=.5,r=64,i="xy",o=!1){let a=Math.max(3,Math.floor(r)),s=[],l=[],u=[],m=[],c=i==="xz",d=0,f=0,p=0;switch(i){case"xy":p=1;break;case"xz":f=1;break;case"yz":d=1;break}let b=e!==0?1/(2*e):0,g=t!==0?1/(2*t):0,x=(h,w)=>{switch(i){case"xy":s.push(h,w,0);break;case"xz":s.push(h,0,w);break;case"yz":s.push(0,h,w);break}l.push(d,f,p);let S=e!==0?.5+h*b:.5,B=t!==0?.5-w*g:.5;u.push(S,B)};x(0,0);for(let h=0;h<a;h++){let w=h/a*Math.PI*2,S=Math.cos(w)*e,B=Math.sin(w)*t;x(S,B)}for(let h=0;h<a;h++){let S=1+h,B=1+(h+1)%a;c?m.push(0,B,S):m.push(0,S,B)}let M={positions:new Float32Array(s),normals:new Float32Array(l),uvs:new Float32Array(u),indices:new Uint32Array(m)};return new n(o?n._makeDoubleSided(M):M)}static box(e=1,t=1,r=1){let i=e/2,o=t/2,a=r/2,s=new Float32Array([-i,-o,a,i,-o,a,i,o,a,-i,o,a,i,-o,-a,-i,-o,-a,-i,o,-a,i,o,-a,-i,o,a,i,o,a,i,o,-a,-i,o,-a,-i,-o,-a,i,-o,-a,i,-o,a,-i,-o,a,i,-o,a,i,-o,-a,i,o,-a,i,o,a,-i,-o,-a,-i,-o,a,-i,o,a,-i,o,-a]),l=new Float32Array([0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0]),u=new Float32Array([0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0]),m=new Uint32Array([0,1,2,0,2,3,4,5,6,4,6,7,8,9,10,8,10,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23]);return new n({positions:s,normals:l,uvs:u,indices:m})}static sphere(e=.5,t=32,r=16){let i=[],o=[],a=[],s=[];for(let l=0;l<=r;l++){let u=l/r,m=u*Math.PI;for(let c=0;c<=t;c++){let d=c/t,f=d*Math.PI*2,p=-Math.cos(f)*Math.sin(m),b=Math.cos(m),g=Math.sin(f)*Math.sin(m);i.push(e*p,e*b,e*g),o.push(p,b,g),a.push(d,u)}}for(let l=0;l<r;l++)for(let u=0;u<t;u++){let m=u+(t+1)*l,c=u+(t+1)*(l+1),d=u+1+(t+1)*(l+1),f=u+1+(t+1)*l;l!==0&&s.push(m,c,f),l!==r-1&&s.push(c,d,f)}return new n({positions:new Float32Array(i),normals:new Float32Array(o),uvs:new Float32Array(a),indices:new Uint32Array(s)})}static cylinder(e=.5,t=.5,r=1,i=32,o=1,a=!1){let s=[],l=[],u=[],m=[],c=0,d=r/2,f=(t-e)/r;for(let g=0;g<=o;g++){let x=g/o,M=x*r-d,h=x*(e-t)+t;for(let w=0;w<=i;w++){let S=w/i,B=S*Math.PI*2,v=Math.sin(B),A=Math.cos(B);s.push(h*v,M,h*A);let C=Math.sqrt(1+f*f);l.push(v/C,f/C,A/C),u.push(S,1-x)}}for(let g=0;g<o;g++)for(let x=0;x<i;x++){let M=x+(i+1)*g,h=x+(i+1)*(g+1),w=x+1+(i+1)*(g+1),S=x+1+(i+1)*g;m.push(M,S,h,h,S,w)}c=s.length/3;let p=()=>{let g=c;s.push(0,d,0),l.push(0,1,0),u.push(.5,.5),c++;for(let x=0;x<=i;x++){let h=x/i*Math.PI*2,w=e*Math.sin(h),S=e*Math.cos(h);s.push(w,d,S),l.push(0,1,0),u.push(Math.sin(h)*.5+.5,Math.cos(h)*.5+.5),x>0&&m.push(g,c-1,c),c++}},b=()=>{let g=c;s.push(0,-d,0),l.push(0,-1,0),u.push(.5,.5),c++;for(let x=0;x<=i;x++){let h=x/i*Math.PI*2,w=t*Math.sin(h),S=t*Math.cos(h);s.push(w,-d,S),l.push(0,-1,0),u.push(Math.sin(h)*.5+.5,Math.cos(h)*.5+.5),x>0&&m.push(g,c,c-1),c++}};return a||(p(),b()),new n({positions:new Float32Array(s),normals:new Float32Array(l),uvs:new Float32Array(u),indices:new Uint32Array(m)})}static pyramid(e=1,t=1,r=1){let i=e/2,o=t/2,s=[0,r,0],l=[-i,0,-o],u=[i,0,-o],m=[i,0,o],c=[-i,0,o],d=(w,S,B)=>{let v=S[0]-w[0],A=S[1]-w[1],C=S[2]-w[2],k=B[0]-w[0],G=B[1]-w[1],R=B[2]-w[2],T=A*R-C*G,F=C*k-v*R,D=v*G-A*k,U=Math.sqrt(T*T+F*F+D*D);return[T/U,F/U,D/U]},f=[],p=[],b=[],g=[],x=0,M=(w,S,B)=>{let v=d(w,S,B);f.push(...w,...S,...B),p.push(...v,...v,...v),b.push(.5,0,0,1,1,1),g.push(x,x+1,x+2),x+=3};M(s,c,m),M(s,m,u),M(s,u,l),M(s,l,c);let h=[0,-1,0];return f.push(...l,...u,...m,...c),p.push(...h,...h,...h,...h),b.push(0,0,1,0,1,1,0,1),g.push(x,x+1,x+2,x,x+2,x+3),new n({positions:new Float32Array(f),normals:new Float32Array(p),uvs:new Float32Array(b),indices:new Uint32Array(g)})}static torus(e=.5,t=.2,r=32,i=24){let o=[],a=[],s=[],l=[];for(let u=0;u<=r;u++)for(let m=0;m<=i;m++){let c=m/i*Math.PI*2,d=u/r*Math.PI*2,f=(e+t*Math.cos(d))*Math.cos(c),p=t*Math.sin(d),b=(e+t*Math.cos(d))*Math.sin(c);o.push(f,p,b);let g=e*Math.cos(c),x=e*Math.sin(c),M=f-g,h=p,w=b-x,S=Math.sqrt(M*M+h*h+w*w);a.push(M/S,h/S,w/S),s.push(m/i,u/r)}for(let u=0;u<r;u++)for(let m=0;m<i;m++){let c=m+(i+1)*u,d=m+(i+1)*(u+1),f=m+1+(i+1)*(u+1),p=m+1+(i+1)*u;l.push(c,d,p,d,f,p)}return new n({positions:new Float32Array(o),normals:new Float32Array(a),uvs:new Float32Array(s),indices:new Uint32Array(l)})}static prism(e=.5,t=1,r=6){r<3&&(r=3);let i=[],o=[],a=[],s=[],l=t/2,u=0,m=[],c=[];for(let h=0;h<r;h++){let w=h/r*Math.PI*2,S=e*Math.cos(w),B=e*Math.sin(w);m.push([S,l,B]),c.push([S,-l,B])}let d=(h,w,S)=>{let B=w[0]-h[0],v=w[1]-h[1],A=w[2]-h[2],C=S[0]-h[0],k=S[1]-h[1],G=S[2]-h[2],R=v*G-A*k,T=A*C-B*G,F=B*k-v*C,D=Math.sqrt(R*R+T*T+F*F);return[R/D,T/D,F/D]};for(let h=0;h<r;h++){let w=(h+1)%r,S=m[h],B=m[w],v=c[h],A=c[w],C=d(S,B,v);i.push(...S,...v,...A,...B),o.push(...C,...C,...C,...C);let k=h/r,G=(h+1)/r;a.push(k,0,k,1,G,1,G,0),s.push(u,u+2,u+1,u,u+3,u+2),u+=4}let f=[0,l,0],p=[0,1,0],b=u;i.push(...f),o.push(...p),a.push(.5,.5),u++;for(let h=0;h<r;h++){let w=m[h];i.push(...w),o.push(...p);let S=.5+.5*Math.cos(h/r*Math.PI*2),B=.5+.5*Math.sin(h/r*Math.PI*2);a.push(S,B)}for(let h=0;h<r;h++){let w=(h+1)%r;s.push(b,b+1+w,b+1+h)}u+=r;let g=[0,-l,0],x=[0,-1,0],M=u;i.push(...g),o.push(...x),a.push(.5,.5),u++;for(let h=0;h<r;h++){let w=c[h];i.push(...w),o.push(...x);let S=.5+.5*Math.cos(h/r*Math.PI*2),B=.5+.5*Math.sin(h/r*Math.PI*2);a.push(S,B)}for(let h=0;h<r;h++){let w=(h+1)%r;s.push(M,M+1+h,M+1+w)}return new n({positions:new Float32Array(i),normals:new Float32Array(o),uvs:new Float32Array(a),indices:new Uint32Array(s)})}static cartesianCurve(e){let t=e.f,r=e.xMin??-1,i=e.xMax??1,o=Math.max(2,Math.floor(e.segments??256)),a=e.radius??.01,s=Math.max(3,Math.floor(e.radialSegments??8)),l=e.closed??!1,u=e.plane??"xy",m=e.up??[0,0,1],c;switch(u){case"xy":c=m;break;case"xz":c=[m[0],m[2],m[1]];break;case"yz":c=[m[2],m[0],m[1]];break}let d=e.breakOnInvalid??!0,f=[],p=[],b=[],g=[],x=0,M=l?o:o+1,h=[],w=!1,S=v=>{h.length/3>=2&&(x=n._appendTubeSegment(new Float32Array(h),a,s,v,c,f,p,b,g,x)),h=[]},B=i-r;for(let v=0;v<M;v++){let A=o>0?v/o:0,C=r+B*A,k=t(C);if(!Number.isFinite(k)){w=!0,d&&S(!1);continue}let G,R,T;switch(u){case"xy":G=C,R=k,T=0;break;case"xz":G=C,R=0,T=k;break;case"yz":G=0,R=C,T=k;break}h.push(G,R,T)}return S(l&&!w),f.length===0?new n({positions:new Float32Array(0)}):new n({positions:new Float32Array(f),normals:new Float32Array(p),uvs:new Float32Array(b),indices:new Uint32Array(g)})}static cartesianSurface(e){let t=e.f,r=e.xMin??-1,i=e.xMax??1,o=e.zMin??-1,a=e.zMax??1,s=Math.max(1,Math.floor(e.xSegments??128)),l=Math.max(1,Math.floor(e.zSegments??128)),u=e.skipInvalid??!0,m=e.doubleSided??!1,c=e.plane??"xz",d=s,f=l,p=d+1,b=f+1,g=new Float32Array(p*b*3),x=new Float32Array(p*b*3),M=new Float32Array(p*b*2),h=new Uint8Array(p*b),w=i-r,S=a-o;for(let A=0;A<b;A++){let C=f>0?A/f:0,k=o+S*C;for(let G=0;G<p;G++){let R=d>0?G/d:0,T=r+w*R,F=G+p*A,D=t(T,k),U=Number.isFinite(D);h[F]=U?1:0;let L=F*3,E=U?D:0,z,O,I;switch(c){case"xy":z=T,O=k,I=E;break;case"xz":z=T,O=E,I=k;break;case"yz":z=E,O=T,I=k;break}g[L+0]=z,g[L+1]=O,g[L+2]=I;let j=F*2;M[j+0]=R,M[j+1]=1-C}}n._computeGridNormals(g,h,d,f,x);let B=[];for(let A=0;A<f;A++)for(let C=0;C<d;C++){let k=C+p*A,G=C+p*(A+1),R=C+1+p*(A+1),T=C+1+p*A;u&&(!h[k]||!h[G]||!h[R]||!h[T])||B.push(k,G,T,G,R,T)}if(B.length===0)return new n({positions:new Float32Array(0)});let v={positions:g,normals:x,uvs:M,indices:new Uint32Array(B)};return new n(m?n._makeDoubleSided(v):v)}static parametricCurve(e){let t=e.f,r=e.tMin??0,i=e.tMax??1,o=Math.max(2,Math.floor(e.segments??256)),a=e.radius??.01,s=Math.max(3,Math.floor(e.radialSegments??8)),l=e.closed??!1,u=e.breakOnInvalid??!0,m=e.plane??"xy",c=[],d=[],f=[],p=[],b=0,g=l?o:o+1,x=[],M=!1,h=e.up??null,w=null;if(h)switch(m){case"xy":w=h;break;case"xz":w=[h[0],h[2],h[1]];break;case"yz":w=[h[2],h[0],h[1]];break}let S=v=>{if(x.length/3>=2){let C=w??[0,1,0];b=n._appendTubeSegment(new Float32Array(x),a,s,v,C,c,d,f,p,b)}x=[]},B=i-r;for(let v=0;v<g;v++){let A=o>0?v/o:0,C=r+B*A,k=t(C),G,R,T;if(k.length===2){if(G=k[0],R=k[1],T=0,!h)switch(h=[0,0,1],m){case"xy":w=h;break;case"xz":w=[h[0],h[2],h[1]];break;case"yz":w=[h[2],h[0],h[1]];break}}else if(G=k[0],R=k[1],T=k[2],!h)switch(h=[0,1,0],m){case"xy":w=h;break;case"xz":w=[h[0],h[2],h[1]];break;case"yz":w=[h[2],h[0],h[1]];break}if(!Number.isFinite(G)||!Number.isFinite(R)||!Number.isFinite(T)){M=!0,u&&S(!1);continue}let F,D,U;switch(m){case"xy":F=G,D=R,U=T;break;case"xz":F=G,D=T,U=R;break;case"yz":F=T,D=G,U=R;break}x.push(F,D,U)}return S(l&&!M),c.length===0?new n({positions:new Float32Array(0)}):new n({positions:new Float32Array(c),normals:new Float32Array(d),uvs:new Float32Array(f),indices:new Uint32Array(p)})}static parametricSurface(e){let t=e.f,r=e.uMin??0,i=e.uMax??1,o=e.vMin??0,a=e.vMax??1,s=Math.max(1,Math.floor(e.uSegments??128)),l=Math.max(1,Math.floor(e.vSegments??128)),u=e.skipInvalid??!0,m=e.doubleSided??!1,c=e.plane??"xy",d=s,f=l,p=d+1,b=f+1,g=new Float32Array(p*b*3),x=new Float32Array(p*b*3),M=new Float32Array(p*b*2),h=new Uint8Array(p*b),w=i-r,S=a-o;for(let A=0;A<b;A++){let C=f>0?A/f:0,k=o+S*C;for(let G=0;G<p;G++){let R=d>0?G/d:0,T=r+w*R,F=G+p*A,D=t(T,k),U=D[0],L=D[1],E=D[2],z=Number.isFinite(U)&&Number.isFinite(L)&&Number.isFinite(E);h[F]=z?1:0;let O=F*3;if(z){let j,Z,ae;switch(c){case"xy":j=U,Z=L,ae=E;break;case"xz":j=U,Z=E,ae=L;break;case"yz":j=E,Z=U,ae=L;break}g[O+0]=j,g[O+1]=Z,g[O+2]=ae}else g[O+0]=0,g[O+1]=0,g[O+2]=0;let I=F*2;M[I+0]=R,M[I+1]=1-C}}n._computeGridNormals(g,h,d,f,x);let B=[];for(let A=0;A<f;A++)for(let C=0;C<d;C++){let k=C+p*A,G=C+p*(A+1),R=C+1+p*(A+1),T=C+1+p*A;u&&(!h[k]||!h[G]||!h[R]||!h[T])||B.push(k,G,T,G,R,T)}if(B.length===0)return new n({positions:new Float32Array(0)});let v={positions:g,normals:x,uvs:M,indices:new Uint32Array(B)};return new n(m?n._makeDoubleSided(v):v)}static _appendTubeSegment(e,t,r,i,o,a,s,l,u,m){let c=e.length/3;if(c<2)return m;let d=new Float32Array(c*3);for(let U=0;U<c;U++){let L=i?(U-1+c)%c:Math.max(U-1,0),E=i?(U+1)%c:Math.min(U+1,c-1),z=e[E*3+0]-e[L*3+0],O=e[E*3+1]-e[L*3+1],I=e[E*3+2]-e[L*3+2],j=Math.sqrt(z*z+O*O+I*I);j>1e-12?(z/=j,O/=j,I/=j):(z=0,O=1,I=0),d[U*3+0]=z,d[U*3+1]=O,d[U*3+2]=I}let f=new Float32Array(c*3),p=new Float32Array(c*3),b=o[0],g=o[1],x=o[2],M=d[0],h=d[1],w=d[2],S=h*x-w*g,B=w*b-M*x,v=M*g-h*b,A=Math.sqrt(S*S+B*B+v*v);A<1e-6&&(Math.abs(M)<.9?(b=1,g=0,x=0):(b=0,g=1,x=0),S=h*x-w*g,B=w*b-M*x,v=M*g-h*b,A=Math.sqrt(S*S+B*B+v*v)),A>1e-12?(S/=A,B/=A,v/=A):(S=1,B=0,v=0),f[0]=S,f[1]=B,f[2]=v;let C=h*v-w*B,k=w*S-M*v,G=M*B-h*S,R=Math.sqrt(C*C+k*k+G*G);R>1e-12&&(C/=R,k/=R,G/=R),p[0]=C,p[1]=k,p[2]=G;for(let U=1;U<c;U++){let L=d[(U-1)*3+0],E=d[(U-1)*3+1],z=d[(U-1)*3+2],O=d[U*3+0],I=d[U*3+1],j=d[U*3+2],Z=E*j-z*I,ae=z*O-L*j,ue=L*I-E*O,Je=Math.sqrt(Z*Z+ae*ae+ue*ue),se=f[(U-1)*3+0],ce=f[(U-1)*3+1],J=f[(U-1)*3+2];if(Je>1e-6){Z/=Je,ae/=Je,ue/=Je;let va=Math.max(-1,Math.min(1,L*O+E*I+z*j)),Ai=Math.acos(va),qr=Math.cos(Ai),In=Math.sin(Ai),En=1-qr,xa=ae*J-ue*ce,Pa=ue*se-Z*J,wa=Z*ce-ae*se,On=Z*se+ae*ce+ue*J,Sa=se*qr+xa*In+Z*On*En,Ca=ce*qr+Pa*In+ae*On*En,_a=J*qr+wa*In+ue*On*En;se=Sa,ce=Ca,J=_a}let Ie=se*O+ce*I+J*j;se-=O*Ie,ce-=I*Ie,J-=j*Ie;let we=Math.sqrt(se*se+ce*ce+J*J);we>1e-12?(se/=we,ce/=we,J/=we):(se=f[0],ce=f[1],J=f[2]),f[U*3+0]=se,f[U*3+1]=ce,f[U*3+2]=J;let Ee=I*J-j*ce,he=j*se-O*J,Oe=O*ce-I*se,lt=Math.sqrt(Ee*Ee+he*he+Oe*Oe);lt>1e-12&&(Ee/=lt,he/=lt,Oe/=lt),p[U*3+0]=Ee,p[U*3+1]=he,p[U*3+2]=Oe}let T=r+1,F=i?c:c-1;for(let U=0;U<c;U++){let L=F>0?U/F:0,E=e[U*3+0],z=e[U*3+1],O=e[U*3+2],I=f[U*3+0],j=f[U*3+1],Z=f[U*3+2],ae=p[U*3+0],ue=p[U*3+1],Je=p[U*3+2];for(let se=0;se<=r;se++){let ce=r>0?se/r:0,J=ce*Math.PI*2,Ie=Math.cos(J),we=Math.sin(J),Ee=Ie*I+we*ae,he=Ie*j+we*ue,Oe=Ie*Z+we*Je;a.push(E+t*Ee,z+t*he,O+t*Oe),s.push(Ee,he,Oe),l.push(L,ce)}}let D=i?c:c-1;for(let U=0;U<D;U++){let L=i?(U+1)%c:U+1;for(let E=0;E<r;E++){let z=m+T*U+E,O=m+T*L+E,I=m+T*L+E+1,j=m+T*U+E+1;u.push(z,j,O,O,j,I)}}return m+T*c}static _computeGridNormals(e,t,r,i,o){let a=r+1,s=i+1;for(let l=0;l<s;l++)for(let u=0;u<a;u++){let m=u+a*l,c=m*3;if(!t[m]){o[c+0]=0,o[c+1]=0,o[c+2]=0;continue}let d=u>0?m-1:m,f=u<r?m+1:m,p=l>0?m-a:m,b=l<i?m+a:m,g=t[d]?e[d*3+0]:e[c+0],x=t[d]?e[d*3+1]:e[c+1],M=t[d]?e[d*3+2]:e[c+2],h=t[f]?e[f*3+0]:e[c+0],w=t[f]?e[f*3+1]:e[c+1],S=t[f]?e[f*3+2]:e[c+2],B=t[p]?e[p*3+0]:e[c+0],v=t[p]?e[p*3+1]:e[c+1],A=t[p]?e[p*3+2]:e[c+2],C=t[b]?e[b*3+0]:e[c+0],k=t[b]?e[b*3+1]:e[c+1],G=t[b]?e[b*3+2]:e[c+2],R=h-g,T=w-x,F=S-M,D=C-B,U=k-v,L=G-A,E=U*F-L*T,z=L*R-D*F,O=D*T-U*R,I=Math.sqrt(E*E+z*z+O*O);I>1e-12?(E/=I,z/=I,O/=I):(E=0,z=1,O=0),o[c+0]=E,o[c+1]=z,o[c+2]=O}}static _makeDoubleSided(e){let t=e.positions,r=e.normals??new Float32Array(t.length/3*3),i=e.uvs??new Float32Array(t.length/3*2),o=e.indices;if(!o)return e;let a=t.length/3,s=new Float32Array(t.length*2);s.set(t,0),s.set(t,t.length);let l=new Float32Array(r.length*2);l.set(r,0);for(let c=0;c<a;c++){let d=c*3;l[r.length+d+0]=-r[d+0],l[r.length+d+1]=-r[d+1],l[r.length+d+2]=-r[d+2]}let u=new Float32Array(i.length*2);u.set(i,0),u.set(i,i.length);let m=new Uint32Array(o.length*2);m.set(o,0);for(let c=0;c<o.length;c+=3){let d=o[c+0],f=o[c+1],p=o[c+2],b=o.length+c;m[b+0]=a+d,m[b+1]=a+p,m[b+2]=a+f}return{...e,positions:s,normals:l,uvs:u,indices:m}}};var oo=60,os=oo*4,as=n=>n<0?0:n>1?1:n,ss=n=>{if(!n)return null;let e=[];for(let t=0;t<n.length;t++){let r=n[t];P(Number.isInteger(r)&&r>0,`GlyphField: ndShape[${t}] must be an integer > 0.`),e.push(r|0)}return e.length>0?e:null},ls=(n,e)=>{if(!n||n.length===0||!Number.isInteger(e)||e<0)return null;let t=e|0,r=new Array(n.length);for(let i=n.length-1;i>=0;i--){let o=n[i];r[i]=t%o,t=Math.floor(t/o)}return t===0?r:null},ro=n=>{if(!n||n.length===0)return[[0,0,0,1],[1,1,1,1]];let e=[],t=Math.min(8,n.length);for(let r=0;r<t;r++){let i=n[r];e.push([i[0],i[1],i[2],i[3]])}return e},Jr=n=>ie({componentCount:4,componentIndex:0,stride:4,...n}),us=n=>{switch(n){case"rgba":return 0;case"scalar":return 1;case"solid":return 2}},en=n=>n?n.buffer?n.buffer:n:null,no=(n=8,e=12)=>{let t=Math.max(3,n|0),r=Math.max(3,e|0),i=[],o=[],a=[],s=[];for(let u=0;u<=t;u++){let m=u/t,c=m*Math.PI,d=Math.sin(c),f=Math.cos(c);for(let p=0;p<=r;p++){let b=p/r,g=b*Math.PI*2,x=Math.sin(g),h=Math.cos(g)*d,w=f,S=x*d;i.push(h,w,S),o.push(h,w,S),a.push(b,1-m)}}let l=r+1;for(let u=0;u<t;u++)for(let m=0;m<r;m++){let c=u*l+m,d=c+1,f=c+l,p=f+1;s.push(c,d,f),s.push(d,p,f)}return new X({positions:new Float32Array(i),normals:new Float32Array(o),uvs:new Float32Array(a),indices:new Uint32Array(s)})},cs=(n=12)=>{let e=Math.max(3,n|0),t=[],r=[],i=[],o=[],a=-.5,s=.15,l=.2,u=.5,m=.05,c=.1,d=(C,k,G,R,T,F,D,U)=>{let L=t.length/3|0;return t.push(C,k,G),r.push(R,T,F),i.push(D,U),L},f=(C,k,G,R)=>{let T=[];for(let F=0;F<=e;F++){let D=F/e,U=D*Math.PI*2,L=Math.cos(U),E=Math.sin(U),z=L*k,O=E*k,I=L,j=E,Z=G;R&&(I=0,j=0,Z=G),T.push(d(z,O,C,I,j,Z,D,C-a))}return T},p=f(a,m,0,!1),b=f(s,m,0,!1);for(let C=0;C<e;C++){let k=p[C],G=p[C+1],R=b[C],T=b[C+1];o.push(k,G,R),o.push(G,T,R)}let g=f(s,m,0,!1),x=f(l,c,0,!1),M=(m-c)/(l-s);for(let C=0;C<=e;C++){let G=C/e*Math.PI*2,R=Math.cos(G),T=Math.sin(G),F=R,D=T,U=M,L=1/Math.hypot(F,D,U);r[g[C]*3+0]=F*L,r[g[C]*3+1]=D*L,r[g[C]*3+2]=U*L,r[x[C]*3+0]=F*L,r[x[C]*3+1]=D*L,r[x[C]*3+2]=U*L}for(let C=0;C<e;C++){let k=g[C],G=g[C+1],R=x[C],T=x[C+1];o.push(k,G,R),o.push(G,T,R)}let h=f(l,c,0,!1),w=[],S=u-l,B=c/S;for(let C=0;C<=e;C++){let k=C/e,G=k*Math.PI*2,R=Math.cos(G),T=Math.sin(G),F=R,D=T,U=B,L=1/Math.hypot(F,D,U);w.push(d(0,0,u,F*L,D*L,U*L,k,u-a))}for(let C=0;C<=e;C++){let G=C/e*Math.PI*2,R=Math.cos(G),T=Math.sin(G),F=R,D=T,U=B,L=1/Math.hypot(F,D,U);r[h[C]*3+0]=F*L,r[h[C]*3+1]=D*L,r[h[C]*3+2]=U*L}for(let C=0;C<e;C++){let k=h[C],G=h[C+1],R=w[C];o.push(k,G,R)}let v=d(0,0,a,0,0,-1,.5,0),A=f(a,m,-1,!0);for(let C=0;C<e;C++){let k=A[C],G=A[C+1];o.push(v,G,k)}return new X({positions:new Float32Array(t),normals:new Float32Array(r),uvs:new Float32Array(i),indices:new Uint32Array(o)})},tn=null,io=null,ms=n=>{switch(n){case"ellipsoid":return tn??=no(),tn;case"arrow":return io??=cs(),io;default:return tn??=no(),tn}},Re=class{transform=new pe;name=null;visible=!0;boundsMin=[0,0,0];boundsMax=[0,0,0];blendMode="opaque";cullMode="back";depthWrite=!0;depthTest=!0;boundsCenter=[0,0,0];boundsRadius=0;shape="ellipsoid";geometry;positionsBuffer=null;rotationsBuffer=null;scalesBuffer=null;attributesBuffer=null;uniformBuffer=null;bindGroup=null;bindGroupKey=null;_instanceCount=0;_positionsCPU=null;_rotationsCPU=null;_scalesCPU=null;_attributesCPU=null;_positionsPtr=0;_rotationsPtr=0;_scalesPtr=0;_attributesPtr=0;_usingWasmPtrs=!1;_usingExternalBuffers=!1;_keepCPUData=!1;_ndShape=null;_boundsSource="none";_dataDirty=!0;_uniformDirty=!0;_colorMode="rgba";_colormap="viridis";_colormapStops=[[.267,.00487,.32942,1],[.99325,.90616,.14394,1]];_scaleTransform=Jr({});_scaleRevision=0;_visualChangeListeners=new Set;_opacity=1;_lit=!1;_solidColor=[1,1,1,1];constructor(e){P(!!e&&!!e.scaleTransform,"GlyphField: scaleTransform is required."),this._scaleTransform=Jr(e.scaleTransform),e.name!==void 0&&(this.name=e.name),e.visible!==void 0&&(this.visible=!!e.visible),this.shape=e.shape??"ellipsoid",this.geometry=e.geometry??ms(this.shape),this.applyExplicitBounds(e),e.blendMode!==void 0&&(this.blendMode=e.blendMode),e.cullMode!==void 0&&(this.cullMode=e.cullMode),e.depthWrite!==void 0&&(this.depthWrite=!!e.depthWrite),e.depthTest!==void 0&&(this.depthTest=!!e.depthTest),e.colorMode!==void 0&&(this._colorMode=e.colorMode),e.colormap!==void 0&&(this._colormap=e.colormap),e.colormapStops!==void 0&&(this._colormapStops=ro(e.colormapStops)),e.opacity!==void 0&&(this._opacity=e.opacity),e.lit!==void 0&&(this._lit=!!e.lit),e.solidColor!==void 0&&(this._solidColor=[e.solidColor[0],e.solidColor[1],e.solidColor[2],e.solidColor[3]]),e.keepCPUData!==void 0&&(this._keepCPUData=!!e.keepCPUData),e.ndShape!==void 0&&(this.ndShape=e.ndShape);let t=en(e.positionsBuffer),r=en(e.rotationsBuffer),i=en(e.scalesBuffer),o=en(e.attributesBuffer);if(t||r||i||o){P(!!t&&!!r&&!!i,"GlyphField: positionsBuffer, rotationsBuffer, and scalesBuffer are required when using external buffers.");let a=e.instanceCount??0;P(a>0,"GlyphField: instanceCount is required when using external buffers."),this.setBuffers(t,r,i,o,a)}else if(e.positionsPtr||e.rotationsPtr||e.scalesPtr){P(!!e.positionsPtr&&!!e.rotationsPtr&&!!e.scalesPtr,"GlyphField: positionsPtr, rotationsPtr, and scalesPtr are required when using wasm pointers.");let a=e.instanceCount??0;P(a>0,"GlyphField: instanceCount is required when using wasm pointers."),this.setWasmSoA(e.positionsPtr,e.rotationsPtr,e.scalesPtr,e.attributesPtr??0,a)}else e.positions||e.rotations||e.scales||e.attributes?this.setCPUData(e.positions??null,e.rotations??null,e.scales??null,e.attributes??null,{keepCPUData:this._keepCPUData,instanceCount:e.instanceCount}):e.instanceCount!==void 0&&(this._instanceCount=e.instanceCount|0,this._dataDirty=!1)}applyExplicitBounds(e){if(e.boundsMin&&e.boundsMax){let t=qe(e.boundsMin,e.boundsMax);this.setBounds(t,"explicit"),e.boundsCenter&&(this.boundsCenter=[e.boundsCenter[0],e.boundsCenter[1],e.boundsCenter[2]]),e.boundsRadius!==void 0&&(this.boundsRadius=Math.max(0,e.boundsRadius));return}if(e.boundsCenter||e.boundsRadius!==void 0){let t=e.boundsCenter??[0,0,0],r=e.boundsRadius??0;this.setBounds(ct(t,r),"explicit")}}setBounds(e,t){this.boundsMin=[e.boxMin[0],e.boxMin[1],e.boxMin[2]],this.boundsMax=[e.boxMax[0],e.boxMax[1],e.boxMax[2]],this.boundsCenter=[e.sphereCenter[0],e.sphereCenter[1],e.sphereCenter[2]],this.boundsRadius=e.sphereRadius,this._boundsSource=t}clearComputedBoundsIfNeeded(){this._boundsSource==="computed"&&(this._boundsSource="none",this.boundsMin=[0,0,0],this.boundsMax=[0,0,0],this.boundsCenter=[0,0,0],this.boundsRadius=0)}get instanceCount(){return this._instanceCount}get ndShape(){return this._ndShape?this._ndShape.slice():null}set ndShape(e){this._ndShape=ss(e)}get scaleTransform(){return We(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=Jr(e),this._uniformDirty=!0,this.emitVisualChange("scale")}applyScaleStats(e){let t=We(this._scaleTransform);Number.isFinite(e.min)&&(t.domainMin=e.min),Number.isFinite(e.max)&&(t.domainMax=e.max),e.percentileMin!==null&&e.percentileMax!==null&&(t.clampMin=e.percentileMin,t.clampMax=e.percentileMax),this._scaleTransform=Jr(t),this._uniformDirty=!0,this.emitVisualChange("scale")}onVisualChange(e){return this._visualChangeListeners.add(e),()=>this._visualChangeListeners.delete(e)}getScaleSourceDescriptor(e=this._scaleRevision){return!this.attributesBuffer||this._instanceCount<=0?null:{buffer:this.attributesBuffer,count:this._instanceCount,componentCount:this._scaleTransform.componentCount,componentIndex:this._scaleTransform.componentIndex,valueMode:this._scaleTransform.valueMode,stride:this._scaleTransform.stride,offset:this._scaleTransform.offset,revision:e}}set instanceCount(e){let t=e|0;t!==this._instanceCount&&(P(t>=0,"GlyphField: instanceCount must be >= 0."),this._instanceCount=t,this._dataDirty=!0,this._scaleRevision++)}get colorMode(){return this._colorMode}set colorMode(e){e!==this._colorMode&&(this._colorMode=e,this._uniformDirty=!0)}get colormap(){return this._colormap}set colormap(e){this._colormap=e,this._uniformDirty=!0,this.bindGroupKey=null,this.emitVisualChange("colormap")}get colormapStops(){return this._colormapStops}set colormapStops(e){this._colormapStops=ro(e),this._uniformDirty=!0,this.emitVisualChange("colormap")}getColormapKey(){let e=this._colormap;return e instanceof H?`cm:${e.id}`:`cm:${e}`}getColormapForBinding(){let e=this._colormap;return e instanceof H?e:e==="custom"?H.builtin("grayscale"):H.builtin(e)}get opacity(){return this._opacity}set opacity(e){e!==this._opacity&&(this._opacity=e,this._uniformDirty=!0)}get lit(){return this._lit}set lit(e){let t=!!e;t!==this._lit&&(this._lit=t,this._uniformDirty=!0)}get solidColor(){return this._solidColor}set solidColor(e){this._solidColor=[e[0],e[1],e[2],e[3]],this._uniformDirty=!0}markDataDirty(){this._usingExternalBuffers||(this._dataDirty=!0),this._scaleRevision++}markUniformsDirty(){this._uniformDirty=!0}getAttributeRecord(e){let t=this._attributesCPU;if(!t||!Number.isInteger(e)||e<0||e>=this._instanceCount)return null;let r=e*4;return[t[r+0],t[r+1],t[r+2],t[r+3]]}mapLinearIndexToNd(e){return ls(this._ndShape,e)}setCPUData(e,t,r,i,o={}){e&&P(e.length%4===0,"GlyphField: positions length must be a multiple of 4 (x,y,z,_ per instance)."),t&&P(t.length%4===0,"GlyphField: rotations length must be a multiple of 4 (qx,qy,qz,qw per instance)."),r&&P(r.length%4===0,"GlyphField: scales length must be a multiple of 4 (sx,sy,sz,_ per instance)."),i&&P(i.length%4===0,"GlyphField: attributes length must be a multiple of 4 (a0,a1,a2,a3 per instance).");let a=o.instanceCount!==void 0?o.instanceCount|0:e?e.length/4:t?t.length/4:r?r.length/4:i?i.length/4:0;P(a>=0,"GlyphField: instanceCount must be >= 0."),a>0&&P(!!e&&!!t&&!!r,"GlyphField: positions, rotations, and scales are required for CPU-backed glyph fields."),e&&P(e.length/4===a,"GlyphField: positions length does not match instanceCount."),t&&P(t.length/4===a,"GlyphField: rotations length does not match instanceCount."),r&&P(r.length/4===a,"GlyphField: scales length does not match instanceCount."),i&&P(i.length/4===a,"GlyphField: attributes length does not match instanceCount."),this._instanceCount=a,this._positionsCPU=e,this._rotationsCPU=t,this._scalesCPU=r,this._attributesCPU=i,this._positionsPtr=0,this._rotationsPtr=0,this._scalesPtr=0,this._attributesPtr=0,this._usingWasmPtrs=!1,this._usingExternalBuffers=!1,this._keepCPUData=o.keepCPUData??this._keepCPUData,this.clearComputedBoundsIfNeeded(),this._dataDirty=!0,this._scaleRevision++,this.bindGroupKey=null}setWasmSoA(e,t,r,i,o){let a=o|0;P(a>0,"GlyphField: instanceCount must be > 0."),this._instanceCount=a,this._positionsCPU=null,this._rotationsCPU=null,this._scalesCPU=null,this._attributesCPU=null,this._positionsPtr=e>>>0,this._rotationsPtr=t>>>0,this._scalesPtr=r>>>0,this._attributesPtr=i>>>0,this._usingWasmPtrs=!0,this._usingExternalBuffers=!1,this.clearComputedBoundsIfNeeded(),this._dataDirty=!0,this._scaleRevision++,this.bindGroupKey=null}setBuffers(e,t,r,i,o){let a=o|0;P(a>0,"GlyphField: instanceCount must be > 0."),this._instanceCount=a,this.positionsBuffer=e,this.rotationsBuffer=t,this.scalesBuffer=r,this.attributesBuffer=i,this._positionsCPU=null,this._rotationsCPU=null,this._scalesCPU=null,this._attributesCPU=null,this._positionsPtr=0,this._rotationsPtr=0,this._scalesPtr=0,this._attributesPtr=0,this._usingWasmPtrs=!1,this._usingExternalBuffers=!0,this.clearComputedBoundsIfNeeded(),this._dataDirty=!1,this._scaleRevision++,this.bindGroupKey=null}computeBoundsFromCPUData(){let e=this._positionsCPU,t=this._scalesCPU,r=this._instanceCount;if(!e||!t||r<=0)return;let i=this._rotationsCPU,o=_.allocF32(e.length),a=_.allocF32(t.length),s=0,l=_.allocF32(3),u=_.allocF32(3),m=_.allocF32(3),c=_.allocF32(3),d=_.allocF32(1);try{_.f32view(o,e.length).set(e),_.f32view(a,t.length).set(t),i&&(s=_.allocF32(i.length),_.f32view(s,i.length).set(i)),_.writeF32(l,3,this.geometry.boundsCenter),Tt.glyphInstances(u,m,c,d,o,a,s,r,l,this.geometry.boundsRadius);let f=_.f32view(u,3),p=_.f32view(m,3);this.setBounds(qe([f[0],f[1],f[2]],[p[0],p[1],p[2]]),"computed")}finally{_.freeF32(d,1),_.freeF32(c,3),_.freeF32(m,3),_.freeF32(u,3),_.freeF32(l,3),s&&i&&_.freeF32(s,i.length),_.freeF32(a,t.length),_.freeF32(o,e.length)}}getLocalBounds(){return this._boundsSource==="none"&&this._positionsCPU&&this._scalesCPU&&this.computeBoundsFromCPUData(),this._boundsSource==="none"?ut(this._instanceCount>0):qe(this.boundsMin,this.boundsMax)}getWorldBounds(){return dt(this.getLocalBounds(),this.transform.worldMatrix)}getBounds(){return this.getWorldBounds()}upload(e,t){if(this._usingExternalBuffers||!this._dataDirty)return;if(this._instanceCount<=0){this._dataDirty=!1;return}let r=oe.bytes(),i=this._instanceCount*16,o=(a,s,l,u)=>{if(!s&&!l)return a;let m=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,c=i;a||(a=e.createBuffer({size:c,usage:m,label:u}));try{s?t.writeBuffer(a,0,s.buffer,s.byteOffset,Math.min(s.byteLength,c)):t.writeBuffer(a,0,r,l>>>0,c)}catch{a.destroy(),a=e.createBuffer({size:c,usage:m,label:u}),s?t.writeBuffer(a,0,s.buffer,s.byteOffset,Math.min(s.byteLength,c)):t.writeBuffer(a,0,r,l>>>0,c)}return a};this.positionsBuffer=o(this.positionsBuffer,this._positionsCPU,this._positionsPtr,"GlyphField.positions"),this.rotationsBuffer=o(this.rotationsBuffer,this._rotationsCPU,this._rotationsPtr,"GlyphField.rotations"),this.scalesBuffer=o(this.scalesBuffer,this._scalesCPU,this._scalesPtr,"GlyphField.scales"),this._attributesCPU||this._attributesPtr?this.attributesBuffer=o(this.attributesBuffer,this._attributesCPU,this._attributesPtr,"GlyphField.attributes"):this.attributesBuffer||(this.attributesBuffer=e.createBuffer({size:16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,label:"GlyphField.attributesDummy"})),this._keepCPUData||(this._positionsCPU=null,this._rotationsCPU=null,this._scalesCPU=null,this._attributesCPU=null),this._dataDirty=!1,this.bindGroupKey=null}getUniformBufferSize(){return os}getUniformData(){let e=new Float32Array(oo);e.fill(0),Ne(this._scaleTransform,e,0),e[20]=as(this._opacity),e[21]=typeof this._colormap=="string"&&this._colormap==="custom"?Math.min(8,Math.max(2,this._colormapStops.length)):0,e[22]=us(this._colorMode),e[23]=this._lit?1:0,e[24]=this._solidColor[0],e[25]=this._solidColor[1],e[26]=this._solidColor[2],e[27]=this._solidColor[3];let t=this._colormapStops,r=Math.min(8,Math.max(2,t.length));for(let i=0;i<8;i++){let o=t[Math.min(i,r-1)],a=28+i*4;e[a+0]=o[0],e[a+1]=o[1],e[a+2]=o[2],e[a+3]=o[3]}return e}get dirtyUniforms(){return this._uniformDirty}markUniformsClean(){this._uniformDirty=!1}emitVisualChange(e){for(let t of this._visualChangeListeners)try{t(e)}catch{}}destroy(){this.positionsBuffer?.destroy(),this.rotationsBuffer?.destroy(),this.scalesBuffer?.destroy(),this.attributesBuffer?.destroy(),this.uniformBuffer?.destroy(),this.positionsBuffer=null,this.rotationsBuffer=null,this.scalesBuffer=null,this.attributesBuffer=null,this.uniformBuffer=null,this.bindGroup=null,this.bindGroupKey=null,this._positionsCPU=null,this._rotationsCPU=null,this._scalesCPU=null,this._attributesCPU=null,this._ndShape=null,this._instanceCount=0,this._visualChangeListeners.clear(),this.transform.dispose()}};var ao="struct Params { rtMetrics: vec4f, threshold: f32, _pad0: f32, _pad1: f32, _pad2: f32 }; @group(0) @binding(0) var<uniform> params: Params; @group(0) @binding(1) var sampLinear: sampler; @group(0) @binding(2) var sampPoint: sampler; @group(0) @binding(3) var sceneTex: texture_2d<f32>; @group(0) @binding(4) var edgesTex: texture_2d<f32>; @group(0) @binding(5) var blendTex: texture_2d<f32>; struct VertexOutput { @builtin(position) pos: vec4f, @location(0) uv: vec2f }; @vertex fn vs_fullscreen(@builtin(vertex_index) vi: u32) -> VertexOutput { var positions = array<vec2f, 3>( vec2f(-1.0, -1.0), vec2f(3.0, -1.0), vec2f(-1.0, 3.0) ); var uvs = array<vec2f, 3>( vec2f(0.0, 1.0), vec2f(2.0, 1.0), vec2f(0.0, -1.0) ); var out: VertexOutput; out.pos = vec4f(positions[vi], 0.0, 1.0); out.uv = uvs[vi]; return out; } fn luma(rgb: vec3f) -> f32 { return dot(rgb, vec3f(0.2126, 0.7152, 0.0722)); } @fragment fn fs_smaa_edges(in: VertexOutput) -> @location(0) vec4f { let t = params.rtMetrics.xy; let c = textureSampleLevel(sceneTex, sampPoint, in.uv, 0.0).rgb; let l = luma(c); let lLeft = luma(textureSampleLevel(sceneTex, sampPoint, in.uv + vec2f(-t.x, 0.0), 0.0).rgb); let lTop = luma(textureSampleLevel(sceneTex, sampPoint, in.uv + vec2f(0.0, -t.y), 0.0).rgb); let dLeft = abs(l - lLeft); let dTop = abs(l - lTop); let eV = select(0.0, 1.0, dLeft >= params.threshold); let eH = select(0.0, 1.0, dTop >= params.threshold); return vec4f(eV, eH, 0.0, 0.0); } fn edgeV(uv: vec2f) -> bool { return textureSampleLevel(edgesTex, sampPoint, uv, 0.0).r > 0.5; } fn edgeH(uv: vec2f) -> bool { return textureSampleLevel(edgesTex, sampPoint, uv, 0.0).g > 0.5; } @fragment fn fs_smaa_weights(in: VertexOutput) -> @location(0) vec4f { let t = params.rtMetrics.xy; let e = textureSampleLevel(edgesTex, sampPoint, in.uv, 0.0); var wLeft: f32 = 0.0; var wTop: f32 = 0.0; if (e.r > 0.5) { var up: i32 = 0; var down: i32 = 0; for (var s: i32 = 1; s <= 8; s = s + 1) { if (!edgeV(in.uv + vec2f(0.0, -t.y * f32(s)))) { break; } up = up + 1; } for (var s: i32 = 1; s <= 8; s = s + 1) { if (!edgeV(in.uv + vec2f(0.0, t.y * f32(s)))) { break; } down = down + 1; } let len = f32(up + down + 1); wLeft = clamp(len / 17.0, 0.0, 1.0) * 0.5; } if (e.g > 0.5) { var left: i32 = 0; var right: i32 = 0; for (var s: i32 = 1; s <= 8; s = s + 1) { if (!edgeH(in.uv + vec2f(-t.x * f32(s), 0.0))) { break; } left = left + 1; } for (var s: i32 = 1; s <= 8; s = s + 1) { if (!edgeH(in.uv + vec2f(t.x * f32(s), 0.0))) { break; } right = right + 1; } let len = f32(left + right + 1); wTop = clamp(len / 17.0, 0.0, 1.0) * 0.5; } return vec4f(wLeft, wTop, 0.0, 0.0); } @fragment fn fs_smaa_neighborhood(in: VertexOutput) -> @location(0) vec4f { let t = params.rtMetrics.xy; let c = textureSampleLevel(sceneTex, sampLinear, in.uv, 0.0); let w = textureSampleLevel(blendTex, sampPoint, in.uv, 0.0); let wL = w.r; let wT = w.g; let wR = textureSampleLevel(blendTex, sampPoint, in.uv + vec2f(t.x, 0.0), 0.0).r; let wB = textureSampleLevel(blendTex, sampPoint, in.uv + vec2f(0.0, t.y), 0.0).g; var bestW: f32 = 0.0; var dir: i32 = -1; if (wL > bestW) { bestW = wL; dir = 0; } if (wR > bestW) { bestW = wR; dir = 1; } if (wT > bestW) { bestW = wT; dir = 2; } if (wB > bestW) { bestW = wB; dir = 3; } if (bestW <= 0.0) { return c; } var n: vec4f = c; if (dir == 0) { n = textureSampleLevel(sceneTex, sampLinear, in.uv + vec2f(-t.x, 0.0), 0.0); } else if (dir == 1) { n = textureSampleLevel(sceneTex, sampLinear, in.uv + vec2f(t.x, 0.0), 0.0); } else if (dir == 2) { n = textureSampleLevel(sceneTex, sampLinear, in.uv + vec2f(0.0, -t.y), 0.0); } else { n = textureSampleLevel(sceneTex, sampLinear, in.uv + vec2f(0.0, t.y), 0.0); } return mix(c, n, bestW); }";var rn="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct PointData { position: vec3f, scalar: f32 }; @group(1) @binding(0) var<storage, read> points: array<PointData>; struct PointCloudUniforms { sizeParams: vec4f, scaleSource: vec4f, scaleDomain: vec4f, scaleClamp: vec4f, scaleParams: vec4f, scaleFlags: vec4f, visual: vec4f, colors: array<vec4f, 8> }; @group(1) @binding(1) var<uniform> pc: PointCloudUniforms; @group(1) @binding(2) var colormapSampler: sampler; @group(1) @binding(3) var colormapTex: texture_1d<f32>; struct VertexOutput { @builtin(position) position: vec4f, @location(0) col: vec4f, @location(1) pointCoord: vec2f, }; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3f, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; fn srgbFromLinear(linear: vec3f) -> vec3f { let a = 0.055; let lo = 12.92 * linear; let hi = (1.0 + a) * pow(linear, vec3f(1.0 / 2.4)) - vec3f(a); let useHi = linear > vec3f(0.0031308); return select(lo, hi, useHi); } fn sampleCustomStops(t: f32, stopCount: u32) -> vec4f { let n = min(stopCount, 8u); let x = scale_clamp01(t) * f32(n - 1u); let i = u32(floor(x)); let f = x - f32(i); if (i >= n - 1u) { return pc.colors[n - 1u]; } return pc.colors[i] + f * (pc.colors[i + 1u] - pc.colors[i]); } fn colormap(tIn: f32) -> vec4f { let t = scale_clamp01(tIn); let stopCount = u32(pc.visual.z + 0.5); if (stopCount >= 2u) { return sampleCustomStops(t, stopCount); } return textureSampleLevel(colormapTex, colormapSampler, t, 0.0); } fn vec4Component(v: vec4f, idx: u32) -> f32 { if (idx == 0u) { return v.x; } if (idx == 1u) { return v.y; } if (idx == 2u) { return v.z; } return v.w; } fn shiftedValueVector(v: vec4f, offsetFloats: f32) -> vec4f { let o = min(3u, u32(offsetFloats + 0.5)); let i0 = min(3u, o + 0u); let i1 = min(3u, o + 1u); let i2 = min(3u, o + 2u); let i3 = min(3u, o + 3u); return vec4f(vec4Component(v, i0), vec4Component(v, i1), vec4Component(v, i2), vec4Component(v, i3)); } @vertex fn vs_main(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> VertexOutput { let p = points[instanceIndex]; let worldPos = model.model * vec4f(p.position, 1.0); let clip = camera.viewProj * worldPos; let baseSize = pc.sizeParams.x; let minSize = pc.sizeParams.y; let maxSize = pc.sizeParams.z; let atten = pc.sizeParams.w; var sizePx = baseSize; if (atten > 0.0) { let dist = distance(camera.position, worldPos.xyz); sizePx = baseSize * (atten / max(dist, 1e-6)); } sizePx = clamp(sizePx, minSize, maxSize); let uv = vec2f( f32((vertexIndex + 2u) / 3u % 2u), f32((vertexIndex + 1u) / 3u % 2u) ); let row0 = vec3f(camera.viewProj[0][0], camera.viewProj[1][0], camera.viewProj[2][0]); let row1 = vec3f(camera.viewProj[0][1], camera.viewProj[1][1], camera.viewProj[2][1]); let aspect = length(row1) / max(length(row0), 1e-6); let ndcSize = (sizePx * 2.0) / max(camera._pad0, 1.0); let offsetX = (uv.x - 0.5) * ndcSize / aspect * clip.w; let offsetY = -(uv.y - 0.5) * ndcSize * clip.w; let rawVec = shiftedValueVector(vec4f(p.position, p.scalar), pc.scaleDomain.z); let componentCount = u32(pc.scaleSource.x + 0.5); let componentIndex = u32(pc.scaleSource.y + 0.5); let valueMode = u32(pc.scaleSource.z + 0.5); let rawValue = scale_select_value(rawVec, componentCount, componentIndex, valueMode); let finiteRaw = scale_is_finite(rawValue); var t = scale_apply_transform(rawValue, vec4f(pc.scaleDomain.x, pc.scaleDomain.y, 0.0, pc.scaleDomain.w), pc.scaleClamp, pc.scaleParams, pc.scaleFlags); var c = colormap(t); if (!finiteRaw) { c = vec4f(0.0, 0.0, 0.0, 0.0); } c.a = c.a * scale_clamp01(pc.visual.x); var out: VertexOutput; out.position = clip + vec4f(offsetX, offsetY, 0.0, 0.0); out.pointCoord = uv * 2.0 - vec2f(1.0, 1.0); out.col = vec4f(srgbFromLinear(c.rgb), c.a); return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let uv = in.pointCoord; let r2 = dot(uv, uv); if (r2 > 1.0) { discard; } let falloff = (1.0 - r2); let alpha = falloff * falloff; return vec4f(in.col.rgb, in.col.a * alpha); }";var so="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } @group(1) @binding(0) var<storage, read> positions: array<vec4f>; @group(1) @binding(1) var<storage, read> rotations: array<vec4f>; @group(1) @binding(2) var<storage, read> scales: array<vec4f>; @group(1) @binding(3) var<storage, read> attributes: array<vec4f>; struct GlyphFieldUniforms { scaleSource: vec4f, scaleDomain: vec4f, scaleClamp: vec4f, scaleParams: vec4f, scaleFlags: vec4f, visual: vec4f, solidColor: vec4f, colors: array<vec4f, 8> }; @group(1) @binding(4) var<uniform> glyph: GlyphFieldUniforms; @group(1) @binding(5) var colormapSampler: sampler; @group(1) @binding(6) var colormapTex: texture_1d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) @interpolate(flat) attrib: vec4f }; struct CameraUniforms { viewProj: mat4x4f, position: vec3f, _pad0: f32 }; struct ModelUniforms { model: mat4x4f, normal: mat4x4f }; struct Light { position: vec4f, color: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; fn srgbFromLinear(linear: vec3f) -> vec3f { let a = 0.055; let lo = 12.92 * linear; let hi = (1.0 + a) * pow(linear, vec3f(1.0 / 2.4)) - vec3f(a); let useHi = linear > vec3f(0.0031308); return select(lo, hi, useHi); } fn rotateByQuat(v: vec3f, q: vec4f) -> vec3f { let u = q.xyz; let s = q.w; let t = 2.0 * cross(u, v); return v + s * t + cross(u, t); } fn sampleCustomStops(t: f32) -> vec4f { let count = u32(glyph.visual.y + 0.5); if (count <= 1u) { return glyph.colors[0u]; } let n = min(count, 8u); let x = scale_clamp01(t) * f32(n - 1u); let i = u32(floor(x)); let f = x - f32(i); if (i >= n - 1u) { return glyph.colors[n - 1u]; } return glyph.colors[i] + f * (glyph.colors[i + 1u] - glyph.colors[i]); } fn colormap(tIn: f32) -> vec4f { let t = scale_clamp01(tIn); let stopCount = u32(glyph.visual.y + 0.5); if (stopCount >= 2u) { return sampleCustomStops(t); } return textureSample(colormapTex, colormapSampler, t); } fn applyLighting(worldPos: vec3f, N: vec3f, baseColor: vec3f) -> vec3f { var Lo = lighting.ambient.rgb * baseColor; let lightCount = min(lighting.lightCount, 8u); for (var i = 0u; i < lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - worldPos; let distance = length(lightDir); L = select(vec3f(0.0, 1.0, 0.0), lightDir / distance, distance > 1e-6); attenuation = 1.0 / max(distance * distance, 1e-6); let range = light.params.x; if (range > 0.0) { let f = scale_clamp01(1.0 - distance / range); attenuation *= f * f; } } let NdotL = max(dot(N, L), 0.0); let radiance = light.color.rgb * light.color.a * attenuation; Lo += baseColor * radiance * NdotL; } return Lo; } fn vec4Component(v: vec4f, idx: u32) -> f32 { if (idx == 0u) { return v.x; } if (idx == 1u) { return v.y; } if (idx == 2u) { return v.z; } return v.w; } fn shiftedValueVector(v: vec4f, offsetFloats: f32) -> vec4f { let o = min(3u, u32(offsetFloats + 0.5)); let i0 = min(3u, o + 0u); let i1 = min(3u, o + 1u); let i2 = min(3u, o + 2u); let i3 = min(3u, o + 3u); return vec4f(vec4Component(v, i0), vec4Component(v, i1), vec4Component(v, i2), vec4Component(v, i3)); } @vertex fn vs_main(in: VertexInput, @builtin(instance_index) instanceIndex: u32) -> VertexOutput { let p4 = positions[instanceIndex]; let q = rotations[instanceIndex]; let s4 = scales[instanceIndex]; let a4 = attributes[instanceIndex]; let scl = s4.xyz; let localPos = rotateByQuat(in.position * scl, q) + p4.xyz; let worldPos4 = model.model * vec4f(localPos, 1.0); let worldPos = worldPos4.xyz; let invScale = 1.0 / max(abs(scl), vec3f(1e-6)); let localN = in.normal * invScale; let instN = rotateByQuat(localN, q); let worldN = normalize((model.normal * vec4f(instN, 0.0)).xyz); var out: VertexOutput; out.position = camera.viewProj * vec4f(worldPos, 1.0); out.worldPos = worldPos; out.normal = worldN; out.attrib = a4; return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let colorMode = u32(round(glyph.visual.z)); let lit = glyph.visual.w > 0.5; var baseColor: vec3f; var alpha: f32 = 1.0; if (colorMode == 0u) { baseColor = in.attrib.rgb; alpha = in.attrib.a; } else if (colorMode == 1u) { let shifted = shiftedValueVector(in.attrib, glyph.scaleDomain.z); let componentCount = u32(glyph.scaleSource.x + 0.5); let componentIndex = u32(glyph.scaleSource.y + 0.5); let valueMode = u32(glyph.scaleSource.z + 0.5); let rawValue = scale_select_value(shifted, componentCount, componentIndex, valueMode); if (!scale_is_finite(rawValue)) { discard; } let t = scale_apply_transform(rawValue, vec4f(glyph.scaleDomain.x, glyph.scaleDomain.y, 0.0, glyph.scaleDomain.w), glyph.scaleClamp, glyph.scaleParams, glyph.scaleFlags); let cmap = colormap(t); baseColor = cmap.rgb; alpha = cmap.a; } else { baseColor = glyph.solidColor.rgb; alpha = glyph.solidColor.a; } baseColor = max(baseColor, vec3f(0.0)); alpha = scale_clamp01(alpha) * scale_clamp01(glyph.visual.x); var shaded = baseColor; if (lit) { shaded = applyLighting(in.worldPos, normalize(in.normal), baseColor); } return vec4f(srgbFromLinear(shaded), alpha); }";var lo="enable primitive_index; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<uniform> pick: PickUniforms; struct VertexOutput { @builtin(position) position: vec4<f32> }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; @vertex fn vs_main(@location(0) position: vec3<f32>) -> VertexOutput { var out: VertexOutput; out.position = camera.viewProj * model.model * vec4<f32>(position, 1.0); return out; } @fragment fn fs_main(@builtin(position) fragCoord: vec4<f32>, @builtin(primitive_index) primitiveIndex: u32) -> FragmentOutput { var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + primitiveIndex); out.depth = fragCoord.z; return out; }";var uo="enable primitive_index; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; struct SkinBuffer { joints: array<mat4x4<f32>> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<uniform> pick: PickUniforms; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; struct VertexOutput { @builtin(position) position: vec4<f32> }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; @vertex fn vs_main(@location(0) position: vec3<f32>, @location(3) joints: vec4<u32>, @location(4) weights: vec4<f32> ) -> VertexOutput { var out: VertexOutput; let m = skin.joints[joints.x] * weights.x + skin.joints[joints.y] * weights.y + skin.joints[joints.z] * weights.z + skin.joints[joints.w] * weights.w; let localPos = m * vec4<f32>(position, 1.0); out.position = camera.viewProj * model.model * localPos; return out; } @fragment fn fs_main(@builtin(position) fragCoord: vec4<f32>, @builtin(primitive_index) primitiveIndex: u32) -> FragmentOutput { var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + primitiveIndex); out.depth = fragCoord.z; return out; }";var co="enable primitive_index; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; struct SkinBuffer { joints: array<mat4x4<f32>> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<uniform> pick: PickUniforms; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; struct VertexOutput { @builtin(position) position: vec4<f32> }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; @vertex fn vs_main(@location(0) position: vec3<f32>, @location(3) joints0: vec4<u32>, @location(4) weights0: vec4<f32>, @location(5) joints1: vec4<u32>, @location(6) weights1: vec4<f32>) -> VertexOutput { var out: VertexOutput; let m = skin.joints[joints0.x] * weights0.x + skin.joints[joints0.y] * weights0.y + skin.joints[joints0.z] * weights0.z + skin.joints[joints0.w] * weights0.w + skin.joints[joints1.x] * weights1.x + skin.joints[joints1.y] * weights1.y + skin.joints[joints1.z] * weights1.z + skin.joints[joints1.w] * weights1.w; let localPos = m * vec4<f32>(position, 1.0); out.position = camera.viewProj * model.model * localPos; return out; } @fragment fn fs_main(@builtin(position) fragCoord: vec4<f32>, @builtin(primitive_index) primitiveIndex: u32) -> FragmentOutput { var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + primitiveIndex); out.depth = fragCoord.z; return out; }";var nn="struct PointData { position: vec3<f32>, scalar: f32 }; struct PointCloudUniforms { sizeParams: vec4<f32>, scalarParams: vec4<f32>, options: vec4<f32>, colors: array<vec4<f32>, 8> }; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<storage, read> points: array<PointData>; @group(1) @binding(1) var<uniform> pc: PointCloudUniforms; @group(2) @binding(0) var<uniform> pick: PickUniforms; struct VertexOutput { @builtin(position) position: vec4<f32>, @location(0) pointCoord: vec2<f32>, @location(1) @interpolate(flat) pointIndex: u32 }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; @vertex fn vs_main(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> VertexOutput { let p = points[instanceIndex]; let worldPos = model.model * vec4<f32>(p.position, 1.0); let clip = camera.viewProj * worldPos; let dist = distance(camera.position, worldPos.xyz); let baseSize = pc.sizeParams.x; let minSize = pc.sizeParams.y; let maxSize = pc.sizeParams.z; let atten = pc.sizeParams.w; var sizePx = baseSize; if (atten > 0.0) { sizePx = baseSize * (atten / max(dist, 1e-6)); } sizePx = clamp(sizePx, minSize, maxSize); var uv = vec2<f32>(0.0); if (vertexIndex == 0u) { uv = vec2<f32>(0.0, 0.0); } else if (vertexIndex == 1u) { uv = vec2<f32>(1.0, 0.0); } else if (vertexIndex == 2u) { uv = vec2<f32>(0.0, 1.0); } else if (vertexIndex == 3u) { uv = vec2<f32>(1.0, 0.0); } else if (vertexIndex == 4u) { uv = vec2<f32>(1.0, 1.0); } else if (vertexIndex == 5u) { uv = vec2<f32>(0.0, 1.0); } let row0 = vec3<f32>(camera.viewProj[0][0], camera.viewProj[1][0], camera.viewProj[2][0]); let row1 = vec3<f32>(camera.viewProj[0][1], camera.viewProj[1][1], camera.viewProj[2][1]); let aspect = length(row1) / max(length(row0), 1e-6); let ndcSize = (sizePx * 2.0) / max(camera._pad0, 1.0); let offsetX = (uv.x - 0.5) * ndcSize / aspect * clip.w; let offsetY = -(uv.y - 0.5) * ndcSize * clip.w; var out: VertexOutput; out.position = clip + vec4<f32>(offsetX, offsetY, 0.0, 0.0); out.pointCoord = uv; out.pointIndex = instanceIndex; return out; } @fragment fn fs_main(in: VertexOutput) -> FragmentOutput { let uv = in.pointCoord * 2.0 - vec2<f32>(1.0, 1.0); let r2 = dot(uv, uv); if (r2 > 1.0) { discard; } var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + in.pointIndex); out.depth = in.position.z; return out; }";var on="@group(1) @binding(0) var<storage, read> positions: array<vec4<f32>>; @group(1) @binding(1) var<storage, read> rotations: array<vec4<f32>>; @group(1) @binding(2) var<storage, read> scales: array<vec4<f32>>; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(2) @binding(0) var<uniform> pick: PickUniforms; struct VertexInput { @location(0) position: vec3<f32> }; struct VertexOutput { @builtin(position) position: vec4<f32>, @location(0) @interpolate(flat) instanceIndex: u32 }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; fn rotateByQuat(v: vec3<f32>, q: vec4<f32>) -> vec3<f32> { let u = q.xyz; let s = q.w; let t = 2.0 * cross(u, v); return v + s * t + cross(u, t); } @vertex fn vs_main(in: VertexInput, @builtin(instance_index) instanceIndex: u32) -> VertexOutput { let p4 = positions[instanceIndex]; let q = rotations[instanceIndex]; let s4 = scales[instanceIndex]; let localPos = rotateByQuat(in.position * s4.xyz, q) + p4.xyz; let worldPos = model.model * vec4<f32>(localPos, 1.0); var out: VertexOutput; out.position = camera.viewProj * worldPos; out.instanceIndex = instanceIndex; return out; } @fragment fn fs_main(in: VertexOutput) -> FragmentOutput { var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + in.instanceIndex); out.depth = in.position.z; return out; }";var Sr=class n{canvas;context;device;queue;format;depthTexture;depthView;width=0;height=0;smaaEnabled=!1;smaaSceneColorTexture=null;smaaSceneColorView=null;smaaEdgesTexture=null;smaaEdgesView=null;smaaBlendTexture=null;smaaBlendView=null;smaaParamsBuffer=null;smaaSamplerPoint=null;smaaSamplerLinear=null;smaaShaderModule=null;smaaEdgePipeline=null;smaaWeightPipeline=null;smaaNeighborhoodPipeline=null;smaaEdgeBindGroupLayout=null;smaaWeightBindGroupLayout=null;smaaNeighborhoodBindGroupLayout=null;smaaEdgeBindGroup=null;smaaWeightBindGroup=null;smaaNeighborhoodBindGroup=null;globalBindGroupLayout;globalBindGroups=[];skinBindGroupLayout;cameraUniformBuffer;modelUniformBuffers=[];modelBufferIndex=0;MODEL_BUFFER_POOL_SIZE=64;lightingUniformBuffer;instanceBuffer=null;instanceBufferCapacityBytes=0;instanceBufferOffset=0;INSTANCE_STRIDE_BYTES=128;pipelineCache=new Map;shaderCache=new Map;drawItemPool=[];drawItemPoolUsed=0;opaqueDrawList=[];transparentDrawList=[];pointCloudBindGroupLayout=null;pointCloudDrawItemPool=[];pointCloudDrawItemPoolUsed=0;opaquePointCloudDrawList=[];transparentPointCloudDrawList=[];glyphFieldBindGroupLayout=null;glyphFieldDummyAttributesBuffer=null;glyphFieldDrawItemPool=[];glyphFieldDrawItemPoolUsed=0;opaqueGlyphFieldDrawList=[];transparentGlyphFieldDrawList=[];cullGlyphFieldScratch=[];transparentMergedDrawList=[];cullPointCloudScratch=[];objectIds=new WeakMap;objectsById=new Map;nextObjectId=1;cameraUniformStagingPtr;lightingUniformStagingPtr;modelUniformStagingPtr;cameraUniformStagingView;lightingUniformStagingView;lightingCountView;modelUniformStagingView;_wasmBuffer=null;frustumCullingEnabled=!0;frustumCullingStatsEnabled=!1;cullingStats={tested:0,visible:0};cullCentersPtr=0;cullRadiiPtr=0;cullCapacity=0;cullMeshScratch=[];fallbackSampler;fallbackWhiteTexture;fallbackWhiteViewLinear;fallbackWhiteViewSrgb;fallbackNormalTexture;fallbackNormalViewLinear;fallbackMRTex;fallbackMRViewLinear;fallbackOcclusionTex;fallbackOcclusionViewLinear;gpuTimingSupported=!1;gpuTimingEnabled=!1;gpuQuerySet=null;gpuResolveBuffer=null;gpuResultBuffer=null;gpuResultPending=!1;_gpuTimeNs=null;dataMaterialDummyDataBuffer=null;pickBindGroupLayout=null;pickUniformBuffers=[];pickBindGroups=[];pickIdTexture=null;pickIdView=null;pickDepthTexture=null;pickDepthView=null;pickDepthPayloadTexture=null;pickDepthPayloadView=null;pickIdReadbackBuffer=null;pickDepthReadbackBuffer=null;pickIdReadbackCapacityBytes=0;pickDepthReadbackCapacityBytes=0;pickTail=Promise.resolve();constructor(e){this.canvas=e}static async create(e,t={}){let r=new n(e);return await r.init(t),r}async init(e){if(!navigator.gpu)throw new Error("WebGPU is not supported in this browser.");let t=await navigator.gpu.requestAdapter({powerPreference:e.powerPreference??"high-performance"});if(!t)throw new Error("Failed to get GPU adapter.");let r=[];t.features.has("timestamp-query")&&r.push("timestamp-query"),t.features.has("primitive-index")&&r.push("primitive-index");let i={};if(r.length>0&&(i.requiredFeatures=r),this.device=await t.requestDevice(i),this.gpuTimingSupported=this.device.features.has("timestamp-query"),this.queue=this.device.queue,this.context=this.canvas.getContext("webgpu"),!this.context)throw new Error("Failed to get WebGPU canvas context.");e.canvasFormat?this.format=e.canvasFormat:typeof navigator.gpu.getPreferredCanvasFormat=="function"?this.format=navigator.gpu.getPreferredCanvasFormat():this.format="rgba8unorm",this.smaaEnabled=e.antialias??!1,this.smaaEnabled&&this.createSmaaResources(),this.createGlobalBindGroupLayout(),this.createSkinBindGroupLayout(),this.createUniformBuffers(),this.createFallbackTextures(),this.resize(),this.frustumCullingEnabled=e.frustumCulling??!0,this.frustumCullingStatsEnabled=e.frustumCullingStats??!1}get gpu(){return{device:this.device,queue:this.queue,format:this.format}}get gpuTimeNs(){return this._gpuTimeNs}get isGpuTimingSupported(){return this.gpuTimingSupported}enableGpuTiming(e){let t=!!e;t&&this.gpuTimingSupported&&!this.gpuQuerySet&&this.createGpuTimingResources(),this.gpuTimingEnabled=t&&this.gpuTimingSupported}createGpuTimingResources(){if(this.gpuTimingSupported&&!this.gpuQuerySet)try{this.gpuQuerySet=this.device.createQuerySet({type:"timestamp",count:2}),this.gpuResolveBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),this.gpuResultBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ})}catch(e){this.gpuQuerySet=null,this.gpuResolveBuffer?.destroy(),this.gpuResolveBuffer=null,this.gpuResultBuffer?.destroy(),this.gpuResultBuffer=null,this.gpuTimingSupported=!1,this.gpuTimingEnabled=!1,console.warn("Renderer: failed to initialize GPU timing resources:",e)}}tryReadGpuTiming(){if(!this.gpuResultPending)return;let e=this.gpuResultBuffer;e&&e.mapState==="unmapped"&&(this.gpuResultPending=!1,e.mapAsync(GPUMapMode.READ).then(()=>{try{let t=e.getMappedRange(),r=new BigUint64Array(t),i=r[0],a=r[1]-i,s=a>0n?Number(a):0;this._gpuTimeNs=Number.isFinite(s)?s:0}catch{}finally{try{e.unmap()}catch{}}}).catch(()=>{try{e.unmap()}catch{}}))}resize(){let e=Math.max(1,window.devicePixelRatio||1),t=Math.max(1,Math.floor(this.canvas.clientWidth*e)),r=Math.max(1,Math.floor(this.canvas.clientHeight*e));t===this.width&&r===this.height||(this.width=t,this.height=r,this.canvas.width=t,this.canvas.height=r,this.context.configure({device:this.device,format:this.format,alphaMode:"opaque"}),this.depthTexture&&this.depthTexture.destroy(),this.depthTexture=Kn(this.device,this.width,this.height),this.depthView=this.depthTexture.createView(),this.smaaEnabled&&this.resizeSmaaTargets(),this.resizePickTargets())}get aspectRatio(){return this.width/this.height}refreshWasmStagingViews(){let e=_.memory().buffer;(e!==this._wasmBuffer||!this.cameraUniformStagingView||this.cameraUniformStagingView.byteOffset!==this.cameraUniformStagingPtr||!this.lightingUniformStagingView||this.lightingUniformStagingView.byteOffset!==this.lightingUniformStagingPtr||!this.modelUniformStagingView||this.modelUniformStagingView.byteOffset!==this.modelUniformStagingPtr)&&(this._wasmBuffer=e,this.cameraUniformStagingView=_.f32view(this.cameraUniformStagingPtr,20),this.lightingUniformStagingView=_.f32view(this.lightingUniformStagingPtr,104),this.lightingCountView=_.u32view(this.lightingUniformStagingPtr+16,1),this.modelUniformStagingView=_.f32view(this.modelUniformStagingPtr,32))}getObjectId(e){let t=this.objectIds.get(e);return t!==void 0||(t=this.nextObjectId++,this.objectIds.set(e,t),this.objectsById.set(t,e)),t}acquireDrawItem(){let e=this.drawItemPoolUsed++,t=this.drawItemPool[e];return t||(t={mesh:null,geometry:null,material:null,pipeline:null,pipelineId:0,materialId:0,geometryId:0,skinned:!1,skinned8:!1,sortKey:0},this.drawItemPool[e]=t),t}acquirePointCloudDrawItem(){let e=this.pointCloudDrawItemPoolUsed++,t=this.pointCloudDrawItemPool[e];return t||(t={cloud:null,pipeline:null,pipelineId:0,cloudId:0,sortKey:0},this.pointCloudDrawItemPool[e]=t),t}acquireGlyphFieldDrawItem(){let e=this.glyphFieldDrawItemPoolUsed++;return e>=this.glyphFieldDrawItemPool.length&&this.glyphFieldDrawItemPool.push({}),this.glyphFieldDrawItemPool[e]}ensureCullingCapacity(e){if(e<=this.cullCapacity)return;let t=Math.max(1,this.cullCapacity);for(;t<e;)t*=2;this.cullCentersPtr=_.allocF32(t*3),this.cullRadiiPtr=_.allocF32(t),this.cullCapacity=t}render(e,t){this.resize(),this.modelBufferIndex=0,this.instanceBufferOffset=0,this.cameraUniformStagingPtr=W.allocF32(20),this.lightingUniformStagingPtr=W.allocF32(104),this.modelUniformStagingPtr=W.allocF32(32),"aspect"in t&&(t.aspect=this.aspectRatio);let i=this.context.getCurrentTexture().createView();pe.updateAll(),this.writeCameraUniforms(t),this.writeLightingUniforms(e);let o=this.device.createCommandEncoder(),a=this.gpuTimingEnabled&&this.gpuQuerySet?{querySet:this.gpuQuerySet,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1}:void 0;if(this.smaaEnabled){(!this.smaaSceneColorView||!this.smaaEdgesView||!this.smaaBlendView)&&this.resizeSmaaTargets();let s=o.beginRenderPass({colorAttachments:[{view:this.smaaSceneColorView,clearValue:{r:e.background[0],g:e.background[1],b:e.background[2],a:1},loadOp:"clear",storeOp:"store"}],depthStencilAttachment:{view:this.depthView,depthClearValue:1,depthLoadOp:"clear",depthStoreOp:"store"},...a?{timestampWrites:a}:{}});this.buildDrawLists(e,t),this.buildPointCloudDrawLists(e,t),this.buildGlyphFieldDrawLists(e,t),this.executeDrawList(s,this.opaqueDrawList),this.executeGlyphFieldDrawList(s,this.opaqueGlyphFieldDrawList),this.executePointCloudDrawList(s,this.opaquePointCloudDrawList),this.executeTransparentMergedDrawList(s),s.end(),a&&this.gpuResolveBuffer&&this.gpuResultBuffer&&(o.resolveQuerySet(this.gpuQuerySet,0,2,this.gpuResolveBuffer,0),this.gpuResultBuffer.mapState==="unmapped"&&(o.copyBufferToBuffer(this.gpuResolveBuffer,0,this.gpuResultBuffer,0,16),this.gpuResultPending=!0)),this.executeSmaa(o,i)}else{let s=o.beginRenderPass({colorAttachments:[{view:i,clearValue:{r:e.background[0],g:e.background[1],b:e.background[2],a:1},loadOp:"clear",storeOp:"store"}],depthStencilAttachment:{view:this.depthView,depthClearValue:1,depthLoadOp:"clear",depthStoreOp:"store"},...a?{timestampWrites:a}:{}});this.buildDrawLists(e,t),this.buildPointCloudDrawLists(e,t),this.buildGlyphFieldDrawLists(e,t),this.executeDrawList(s,this.opaqueDrawList),this.executeGlyphFieldDrawList(s,this.opaqueGlyphFieldDrawList),this.executePointCloudDrawList(s,this.opaquePointCloudDrawList),this.executeTransparentMergedDrawList(s),s.end(),a&&this.gpuResolveBuffer&&this.gpuResultBuffer&&(o.resolveQuerySet(this.gpuQuerySet,0,2,this.gpuResolveBuffer,0),this.gpuResultBuffer.mapState==="unmapped"&&(o.copyBufferToBuffer(this.gpuResolveBuffer,0,this.gpuResultBuffer,0,16),this.gpuResultPending=!0))}this.queue.submit([o.finish()]),this.tryReadGpuTiming()}schedulePick(e){let t=this.pickTail.then(e,e);return this.pickTail=t.then(()=>{},()=>{}),t}pick(e,t,r,i,o={}){return this.schedulePick(()=>this.runPick(e,t,r,i))}pickRect(e,t,r,i,o,a,s={}){return this.schedulePick(()=>this.runPickRect(e,t,r,i,o,a,s))}pickLasso(e,t,r,i={}){return this.schedulePick(()=>this.runPickLasso(e,t,r,i))}clamp(e,t,r){return e<t?t:e>r?r:e}alignTo256(e){return e+255&-256}getPickMaxHits(e){let t=e.maxHits;return Number.isFinite(t)?Math.max(1,Math.floor(t)):1e4}toFramebufferPixel(e,t,r){let i=Math.max(1,r|0),o=e/Math.max(1,t)*i,a=Math.floor(o);return a<0?0:a>=i?i-1:a}toClientBounds(e,t,r,i,o,a){let s=this.clamp(e,0,o),l=this.clamp(t,0,a),u=this.clamp(r,0,o),m=this.clamp(i,0,a);return{x:s,y:l,width:Math.max(0,u-s),height:Math.max(0,m-l)}}resolveSinglePixel(e,t,r,i){if(!Number.isFinite(e)||!Number.isFinite(t)||e<0||t<0||e>=r||t>=i)return null;let o=this.toFramebufferPixel(e,r,this.width),a=this.toFramebufferPixel(t,i,this.height);return{px:o,py:a}}resolveRectPickQuery(e,t,r,i,o,a,s){let l=Math.min(e,r),u=Math.min(t,i),m=Math.max(e,r),c=Math.max(t,i),d=this.toClientBounds(l,u,m,c,a,s),f=Math.abs(e-r)<=1e-6,p=Math.abs(t-i)<=1e-6;if(f&&p){let S=this.resolveSinglePixel(e,t,a,s);return S?{mode:"rect",bounds:d,x:S.px,y:S.py,width:1,height:1,maxHits:o,lasso:null}:{mode:"rect",bounds:d,x:0,y:0,width:0,height:0,maxHits:o,lasso:null}}if(d.width<=0||d.height<=0)return{mode:"rect",bounds:d,x:0,y:0,width:0,height:0,maxHits:o,lasso:null};let b=Math.max(d.x,d.x+d.width-1e-6),g=Math.max(d.y,d.y+d.height-1e-6),x=this.toFramebufferPixel(d.x,a,this.width),M=this.toFramebufferPixel(d.y,s,this.height),h=this.toFramebufferPixel(b,a,this.width),w=this.toFramebufferPixel(g,s,this.height);return{mode:"rect",bounds:d,x:Math.min(x,h),y:Math.min(M,w),width:Math.abs(h-x)+1,height:Math.abs(w-M)+1,maxHits:o,lasso:null}}resolveLassoPickQuery(e,t,r,i){if(!Array.isArray(e)||e.length<3)return{mode:"lasso",bounds:{x:0,y:0,width:0,height:0},x:0,y:0,width:0,height:0,maxHits:t,lasso:null};let o=1/0,a=1/0,s=-1/0,l=-1/0;for(let h=0;h<e.length;h++){let w=e[h];!Number.isFinite(w.x)||!Number.isFinite(w.y)||(w.x<o&&(o=w.x),w.y<a&&(a=w.y),w.x>s&&(s=w.x),w.y>l&&(l=w.y))}if(!Number.isFinite(o)||!Number.isFinite(a)||!Number.isFinite(s)||!Number.isFinite(l))return{mode:"lasso",bounds:{x:0,y:0,width:0,height:0},x:0,y:0,width:0,height:0,maxHits:t,lasso:null};let u=this.toClientBounds(o,a,s,l,r,i);if(u.width<=0||u.height<=0)return{mode:"lasso",bounds:u,x:0,y:0,width:0,height:0,maxHits:t,lasso:null};let m=[],c=1/0,d=1/0,f=-1/0,p=-1/0;for(let h=0;h<e.length;h++){let w=e[h];if(!Number.isFinite(w.x)||!Number.isFinite(w.y))continue;let S=w.x/Math.max(1,r)*Math.max(1,this.width),B=w.y/Math.max(1,i)*Math.max(1,this.height);m.push({x:S,y:B}),S<c&&(c=S),B<d&&(d=B),S>f&&(f=S),B>p&&(p=B)}if(m.length<3||!Number.isFinite(c)||!Number.isFinite(d)||!Number.isFinite(f)||!Number.isFinite(p))return{mode:"lasso",bounds:u,x:0,y:0,width:0,height:0,maxHits:t,lasso:null};let b=this.clamp(Math.floor(c),0,Math.max(0,this.width-1)),g=this.clamp(Math.floor(d),0,Math.max(0,this.height-1)),x=this.clamp(Math.floor(f),0,Math.max(0,this.width-1)),M=this.clamp(Math.floor(p),0,Math.max(0,this.height-1));return x<b||M<g?{mode:"lasso",bounds:u,x:0,y:0,width:0,height:0,maxHits:t,lasso:null}:{mode:"lasso",bounds:u,x:b,y:g,width:x-b+1,height:M-g+1,maxHits:t,lasso:m}}preparePickFrame(e,t){this.modelBufferIndex=0,this.instanceBufferOffset=0,this.cameraUniformStagingPtr=W.allocF32(20),this.lightingUniformStagingPtr=W.allocF32(104),this.modelUniformStagingPtr=W.allocF32(32),"aspect"in t&&(t.aspect=this.aspectRatio),pe.updateAll(),this.writeCameraUniforms(t),this.writeLightingUniforms(e),this.buildDrawLists(e,t),this.buildPointCloudDrawLists(e,t),this.buildGlyphFieldDrawLists(e,t),(!this.pickIdView||!this.pickDepthView||!this.pickDepthPayloadView)&&this.resizePickTargets()}resolveRendererPickHit(e,t){let r=this.objectsById.get(t.objectId);if(!r)return null;let i=this.unprojectDepth(e,t.px,t.py,t.depth);return r instanceof Me?{kind:"mesh",object:r,objectId:t.objectId,elementIndex:t.elementIndex,worldPosition:i}:r instanceof Ue?{kind:"pointcloud",object:r,objectId:t.objectId,elementIndex:t.elementIndex,worldPosition:i}:r instanceof Re?{kind:"glyphfield",object:r,objectId:t.objectId,elementIndex:t.elementIndex,worldPosition:i}:null}pointInPolygon(e,t,r){let i=!1;for(let o=0,a=r.length-1;o<r.length;a=o++){let s=r[o].x,l=r[o].y,u=r[a].x,m=r[a].y;l>t!=m>t&&e<(u-s)*(t-l)/(m-l||1e-12)+s&&(i=!i)}return i}async executePickRegion(e,t,r){if(r.width<=0||r.height<=0)return{mode:r.mode,hits:[],truncated:!1,bounds:r.bounds,sampledPixels:0};if(this.preparePickFrame(e,t),!this.pickIdView||!this.pickDepthView||!this.pickDepthPayloadView)return{mode:r.mode,hits:[],truncated:!1,bounds:r.bounds,sampledPixels:0};let i=this.ensurePickReadbackBuffers(r.width,r.height);if(!this.pickIdTexture||!this.pickDepthPayloadTexture||!this.pickIdReadbackBuffer||!this.pickDepthReadbackBuffer)return{mode:r.mode,hits:[],truncated:!1,bounds:r.bounds,sampledPixels:0};if(this.pickIdReadbackBuffer.mapState!=="unmapped")try{this.pickIdReadbackBuffer.unmap()}catch{}if(this.pickDepthReadbackBuffer.mapState!=="unmapped")try{this.pickDepthReadbackBuffer.unmap()}catch{}let o=this.device.createCommandEncoder(),a=o.beginRenderPass({colorAttachments:[{view:this.pickIdView,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"},{view:this.pickDepthPayloadView,clearValue:{r:1,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}],depthStencilAttachment:{view:this.pickDepthView,depthClearValue:1,depthLoadOp:"clear",depthStoreOp:"store"}});a.setScissorRect(r.x,r.y,r.width,r.height),this.executeMeshPickDrawList(a,this.opaqueDrawList),this.executeMeshPickDrawList(a,this.transparentDrawList),this.executeGlyphPickDrawList(a,this.opaqueGlyphFieldDrawList),this.executeGlyphPickDrawList(a,this.transparentGlyphFieldDrawList),this.executePointCloudPickDrawList(a,this.opaquePointCloudDrawList),this.executePointCloudPickDrawList(a,this.transparentPointCloudDrawList),a.end(),o.copyTextureToBuffer({texture:this.pickIdTexture,origin:{x:r.x,y:r.y,z:0}},{buffer:this.pickIdReadbackBuffer,bytesPerRow:i.idBytesPerRow,rowsPerImage:r.height},{width:r.width,height:r.height,depthOrArrayLayers:1}),o.copyTextureToBuffer({texture:this.pickDepthPayloadTexture,origin:{x:r.x,y:r.y,z:0}},{buffer:this.pickDepthReadbackBuffer,bytesPerRow:i.depthBytesPerRow,rowsPerImage:r.height},{width:r.width,height:r.height,depthOrArrayLayers:1}),this.queue.submit([o.finish()]),await Promise.all([this.pickIdReadbackBuffer.mapAsync(GPUMapMode.READ,0,i.idSizeBytes),this.pickDepthReadbackBuffer.mapAsync(GPUMapMode.READ,0,i.depthSizeBytes)]);let s=!1,l=0,u=new Map;try{let c=new Uint32Array(this.pickIdReadbackBuffer.getMappedRange(0,i.idSizeBytes)),d=new Float32Array(this.pickDepthReadbackBuffer.getMappedRange(0,i.depthSizeBytes)),f=r.mode==="lasso"?r.lasso:null;e:for(let p=0;p<r.height;p++){let b=p*i.idBytesPerRow>>>2,g=p*i.depthBytesPerRow>>>2,x=r.y+p;for(let M=0;M<r.width;M++){let h=r.x+M;if(f&&!this.pointInPolygon(h+.5,x+.5,f))continue;l++;let w=b+M*2,S=c[w]>>>0;if(S===0)continue;let B=c[w+1]>>>0,v=d[g+M];if(!Number.isFinite(v)||v>=1)continue;let A=`${S}:${B}`,C=u.get(A);if(C)v<C.depth&&(C.depth=v,C.px=h,C.py=x);else{if(u.size>=r.maxHits){s=!0;break e}u.set(A,{objectId:S,elementIndex:B,depth:v,px:h,py:x})}}}}finally{try{this.pickIdReadbackBuffer.unmap()}catch{}try{this.pickDepthReadbackBuffer.unmap()}catch{}}let m=[];for(let c of u.values()){let d=this.resolveRendererPickHit(t,c);d&&m.push(d)}return{mode:r.mode,hits:m,truncated:s,bounds:r.bounds,sampledPixels:l}}async runPick(e,t,r,i){W.reset(),this.resize();let o=Math.max(1,this.canvas.clientWidth||this.width),a=Math.max(1,this.canvas.clientHeight||this.height),s=this.resolveSinglePixel(r,i,o,a);if(!s)return null;let l={mode:"rect",bounds:{x:r,y:i,width:0,height:0},x:s.px,y:s.py,width:1,height:1,maxHits:1,lasso:null},u=await this.executePickRegion(e,t,l);return u.hits.length>0?u.hits[0]:null}async runPickRect(e,t,r,i,o,a,s){W.reset(),this.resize();let l=Math.max(1,this.canvas.clientWidth||this.width),u=Math.max(1,this.canvas.clientHeight||this.height),m=this.resolveRectPickQuery(r,i,o,a,this.getPickMaxHits(s),l,u);return this.executePickRegion(e,t,m)}async runPickLasso(e,t,r,i){W.reset(),this.resize();let o=Math.max(1,this.canvas.clientWidth||this.width),a=Math.max(1,this.canvas.clientHeight||this.height),s=this.resolveLassoPickQuery(r,this.getPickMaxHits(i),o,a);return this.executePickRegion(e,t,s)}destroy(){this.depthTexture?.destroy(),this.smaaSceneColorTexture?.destroy(),this.smaaEdgesTexture?.destroy(),this.smaaBlendTexture?.destroy(),this.smaaSceneColorTexture=null,this.smaaSceneColorView=null,this.smaaEdgesTexture=null,this.smaaEdgesView=null,this.smaaBlendTexture=null,this.smaaBlendView=null,this.smaaParamsBuffer?.destroy(),this.smaaParamsBuffer=null,this.smaaEdgeBindGroup=null,this.smaaWeightBindGroup=null,this.smaaNeighborhoodBindGroup=null,this.smaaEdgePipeline=null,this.smaaWeightPipeline=null,this.smaaNeighborhoodPipeline=null,this.smaaShaderModule=null,this.smaaEdgeBindGroupLayout=null,this.smaaWeightBindGroupLayout=null,this.smaaNeighborhoodBindGroupLayout=null,this.smaaSamplerPoint=null,this.smaaSamplerLinear=null,this.fallbackWhiteTexture?.destroy(),this.fallbackNormalTexture?.destroy(),this.fallbackMRTex?.destroy(),this.fallbackOcclusionTex?.destroy(),this.cameraUniformBuffer?.destroy();for(let e of this.modelUniformBuffers)e.destroy();for(let e of this.pickUniformBuffers)e.destroy();this.modelUniformBuffers=[],this.pickUniformBuffers=[],this.pickBindGroups=[],this.pickBindGroupLayout=null,this.pickIdTexture?.destroy(),this.pickDepthTexture?.destroy(),this.pickDepthPayloadTexture?.destroy(),this.pickIdTexture=null,this.pickIdView=null,this.pickDepthTexture=null,this.pickDepthView=null,this.pickDepthPayloadTexture=null,this.pickDepthPayloadView=null,this.pickIdReadbackBuffer?.destroy(),this.pickDepthReadbackBuffer?.destroy(),this.pickIdReadbackBuffer=null,this.pickDepthReadbackBuffer=null,this.pickIdReadbackCapacityBytes=0,this.pickDepthReadbackCapacityBytes=0,this.pickTail=Promise.resolve(),this.lightingUniformBuffer?.destroy(),this.instanceBuffer?.destroy(),this.instanceBuffer=null,this.instanceBufferCapacityBytes=0,this.globalBindGroups=[],this.pipelineCache.clear(),this.shaderCache.clear(),this.pointCloudBindGroupLayout=null,this.glyphFieldBindGroupLayout=null,this.glyphFieldDummyAttributesBuffer?.destroy(),this.glyphFieldDummyAttributesBuffer=null,this.gpuQuerySet?.destroy(),this.gpuQuerySet=null,this.gpuResolveBuffer?.destroy(),this.gpuResolveBuffer=null,this.gpuResultBuffer?.destroy(),this.gpuResultBuffer=null,this.gpuResultPending=!1,this._gpuTimeNs=null,this.dataMaterialDummyDataBuffer?.destroy(),this.dataMaterialDummyDataBuffer=null,this.objectsById.clear(),this.objectIds=new WeakMap,this.nextObjectId=1}createGlobalBindGroupLayout(){this.globalBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:80}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",minBindingSize:128}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:416}}]})}createSkinBindGroupLayout(){this.skinBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]})}createUniformBuffers(){this.cameraUniformBuffer=this.device.createBuffer({size:80,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.lightingUniformBuffer=this.device.createBuffer({size:416,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.modelUniformBuffers=[],this.globalBindGroups=[],this.pickUniformBuffers=[],this.pickBindGroups=[];let e=this.getPickBindGroupLayout();for(let t=0;t<this.MODEL_BUFFER_POOL_SIZE;t++){let r=this.device.createBuffer({size:128,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});this.modelUniformBuffers.push(r),this.globalBindGroups.push(this.device.createBindGroup({layout:this.globalBindGroupLayout,entries:[{binding:0,resource:{buffer:this.cameraUniformBuffer}},{binding:1,resource:{buffer:r}},{binding:2,resource:{buffer:this.lightingUniformBuffer}}]}));let i=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});this.pickUniformBuffers.push(i),this.pickBindGroups.push(this.device.createBindGroup({layout:e,entries:[{binding:0,resource:{buffer:i}}]}))}this.cameraUniformStagingPtr=0,this.lightingUniformStagingPtr=0,this.modelUniformStagingPtr=0,this._wasmBuffer=null}getPickBindGroupLayout(){return this.pickBindGroupLayout?this.pickBindGroupLayout:(this.pickBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:16}}]}),this.pickBindGroupLayout)}ensureModelBufferPool(e){let t=this.modelUniformBuffers.length;if(e<=t)return;let r=Math.max(1,t);for(;r<e;)r*=2;this.modelUniformBuffers.length=r,this.globalBindGroups.length=r,this.pickUniformBuffers.length=r,this.pickBindGroups.length=r;let i=this.getPickBindGroupLayout();for(let o=t;o<r;o++){let a=this.device.createBuffer({size:128,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});this.modelUniformBuffers[o]=a,this.globalBindGroups[o]=this.device.createBindGroup({layout:this.globalBindGroupLayout,entries:[{binding:0,resource:{buffer:this.cameraUniformBuffer}},{binding:1,resource:{buffer:a}},{binding:2,resource:{buffer:this.lightingUniformBuffer}}]});let s=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});this.pickUniformBuffers[o]=s,this.pickBindGroups[o]=this.device.createBindGroup({layout:i,entries:[{binding:0,resource:{buffer:s}}]})}}createFallbackTextures(){this.fallbackSampler=this.device.createSampler({addressModeU:"repeat",addressModeV:"repeat",magFilter:"linear",minFilter:"linear",mipmapFilter:"linear"});let e=(a,s)=>{let l=this.device.createTexture({size:{width:1,height:1},format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST,viewFormats:["rgba8unorm-srgb"]}),u=new Uint8Array(256);u[0]=a[0],u[1]=a[1],u[2]=a[2],u[3]=a[3],this.queue.writeTexture({texture:l},u,{bytesPerRow:256,rowsPerImage:1},{width:1,height:1});let m=l.createView({format:"rgba8unorm"}),c=s?l.createView({format:"rgba8unorm-srgb"}):m;return{tex:l,linear:m,srgb:c}},t=e([255,255,255,255],!0);this.fallbackWhiteTexture=t.tex,this.fallbackWhiteViewLinear=t.linear,this.fallbackWhiteViewSrgb=t.srgb;let r=e([128,128,255,255],!1);this.fallbackNormalTexture=r.tex,this.fallbackNormalViewLinear=r.linear;let i=e([0,255,255,255],!1);this.fallbackMRTex=i.tex,this.fallbackMRViewLinear=i.linear;let o=e([255,0,0,255],!1);this.fallbackOcclusionTex=o.tex,this.fallbackOcclusionViewLinear=o.linear}createSmaaResources(){if(this.smaaParamsBuffer)return;this.smaaParamsBuffer=this.device.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.smaaSamplerPoint=this.device.createSampler({addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge",magFilter:"nearest",minFilter:"nearest"}),this.smaaSamplerLinear=this.device.createSampler({addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge",magFilter:"linear",minFilter:"linear"});let e=ao;this.smaaShaderModule=this.device.createShaderModule({code:e}),this.smaaEdgeBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:3,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]}),this.smaaWeightBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:4,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]}),this.smaaNeighborhoodBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:3,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:5,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]});let t=this.device.createPipelineLayout({bindGroupLayouts:[this.smaaEdgeBindGroupLayout]}),r=this.device.createPipelineLayout({bindGroupLayouts:[this.smaaWeightBindGroupLayout]}),i=this.device.createPipelineLayout({bindGroupLayouts:[this.smaaNeighborhoodBindGroupLayout]});this.smaaEdgePipeline=this.device.createRenderPipeline({layout:t,vertex:{module:this.smaaShaderModule,entryPoint:"vs_fullscreen"},fragment:{module:this.smaaShaderModule,entryPoint:"fs_smaa_edges",targets:[{format:"rgba8unorm"}]},primitive:{topology:"triangle-list",cullMode:"none"}}),this.smaaWeightPipeline=this.device.createRenderPipeline({layout:r,vertex:{module:this.smaaShaderModule,entryPoint:"vs_fullscreen"},fragment:{module:this.smaaShaderModule,entryPoint:"fs_smaa_weights",targets:[{format:"rgba8unorm"}]},primitive:{topology:"triangle-list",cullMode:"none"}}),this.smaaNeighborhoodPipeline=this.device.createRenderPipeline({layout:i,vertex:{module:this.smaaShaderModule,entryPoint:"vs_fullscreen"},fragment:{module:this.smaaShaderModule,entryPoint:"fs_smaa_neighborhood",targets:[{format:this.format}]},primitive:{topology:"triangle-list",cullMode:"none"}})}resizeSmaaTargets(){if(!this.smaaEnabled)return;this.smaaParamsBuffer||this.createSmaaResources(),this.smaaSceneColorTexture?.destroy(),this.smaaEdgesTexture?.destroy(),this.smaaBlendTexture?.destroy();let e=this.width|0,t=this.height|0;if(e<=0||t<=0)return;this.smaaSceneColorTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:this.format,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),this.smaaSceneColorView=this.smaaSceneColorTexture.createView();let r="rgba8unorm";this.smaaEdgesTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:r,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),this.smaaEdgesView=this.smaaEdgesTexture.createView(),this.smaaBlendTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:r,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),this.smaaBlendView=this.smaaBlendTexture.createView();let i=new Float32Array(8);i[0]=1/e,i[1]=1/t,i[2]=e,i[3]=t,i[4]=.1,this.queue.writeBuffer(this.smaaParamsBuffer,0,i),this.smaaEdgeBindGroup=this.device.createBindGroup({layout:this.smaaEdgeBindGroupLayout,entries:[{binding:0,resource:{buffer:this.smaaParamsBuffer}},{binding:2,resource:this.smaaSamplerPoint},{binding:3,resource:this.smaaSceneColorView}]}),this.smaaWeightBindGroup=this.device.createBindGroup({layout:this.smaaWeightBindGroupLayout,entries:[{binding:0,resource:{buffer:this.smaaParamsBuffer}},{binding:2,resource:this.smaaSamplerPoint},{binding:4,resource:this.smaaEdgesView}]}),this.smaaNeighborhoodBindGroup=this.device.createBindGroup({layout:this.smaaNeighborhoodBindGroupLayout,entries:[{binding:0,resource:{buffer:this.smaaParamsBuffer}},{binding:1,resource:this.smaaSamplerLinear},{binding:2,resource:this.smaaSamplerPoint},{binding:3,resource:this.smaaSceneColorView},{binding:5,resource:this.smaaBlendView}]})}resizePickTargets(){let e=this.width|0,t=this.height|0;e<=0||t<=0||(this.pickIdTexture?.destroy(),this.pickDepthTexture?.destroy(),this.pickDepthPayloadTexture?.destroy(),this.pickIdTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:"rg32uint",usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC}),this.pickIdView=this.pickIdTexture.createView(),this.pickDepthTexture=Kn(this.device,e,t),this.pickDepthView=this.pickDepthTexture.createView(),this.pickDepthPayloadTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:"r32float",usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC}),this.pickDepthPayloadView=this.pickDepthPayloadTexture.createView(),this.ensurePickReadbackBuffers(1,1))}ensurePickReadbackBuffers(e,t){let r=Math.max(1,e|0),i=Math.max(1,t|0),o=this.alignTo256(r*8),a=this.alignTo256(r*4),s=o*i,l=a*i;return(!this.pickIdReadbackBuffer||this.pickIdReadbackCapacityBytes<s)&&(this.pickIdReadbackBuffer?.destroy(),this.pickIdReadbackBuffer=this.device.createBuffer({size:s,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),this.pickIdReadbackCapacityBytes=s),(!this.pickDepthReadbackBuffer||this.pickDepthReadbackCapacityBytes<l)&&(this.pickDepthReadbackBuffer?.destroy(),this.pickDepthReadbackBuffer=this.device.createBuffer({size:l,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),this.pickDepthReadbackCapacityBytes=l),{idBytesPerRow:o,depthBytesPerRow:a,idSizeBytes:s,depthSizeBytes:l}}writePickUniform(e,t,r=0){e>=this.pickUniformBuffers.length&&this.ensureModelBufferPool(e+1);let i=new Uint32Array([t>>>0,r>>>0,0,0]);this.queue.writeBuffer(this.pickUniformBuffers[e],0,i.buffer,i.byteOffset,i.byteLength)}unprojectDepth(e,t,r,i){let o=(t+.5)/Math.max(1,this.width)*2-1,a=1-(r+.5)/Math.max(1,this.height)*2,s=i,l=ze.invert(e.viewProjectionMatrix),u=l[0]*o+l[4]*a+l[8]*s+l[12],m=l[1]*o+l[5]*a+l[9]*s+l[13],c=l[2]*o+l[6]*a+l[10]*s+l[14],d=l[3]*o+l[7]*a+l[11]*s+l[15];return!Number.isFinite(d)||Math.abs(d)<=1e-8?[0,0,0]:[u/d,m/d,c/d]}executeSmaa(e,t){if(!this.smaaEdgePipeline||!this.smaaWeightPipeline||!this.smaaNeighborhoodPipeline||!this.smaaEdgeBindGroup||!this.smaaWeightBindGroup||!this.smaaNeighborhoodBindGroup||!this.smaaEdgesView||!this.smaaBlendView)return;let r=e.beginRenderPass({colorAttachments:[{view:this.smaaEdgesView,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]});r.setPipeline(this.smaaEdgePipeline),r.setBindGroup(0,this.smaaEdgeBindGroup),r.draw(3),r.end();let i=e.beginRenderPass({colorAttachments:[{view:this.smaaBlendView,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]});i.setPipeline(this.smaaWeightPipeline),i.setBindGroup(0,this.smaaWeightBindGroup),i.draw(3),i.end();let o=e.beginRenderPass({colorAttachments:[{view:t,clearValue:{r:0,g:0,b:0,a:1},loadOp:"clear",storeOp:"store"}]});o.setPipeline(this.smaaNeighborhoodPipeline),o.setBindGroup(0,this.smaaNeighborhoodBindGroup),o.draw(3),o.end()}writeCameraUniforms(e){this.refreshWasmStagingViews();let t=e.getProjectionMatrix();this.modelUniformStagingView.set(t,0);let r=this.modelUniformStagingPtr+64;ne.invert(r,e.transform.worldMatrixPtr),ne.mul(this.cameraUniformStagingPtr,this.modelUniformStagingPtr,r);let i=N.global(),o=i.f32(),a=(i.worldPtr>>>2)+e.transform.index*16;this.cameraUniformStagingView[16]=o[a+12],this.cameraUniformStagingView[17]=o[a+13],this.cameraUniformStagingView[18]=o[a+14],this.cameraUniformStagingView[19]=this.height,this.queue.writeBuffer(this.cameraUniformBuffer,0,this.cameraUniformStagingView)}writeLightingUniforms(e){let{ambient:t,lights:r}=e.getLightingData();this.refreshWasmStagingViews();let i=this.lightingUniformStagingView;i[0]=t[0],i[1]=t[1],i[2]=t[2],i[3]=1,this.lightingCountView[0]=r.length;let o=8;for(let a=0;a<r.length&&a<Xe.MAX_LIGHTS;a++){let s=r[a];s instanceof Ye?(i[o+0]=s.direction[0],i[o+1]=s.direction[1],i[o+2]=s.direction[2],i[o+3]=0):s instanceof Ve&&(i[o+0]=s.position[0],i[o+1]=s.position[1],i[o+2]=s.position[2],i[o+3]=1),i[o+4]=s.color[0],i[o+5]=s.color[1],i[o+6]=s.color[2],i[o+7]=s.intensity,s instanceof Ve&&(i[o+8]=s.range),o+=12}this.queue.writeBuffer(this.lightingUniformBuffer,0,i)}buildDrawLists(e,t){this.drawItemPoolUsed=0,this.opaqueDrawList.length=0,this.transparentDrawList.length=0;let r=this.cullMeshScratch;r.length=0;for(let p of e.meshes)p.visible&&r.push(p);let i=r.length;if(i===0){this.frustumCullingStatsEnabled&&(this.cullingStats.tested=0,this.cullingStats.visible=0);return}let o=0,a=i,s=N.global(),l=s.f32(),u=s.u32(),m=t.transform.worldMatrixPtr>>>2,c=l[m+12],d=l[m+13],f=l[m+14];if(this.frustumCullingEnabled){this.ensureCullingCapacity(i);let p=W.alloc(i*4,4),b=W.allocF32(i*3),g=W.allocF32(i),x=u.subarray(p>>>2,(p>>>2)+i),M=l.subarray(b>>>2,(b>>>2)+i*3),h=l.subarray(g>>>2,(g>>>2)+i);for(let B=0;B<i;B++){let v=r[B],A=v.geometry,C=A.boundsCenter,k=B*3;x[B]=v.transform.worldMatrixPtr>>>0,M[k+0]=C[0],M[k+1]=C[1],M[k+2]=C[2],h[B]=A.boundsRadius}et.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,p,b,g,i);let w=W.allocF32(24);pr.writePlanesFromViewProjection(w,this.cameraUniformStagingPtr);let S=W.alloc(i*4,4);a=et.spheresFrustum(S,this.cullCentersPtr,this.cullRadiiPtr,i,w),o=S>>>2}if(this.frustumCullingStatsEnabled&&(this.cullingStats.tested=i,this.cullingStats.visible=a),this.frustumCullingEnabled){let p=o;for(let b=0;b<a;b++){let g=u[p+b],x=r[g],M=x.geometry,h=x.material,w=x.skin!==null&&M.joints!==null&&M.weights!==null&&this.materialSupportsSkinning(h),S=w&&M.joints1!==null&&M.weights1!==null,B=this.getOrCreatePipeline(h,!1,w,S),v=this.acquireDrawItem();if(v.mesh=x,v.geometry=M,v.material=h,v.pipeline=B,v.pipelineId=this.getObjectId(B),v.materialId=this.getObjectId(h),v.geometryId=this.getObjectId(M),v.skinned=w,v.skinned8=S,v.sortKey=0,h.blendMode==="opaque")this.opaqueDrawList.push(v);else{let A=x.transform.worldMatrixPtr>>>2,C=l[A+12]-c,k=l[A+13]-d,G=l[A+14]-f;v.sortKey=C*C+k*k+G*G,this.transparentDrawList.push(v)}}}else for(let p=0;p<i;p++){let b=r[p],g=b.geometry,x=b.material,M=b.skin!==null&&g.joints!==null&&g.weights!==null&&this.materialSupportsSkinning(x),h=M&&g.joints1!==null&&g.weights1!==null,w=this.getOrCreatePipeline(x,!1,M,h),S=this.acquireDrawItem();if(S.mesh=b,S.geometry=g,S.material=x,S.pipeline=w,S.pipelineId=this.getObjectId(w),S.materialId=this.getObjectId(x),S.geometryId=this.getObjectId(g),S.skinned=M,S.skinned8=h,S.sortKey=0,x.blendMode==="opaque")this.opaqueDrawList.push(S);else{let B=b.transform.worldMatrixPtr>>>2,v=l[B+12]-c,A=l[B+13]-d,C=l[B+14]-f;S.sortKey=v*v+A*A+C*C,this.transparentDrawList.push(S)}}this.opaqueDrawList.sort((p,b)=>p.pipelineId-b.pipelineId||p.materialId-b.materialId||p.geometryId-b.geometryId),this.transparentDrawList.sort((p,b)=>b.sortKey-p.sortKey||p.pipelineId-b.pipelineId||p.materialId-b.materialId||p.geometryId-b.geometryId)}buildPointCloudDrawLists(e,t){this.pointCloudDrawItemPoolUsed=0,this.opaquePointCloudDrawList.length=0,this.transparentPointCloudDrawList.length=0,this.transparentMergedDrawList.length=0,this.cullPointCloudScratch.length=0;for(let c of e.pointClouds)c.visible&&(c.pointCount<=0||this.cullPointCloudScratch.push(c));if(this.cullPointCloudScratch.length===0)return;let r=N.global(),i=r.f32(),o=r.u32(),a=this.cameraUniformStagingView,s=a[16],l=a[17],u=a[18],m=[];if(this.frustumCullingEnabled){let c=[],d=[];for(let f of this.cullPointCloudScratch)f.boundsRadius>0?c.push(f):d.push(f);if(c.length>0){this.ensureCullingCapacity(c.length);let f=c.length,p=W.alloc(f*4,4),b=W.allocF32(f*3),g=W.allocF32(f),x=o.subarray(p>>>2,(p>>>2)+f),M=i.subarray(b>>>2,(b>>>2)+f*3),h=i.subarray(g>>>2,(g>>>2)+f);for(let A=0;A<c.length;A++){let C=c[A],k=C.boundsCenter[0],G=C.boundsCenter[1],R=C.boundsCenter[2],T=A*3;x[A]=C.transform.worldMatrixPtr>>>0,M[T+0]=k,M[T+1]=G,M[T+2]=R,h[A]=C.boundsRadius}et.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,p,b,g,f);let w=W.allocF32(24);pr.writePlanesFromViewProjection(w,this.cameraUniformStagingPtr);let S=W.alloc(c.length*4,4),B=et.spheresFrustum(S,this.cullCentersPtr,this.cullRadiiPtr,c.length,w),v=S>>>2;for(let A=0;A<B;A++)m.push(c[o[v+A]])}for(let f of d)m.push(f)}else for(let c of this.cullPointCloudScratch)m.push(c);for(let c of m){let d=this.getOrCreatePointCloudPipeline(c),f=this.getObjectId(d),p=this.getObjectId(c),b=this.acquirePointCloudDrawItem();if(b.cloud=c,b.pipeline=d,b.pipelineId=f,b.cloudId=p,c.blendMode==="opaque")b.sortKey=0,this.opaquePointCloudDrawList.push(b);else{let g=c.transform.worldMatrixPtr>>>2,x=c.boundsCenter[0],M=c.boundsCenter[1],h=c.boundsCenter[2],w=i[g+0]*x+i[g+4]*M+i[g+8]*h+i[g+12],S=i[g+1]*x+i[g+5]*M+i[g+9]*h+i[g+13],B=i[g+2]*x+i[g+6]*M+i[g+10]*h+i[g+14],v=w-s,A=S-l,C=B-u;b.sortKey=v*v+A*A+C*C,this.transparentPointCloudDrawList.push(b)}}this.opaquePointCloudDrawList.sort((c,d)=>c.pipelineId-d.pipelineId||c.cloudId-d.cloudId),this.transparentPointCloudDrawList.sort((c,d)=>d.sortKey-c.sortKey||c.pipelineId-d.pipelineId||c.cloudId-d.cloudId)}buildGlyphFieldDrawLists(e,t){this.glyphFieldDrawItemPoolUsed=0,this.opaqueGlyphFieldDrawList.length=0,this.transparentGlyphFieldDrawList.length=0,this.cullGlyphFieldScratch.length=0;for(let u of e.glyphFields)u.visible&&(u.instanceCount<=0||this.cullGlyphFieldScratch.push(u));if(this.cullGlyphFieldScratch.length===0)return;let r=N.global(),i=r.f32(),o=t.position[0],a=t.position[1],s=t.position[2],l=[];if(this.frustumCullingEnabled){let u=[],m=[];for(let c of this.cullGlyphFieldScratch)c.boundsRadius>0?u.push(c):m.push(c);if(u.length>0){this.ensureCullingCapacity(u.length);let c=u.length,d=W.alloc(c*4,4),f=W.allocF32(c*3),p=W.allocF32(c),b=r.u32().subarray(d>>>2,(d>>>2)+c),g=r.f32().subarray(f>>>2,(f>>>2)+c*3),x=r.f32().subarray(p>>>2,(p>>>2)+c);for(let v=0;v<u.length;v++){let A=u[v],C=A.boundsCenter[0],k=A.boundsCenter[1],G=A.boundsCenter[2],R=v*3;b[v]=A.transform.worldMatrixPtr>>>0,g[R+0]=C,g[R+1]=k,g[R+2]=G,x[v]=A.boundsRadius}et.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,d,f,p,c);let M=W.allocF32(24);pr.writePlanesFromViewProjection(M,this.cameraUniformStagingPtr);let h=W.alloc(u.length*4,4),w=et.spheresFrustum(h,this.cullCentersPtr,this.cullRadiiPtr,u.length,M),S=r.u32(),B=h>>>2;for(let v=0;v<w;v++)l.push(u[S[B+v]]);this.frustumCullingStatsEnabled&&(this.cullingStats.tested+=u.length,this.cullingStats.visible+=l.length)}for(let c of m)l.push(c)}else for(let u of this.cullGlyphFieldScratch)l.push(u);for(let u of l){let m=u.geometry,c=this.getOrCreateGlyphFieldPipeline(u),d=this.acquireGlyphFieldDrawItem();if(d.field=u,d.geometry=m,d.pipeline=c,d.pipelineId=this.getObjectId(c),d.geometryId=this.getObjectId(m),d.fieldId=this.getObjectId(u),u.blendMode==="opaque")d.sortKey=0,this.opaqueGlyphFieldDrawList.push(d);else{let f=u.transform.worldMatrixPtr>>>2,p=i[f+12]-o,b=i[f+13]-a,g=i[f+14]-s;d.sortKey=p*p+b*b+g*g,this.transparentGlyphFieldDrawList.push(d)}}this.opaqueGlyphFieldDrawList.length>0&&this.opaqueGlyphFieldDrawList.sort((u,m)=>{let c=u.pipelineId-m.pipelineId;if(c!==0)return c;let d=u.geometryId-m.geometryId;return d!==0?d:u.fieldId-m.fieldId}),this.transparentGlyphFieldDrawList.length>0&&this.transparentGlyphFieldDrawList.sort((u,m)=>{let c=m.sortKey-u.sortKey;if(c!==0)return c;let d=u.pipelineId-m.pipelineId;if(d!==0)return d;let f=u.geometryId-m.geometryId;return f!==0?f:u.fieldId-m.fieldId})}executeDrawList(e,t){let r=null,i=null,o=null;for(let a=0;a<t.length;){let s=t[a],l=s.pipeline,u=s.material,m=s.geometry,c=a+1;for(;c<t.length;){let p=t[c];if(p.pipeline!==l||p.material!==u||p.geometry!==m)break;c++}let d=c-a;if(m!==o&&m.upload(this.device),u!==i&&this.ensureMaterialBindGroup(u),l!==r&&(e.setPipeline(l),r=l),u!==i&&(e.setBindGroup(1,u.bindGroup),i=u),m!==o&&(e.setVertexBuffer(0,m.positionBuffer),e.setVertexBuffer(1,m.normalBuffer),e.setVertexBuffer(2,m.uvBuffer),s.skinned&&(e.setVertexBuffer(3,m.jointsBuffer),e.setVertexBuffer(4,m.weightsBuffer),s.skinned8&&(e.setVertexBuffer(5,m.joints1Buffer),e.setVertexBuffer(6,m.weights1Buffer))),m.isIndexed&&e.setIndexBuffer(m.indexBuffer,"uint32"),o=m),d>1&&!s.skinned&&this.materialSupportsInstancing(u)&&t===this.opaqueDrawList){let p=this.getOrCreatePipeline(u,!0);p!==r&&(e.setPipeline(p),r=p),this.drawInstancedRun(e,m,u,t,a,d)}else for(let p=a;p<c;p++){this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let b=this.modelBufferIndex++,g=this.modelUniformBuffers[b],x=this.globalBindGroups[b],M=oe.bytes(),h=t[p].mesh,w=s.skinned?h.skin:null;if(w){w.ensureGpuResources(this.device,this.skinBindGroupLayout);let A=w.jointCount|0,C=W.allocF32(A*16);Gt.computeJointMatricesTo(C,w.skin.jointIndicesPtr,A,w.skin.invBindPtr,N.global().worldPtr,w.bindMatrixPtr),this.queue.writeBuffer(w.boneBuffer,0,M,C,A*64),e.setBindGroup(2,w.bindGroup)}let S=h.transform.worldMatrixPtr,B=this.modelUniformStagingPtr,v=this.modelUniformStagingPtr+64;ne.invert(B,S),ne.transpose(v,B),this.queue.writeBuffer(g,0,M,S,64),this.queue.writeBuffer(g,64,M,v,64),e.setBindGroup(0,x),m.isIndexed?e.drawIndexed(m.indexCount):e.draw(m.vertexCount)}a=c}}executePointCloudDrawList(e,t){if(t.length===0)return;let r=oe.bytes(),i=ne,o=null;for(let a=0;a<t.length;a++){let s=t[a],l=s.cloud;if(!l.visible||l.pointCount<=0||(this.ensurePointCloudBindGroup(l),!l.bindGroup))continue;s.pipeline!==o&&(e.setPipeline(s.pipeline),o=s.pipeline),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let u=this.modelBufferIndex++,m=this.modelUniformBuffers[u],c=this.globalBindGroups[u],d=l.transform.worldMatrixPtr,f=this.modelUniformStagingPtr,p=this.modelUniformStagingPtr+64;i.invert(f,d),i.transpose(p,f),this.queue.writeBuffer(m,0,r,d,64),this.queue.writeBuffer(m,64,r,p,64),e.setBindGroup(0,c),e.setBindGroup(1,l.bindGroup),e.draw(6,l.pointCount)}}executeGlyphFieldDrawList(e,t){if(t.length===0)return;let r=oe.bytes(),i=null,o=null,a=null;for(let s=0;s<t.length;s++){let l=t[s],u=l.field,m=l.geometry;if(!u.visible||u.instanceCount<=0||(this.ensureGlyphFieldBindGroup(u),!u.bindGroup))continue;l.pipeline!==i&&(e.setPipeline(l.pipeline),i=l.pipeline,o=null,a=null),m!==o&&(m.upload(this.device),e.setVertexBuffer(0,m.positionBuffer),e.setVertexBuffer(1,m.normalBuffer),m.isIndexed&&e.setIndexBuffer(m.indexBuffer,"uint32"),o=m),u!==a&&(e.setBindGroup(1,u.bindGroup),a=u),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let c=this.modelBufferIndex++,d=this.modelUniformBuffers[c],f=this.globalBindGroups[c],p=u.transform.worldMatrixPtr,b=this.modelUniformStagingPtr,g=this.modelUniformStagingPtr+64;ne.invert(b,p),ne.transpose(g,b),this.queue.writeBuffer(d,0,r,p,64),this.queue.writeBuffer(d,64,r,g,64),e.setBindGroup(0,f),m.isIndexed?e.drawIndexed(m.indexCount,u.instanceCount):e.draw(m.vertexCount,u.instanceCount)}}executeTransparentMergedDrawList(e){this.transparentMergedDrawList.length=0;for(let c of this.transparentDrawList)this.transparentMergedDrawList.push(c);for(let c of this.transparentGlyphFieldDrawList)this.transparentMergedDrawList.push(c);for(let c of this.transparentPointCloudDrawList)this.transparentMergedDrawList.push(c);if(this.transparentMergedDrawList.length===0)return;let t=c=>"mesh"in c?0:"field"in c?1:2;this.transparentMergedDrawList.sort((c,d)=>{let f=d.sortKey-c.sortKey;if(f!==0)return f;let p=c.pipelineId-d.pipelineId;if(p!==0)return p;let b="mesh"in c,g="mesh"in d;if(b&&g){let S=c,B=d;return S.materialId-B.materialId||S.geometryId-B.geometryId||(S.skinned?1:0)-(B.skinned?1:0)||(S.skinned8?1:0)-(B.skinned8?1:0)}let x="cloud"in c,M="cloud"in d;if(x&&M){let S=c,B=d;return S.cloudId-B.cloudId}let h="field"in c,w="field"in d;if(h&&w){let S=c,B=d;return S.geometryId-B.geometryId||S.fieldId-B.fieldId}return t(c)-t(d)});let r=oe.bytes(),i=null,o=null,a=null,s=!1,l=!1,u=null,m=null;for(let c=0;c<this.transparentMergedDrawList.length;c++){let d=this.transparentMergedDrawList[c];if("mesh"in d){let S=d,B=S.mesh,v=S.geometry,A=S.material;if(S.pipeline!==i&&(e.setPipeline(S.pipeline),i=S.pipeline,o=null,a=null,s=!1,l=!1,u=null,m=null),v!==a&&v.upload(this.device),A!==o&&this.ensureMaterialBindGroup(A),A!==o&&(e.setBindGroup(1,A.bindGroup),o=A),(v!==a||S.skinned!==s||S.skinned8!==l)&&(e.setVertexBuffer(0,v.positionBuffer),e.setVertexBuffer(1,v.normalBuffer),e.setVertexBuffer(2,v.uvBuffer),S.skinned&&(e.setVertexBuffer(3,v.jointsBuffer),e.setVertexBuffer(4,v.weightsBuffer),S.skinned8&&(e.setVertexBuffer(5,v.joints1Buffer),e.setVertexBuffer(6,v.weights1Buffer))),v.isIndexed&&e.setIndexBuffer(v.indexBuffer,"uint32"),a=v,s=S.skinned,l=S.skinned8),S.skinned){let D=B.skin;if(D){D.ensureGpuResources(this.device,this.skinBindGroupLayout);let U=D.jointCount|0,L=W.allocF32(U*16);Gt.computeJointMatricesTo(L,D.skin.jointIndicesPtr,U,D.skin.invBindPtr,N.global().worldPtr,D.bindMatrixPtr),this.queue.writeBuffer(D.boneBuffer,0,r,L,U*64),e.setBindGroup(2,D.bindGroup)}}this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let C=this.modelBufferIndex++,k=this.modelUniformBuffers[C],G=this.globalBindGroups[C],R=B.transform.worldMatrixPtr,T=this.modelUniformStagingPtr,F=this.modelUniformStagingPtr+64;ne.invert(T,R),ne.transpose(F,T),this.queue.writeBuffer(k,0,r,R,64),this.queue.writeBuffer(k,64,r,F,64),e.setBindGroup(0,G),v.isIndexed?e.drawIndexed(v.indexCount):e.draw(v.vertexCount);continue}if("field"in d){let S=d,B=S.field,v=S.geometry;if(!B.visible||B.instanceCount<=0||(this.ensureGlyphFieldBindGroup(B),!B.bindGroup))continue;S.pipeline!==i&&(e.setPipeline(S.pipeline),i=S.pipeline,o=null,a=null,s=!1,l=!1,u=null,m=null),v!==a&&(v.upload(this.device),e.setVertexBuffer(0,v.positionBuffer),e.setVertexBuffer(1,v.normalBuffer),v.isIndexed&&e.setIndexBuffer(v.indexBuffer,"uint32"),a=v),B!==m&&(e.setBindGroup(1,B.bindGroup),m=B,u=null,o=null),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let A=this.modelBufferIndex++,C=this.modelUniformBuffers[A],k=this.globalBindGroups[A],G=B.transform.worldMatrixPtr,R=this.modelUniformStagingPtr,T=this.modelUniformStagingPtr+64;ne.invert(R,G),ne.transpose(T,R),this.queue.writeBuffer(C,0,r,G,64),this.queue.writeBuffer(C,64,r,T,64),e.setBindGroup(0,k),v.isIndexed?e.drawIndexed(v.indexCount,B.instanceCount):e.draw(v.vertexCount,B.instanceCount);continue}let f=d,p=f.cloud;if(!p.visible||p.pointCount<=0||(this.ensurePointCloudBindGroup(p),!p.bindGroup))continue;f.pipeline!==i&&(e.setPipeline(f.pipeline),i=f.pipeline,o=null,a=null,s=!1,l=!1,u=null,m=null),p!==u&&(e.setBindGroup(1,p.bindGroup),u=p,m=null,o=null),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let b=this.modelBufferIndex++,g=this.modelUniformBuffers[b],x=this.globalBindGroups[b],M=p.transform.worldMatrixPtr,h=this.modelUniformStagingPtr,w=this.modelUniformStagingPtr+64;ne.invert(h,M),ne.transpose(w,h),this.queue.writeBuffer(g,0,r,M,64),this.queue.writeBuffer(g,64,r,w,64),e.setBindGroup(0,x),e.draw(6,p.pointCount)}}executeMeshPickDrawList(e,t){let r=oe.bytes(),i=null,o=null,a=!1,s=!1;for(let l=0;l<t.length;l++){let u=t[l],m=u.mesh,c=u.geometry;if(!m.visible)continue;let d=this.getOrCreatePickMeshPipeline(u.material,u.skinned,u.skinned8);d!==i&&(e.setPipeline(d),i=d,o=null,a=!1,s=!1),(c!==o||u.skinned!==a||u.skinned8!==s)&&(c.upload(this.device),e.setVertexBuffer(0,c.positionBuffer),u.skinned&&(e.setVertexBuffer(3,c.jointsBuffer),e.setVertexBuffer(4,c.weightsBuffer),u.skinned8&&(e.setVertexBuffer(5,c.joints1Buffer),e.setVertexBuffer(6,c.weights1Buffer))),c.isIndexed&&e.setIndexBuffer(c.indexBuffer,"uint32"),o=c,a=u.skinned,s=u.skinned8),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let f=this.modelBufferIndex++,p=this.modelUniformBuffers[f],b=this.globalBindGroups[f],g=m.transform.worldMatrixPtr,x=this.modelUniformStagingPtr,M=this.modelUniformStagingPtr+64;if(ne.invert(x,g),ne.transpose(M,x),this.queue.writeBuffer(p,0,r,g,64),this.queue.writeBuffer(p,64,r,M,64),this.writePickUniform(f,this.getObjectId(m),0),e.setBindGroup(0,b),e.setBindGroup(1,this.pickBindGroups[f]),u.skinned){let h=m.skin;if(h){h.ensureGpuResources(this.device,this.skinBindGroupLayout);let w=h.jointCount|0,S=W.allocF32(w*16);Gt.computeJointMatricesTo(S,h.skin.jointIndicesPtr,w,h.skin.invBindPtr,N.global().worldPtr,h.bindMatrixPtr),this.queue.writeBuffer(h.boneBuffer,0,r,S,w*64),e.setBindGroup(2,h.bindGroup)}}c.isIndexed?e.drawIndexed(c.indexCount):e.draw(c.vertexCount)}}executePointCloudPickDrawList(e,t){let r=oe.bytes(),i=null,o=null;for(let a=0;a<t.length;a++){let s=t[a].cloud;if(!s.visible||s.pointCount<=0||(this.ensurePointCloudBindGroup(s),!s.bindGroup))continue;let l=this.getOrCreatePickPointCloudPipeline();l!==i&&(e.setPipeline(l),i=l,o=null),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let u=this.modelBufferIndex++,m=this.modelUniformBuffers[u],c=this.globalBindGroups[u],d=s.transform.worldMatrixPtr,f=this.modelUniformStagingPtr,p=this.modelUniformStagingPtr+64;ne.invert(f,d),ne.transpose(p,f),this.queue.writeBuffer(m,0,r,d,64),this.queue.writeBuffer(m,64,r,p,64),this.writePickUniform(u,this.getObjectId(s),0),e.setBindGroup(0,c),s!==o&&(e.setBindGroup(1,s.bindGroup),o=s),e.setBindGroup(2,this.pickBindGroups[u]),e.draw(6,s.pointCount)}}executeGlyphPickDrawList(e,t){let r=oe.bytes(),i=null,o=null,a=null;for(let s=0;s<t.length;s++){let l=t[s],u=l.field,m=l.geometry;if(!u.visible||u.instanceCount<=0||(this.ensureGlyphFieldBindGroup(u),!u.bindGroup))continue;let c=this.getOrCreatePickGlyphFieldPipeline(u);c!==i&&(e.setPipeline(c),i=c,o=null,a=null),m!==o&&(m.upload(this.device),e.setVertexBuffer(0,m.positionBuffer),m.isIndexed&&e.setIndexBuffer(m.indexBuffer,"uint32"),o=m),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let d=this.modelBufferIndex++,f=this.modelUniformBuffers[d],p=this.globalBindGroups[d],b=u.transform.worldMatrixPtr,g=this.modelUniformStagingPtr,x=this.modelUniformStagingPtr+64;ne.invert(g,b),ne.transpose(x,g),this.queue.writeBuffer(f,0,r,b,64),this.queue.writeBuffer(f,64,r,x,64),this.writePickUniform(d,this.getObjectId(u),0),e.setBindGroup(0,p),u!==a&&(e.setBindGroup(1,u.bindGroup),a=u),e.setBindGroup(2,this.pickBindGroups[d]),m.isIndexed?e.drawIndexed(m.indexCount,u.instanceCount):e.draw(m.vertexCount,u.instanceCount)}}drawInstancedRun(e,t,r,i,o,a){let s=W.alloc(a*4,4),l=N.global().u32(),u=s>>>2;for(let b=0;b<a;b++)l[u+b]=i[o+b].mesh.transform.worldMatrixPtr>>>0;let m=W.allocF32(a*32);Rt.packModelNormalMat4FromPtrs(m,s,a);let c=a*this.INSTANCE_STRIDE_BYTES,d=this.instanceBufferOffset,f=d+c;this.ensureInstanceBuffer(f);let p=oe.bytes();this.queue.writeBuffer(this.instanceBuffer,d,p,m,c),e.setBindGroup(0,this.globalBindGroups[0]),e.setVertexBuffer(3,this.instanceBuffer,d,c),t.isIndexed?e.drawIndexed(t.indexCount,a):e.draw(t.vertexCount,a),this.instanceBufferOffset=f}getOrCreatePipeline(e,t=!1,r=!1,i=!1){if(t&&r)throw new Error("Renderer: instanced + skinned pipelines are not supported (attribute layout conflict).");i&&!r&&(r=!0);let o=this.getPipelineCacheKey(e,t,r,i),a=this.pipelineCache.get(o);if(a)return a;let s=e.getShaderCode({instanced:t,skinned:r,skinned8:i}),l=this.shaderCache.get(s);l||(l=this.device.createShaderModule({code:s}),this.shaderCache.set(s,l));let u=e.createBindGroupLayout(this.device),m=[this.globalBindGroupLayout,u];r&&m.push(this.skinBindGroupLayout);let c=this.device.createPipelineLayout({bindGroupLayouts:m}),d;return t?d=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:this.INSTANCE_STRIDE_BYTES,stepMode:"instance",attributes:[{shaderLocation:3,offset:0,format:"float32x4"},{shaderLocation:4,offset:16,format:"float32x4"},{shaderLocation:5,offset:32,format:"float32x4"},{shaderLocation:6,offset:48,format:"float32x4"},{shaderLocation:7,offset:64,format:"float32x4"},{shaderLocation:8,offset:80,format:"float32x4"},{shaderLocation:9,offset:96,format:"float32x4"},{shaderLocation:10,offset:112,format:"float32x4"}]}]:i?d=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:3,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:4,offset:0,format:"float32x4"}]},{arrayStride:8,attributes:[{shaderLocation:5,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:6,offset:0,format:"float32x4"}]}]:r?d=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:3,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:4,offset:0,format:"float32x4"}]}]:d=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]}],a=this.device.createRenderPipeline({layout:c,vertex:{module:l,entryPoint:"vs_main",buffers:d},fragment:{module:l,entryPoint:"fs_main",targets:[{format:this.format,blend:this.getBlendState(e.blendMode)}]},primitive:{topology:"triangle-list",cullMode:this.getCullMode(e.cullMode),frontFace:"ccw"},depthStencil:{format:"depth24plus",depthWriteEnabled:e.depthWrite,depthCompare:e.depthTest?"less":"always"}}),this.pipelineCache.set(o,a),a}getOrCreatePickMeshPipeline(e,t,r){r&&!t&&(t=!0);let i=this.getCullMode(e.cullMode),o=`pick:mesh:${i}:${r?"skin8":t?"skin4":"noskin"}`,a=this.pipelineCache.get(o);if(a)return a;let s=r?co:t?uo:lo,l=this.shaderCache.get(s);l||(l=this.device.createShaderModule({code:s}),this.shaderCache.set(s,l));let u=[this.globalBindGroupLayout,this.getPickBindGroupLayout()];t&&u.push(this.skinBindGroupLayout);let m=this.device.createPipelineLayout({bindGroupLayouts:u}),c;r?c=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:3,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:4,offset:0,format:"float32x4"}]},{arrayStride:8,attributes:[{shaderLocation:5,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:6,offset:0,format:"float32x4"}]}]:t?c=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:3,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:4,offset:0,format:"float32x4"}]}]:c=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}];let d=this.device.createRenderPipeline({layout:m,vertex:{module:l,entryPoint:"vs_main",buffers:c},fragment:{module:l,entryPoint:"fs_main",targets:[{format:"rg32uint"},{format:"r32float"}]},primitive:{topology:"triangle-list",cullMode:i,frontFace:"ccw"},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(o,d),d}getOrCreatePickPointCloudPipeline(){let e="pick:pointcloud",t=this.pipelineCache.get(e);if(t)return t;let r=this.shaderCache.get(nn);r||(r=this.device.createShaderModule({code:nn}),this.shaderCache.set(nn,r));let i=this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getPointCloudBindGroupLayout(),this.getPickBindGroupLayout()]}),o=this.device.createRenderPipeline({label:e,layout:i,vertex:{module:r,entryPoint:"vs_main",buffers:[]},fragment:{module:r,entryPoint:"fs_main",targets:[{format:"rg32uint"},{format:"r32float"}]},primitive:{topology:"triangle-list",cullMode:"none"},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(e,o),o}getOrCreatePickGlyphFieldPipeline(e){let t=this.getCullMode(e.cullMode),r=`pick:glyphfield:${t}`,i=this.pipelineCache.get(r);if(i)return i;let o=this.shaderCache.get(on);o||(o=this.device.createShaderModule({code:on}),this.shaderCache.set(on,o));let a=this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getGlyphFieldBindGroupLayout(),this.getPickBindGroupLayout()]}),s=this.device.createRenderPipeline({label:r,layout:a,vertex:{module:o,entryPoint:"vs_main",buffers:[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}]},fragment:{module:o,entryPoint:"fs_main",targets:[{format:"rg32uint"},{format:"r32float"}]},primitive:{topology:"triangle-list",cullMode:t},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(r,s),s}getPipelineCacheKey(e,t,r,i){let o=this.getObjectId(e.constructor);return`${e.constructor===Se||e.constructor===xe||e.constructor===Ae?`${o}`:`${o}_${this.getObjectId(e)}`}_${e.blendMode}_${e.cullMode}_${e.depthWrite}_${e.depthTest}_${t?"inst":"mesh"}_${i?"skin8":r?"skin4":"noskin"}`}getBlendState(e){switch(e){case"opaque":return;case"transparent":return{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha",operation:"add"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha",operation:"add"}};case"additive":return{color:{srcFactor:"src-alpha",dstFactor:"one",operation:"add"},alpha:{srcFactor:"one",dstFactor:"one",operation:"add"}}}}getCullMode(e){switch(e){case"none":return"none";case"back":return"back";case"front":return"front"}}getMaterialBindGroupKey(e){if(e instanceof Se){let t=e.baseColorTexture;return`unlit:${t?.id??0}:${t?.revision??0}`}if(e instanceof xe){let t=e.baseColorTexture,r=e.metallicRoughnessTexture,i=e.normalTexture,o=e.occlusionTexture,a=e.emissiveTexture;return`standard:${t?.id??0}:${t?.revision??0}:${r?.id??0}:${r?.revision??0}:${i?.id??0}:${i?.revision??0}:${o?.id??0}:${o?.revision??0}:${a?.id??0}:${a?.revision??0}`}return e instanceof Ae?`data:${e.dataBuffer?this.getObjectId(e.dataBuffer):0}:${e.getColormapKey()}`:"custom"}ensureMaterialBindGroup(e){if(e.uniformBuffer||(e.uniformBuffer=this.device.createBuffer({size:e.getUniformBufferSize(),usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST})),e.dirty){let i=e.getUniformData();this.queue.writeBuffer(e.uniformBuffer,0,i.buffer,i.byteOffset,i.byteLength),e.markClean()}e instanceof Ae&&e.upload(this.device,this.queue);let t=this.getMaterialBindGroupKey(e);if(e.bindGroup&&e.bindGroupKey===t)return;let r=e.createBindGroupLayout(this.device);if(e instanceof Se){let i=e.baseColorTexture,o=i?i.getSampler(this.device,this.fallbackSampler):this.fallbackSampler,a=i?i.getView(this.device,this.queue,"srgb",this.fallbackWhiteViewSrgb):this.fallbackWhiteViewSrgb;e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:o},{binding:2,resource:a}]}),e.bindGroupKey=t;return}if(e instanceof xe){let i=e.baseColorTexture,o=e.metallicRoughnessTexture,a=e.normalTexture,s=e.occlusionTexture,l=e.emissiveTexture;e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:i?i.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:2,resource:i?i.getView(this.device,this.queue,"srgb",this.fallbackWhiteViewSrgb):this.fallbackWhiteViewSrgb},{binding:3,resource:o?o.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:4,resource:o?o.getView(this.device,this.queue,"linear",this.fallbackMRViewLinear):this.fallbackMRViewLinear},{binding:5,resource:a?a.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:6,resource:a?a.getView(this.device,this.queue,"linear",this.fallbackNormalViewLinear):this.fallbackNormalViewLinear},{binding:7,resource:s?s.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:8,resource:s?s.getView(this.device,this.queue,"linear",this.fallbackOcclusionViewLinear):this.fallbackOcclusionViewLinear},{binding:9,resource:l?l.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:10,resource:l?l.getView(this.device,this.queue,"srgb",this.fallbackWhiteViewSrgb):this.fallbackWhiteViewSrgb}]}),e.bindGroupKey=t;return}if(e instanceof Ae){this.dataMaterialDummyDataBuffer||(this.dataMaterialDummyDataBuffer=this.device.createBuffer({size:4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.queue.writeBuffer(this.dataMaterialDummyDataBuffer,0,new Uint8Array(4)));let i=e.dataBuffer??this.dataMaterialDummyDataBuffer,o=e.getColormapForBinding().getGPUResources(this.device,this.queue);e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i}},{binding:2,resource:o.sampler},{binding:3,resource:o.view}]}),e.bindGroupKey=t;return}e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.uniformBuffer}}]}),e.bindGroupKey=t}materialSupportsInstancing(e){return e instanceof Se||e instanceof xe}materialSupportsSkinning(e){return e instanceof Se||e instanceof xe}ensureInstanceBuffer(e){if(this.instanceBuffer&&this.instanceBufferCapacityBytes>=e)return;this.instanceBuffer?.destroy();let t=this.instanceBufferCapacityBytes||this.INSTANCE_STRIDE_BYTES*256;for(;t<e;)t*=2;this.instanceBufferCapacityBytes=t,this.instanceBuffer=this.device.createBuffer({size:t,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}getPointCloudBindGroupLayout(){return this.pointCloudBindGroupLayout?this.pointCloudBindGroupLayout:(this.pointCloudBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:240}},{binding:2,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:3,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,texture:{sampleType:"float",viewDimension:"1d"}}]}),this.pointCloudBindGroupLayout)}getPointCloudPipelineCacheKey(e){return["pointcloud",`blend=${e.blendMode}`,`depthTest=${e.depthTest?1:0}`,`depthWrite=${e.depthWrite?1:0}`,`fmt=${this.format}`].join("|")}getOrCreatePointCloudPipeline(e){let t=this.getPointCloudPipelineCacheKey(e),r=this.pipelineCache.get(t);if(r)return r;let i=this.shaderCache.get(rn);i||(i=this.device.createShaderModule({code:rn}),this.shaderCache.set(rn,i));let o=this.getPointCloudBindGroupLayout(),a=this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,o]}),s=this.getBlendState(e.blendMode),l=this.device.createRenderPipeline({label:t,layout:a,vertex:{module:i,entryPoint:"vs_main",buffers:[]},fragment:{module:i,entryPoint:"fs_main",targets:[{format:this.format,blend:s}]},primitive:{topology:"triangle-list",cullMode:"none"},depthStencil:e.depthTest?{format:"depth24plus",depthWriteEnabled:e.depthWrite,depthCompare:"less"}:void 0});return this.pipelineCache.set(t,l),l}getPointCloudBindGroupKey(e){let t=e.pointsBuffer,r=e.uniformBuffer;return`pointcloud:${t?this.getObjectId(t):0}:${r?this.getObjectId(r):0}:${e.getColormapKey()}`}ensurePointCloudBindGroup(e){if(e.upload(this.device,this.queue),!e.pointsBuffer||e.pointCount<=0)return;if(e.uniformBuffer||(e.uniformBuffer=this.device.createBuffer({size:e.getUniformBufferSize(),usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),e.bindGroupKey=null),e.dirtyUniforms){let o=e.getUniformData();this.queue.writeBuffer(e.uniformBuffer,0,o.buffer,o.byteOffset,o.byteLength),e.markUniformsClean()}let t=this.getPointCloudBindGroupKey(e);if(e.bindGroup&&e.bindGroupKey===t)return;let r=this.getPointCloudBindGroupLayout(),i=e.getColormapForBinding().getGPUResources(this.device,this.queue);e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.pointsBuffer}},{binding:1,resource:{buffer:e.uniformBuffer}},{binding:2,resource:i.sampler},{binding:3,resource:i.view}]}),e.bindGroupKey=t}getGlyphFieldBindGroupLayout(){return this.glyphFieldBindGroupLayout?this.glyphFieldBindGroupLayout:(this.glyphFieldBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:240}},{binding:5,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:6,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float",viewDimension:"1d"}}]}),this.glyphFieldBindGroupLayout)}getOrCreateGlyphFieldPipeline(e){let t=`glyphfield:${this.format}:${e.blendMode}:${e.depthWrite?1:0}:${e.depthTest?1:0}:${e.cullMode}`,r=this.pipelineCache.get(t);if(r)return r;let i=so,o=this.shaderCache.get(i);o||(o=this.device.createShaderModule({code:i}),this.shaderCache.set(i,o));let a=this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getGlyphFieldBindGroupLayout()]}),s=this.device.createRenderPipeline({layout:a,vertex:{module:o,entryPoint:"vs_main",buffers:[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]}]},fragment:{module:o,entryPoint:"fs_main",targets:[{format:this.format,blend:this.getBlendState(e.blendMode)}]},primitive:{topology:"triangle-list",cullMode:this.getCullMode(e.cullMode)},depthStencil:e.depthTest||e.depthWrite?{format:"depth24plus",depthWriteEnabled:e.depthWrite,depthCompare:e.depthTest?"less":"always"}:void 0});return this.pipelineCache.set(t,s),s}getGlyphFieldBindGroupKey(e){let t=e.positionsBuffer,r=e.rotationsBuffer,i=e.scalesBuffer,o=e.attributesBuffer,a=e.uniformBuffer;return`glyphfield:${t?this.getObjectId(t):0}:${r?this.getObjectId(r):0}:${i?this.getObjectId(i):0}:${o?this.getObjectId(o):0}:${a?this.getObjectId(a):0}:${e.getColormapKey()}`}ensureGlyphFieldBindGroup(e){if(e.upload(this.device,this.queue),!e.positionsBuffer||!e.rotationsBuffer||!e.scalesBuffer||e.instanceCount<=0)return;if(e.uniformBuffer||(e.uniformBuffer=this.device.createBuffer({size:e.getUniformBufferSize(),usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),e.bindGroupKey=null),e.dirtyUniforms){let o=e.getUniformData();this.queue.writeBuffer(e.uniformBuffer,0,o.buffer,o.byteOffset,o.byteLength),e.markUniformsClean()}e.attributesBuffer||(this.glyphFieldDummyAttributesBuffer||(this.glyphFieldDummyAttributesBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),e.attributesBuffer=this.glyphFieldDummyAttributesBuffer,e.bindGroupKey=null);let t=this.getGlyphFieldBindGroupKey(e);if(e.bindGroup&&e.bindGroupKey===t)return;let r=this.getGlyphFieldBindGroupLayout(),i=e.getColormapForBinding().getGPUResources(this.device,this.queue);e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.positionsBuffer}},{binding:1,resource:{buffer:e.rotationsBuffer}},{binding:2,resource:{buffer:e.scalesBuffer}},{binding:3,resource:{buffer:e.attributesBuffer}},{binding:4,resource:{buffer:e.uniformBuffer}},{binding:5,resource:i.sampler},{binding:6,resource:i.view}]}),e.bindGroupKey=t}};var Wt=class{constructor(e){this.capacity=e;this.values=new Float64Array(Math.max(1,e|0))}values;cursor=0;count=0;total=0;addSample(e){if(!Number.isFinite(e)||e<0)return;let t=this.cursor;this.total-=this.values[t],this.values[t]=e,this.total+=e,this.cursor=(t+1)%this.values.length,this.count<this.values.length&&this.count++}get(){return this.count>0?this.total/this.count:0}},ti=(n,e,t)=>Math.max(e,Math.min(t,n)),je=(n,e)=>{if(!Number.isFinite(n))return"n/a";let t=Math.max(0,e|0);return n.toFixed(t)},zt=(n,e)=>{if(!Number.isFinite(n))return"n/a";let t=Math.abs(n);return t<1024?`${je(n,0)} B`:t<1024*1024?`${je(n/1024,e)} KiB`:`${je(n/(1024*1024),e)} MiB`},Cr=class{element;textEl;graphCanvas;graphCtx;sources;fpsAvg;frameMsAvg;cpuMsAvg;gpuMsAvg;history;historyCursor=0;targetFps;updateIntervalMs;decimals;lastTextUpdateMs=0;lastDtSeconds=0;show;label;constructor(e={},t={}){if(typeof document>"u")throw new Error("PerformanceStats requires a DOM environment (document is undefined).");this.sources=e,this.targetFps=Math.max(1,t.targetFps??60),this.updateIntervalMs=Math.max(0,t.updateIntervalMs??250),this.decimals=Math.max(0,t.decimals??1);let r=Math.max(4,t.historyLength??60)|0;this.history=new Float32Array(r);let i=Math.max(1,Math.min(240,r));this.fpsAvg=new Wt(i),this.frameMsAvg=new Wt(i),this.cpuMsAvg=new Wt(i),this.gpuMsAvg=new Wt(i),this.show={showFps:t.showFps??!0,showFrameTime:t.showFrameTime??!0,showCpuTime:t.showCpuTime??!0,showGpuTime:t.showGpuTime??!0,showMemory:t.showMemory??!0,showCulling:t.showCulling??!1,graph:t.graph??!0},this.label=t.label??null;let o=t.canvas??null,a=t.parent??o?.parentElement??document.body,s=t.position??"top-left",l=Math.max(0,t.paddingPx??8),u=(t.zIndex??9999)|0,m=t.pointerEvents??"none",c=document.createElement("div");this.element=c,c.style.position=a===document.body||a===document.documentElement?"fixed":"absolute",c.style.zIndex=String(u),c.style.pointerEvents=m,c.style.padding=`${l}px`,c.style.background="rgba(0, 0, 0, 0.75)",c.style.color="#ffffff",c.style.fontFamily="ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",c.style.fontSize="12px",c.style.lineHeight="1.2",c.style.whiteSpace="pre",c.style.userSelect="none",c.style.position==="absolute"&&getComputedStyle(a).position==="static"&&(a.style.position="relative"),s.includes("top")&&(c.style.top="0"),s.includes("bottom")&&(c.style.bottom="0"),s.includes("left")&&(c.style.left="0"),s.includes("right")&&(c.style.right="0");let d=document.createElement("pre");if(this.textEl=d,d.style.margin="0",d.style.padding="0",d.style.whiteSpace="pre",c.appendChild(d),this.show.graph){let f=Math.max(32,t.graphWidthPx??120)|0,p=Math.max(16,t.graphHeightPx??40)|0,b=document.createElement("canvas");b.style.display="block",b.style.marginTop="6px",b.style.width=`${f}px`,b.style.height=`${p}px`;let g=Math.max(1,globalThis.devicePixelRatio||1);b.width=Math.max(1,Math.floor(f*g)),b.height=Math.max(1,Math.floor(p*g));let x=b.getContext("2d");x&&x.scale(g,g),this.graphCanvas=b,this.graphCtx=x,c.appendChild(b)}else this.graphCanvas=null,this.graphCtx=null;a.appendChild(c),this.refreshText()}update(e,t=0){this.lastDtSeconds=e;let r=e*1e3,i=e>0?1/e:0;this.fpsAvg.addSample(i),this.frameMsAvg.addSample(r),this.cpuMsAvg.addSample(t);let o=this.sources.getGpuTimeNs?.()??null;o!==null&&Number.isFinite(o)&&this.gpuMsAvg.addSample(o/1e6),this.history[this.historyCursor]=i,this.historyCursor=(this.historyCursor+1)%this.history.length,this.drawGraph();let a=typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now();(this.updateIntervalMs===0||a-this.lastTextUpdateMs>=this.updateIntervalMs)&&(this.lastTextUpdateMs=a,this.refreshText())}destroy(){this.element.remove()}drawGraph(){if(!this.graphCanvas||!this.graphCtx)return;let e=this.graphCtx,t=parseFloat(this.graphCanvas.style.width)||120,r=parseFloat(this.graphCanvas.style.height)||40;e.clearRect(0,0,t,r);let i=this.history.length,o=t/i,a=r/this.targetFps;for(let s=0;s<i;s++){let l=(this.historyCursor+s)%i,u=this.history[l],m=ti(u*a,0,r),c=s*o,d=r-m;e.fillStyle="rgba(255, 255, 255, 0.85)",e.fillRect(c,d,Math.max(1,o-.5),m)}e.strokeStyle="rgba(255, 255, 255, 0.35)",e.strokeRect(.5,.5,t-1,r-1)}refreshText(){let e=this.decimals,t=[];this.label&&t.push(this.label);let r=this.fpsAvg.get(),i=this.frameMsAvg.get(),o=i>0?1e3/i:0,a=this.cpuMsAvg.get();if(this.show.showFps&&t.push(`FPS: ${je(r,1)}`),this.show.showFrameTime&&t.push(`Frame: ${je(i,e)} ms (\u2248${je(o,0)} Hz)`),this.show.showCpuTime){let s=Math.max(1e-4,this.lastDtSeconds)*1e3,l=ti(a/s*100,0,1e3);t.push(`CPU: ${je(a,e)} ms (${je(l,0)}%)`)}if(this.show.showGpuTime){let s=this.sources.getGpuTimeNs?.()??null;if(s===null||!Number.isFinite(s))t.push("GPU: n/a");else{let l=this.gpuMsAvg.get(),u=Math.max(1e-4,this.lastDtSeconds)*1e3,m=ti(l/u*100,0,1e3);t.push(`GPU: ${je(l,e)} ms (${je(m,0)}%)`)}}if(this.show.showMemory){try{let l=W.usedBytes(),u=W.capBytes();t.push(`Frame arena: ${zt(l,e)} / ${zt(u,e)}`)}catch{}try{let l=_.memory().buffer.byteLength;t.push(`WASM memory: ${zt(l,e)}`)}catch{}let s=typeof performance<"u"?performance.memory:null;if(s&&typeof s.usedJSHeapSize=="number"){let l=s.usedJSHeapSize,u=typeof s.totalJSHeapSize=="number"?s.totalJSHeapSize:NaN;Number.isFinite(u)?t.push(`JS heap: ${zt(l,e)} / ${zt(u,e)}`):t.push(`JS heap: ${zt(l,e)}`)}}if(this.show.showCulling){let s=this.sources.getCullingStats?.()??null;s&&t.push(`Culling: visible ${s.visible} / tested ${s.tested}`)}this.textEl.textContent=t.join(`
|
|
12
|
-
`)}};var xs=n=>ArrayBuffer.isView(n),_r=(n,e=0,t)=>{if(xs(n)){let o=n.byteOffset+e,a=n.byteLength-e,s=t===void 0?a:Math.min(a,t);return{buffer:n.buffer,offset:o,size:s}}let r=n.byteLength-e,i=t===void 0?r:Math.min(r,t);return{buffer:n,offset:e,size:i}},Ps=(n,e,t,r,i=0,o)=>{P(Number.isInteger(t)&&t>=0,`dstOffsetBytes must be an integer >= 0 (got ${t})`);let a=_r(r,i,o);P((t&3)===0,`dstOffsetBytes must be 4-byte aligned (got ${t})`),P((a.offset&3)===0,`srcOffsetBytes must be 4-byte aligned (got ${a.offset})`);let s=le(a.size,4);if(s===a.size){n.writeBuffer(e,t,a.buffer,a.offset,a.size);return}let l=new Uint8Array(s);l.set(new Uint8Array(a.buffer,a.offset,a.size)),n.writeBuffer(e,t,l,0,s)},an=class{device;queue;buffer;byteLength;usage;constructor(e,t,r,i,o){this.device=e,this.queue=t,this.buffer=r,this.byteLength=i,this.usage=o}destroy(){this.buffer.destroy()}write(e,t=0,r=0,i){Ps(this.queue,this.buffer,t,e,r,i)}writeFromArrayBuffer(e,t,r,i=0){this.write(e,i,t,r)}writeFromWasmMemory(e,t,r,i=0){let o=new Uint8Array(e.buffer,t>>>0,r>>>0);this.write(o,i,0,r)}},q=class extends an{label;constructor(e,t,r){let i=r.data?_r(r.data).size:r.byteLength??0;P(Number.isInteger(i)&&i>=0,`StorageBuffer.byteLength must be an integer >= 0 (got ${i})`);let o=le(i,4),a=GPUBufferUsage.STORAGE;r.copyDst!==!1&&(a|=GPUBufferUsage.COPY_DST),r.copySrc&&(a|=GPUBufferUsage.COPY_SRC),r.usage&&(a|=r.usage);let s=e.createBuffer({label:r.label,size:Math.max(4,o),usage:a,mappedAtCreation:!!r.data});if(r.data){let l=_r(r.data),u=new Uint8Array(s.getMappedRange());u.fill(0),u.set(new Uint8Array(l.buffer,l.offset,l.size),0),s.unmap()}super(e,t,s,i,a),this.label=r.label??null}get canReadback(){return(this.usage&GPUBufferUsage.COPY_SRC)!==0}async read(e=0,t){P(this.canReadback,"StorageBuffer.read() requires the buffer to be created with copySrc: true"),P(Number.isInteger(e)&&e>=0,`srcOffsetBytes must be an integer >= 0 (got ${e})`);let r=t??this.byteLength-e;P(Number.isInteger(r)&&r>=0,`sizeBytes must be an integer >= 0 (got ${r})`),P(e+r<=this.byteLength,`read range out of bounds (offset ${e}, size ${r}, byteLength ${this.byteLength})`);let i=le(r,4),o=le(e,4);P(o===e,`srcOffsetBytes must be 4-byte aligned for readback (got ${e})`);let a=this.device.createBuffer({size:Math.max(4,i),usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),s=this.device.createCommandEncoder();s.copyBufferToBuffer(this.buffer,e,a,0,i),this.queue.submit([s.finish()]),await a.mapAsync(GPUMapMode.READ,0,i);let u=a.getMappedRange(0,i).slice(0,r);return a.unmap(),a.destroy(),u}async readAs(e,t=0,r){let i=await this.read(t,r),o=e.BYTES_PER_ELEMENT;P(i.byteLength%o===0,`readAs: byteLength (${i.byteLength}) is not divisible by BYTES_PER_ELEMENT (${o})`);let a=i.byteLength/o;return new e(i,0,a)}},Nt=class extends an{label;constructor(e,t,r){let i=r.data?_r(r.data).size:r.byteLength??0;P(Number.isInteger(i)&&i>=0,`UniformBuffer.byteLength must be an integer >= 0 (got ${i})`);let o=le(i,4),a=GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST;r.usage&&(a|=r.usage);let s=e.createBuffer({label:r.label,size:Math.max(4,o),usage:a,mappedAtCreation:!!r.data});if(r.data){let l=_r(r.data),u=new Uint8Array(s.getMappedRange());u.fill(0),u.set(new Uint8Array(l.buffer,l.offset,l.size),0),s.unmap()}super(e,t,s,i,a),this.label=r.label??null}};var $=n=>({binding:n.binding,visibility:n.visibility??GPUShaderStage.COMPUTE,buffer:{type:n.readOnly?"read-only-storage":"storage",hasDynamicOffset:n.hasDynamicOffset??!1,minBindingSize:n.minBindingSize}}),Br=n=>({binding:n.binding,visibility:n.visibility??GPUShaderStage.COMPUTE,buffer:{type:"uniform",hasDynamicOffset:n.hasDynamicOffset??!1,minBindingSize:n.minBindingSize}}),fo=n=>n.mapState!==void 0,mo=n=>fo(n)?n:n.buffer,po=n=>{if(fo(n))return{buffer:n};if(n.buffer!==void 0&&n.device!==void 0)return{buffer:mo(n)};let e=n;return{buffer:mo(e.buffer),offset:e.offset,size:e.size}},ws=n=>{let e=[];if(Array.isArray(n)){for(let r of n)e.push({binding:r.binding,resource:po(r.resource)});return e}let t=Object.keys(n).map(r=>Number(r)).filter(r=>Number.isFinite(r));t.sort((r,i)=>r-i);for(let r of t){let i=n[r];i&&e.push({binding:r,resource:po(i)})}return e},ee=class{device;shaderCode;entryPoint;constants;pipeline;bindGroupLayouts;label;constructor(e,t){this.device=e,this.shaderCode=t.code,this.entryPoint=t.entryPoint??"main",this.constants=t.constants,this.label=t.label??null;let r=e.createShaderModule({code:t.code});if(t.bindGroups&&t.bindGroups.length>0){let i=t.bindGroups.map(a=>e.createBindGroupLayout({label:a.label,entries:a.entries})),o=e.createPipelineLayout({bindGroupLayouts:i});this.pipeline=e.createComputePipeline({label:t.label,layout:o,compute:{module:r,entryPoint:this.entryPoint,constants:this.constants}}),this.bindGroupLayouts=i}else this.pipeline=e.createComputePipeline({label:t.label,layout:"auto",compute:{module:r,entryPoint:this.entryPoint,constants:this.constants}}),this.bindGroupLayouts=[]}getBindGroupLayout(e){if(this.bindGroupLayouts.length>0){let t=this.bindGroupLayouts[e];return P(!!t,`Bind group layout ${e} not found (pipeline has ${this.bindGroupLayouts.length} explicit groups)`),t}return this.pipeline.getBindGroupLayout(e)}createBindGroup(e,t,r){let i=this.getBindGroupLayout(e),o=ws(t);return this.device.createBindGroup({label:r,layout:i,entries:o})}};var Qe=n=>Number.isInteger(n)&&n>0,ri=n=>Number.isInteger(n)&&n>=0,Le=(n,e)=>(P(Number.isFinite(n)&&Number.isFinite(e),"ceilDiv expects finite numbers"),P(e!==0,"ceilDiv divisor must be non-zero"),Math.floor((n+e-1)/e)),ho=(n,e=1,t=1)=>(P(Qe(n),`workgroupSize.x must be a positive integer (got ${n})`),P(Qe(e),`workgroupSize.y must be a positive integer (got ${e})`),P(Qe(t),`workgroupSize.z must be a positive integer (got ${t})`),[n,e,t]),Vt=(n,e=1,t=1)=>(P(ri(n),`workgroups.x must be an integer >= 0 (got ${n})`),P(ri(e),`workgroups.y must be an integer >= 0 (got ${e})`),P(ri(t),`workgroups.z must be an integer >= 0 (got ${t})`),[n,e,t]),fe=(n,e)=>(P(Number.isFinite(n),`invocations must be finite (got ${n})`),P(n>=0,`invocations must be >= 0 (got ${n})`),P(Qe(e),`workgroupSizeX must be a positive integer (got ${e})`),n===0?[0,1,1]:[Le(n,e),1,1]),Mr=(n,e,t,r)=>{if(P(Number.isFinite(n)&&Number.isFinite(e),"width/height must be finite"),P(n>=0&&e>=0,`width/height must be >= 0 (got ${n}x${e})`),P(Qe(t),`workgroupSizeX must be a positive integer (got ${t})`),P(Qe(r),`workgroupSizeY must be a positive integer (got ${r})`),n===0||e===0)return[0,1,1];let i=Le(n,t),o=Le(e,r);return[i,o,1]},Ar=(n,e,t,r,i,o)=>{if(P(Number.isFinite(n)&&Number.isFinite(e)&&Number.isFinite(t),"width/height/depth must be finite"),P(n>=0&&e>=0&&t>=0,`width/height/depth must be >= 0 (got ${n}x${e}x${t})`),P(Qe(r),`workgroupSizeX must be a positive integer (got ${r})`),P(Qe(i),`workgroupSizeY must be a positive integer (got ${i})`),P(Qe(o),`workgroupSizeZ must be a positive integer (got ${o})`),n===0||e===0||t===0)return[0,1,1];let a=Le(n,r),s=Le(e,i),l=Le(t,o);return[a,s,l]};var jt=n=>Number.isInteger(n)&&n>=0,Ur=n=>{if(Array.isArray(n)){let i=n[0]??0,o=n[1]??1,a=n[2]??1;return P(jt(i),`workgroups.x must be an integer >= 0 (got ${i})`),P(jt(o),`workgroups.y must be an integer >= 0 (got ${o})`),P(jt(a),`workgroups.z must be an integer >= 0 (got ${a})`),{x:i,y:o,z:a}}let e=n.x,t=n.y??1,r=n.z??1;return P(jt(e),`workgroups.x must be an integer >= 0 (got ${e})`),P(jt(t),`workgroups.y must be an integer >= 0 (got ${t})`),P(jt(r),`workgroups.z must be an integer >= 0 (got ${r})`),{x:e,y:t,z:r}},$t=(n,e)=>{let{x:t,y:r,z:i}=Ur(e),o=n.limits.maxComputeWorkgroupsPerDimension;P(t<=o&&r<=o&&i<=o,`dispatchWorkgroups exceeds device.limits.maxComputeWorkgroupsPerDimension (${o})`)},bo=n=>n instanceof ee?n.pipeline:n,ni=(n,e)=>{let t=n.beginComputePass({label:e.label}),r=bo(e.pipeline);if(t.setPipeline(r),e.bindGroups)for(let s=0;s<e.bindGroups.length;s++){let l=e.bindGroups[s];l&&t.setBindGroup(s,l)}let{x:i,y:o,z:a}=Ur(e.workgroups);i>0&&o>0&&a>0&&t.dispatchWorkgroups(i,o,a),t.end()},kr=(n,e,t)=>{let r=n.beginComputePass({label:t}),i=null;for(let o of e){let a=bo(o.pipeline);if(a!==i&&(r.setPipeline(a),i=a),o.bindGroups)for(let m=0;m<o.bindGroups.length;m++){let c=o.bindGroups[m];c&&r.setBindGroup(m,c)}let{x:s,y:l,z:u}=Ur(o.workgroups);s===0||l===0||u===0||(o.label&&r.pushDebugGroup(o.label),r.dispatchWorkgroups(s,l,u),o.label&&r.popDebugGroup())}r.end()};var sn=class{device;usage;labelPrefix;buffersBySize=new Map;cursorBySize=new Map;constructor(e,t){this.device=e,this.usage=t.usage,this.labelPrefix=t.labelPrefix??"scratch"}acquire(e,t){P(Number.isInteger(e)&&e>=0,`ScratchBufferPool.acquire: byteLength must be an integer >= 0 (got ${e})`);let r=Math.max(4,le(e,4)),i=this.buffersBySize.get(r);i||(i=[],this.buffersBySize.set(r,i));let o=this.cursorBySize.get(r)??0,a;if(o<i.length)a=i[o];else{let s=t?`${this.labelPrefix}:${t}`:`${this.labelPrefix}:${r}`,l=o===0?s:`${s}:${o}`;a=this.device.createBuffer({label:l,size:r,usage:this.usage}),i.push(a)}return this.cursorBySize.set(r,o+1),a}reset(){for(let e of this.cursorBySize.keys())this.cursorBySize.set(e,0)}destroy(){for(let e of this.buffersBySize.values())for(let t of e)t.destroy();this.buffersBySize.clear(),this.cursorBySize.clear()}};var go="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read_write> output: array<f32>; var<workgroup> share: array<f32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = -0x1.fffffep+127f; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = max(acc, input[i1]); } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = max(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var yo="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<u32>; @group(0) @binding(1) var<storage, read_write> output: array<u32>; var<workgroup> share: array<u32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = 0u; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = max(acc, input[i1]); } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = max(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var vo="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read_write> output: array<f32>; var<workgroup> share: array<f32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = 0x1.fffffep+127f; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = min(acc, input[i1]); } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = min(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var xo="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<u32>; @group(0) @binding(1) var<storage, read_write> output: array<u32>; var<workgroup> share: array<u32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = 0xFFFFFFFFu; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = min(acc, input[i1]); } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = min(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var Po="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read_write> output: array<f32>; var<workgroup> share: array<f32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = 0.0; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = acc + input[i1]; } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = share[tid] + share[tid + stride]; } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var wo="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<u32>; @group(0) @binding(1) var<storage, read_write> output: array<u32>; var<workgroup> share: array<u32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = 0u; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = acc + input[i1]; } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = share[tid] + share[tid + stride]; } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var So="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; struct Pair { value: f32, index: u32 }; @group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read_write> output: array<Pair>; var<workgroup> share: array<Pair, 256>; fn isNan(val: f32) -> bool { let u = bitcast<u32>(val); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn invalidPair() -> Pair { return Pair(-0x1.fffffep+127f, 0xFFFFFFFFu); } fn better(a: Pair, b: Pair) -> Pair { let aNan = isNan(a.value); let bNan = isNan(b.value); if (aNan && bNan) { if (a.index <= b.index) { return a; } return b; } if (aNan) { return b; } if (bNan) { return a; } if (a.value > b.value) { return a; } if (b.value > a.value) { return b; } if (a.index <= b.index) { return a; } return b; } @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var a = invalidPair(); var b = invalidPair(); if (i0 < n) { a = Pair(input[i0], i0); } if (i1 < n) { b = Pair(input[i1], i1); } share[tid] = better(a, b); workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = better(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var Co="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; struct Pair { value: f32, index: u32 }; @group(0) @binding(0) var<storage, read> input: array<Pair>; @group(0) @binding(1) var<storage, read_write> output: array<Pair>; var<workgroup> share: array<Pair, 256>; fn isNan(val: f32) -> bool { let u = bitcast<u32>(val); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn invalidPair() -> Pair { return Pair(-0x1.fffffep+127f, 0xFFFFFFFFu); } fn better(a: Pair, b: Pair) -> Pair { let aNan = isNan(a.value); let bNan = isNan(b.value); if (aNan && bNan) { if (a.index <= b.index) { return a; } return b; } if (aNan) { return b; } if (bNan) { return a; } if (a.value > b.value) { return a; } if (b.value > a.value) { return b; } if (a.index <= b.index) { return a; } return b; } @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var a = invalidPair(); var b = invalidPair(); if (i0 < n) { a = input[i0]; } if (i1 < n) { b = input[i1]; } share[tid] = better(a, b); workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = better(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var _o="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; struct Pair { value: f32, index: u32 }; @group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read_write> output: array<Pair>; var<workgroup> share: array<Pair, 256>; fn isNan(val: f32) -> bool { let u = bitcast<u32>(val); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn invalidPair() -> Pair { return Pair(0x1.fffffep+127f, 0xFFFFFFFFu); } fn better(a: Pair, b: Pair) -> Pair { let aNan = isNan(a.value); let bNan = isNan(b.value); if (aNan && bNan) { if (a.index <= b.index) { return a; } return b; } if (aNan) { return b; } if (bNan) { return a; } if (a.value < b.value) { return a; } if (b.value < a.value) { return b; } if (a.index <= b.index) { return a; } return b; } @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var a = invalidPair(); var b = invalidPair(); if (i0 < n) { a = Pair(input[i0], i0); } if (i1 < n) { b = Pair(input[i1], i1); } share[tid] = better(a, b); workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = better(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var Bo="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; struct Pair { value: f32, index: u32 }; @group(0) @binding(0) var<storage, read> input: array<Pair>; @group(0) @binding(1) var<storage, read_write> output: array<Pair>; var<workgroup> share: array<Pair, 256>; fn isNan(val: f32) -> bool { let u = bitcast<u32>(val); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn invalidPair() -> Pair { return Pair(0x1.fffffep+127f, 0xFFFFFFFFu); } fn better(a: Pair, b: Pair) -> Pair { let aNan = isNan(a.value); let bNan = isNan(b.value); if (aNan && bNan) { if (a.index <= b.index) { return a; } return b; } if (aNan) { return b; } if (bNan) { return a; } if (a.value < b.value) { return a; } if (b.value < a.value) { return b; } if (a.index <= b.index) { return a; } return b; } @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var a = invalidPair(); var b = invalidPair(); if (i0 < n) { a = input[i0]; } if (i1 < n) { b = input[i1]; } share[tid] = better(a, b); workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = better(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var Mo="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<u32>; @group(0) @binding(1) var<storage, read_write> output: array<u32>; @group(0) @binding(2) var<storage, read_write> blockSums: array<u32>; var<workgroup> temp: array<u32, 512>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let ai = base + tid; let bi = ai + WORKGROUP_SIZE; temp[tid] = select(0u, input[ai], ai < n); temp[tid + WORKGROUP_SIZE] = select(0u, input[bi], bi < n); var offset = 1u; var d = WORKGROUP_SIZE; loop { workgroupBarrier(); if (d == 0u) { break; } if (tid < d) { let i1 = offset * ((tid * 2u) + 1u) - 1u; let i2 = offset * ((tid * 2u) + 2u) - 1u; temp[i2] = temp[i2] + temp[i1]; } offset = offset * 2u; d = d / 2u; } if (tid == 0u) { blockSums[wid.x] = temp[ELEMENTS_PER_WORKGROUP - 1u]; temp[ELEMENTS_PER_WORKGROUP - 1u] = 0u; } d = 1u; loop { offset = offset / 2u; workgroupBarrier(); if (d > WORKGROUP_SIZE) { break; } if (tid < d) { let i1 = offset * ((tid * 2u) + 1u) - 1u; let i2 = offset * ((tid * 2u) + 2u) - 1u; let t = temp[i1]; temp[i1] = temp[i2]; temp[i2] = temp[i2] + t; } d = d * 2u; } workgroupBarrier(); if (ai < n) { output[ai] = temp[tid]; } if (bi < n) { output[bi] = temp[tid + WORKGROUP_SIZE]; } }";var Ao="const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read_write> data: array<u32>; @group(0) @binding(1) var<storage, read> blockOffsets: array<u32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&data); if (i >= n) { return; } let block = i / ELEMENTS_PER_WORKGROUP; let off = blockOffsets[block]; data[i] = data[i] + off; }";var Uo="@group(0) @binding(0) var<storage, read_write> bins: array<atomic<u32>>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; if (i < arrayLength(&bins)) { atomicStore(&bins[i], 0u); } }";var ko="@group(0) @binding(0) var<storage, read> keys: array<u32>; @group(0) @binding(1) var<storage, read_write> bins: array<atomic<u32>>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&keys); if (i >= n) { return; } let k = keys[i]; let b = arrayLength(&bins); if (k < b) { _ = atomicAdd(&bins[k], 1u); } }";var Go="@group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read> flags: array<u32>; @group(0) @binding(2) var<storage, read> prefix: array<u32>; @group(0) @binding(3) var<storage, read_write> output: array<f32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&flags); if (i >= n) { return; } if (flags[i] != 0u) { let dst = prefix[i]; output[dst] = input[i]; } }";var To="@group(0) @binding(0) var<storage, read> input: array<u32>; @group(0) @binding(1) var<storage, read> flags: array<u32>; @group(0) @binding(2) var<storage, read> prefix: array<u32>; @group(0) @binding(3) var<storage, read_write> output: array<u32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&flags); if (i >= n) { return; } if (flags[i] != 0u) { let dst = prefix[i]; output[dst] = input[i]; } }";var Ro="override BIT: u32 = 0u; @group(0) @binding(0) var<storage, read> keys: array<u32>; @group(0) @binding(1) var<storage, read_write> flags: array<u32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&keys); if (i >= n) { return; } let k = keys[i]; let isZero = ((k >> BIT) & 1u) == 0u; flags[i] = select(0u, 1u, isZero); }";var Lo="override BIT: u32 = 0u; @group(0) @binding(0) var<storage, read> keysIn: array<u32>; @group(0) @binding(1) var<storage, read> prefix: array<u32>; @group(0) @binding(2) var<storage, read> zerosCount: array<u32>; @group(0) @binding(3) var<storage, read_write> keysOut: array<u32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&keysIn); if (i >= n) { return; } let k = keysIn[i]; let isZero = ((k >> BIT) & 1u) == 0u; let zeroPos = prefix[i]; let z = zerosCount[0]; let onePos = z + (i - zeroPos); let dst = select(onePos, zeroPos, isZero); keysOut[dst] = k; }";var Fo="@group(0) @binding(0) var<storage, read> src: array<f32>; @group(0) @binding(1) var<storage, read_write> dst: array<f32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&dst); if (i < n) { dst[i] = src[i]; } }";var Do="@group(0) @binding(0) var<storage, read> src: array<u32>; @group(0) @binding(1) var<storage, read_write> dst: array<u32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&dst); if (i < n) { dst[i] = src[i]; } }";var Io="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct Params { count: u32, componentCount: u32, componentIndex: u32, valueMode: u32, stride: u32, offset: u32, _pad0: u32, _pad1: u32 }; @group(0) @binding(0) var<storage, read> src: array<f32>; @group(0) @binding(1) var<storage, read_write> outValues: array<f32>; @group(0) @binding(2) var<storage, read_write> outFlags: array<u32>; @group(0) @binding(3) var<uniform> params: Params; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; if (i >= params.count) { return; } let cc = max(1u, min(4u, params.componentCount)); let ci = min(3u, params.componentIndex); let base = i * max(1u, params.stride) + params.offset; var x: f32 = src[base + 0u]; var y: f32 = 0.0; var z: f32 = 0.0; var w: f32 = 0.0; if (cc > 1u) { y = src[base + 1u]; } if (cc > 2u) { z = src[base + 2u]; } if (cc > 3u) { w = src[base + 3u]; } let raw = scale_select_value(vec4f(x, y, z, w), cc, ci, params.valueMode); if (scale_is_finite(raw)) { outValues[i] = raw; outFlags[i] = 1u; } else { outValues[i] = 0.0; outFlags[i] = 0u; } }";var Eo="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct Params { count: u32, binCount: u32, minValue: f32, maxValue: f32 }; @group(0) @binding(0) var<storage, read> values: array<f32>; @group(0) @binding(1) var<storage, read_write> bins: array<atomic<u32>>; @group(0) @binding(2) var<uniform> params: Params; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; if (i >= params.count) { return; } if (params.binCount == 0u) { return; } let minValue = params.minValue; let maxValue = params.maxValue; if (!(maxValue > minValue)) { return; } let v = values[i]; if (!scale_is_finite(v)) { return; } let t = clamp((v - minValue) / (maxValue - minValue), 0.0, 0.99999994); let b = min(params.binCount - 1u, u32(t * f32(params.binCount))); atomicAdd(&bins[b], 1u); }";var Oo="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct Params { count: u32, _pad0: u32, _pad1: u32, _pad2: u32, domain: vec4f, clampConfig: vec4f, scaleParams: vec4f, scaleFlags: vec4f }; @group(0) @binding(0) var<storage, read> values: array<f32>; @group(0) @binding(1) var<storage, read_write> outValues: array<f32>; @group(0) @binding(2) var<uniform> params: Params; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; if (i >= params.count) { return; } let v = values[i]; if (!scale_is_finite(v)) { outValues[i] = 0.0; return; } outValues[i] = scale_apply_transform(v, params.domain, params.clampConfig, params.scaleParams, params.scaleFlags); }";var Hs=n=>n.mapState!==void 0,Gr=n=>Hs(n)?n:n.buffer,qs=n=>4,Ks=n=>n==="sum"?0:n==="min"?4294967295:0,Xs=n=>n==="sum"?0:n==="min"?2139095040:4286578688,Ys=n=>n==="argmin"?{valueBits:2139095040,index:4294967295}:{valueBits:4286578688,index:4294967295},Qs=(n,e,t)=>{P(n%e===0,`${t}: byteLength (${n}) must be divisible by ${e}`)},Ht=class{device;queue;scratch;pipelines;constructor(e,t){this.device=e,this.queue=t,this.scratch=new sn(e,{usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST,labelPrefix:"kernels:scratch"}),this.pipelines=new Map}destroy(){this.scratch.destroy(),this.pipelines.clear()}getPipeline(e,t){let r=this.pipelines.get(e);return r||(r=t(),this.pipelines.set(e,r)),r}bindSized(e,t){P(Number.isInteger(t)&&t>=0,`bindSized: sizeBytes must be an integer >= 0 (got ${t})`);let r=le(t,4);return{buffer:e,size:Math.max(4,r)}}resolveCount(e,t,r){Qs(e.byteLength,t,"resolveCount");let i=e.byteLength/t;return r===void 0?i:(P(Number.isInteger(r)&&r>=0,`count must be an integer >= 0 (got ${r})`),P(r<=i,`count (${r}) exceeds buffer element capacity (${i})`),r)}execute(e,t){if(e.length===0)return;let r=t?.encoder??this.device.createCommandEncoder();if(t?.validateLimits)for(let i of e)$t(this.device,i.workgroups);kr(r,e,t?.label),t?.encoder||(this.queue.submit([r.finish()]),this.scratch.reset())}writeScalarU32(e,t){let r=Gr(e),i=new Uint32Array([t>>>0]);this.queue.writeBuffer(r,0,i)}writeScalarF32(e,t){let r=Gr(e),i=new Float32Array([t]);this.queue.writeBuffer(r,0,i)}writeScalarF32Bits(e,t){let r=Gr(e),i=new Uint32Array([t>>>0]);this.queue.writeBuffer(r,0,i)}writeArgPairBits(e,t,r){let i=Gr(e),o=new Uint32Array([t>>>0,r>>>0]);this.queue.writeBuffer(i,0,o)}getReducePipeline(e,t){let r=`kernels:reduce:${e}:${t}`;return this.getPipeline(r,()=>new ee(this.device,{label:r,code:e==="f32"?t==="sum"?Po:t==="max"?go:vo:t==="sum"?wo:t==="max"?yo:xo,entryPoint:"main",bindGroups:[{label:`${r}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1})]}]}))}getArgReduceInitialPipeline(e){let t=`kernels:argreduce:init:${e}`;return this.getPipeline(t,()=>new ee(this.device,{label:t,code:e==="argmax"?So:_o,entryPoint:"main",bindGroups:[{label:`${t}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1})]}]}))}getArgReducePairsPipeline(e){let t=`kernels:argreduce:pairs:${e}`;return this.getPipeline(t,()=>{let r=e==="argmax"?Co:Bo;return new ee(this.device,{label:t,code:r,entryPoint:"main",bindGroups:[{label:`${t}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1})]}]})})}encodeReduceScalar(e,t,r,i,o,a,s){P(Number.isInteger(o)&&o>0,"encodeReduceScalar expects inputCount > 0");let l=qs(t),u=i,m=o,c=0;for(;;){let d=Le(m,512),f=d<=1,p=f?a:this.scratch.acquire(d*l,`${s}:reduce:${c}`),b=this.getReducePipeline(t,r),g=b.createBindGroup(0,{0:this.bindSized(u,m*l),1:this.bindSized(p,d*l)},`${s}:reduce:${c}:bg`);if(e.push({pipeline:b,bindGroups:[g],workgroups:Vt(d,1,1),label:`${s}:reduce:${c}`}),f)break;u=p,m=d,c++}}encodeArgReduceF32Scalar(e,t,r,i,o,a){P(Number.isInteger(i)&&i>0,"encodeArgReduceF32Scalar expects inputCount > 0");let s=r,l=i,u=4,m=0;for(;;){let c=Le(l,512),d=c<=1,f=d?o:this.scratch.acquire(c*8,`${a}:argreduce:${m}`),p=m===0?this.getArgReduceInitialPipeline(t):this.getArgReducePairsPipeline(t),b=p.createBindGroup(0,{0:this.bindSized(s,l*u),1:this.bindSized(f,c*8)},`${a}:argreduce:${m}:bg`);if(e.push({pipeline:p,bindGroups:[b],workgroups:Vt(c,1,1),label:`${a}:argreduce:${m}`}),d)break;s=f,l=c,u=8,m++}}getScanBlockExclusiveU32Pipeline(){let e="kernels:scan:blockExclusiveU32";return this.getPipeline(e,()=>new ee(this.device,{label:e,code:Mo,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1}),$({binding:2,readOnly:!1})]}]}))}getScanAddBlockOffsetsU32Pipeline(){let e="kernels:scan:addBlockOffsetsU32";return this.getPipeline(e,()=>new ee(this.device,{label:e,code:Ao,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!1}),$({binding:1,readOnly:!0})]}]}))}encodeScanExclusiveU32Into(e,t,r,i,o){if(P(Number.isInteger(r)&&r>=0,`encodeScanExclusiveU32Into: count must be an integer >= 0 (got ${r})`),r===0)return;let a=Le(r,512),s=this.scratch.acquire(a*4,`${o}:blockSums`);{let u=this.getScanBlockExclusiveU32Pipeline(),m=u.createBindGroup(0,{0:this.bindSized(t,r*4),1:this.bindSized(i,r*4),2:this.bindSized(s,a*4)},`${o}:scanBlocks:bg`);e.push({pipeline:u,bindGroups:[m],workgroups:Vt(a,1,1),label:`${o}:scanBlocks`})}if(a<=1)return;let l=this.scratch.acquire(a*4,`${o}:blockOffsets`);this.encodeScanExclusiveU32Into(e,s,a,l,`${o}:scanBlockSums`);{let u=this.getScanAddBlockOffsetsU32Pipeline(),m=u.createBindGroup(0,{0:this.bindSized(i,r*4),1:this.bindSized(l,a*4)},`${o}:addOffsets:bg`);e.push({pipeline:u,bindGroups:[m],workgroups:fe(r,256),label:`${o}:addOffsets`})}}getHistogramClearPipeline(){let e="kernels:histogram:clearAtomicU32";return this.getPipeline(e,()=>new ee(this.device,{label:e,code:Uo,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!1})]}]}))}getHistogramPipeline(){let e="kernels:histogram:u32";return this.getPipeline(e,()=>new ee(this.device,{label:e,code:ko,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1})]}]}))}getCompactPipeline(e){let t=`kernels:compact:${e}`;return this.getPipeline(t,()=>new ee(this.device,{label:t,code:e==="u32"?To:Go,entryPoint:"main",bindGroups:[{label:`${t}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!0}),$({binding:2,readOnly:!0}),$({binding:3,readOnly:!1})]}]}))}getRadixFlagsPipeline(e){let t=e|0,r=`kernels:radix:flags:bit${t}`;return this.getPipeline(r,()=>new ee(this.device,{label:r,code:Ro,entryPoint:"main",constants:{BIT:t},bindGroups:[{label:`${r}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1})]}]}))}getRadixScatterPipeline(e){let t=e|0,r=`kernels:radix:scatter:bit${t}`;return this.getPipeline(r,()=>new ee(this.device,{label:r,code:Lo,entryPoint:"main",constants:{BIT:t},bindGroups:[{label:`${r}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!0}),$({binding:2,readOnly:!0}),$({binding:3,readOnly:!1})]}]}))}getCopyF32Pipeline(){let e="kernels:copy:f32";return this.getPipeline(e,()=>new ee(this.device,{label:e,code:Fo,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1})]}]}))}getCopyU32Pipeline(){let e="kernels:copy:u32";return this.getPipeline(e,()=>new ee(this.device,{label:e,code:Do,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1})]}]}))}getScaleExtractF32Pipeline(){let e="kernels:scale:extractF32";return this.getPipeline(e,()=>new ee(this.device,{label:e,code:Io,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1}),$({binding:2,readOnly:!1}),Br({binding:3})]}]}))}getScaleHistogramF32Pipeline(){let e="kernels:scale:histogramF32";return this.getPipeline(e,()=>new ee(this.device,{label:e,code:Eo,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1}),Br({binding:2})]}]}))}getScaleRemapF32Pipeline(){let e="kernels:scale:remapF32";return this.getPipeline(e,()=>new ee(this.device,{label:e,code:Oo,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1}),Br({binding:2})]}]}))}encodeCopyF32(e,t,r,i,o){if(P(Number.isInteger(r)&&r>=0,`encodeCopyF32: count must be an integer >= 0 (got ${r})`),r===0)return;let a=this.getCopyF32Pipeline(),s=a.createBindGroup(0,{0:this.bindSized(t,r*4),1:this.bindSized(i,r*4)},`${o}:copy:bg`);e.push({pipeline:a,bindGroups:[s],workgroups:fe(r,256),label:`${o}:copy`})}encodeCopyU32(e,t,r,i,o){if(P(Number.isInteger(r)&&r>=0,`encodeCopyU32: count must be an integer >= 0 (got ${r})`),r===0)return;let a=this.getCopyU32Pipeline(),s=a.createBindGroup(0,{0:this.bindSized(t,r*4),1:this.bindSized(i,r*4)},`${o}:copy:bg`);e.push({pipeline:a,bindGroups:[s],workgroups:fe(r,256),label:`${o}:copy`})}copyU32(e,t={}){let r=t.count;r===void 0&&(e instanceof q?r=this.resolveCount(e,4,void 0):P(!1,"copyU32: opts.count is required when src is not a StorageBuffer")),P(Number.isInteger(r)&&r>=0,`copyU32: count must be an integer >= 0 (got ${r})`);let i=t.out??new q(this.device,this.queue,{label:"copyU32:out",byteLength:r*4,copySrc:!0});P(i.byteLength>=r*4,"copyU32: out buffer is too small for requested count");let o=[];return this.encodeCopyU32(o,e,r,i,"copyU32"),this.execute(o,t),i}reduceU32(e,t,r={}){let i=this.resolveCount(e,4,r.count),o=r.out??new q(this.device,this.queue,{label:`reduceU32:${t}`,byteLength:4,copySrc:!0});if(P(o.byteLength>=4,"reduceU32: out buffer must be at least 4 bytes"),i===0)return this.writeScalarU32(o,Ks(t)),o;let a=[];return this.encodeReduceScalar(a,"u32",t,e,i,o,`reduceU32:${t}`),this.execute(a,r),o}sumU32(e,t={}){return this.reduceU32(e,"sum",t)}minU32(e,t={}){return this.reduceU32(e,"min",t)}maxU32(e,t={}){return this.reduceU32(e,"max",t)}copyF32(e,t={}){let r=t.count;r===void 0&&(e instanceof q?r=this.resolveCount(e,4,void 0):P(!1,"copyF32: opts.count is required when src is not a StorageBuffer")),P(Number.isInteger(r)&&r>=0,`copyF32: count must be an integer >= 0 (got ${r})`);let i=t.out??new q(this.device,this.queue,{label:"copyF32:out",byteLength:r*4,copySrc:!0});P(i.byteLength>=r*4,"copyF32: out buffer is too small for requested count");let o=[];return this.encodeCopyF32(o,e,r,i,"copyF32"),this.execute(o,t),i}extractScaleValuesF32(e,t){P(!t.encoder,"extractScaleValuesF32 does not support opts.encoder");let r=t.count;P(Number.isInteger(r)&&r>=0,`extractScaleValuesF32: count must be an integer >= 0 (got ${r})`);let i=Math.max(1,Math.min(4,Math.floor(t.componentCount??1))),o=Math.max(0,Math.min(3,Math.floor(t.componentIndex??0))),a=Math.max(i,Math.floor(t.stride??i)),s=Math.max(0,Math.floor(t.offset??0)),l=t.valueMode??"component";P(l==="component"||l==="magnitude",`extractScaleValuesF32: invalid valueMode ${String(l)}`);let u=r>0?s+(r-1)*a+i:0,m=e instanceof q?e.byteLength:Gr(e).size;P(u*4<=m,`extractScaleValuesF32: source range exceeds source buffer capacity (required ${u} f32, capacity ${Math.floor(m/4)} f32)`);let c=t.values??new q(this.device,this.queue,{label:"scale:extract:values",byteLength:r*4,copySrc:!0}),d=t.flags??new q(this.device,this.queue,{label:"scale:extract:flags",byteLength:r*4,copySrc:!0});if(P(c.byteLength>=r*4,"extractScaleValuesF32: values buffer too small for count"),P(d.byteLength>=r*4,"extractScaleValuesF32: flags buffer too small for count"),r===0)return{values:c,flags:d};let f=this.device.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,label:"scale:extract:params"});this.queue.writeBuffer(f,0,new Uint32Array([r>>>0,i>>>0,o>>>0,vr(l)>>>0,a>>>0,s>>>0,0,0]));let p=[],b=this.getScaleExtractF32Pipeline(),g=b.createBindGroup(0,{0:this.bindSized(e,u*4),1:this.bindSized(c,r*4),2:this.bindSized(d,r*4),3:{buffer:f,size:32}},"scale:extract:bg");return p.push({pipeline:b,bindGroups:[g],workgroups:fe(r,256),label:"scale:extract"}),this.execute(p,t),f.destroy(),{values:c,flags:d}}histogramF32(e,t,r){P(!r.encoder,"histogramF32 does not support opts.encoder"),P(Number.isInteger(t)&&t>=0,`histogramF32: binCount must be an integer >= 0 (got ${t})`);let i=this.resolveCount(e,4,r.count),o=r.bins??new q(this.device,this.queue,{label:"histogramF32:bins",byteLength:t*4,copySrc:!0});P(o.byteLength>=t*4,"histogramF32: bins buffer is too small for binCount");let a=[];if(t>0&&(r.clear??!0)){let l=this.getHistogramClearPipeline(),u=l.createBindGroup(0,{0:this.bindSized(o,t*4)},"histogramF32:clear:bg");a.push({pipeline:l,bindGroups:[u],workgroups:fe(t,256),label:"histogramF32:clear"})}let s=null;if(i>0&&t>0&&Number.isFinite(r.minValue)&&Number.isFinite(r.maxValue)&&r.maxValue>r.minValue){s=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,label:"histogramF32:params"});let l=new ArrayBuffer(16),u=new DataView(l);u.setUint32(0,i>>>0,!0),u.setUint32(4,t>>>0,!0),u.setFloat32(8,r.minValue,!0),u.setFloat32(12,r.maxValue,!0),this.queue.writeBuffer(s,0,l);let m=this.getScaleHistogramF32Pipeline(),c=m.createBindGroup(0,{0:this.bindSized(e,i*4),1:this.bindSized(o,t*4),2:{buffer:s,size:16}},"histogramF32:hist:bg");a.push({pipeline:m,bindGroups:[c],workgroups:fe(i,256),label:"histogramF32:accum"})}return this.execute(a,r),s?.destroy(),o}remapScaleF32(e,t){P(!t.encoder,"remapScaleF32 does not support opts.encoder");let r=this.resolveCount(e,4,t.count),i=t.out??new q(this.device,this.queue,{label:"scale:remap:out",byteLength:r*4,copySrc:!0});if(P(i.byteLength>=r*4,"remapScaleF32: out buffer is too small for requested count"),r===0)return i;let o=ie(t.transform),a=new Float32Array(20);Ne(o,a,0);let s=this.device.createBuffer({size:80,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,label:"scale:remap:params"}),l=new ArrayBuffer(80);new DataView(l).setUint32(0,r>>>0,!0);let m=new Float32Array(l);m[4]=a[4],m[5]=a[5],m[6]=0,m[7]=yr(o.clampMode),m[8]=a[8],m[9]=a[9],m[10]=a[10],m[11]=a[11],m[12]=gr(o.mode),m[13]=a[13],m[14]=a[14],m[15]=a[15],m[16]=a[16],m[17]=0,m[18]=0,m[19]=0,this.queue.writeBuffer(s,0,l);let c=this.getScaleRemapF32Pipeline(),d=c.createBindGroup(0,{0:this.bindSized(e,r*4),1:this.bindSized(i,r*4),2:{buffer:s,size:80}},"scale:remap:bg");return this.execute([{pipeline:c,bindGroups:[d],workgroups:fe(r,256),label:"scale:remap"}],t),s.destroy(),i}reduceF32(e,t,r={}){let i=this.resolveCount(e,4,r.count),o=r.out??new q(this.device,this.queue,{label:`reduceF32:${t}`,byteLength:4,copySrc:!0});if(P(o.byteLength>=4,"reduceF32: out buffer must be at least 4 bytes"),i===0)return this.writeScalarF32Bits(o,Xs(t)),o;let a=[];return this.encodeReduceScalar(a,"f32",t,e,i,o,`reduceF32:${t}`),this.execute(a,r),o}sumF32(e,t={}){return this.reduceF32(e,"sum",t)}minF32(e,t={}){return this.reduceF32(e,"min",t)}maxF32(e,t={}){return this.reduceF32(e,"max",t)}argminF32(e,t={}){return this.argReduceF32(e,"argmin",t)}argmaxF32(e,t={}){return this.argReduceF32(e,"argmax",t)}argReduceF32(e,t,r={}){let i=this.resolveCount(e,4,r.count),o=r.out??new q(this.device,this.queue,{label:`argReduceF32:${t}`,byteLength:8,copySrc:!0});if(P(o.byteLength>=8,"argReduceF32: out buffer must be at least 8 bytes"),i===0){let s=Ys(t);return this.writeArgPairBits(o,s.valueBits,s.index),o}let a=[];return this.encodeArgReduceF32Scalar(a,t,e,i,o,`argReduceF32:${t}`),this.execute(a,r),o}scanExclusiveU32(e,t={}){let r=this.resolveCount(e,4,t.count),i=t.out??new q(this.device,this.queue,{label:"scanExclusiveU32",byteLength:r*4,copySrc:!0});if(P(i.byteLength>=r*4,"scanExclusiveU32: out buffer is too small for requested count"),r===0)return i;let o=[];return this.encodeScanExclusiveU32Into(o,e,r,i,"scanExclusiveU32"),this.execute(o,t),i}histogramU32(e,t,r={}){P(Number.isInteger(t)&&t>=0,`binCount must be an integer >= 0 (got ${t})`);let i=this.resolveCount(e,4,r.count),o=r.bins??new q(this.device,this.queue,{label:"histogramU32:bins",byteLength:t*4,copySrc:!0});P(o.byteLength>=t*4,"histogramU32: bins buffer is too small for binCount");let a=[];if(t>0&&(r.clear??!0)){let s=this.getHistogramClearPipeline(),l=s.createBindGroup(0,{0:this.bindSized(o,t*4)},"histogramU32:clear:bg");a.push({pipeline:s,bindGroups:[l],workgroups:fe(t,256),label:"histogramU32:clear"})}if(i>0&&t>0){let s=this.getHistogramPipeline(),l=s.createBindGroup(0,{0:this.bindSized(e,i*4),1:this.bindSized(o,t*4)},"histogramU32:hist:bg");a.push({pipeline:s,bindGroups:[l],workgroups:fe(i,256),label:"histogramU32:accum"})}return this.execute(a,r),o}compactU32(e,t,r={}){return this.compactTyped(e,t,"u32",r)}compactF32(e,t,r={}){return this.compactTyped(e,t,"f32",r)}compactTyped(e,t,r,i){let o=this.resolveCount(t,4,i.count),a=this.resolveCount(e,4,i.count);P(a===o,"compact: input and flags counts must match");let s=i.out??new q(this.device,this.queue,{label:`compact:${r}:out`,byteLength:o*4,copySrc:!0});P(s.byteLength>=o*4,"compact: out buffer is too small for requested count");let l=new q(this.device,this.queue,{label:`compact:${r}:count`,byteLength:4,copySrc:!0});if(o===0)return this.writeScalarU32(l,0),{output:s,count:l};let u=this.scratch.acquire(o*4,`compact:${r}:prefix`),m=[];this.encodeScanExclusiveU32Into(m,t,o,u,`compact:${r}:scan`),this.encodeReduceScalar(m,"u32","sum",t,o,l,`compact:${r}:count`);{let c=this.getCompactPipeline(r),d=c.createBindGroup(0,{0:this.bindSized(e,o*4),1:this.bindSized(t,o*4),2:this.bindSized(u,o*4),3:this.bindSized(s,o*4)},`compact:${r}:compact:bg`);m.push({pipeline:c,bindGroups:[d],workgroups:fe(o,256),label:`compact:${r}:scatter`})}return this.execute(m,i),{output:s,count:l}}radixSortKeysU32(e,t={}){let r=this.resolveCount(e,4,t.count),i=t.inPlace??!1,o=i?e:t.out??new q(this.device,this.queue,{label:"radixSortKeysU32:out",byteLength:r*4,copySrc:!0});if(i||P(o.byteLength>=r*4,"radixSortKeysU32: out buffer is too small for requested count"),r<=1){if(!i&&r===1){let b=[];this.encodeCopyU32(b,e,1,o,"radixSortKeysU32"),this.execute(b,t)}return o}let a=this.scratch.acquire(r*4,"radix:flags"),s=this.scratch.acquire(r*4,"radix:prefix"),l=this.scratch.acquire(4,"radix:zerosCount"),m=this.scratch.acquire(r*4,"radix:keysScratch"),c=o,d=e,f=m,p=[];for(let b=0;b<32;b++){{let g=this.getRadixFlagsPipeline(b),x=g.createBindGroup(0,{0:this.bindSized(d,r*4),1:this.bindSized(a,r*4)},`radix:bit${b}:flags:bg`);p.push({pipeline:g,bindGroups:[x],workgroups:fe(r,256),label:`radix:bit${b}:flags`})}this.encodeScanExclusiveU32Into(p,a,r,s,`radix:bit${b}:scan`),this.encodeReduceScalar(p,"u32","sum",a,r,l,`radix:bit${b}:zerosCount`);{let g=this.getRadixScatterPipeline(b),x=g.createBindGroup(0,{0:this.bindSized(d,r*4),1:this.bindSized(s,r*4),2:this.bindSized(l,4),3:this.bindSized(f,r*4)},`radix:bit${b}:scatter:bg`);p.push({pipeline:g,bindGroups:[x],workgroups:fe(r,256),label:`radix:bit${b}:scatter`})}d=f,f=f===m?c:m}return i?d!==e&&this.encodeCopyU32(p,d,r,e,"radixSortKeysU32:finalize"):d!==o&&this.encodeCopyU32(p,d,r,o,"radixSortKeysU32:finalize"),this.execute(p,t),o}};var zo="struct Params { p0 : vec4f, p1 : vec4f } @group(0) @binding(0) var<uniform> params: Params; @group(0) @binding(1) var<storage, read> pixels: array<u32>; fn unpackRGBA8(x: u32) -> vec4f { let r = f32(x & 255u) / 255.0; let g = f32((x >> 8u) & 255u) / 255.0; let b = f32((x >> 16u) & 255u) / 255.0; let a = f32((x >> 24u) & 255u) / 255.0; return vec4f(r, g, b, a); } struct VSOut { @builtin(position) position: vec4f } @vertex fn vs_main(@builtin(vertex_index) vid: u32) -> VSOut { var pos = array<vec2f, 3>( vec2f(-1.0, -1.0), vec2f( 3.0, -1.0), vec2f(-1.0, 3.0) ); var out: VSOut; out.position = vec4f(pos[vid], 0.0, 1.0); return out; } @fragment fn fs_main(@builtin(position) pos: vec4f) -> @location(0) vec4f { let displayW = max(1.0, params.p0.x); let displayH = max(1.0, params.p0.y); let outW = max(1.0, params.p0.z); let outH = max(1.0, params.p0.w); let flipY = params.p1.x > 0.5; let xOut = clamp(i32(floor(pos.x * outW / displayW)), 0, i32(outW) - 1); var yOut = clamp(i32(floor(pos.y * outH / displayH)), 0, i32(outH) - 1); if (flipY) { yOut = i32(outH) - 1 - yOut; } let idx = u32(yOut) * u32(outW) + u32(xOut); return unpackRGBA8(pixels[idx]); }";var Wo=n=>Number.isInteger(n)&&n>=0,Js=()=>{let n=typeof navigator<"u"?navigator:null,e=n&&n.gpu?n.gpu:null;if(e&&typeof e.getPreferredCanvasFormat=="function")return e.getPreferredCanvasFormat();throw new Error("blitRGBA8BufferToCanvas: opts.format must be provided when navigator.gpu is unavailable.")},el=n=>n instanceof q?n.buffer:n,Tr=class{device;queue;paramsStride;paramsCapacity;paramsBuffer;paramsF32;paramsIndex=0;pipelineByFormat=new Map;canvasState=new WeakMap;constructor(e,t,r={}){this.device=e,this.queue=t;let i=Math.max(256,e.limits.minUniformBufferOffsetAlignment);this.paramsStride=le(32,i),this.paramsCapacity=Math.max(1,r.uniformCapacity??256),this.paramsBuffer=e.createBuffer({label:"WasmGPU:compute:blitRGBA8:params",size:this.paramsStride*this.paramsCapacity,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.paramsF32=new Float32Array(8)}destroy(){this.paramsBuffer.destroy(),this.pipelineByFormat.clear()}encode(e,t,r,i,o,a={}){if(P(Wo(i)&&Wo(o),`outWidth/outHeight must be integers >= 0 (got ${i}x${o})`),i===0||o===0)return;let s=this.getOrCreateCanvasState(t),l=a.format??s.format??Js(),u=a.alphaMode??s.alphaMode??"opaque",m=a.autoResize??!0?this.autoResizeCanvas(t,s,a.dpr):this.syncCanvasSizeWithoutResize(t,s);(!s.configured||m||s.format!==l||s.alphaMode!==u)&&(s.context.configure({device:this.device,format:l,alphaMode:u}),s.configured=!0,s.format=l,s.alphaMode=u);let d=Math.max(1,t.width),f=Math.max(1,t.height);this.paramsF32[0]=d,this.paramsF32[1]=f,this.paramsF32[2]=i,this.paramsF32[3]=o,this.paramsF32[4]=a.flipY?1:0,this.paramsF32[5]=0,this.paramsF32[6]=0,this.paramsF32[7]=0;let p=this.allocParamsChunk();this.queue.writeBuffer(this.paramsBuffer,p,this.paramsF32.buffer,this.paramsF32.byteOffset,this.paramsF32.byteLength);let b=this.getPipeline(l),g=el(r),x=b.bindGroups.get(g);x||(x=this.device.createBindGroup({label:a.label?`${a.label}:bindGroup`:void 0,layout:b.bindGroupLayout,entries:[{binding:0,resource:{buffer:this.paramsBuffer,offset:0,size:32}},{binding:1,resource:{buffer:g}}]}),b.bindGroups.set(g,x));let M=s.context.getCurrentTexture().createView(),h=a.loadOp??"load",w=a.storeOp??"store",S=a.clearColor??{r:0,g:0,b:0,a:1},B=e.beginRenderPass({label:a.label,colorAttachments:[{view:M,clearValue:S,loadOp:h,storeOp:w}]});B.setPipeline(b.pipeline),B.setBindGroup(0,x,[p]),B.draw(3,1,0,0),B.end()}allocParamsChunk(){let e=this.paramsIndex++;return this.paramsIndex>=this.paramsCapacity&&(this.paramsIndex=0),e%this.paramsCapacity*this.paramsStride}getOrCreateCanvasState(e){let t=this.canvasState.get(e);if(t)return t;let r=e.getContext("webgpu");P(!!r,"blitRGBA8BufferToCanvas: failed to acquire a WebGPU canvas context");let i={context:r,width:Math.max(1,e.width),height:Math.max(1,e.height),format:null,alphaMode:"opaque",configured:!1};return this.canvasState.set(e,i),i}autoResizeCanvas(e,t,r){let i=r??Math.max(1,typeof window<"u"&&window.devicePixelRatio||1),o=Math.max(1,Math.floor(e.clientWidth*i)),a=Math.max(1,Math.floor(e.clientHeight*i));return o===t.width&&a===t.height?!1:(t.width=o,t.height=a,e.width=o,e.height=a,!0)}syncCanvasSizeWithoutResize(e,t){let r=Math.max(1,e.width),i=Math.max(1,e.height);return r===t.width&&i===t.height?!1:(t.width=r,t.height=i,!0)}getPipeline(e){let t=this.pipelineByFormat.get(e);if(t)return t;let r=this.device.createShaderModule({label:"WasmGPU:compute:blitRGBA8:shader",code:zo}),i=this.device.createBindGroupLayout({label:"WasmGPU:compute:blitRGBA8:bgl",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform",hasDynamicOffset:!0,minBindingSize:32}},{binding:1,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),a={pipeline:this.device.createRenderPipeline({label:"WasmGPU:compute:blitRGBA8:pipeline",layout:this.device.createPipelineLayout({bindGroupLayouts:[i]}),vertex:{module:r,entryPoint:"vs_main"},fragment:{module:r,entryPoint:"fs_main",targets:[{format:e}]},primitive:{topology:"triangle-list",cullMode:"none"}}),bindGroupLayout:i,bindGroups:new WeakMap};return this.pipelineByFormat.set(e,a),a}};var ln=n=>Number.isInteger(n)&&n>=0,tl=n=>n instanceof q?n.buffer:n,rl=n=>n instanceof q?n.byteLength:Number(n.size),nl=n=>{if(n instanceof q)return n.usage;let e=n.usage;return typeof e=="number"?e:null},bt=class{device;queue;labelPrefix;slots=[];cursor=0;destroyed=!1;constructor(e,t,r={}){this.device=e,this.queue=t;let i=Math.max(1,r.slots??3);this.labelPrefix=r.labelPrefix??"WasmGPU:readback";for(let o=0;o<i;o++)this.slots.push(this.createSlot(4,o))}createSlot(e,t){let r=Math.max(4,le(e,4));return{buffer:this.device.createBuffer({label:`${this.labelPrefix}:slot${t}`,size:r,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),capacityBytes:r,tail:Promise.resolve()}}ensureNotDestroyed(){P(!this.destroyed,"ReadbackRing is destroyed")}assertSourceCanReadback(e){if(e instanceof q){P(e.canReadback,"ReadbackRing requires the source StorageBuffer to be created with copySrc: true");return}let t=nl(e);t!==null&&P((t&GPUBufferUsage.COPY_SRC)!==0,"ReadbackRing requires the source GPUBuffer to have GPUBufferUsage.COPY_SRC")}async read(e,t=0,r,i={}){this.ensureNotDestroyed(),P(this.slots.length>0,"ReadbackRing has no slots"),P(ln(t),`srcOffsetBytes must be an integer >= 0 (got ${t})`),P((t&3)===0,`srcOffsetBytes must be 4-byte aligned for readback (got ${t})`),this.assertSourceCanReadback(e);let o=rl(e),a=o-t;P(a>=0,`srcOffsetBytes (${t}) exceeds source byteLength (${o})`);let s=r??a;P(ln(s),`sizeBytes must be an integer >= 0 (got ${s})`),P(s<=a,`sizeBytes (${s}) exceeds remaining bytes (${a})`);let l=Math.max(4,le(s,4));P(l<=a,`Aligned copy size (${l}) exceeds remaining bytes (${a}). copyBufferToBuffer requires multiples of 4.`);let u=this.cursor;this.cursor=(this.cursor+1)%this.slots.length;let m=this.slots[u],c=async()=>{if(this.ensureNotDestroyed(),m.buffer.mapState==="mapped"||m.buffer.mapState==="pending"){try{m.buffer.unmap()}catch{}P(m.buffer.mapState!=="mapped"&&m.buffer.mapState!=="pending","ReadbackRing internal error: staging buffer is still mapped")}if(l>m.capacityBytes){try{m.buffer.destroy()}catch{}let b=this.createSlot(l,u);m.buffer=b.buffer,m.capacityBytes=b.capacityBytes}let f=tl(e),p=this.device.createCommandEncoder({label:i.label?`${i.label}:copyToStaging`:`${this.labelPrefix}:copyToStaging`});p.copyBufferToBuffer(f,t,m.buffer,0,l),this.queue.submit([p.finish()]);try{await m.buffer.mapAsync(GPUMapMode.READ,0,l);let g=m.buffer.getMappedRange(0,l).slice(0,s);return m.buffer.unmap(),g}catch(b){try{m.buffer.unmap()}catch{}throw b}},d=m.tail.then(c,c);return m.tail=d.then(()=>{},()=>{}),d}async readAs(e,t,r=0,i,o={}){let a=await this.read(t,r,i,o),s=e.BYTES_PER_ELEMENT;P(a.byteLength%s===0,`readAs: byteLength (${a.byteLength}) is not divisible by BYTES_PER_ELEMENT (${s})`);let l=a.byteLength/s;return new e(a,0,l)}readU32(e,t=0,r,i={}){P(ln(t),`elemOffset must be an integer >= 0 (got ${t})`);let o=t*4,a=r===void 0?void 0:r*4;return this.readAs(Uint32Array,e,o,a,i)}readF32(e,t=0,r,i={}){P(ln(t),`elemOffset must be an integer >= 0 (got ${t})`);let o=t*4,a=r===void 0?void 0:r*4;return this.readAs(Float32Array,e,o,a,i)}async readScalarU32(e,t=0,r={}){return(await this.readAs(Uint32Array,e,t,4,r))[0]>>>0}async readScalarF32(e,t=0,r={}){return(await this.readAs(Float32Array,e,t,4,r))[0]}destroy(){if(!this.destroyed){this.destroyed=!0;for(let e of this.slots){try{(e.buffer.mapState==="mapped"||e.buffer.mapState==="pending")&&e.buffer.unmap()}catch{}try{e.buffer.destroy()}catch{}e.tail=Promise.resolve()}this.slots.length=0}}};var il={i8:{dtype:"i8",ctor:Int8Array,bytesPerElement:1,wgslScalarType:null},u8:{dtype:"u8",ctor:Uint8Array,bytesPerElement:1,wgslScalarType:null},i16:{dtype:"i16",ctor:Int16Array,bytesPerElement:2,wgslScalarType:null},u16:{dtype:"u16",ctor:Uint16Array,bytesPerElement:2,wgslScalarType:null},i32:{dtype:"i32",ctor:Int32Array,bytesPerElement:4,wgslScalarType:"i32"},u32:{dtype:"u32",ctor:Uint32Array,bytesPerElement:4,wgslScalarType:"u32"},f32:{dtype:"f32",ctor:Float32Array,bytesPerElement:4,wgslScalarType:"f32"},f64:{dtype:"f64",ctor:Float64Array,bytesPerElement:8,wgslScalarType:"f64"}},ye=n=>{let e=il[n];if(!e)throw new Error(`Unknown dtype: ${String(n)}`);return e},ii=n=>{P(Array.isArray(n),"shape must be an array of dimension sizes");let e=new Array(n.length);for(let t=0;t<n.length;t++){let r=n[t];P(Number.isInteger(r)&&r>=0,`shape[${t}] must be an integer >= 0 (got ${r})`),e[t]=r}return e},un=(n,e)=>{let t=n.length,r=new Array(t),i=e;for(let o=t-1;o>=0;o--)P(Number.isInteger(i)&&i>=0,"Stride overflow while computing row-major strides"),P(i<=2147483647,`row-major stride exceeds i32 range (got ${i})`),r[o]=i,i=i*n[o],P(Number.isFinite(i)&&i>=0,"Stride overflow while computing row-major strides"),P(i<=Number.MAX_SAFE_INTEGER,"Stride overflow while computing row-major strides");return r},oi=(n,e,t)=>{P(Array.isArray(n),"stridesBytes must be an array"),P(n.length===e,`stridesBytes length (${n.length}) must equal shape length (${e})`);let r=new Array(e);for(let i=0;i<e;i++){let o=n[i];P(Number.isInteger(o),`stridesBytes[${i}] must be an integer (got ${o})`),P(o>=-2147483648&&o<=2147483647,`stridesBytes[${i}] must fit in i32 (got ${o})`),P(o%t===0,`stridesBytes[${i}] (${o}) must be a multiple of bytesPerElement (${t})`),r[i]=o}return r},ai=(n,e)=>{let t=n??0;return P(Number.isInteger(t)&&t>=0,`offsetBytes must be an integer >= 0 (got ${t})`),P(t%e===0,`offsetBytes (${t}) must be a multiple of bytesPerElement (${e})`),t},li=n=>{let e=1;for(let t=0;t<n.length;t++){if(e*=n[t],n[t]===0)return 0;P(Number.isFinite(e),"numel overflow")}return e},si=(n,e,t,r)=>{if(n.length===0){let s=t+r;return P(s<=4294967295,`required backing bytes exceeds wasm32 address space (got ${s})`),s}if(li(n)===0)return 0;let i=BigInt(t),o=BigInt(t);for(let s=0;s<n.length;s++){let l=n[s],u=BigInt(e[s]),m=BigInt(l-1)*u;m<0n?i+=m:o+=m}P(i>=0n,`layout underflows: minimum byte offset is ${i} (offsetBytes is too small for negative strides)`);let a=o+BigInt(r);return P(a<=BigInt(4294967295),`required backing bytes exceeds wasm32 address space (got ${a})`),Number(a)},ol=(n,e,t,r)=>{if(t!==0)return!1;if(n.length===0||li(n)===0)return!0;let i=un(n,r);for(let o=0;o<n.length;o++)if(e[o]!==i[o])return!1;return!0},nt=class{dtype;shape;stridesBytes;offsetBytes;bytesPerElement;numel;byteLength;constructor(e,t,r,i,o){this.dtype=e,this.shape=t,this.stridesBytes=r,this.offsetBytes=i,this.bytesPerElement=ye(e).bytesPerElement,this.numel=li(t),this.byteLength=o}get ndim(){return this.shape.length}get wgslScalarType(){return ye(this.dtype).wgslScalarType}get isContiguousC(){return ol(this.shape,this.stridesBytes,this.offsetBytes,this.bytesPerElement)}layout(){return{shape:this.shape.slice(),stridesBytes:this.stridesBytes.slice(),offsetBytes:this.offsetBytes}}},al=4294967295,gt=class n extends nt{basePtrBytes;shapePtr;stridesPtr;indicesPtr;_buf=null;_all=null;constructor(e,t,r,i,o,a,s,l,u){super(e,t,r,i,o),this.basePtrBytes=a,this.shapePtr=s,this.stridesPtr=l,this.indicesPtr=u}static empty(e,t){_.memory();let r=ye(e),i=ii(t.shape),o=ai(t.offsetBytes,r.bytesPerElement),a=t.stridesBytes?oi(t.stridesBytes,i.length,r.bytesPerElement):un(i,r.bytesPerElement),s=si(i,a,o,r.bytesPerElement),l=_.allocU32(i.length>>>0),u=_.allocU32(i.length>>>0),m=_.allocU32(i.length>>>0),c=_.u32view(l,i.length>>>0);for(let p=0;p<i.length;p++)c[p]=i[p]>>>0;let d=_.i32view(u,i.length>>>0);for(let p=0;p<a.length;p++)d[p]=a[p]|0;let f=s>0?_.allocBytes(s>>>0):0;return new n(e,i,a,o,s,f,l,u,m)}static zeros(e,t){let r=n.empty(e,t);return r.zero_(),r}static fromArray(e,t,r){let i=n.empty(e,{shape:t});P(i.isContiguousC,"CPUndarray.fromArray currently requires a contiguous row-major layout"),P(r.length>=i.numel,`source length (${r.length}) must be >= numel (${i.numel})`);let o=i.data();for(let a=0;a<i.numel;a++)o[a]=r[a];return i}get residency(){return"cpu-webassembly"}ensureAllView(){let e=_.memory().buffer;if(this._buf!==e){this._buf=e;let t=ye(this.dtype).ctor;this._all=new t(e)}return this._all}backingBytes(){return this.byteLength===0?new Uint8Array(_.memory().buffer,0,0):_.u8view(this.basePtrBytes,this.byteLength>>>0)}data(){if(P(this.isContiguousC,"CPUndarray.data() requires a contiguous row-major layout (use backingBytes() for raw backing storage)"),this.numel===0){let e=_.memory().buffer,t=ye(this.dtype).ctor;return new t(e,0,0)}return new(ye(this.dtype)).ctor(_.memory().buffer,this.basePtrBytes+this.offsetBytes>>>0,this.numel>>>0)}offsetBytesAt(e){if(P(e.length===this.ndim,`expected ${this.ndim} indices, got ${e.length}`),this.ndim===0)return this.offsetBytes;let t=_.u32view(this.indicesPtr,this.ndim>>>0);for(let i=0;i<this.ndim;i++){let o=e[i];P(Number.isInteger(o)&&o>=0,`index[${i}] must be an integer >= 0 (got ${o})`),t[i]=o>>>0}let r=jn.offsetBytes(this.shapePtr,this.stridesPtr,this.indicesPtr,this.ndim>>>0,this.offsetBytes>>>0);return P(r!==al,"index out of bounds (or offset overflow)"),P(r+this.bytesPerElement<=this.byteLength,"computed byte offset is outside backing storage"),r}get(...e){let t=this.offsetBytesAt(e),r=this.basePtrBytes+t>>>0;P(r%this.bytesPerElement===0,"internal error: misaligned element address");let i=r/this.bytesPerElement;return this.ensureAllView()[i]}set(e,...t){let r=this.offsetBytesAt(t),i=this.basePtrBytes+r>>>0;P(i%this.bytesPerElement===0,"internal error: misaligned element address");let o=i/this.bytesPerElement,a=this.ensureAllView();a[o]=e}zero_(){this.byteLength!==0&&this.backingBytes().fill(0)}uploadToGPU(e,t={}){let r=this.backingBytes(),i=new q(e.device,e.queue,{label:t.label,byteLength:this.byteLength,data:r,copyDst:t.copyDst,copySrc:t.copySrc,usage:t.usage});return new yt(this.dtype,this.shape.slice(),this.stridesBytes.slice(),this.offsetBytes,this.byteLength,i,0,!0)}},yt=class n extends nt{buffer;baseOffsetBytes;owned;constructor(e,t,r,i,o,a,s=0,l=!1){super(e,t,r,i,o),P(Number.isInteger(s)&&s>=0,`baseOffsetBytes must be an integer >= 0 (got ${s})`),P((s&3)===0,`baseOffsetBytes must be 4-byte aligned for storage buffers (got ${s})`),this.buffer=a,this.baseOffsetBytes=s,this.owned=l}static empty(e,t,r,i={}){let o=ye(t),a=ii(r.shape),s=ai(r.offsetBytes,o.bytesPerElement),l=r.stridesBytes?oi(r.stridesBytes,a.length,o.bytesPerElement):un(a,o.bytesPerElement),u=si(a,l,s,o.bytesPerElement),m=new q(e.device,e.queue,{label:i.label,byteLength:u,copyDst:i.copyDst,copySrc:i.copySrc,usage:i.usage});return new n(t,a,l,s,u,m,0,!0)}static wrap(e,t,r,i=0){let o=ye(t),a=ii(r.shape),s=ai(r.offsetBytes,o.bytesPerElement),l=r.stridesBytes?oi(r.stridesBytes,a.length,o.bytesPerElement):un(a,o.bytesPerElement),u=si(a,l,s,o.bytesPerElement);return new n(t,a,l,s,u,e,i,!1)}get residency(){return"gpu-storagebuffer"}bindingResource(){return{buffer:this.buffer,offset:this.baseOffsetBytes,size:le(this.byteLength,4)}}async readbackToCPU(){P(this.buffer.canReadback,"GPUndarray.readbackToCPU() requires the underlying StorageBuffer to be created with copySrc: true");let e=await this.buffer.read(this.baseOffsetBytes,this.byteLength),t=gt.empty(this.dtype,{shape:this.shape,stridesBytes:this.stridesBytes,offsetBytes:this.offsetBytes});return t.backingBytes().set(new Uint8Array(e),0),t}destroy(){this.owned&&this.buffer.destroy()}};var Rr=class{device;queue;kernels;readback;ndarray=nt;CPUndarray=gt;GPUndarray=yt;_rgba8Blitter=null;constructor(e,t,r={}){this.device=e,this.queue=t,this.kernels=new Ht(e,t),this.readback=new bt(e,t,r.readback)}createStorageBuffer(e){return new q(this.device,this.queue,e)}createUniformBuffer(e){return new Nt(this.device,this.queue,e)}createPipeline(e){return new ee(this.device,e)}createReadbackRing(e={}){return new bt(this.device,this.queue,e)}encodeDispatch(e,t,r=!1){r&&$t(this.device,t.workgroups),ni(e,t)}encodeDispatchBatch(e,t,r,i=!1){if(i)for(let o of t)$t(this.device,o.workgroups);kr(e,t,r)}dispatch(e,t={}){let r=this.device.createCommandEncoder();this.encodeDispatch(r,e,t.validateLimits??!1);let i=r.finish();return t.submit!==!1&&this.queue.submit([i]),i}dispatchBatch(e,t,r={}){let i=this.device.createCommandEncoder();this.encodeDispatchBatch(i,e,t,r.validateLimits??!1);let o=i.finish();return r.submit!==!1&&this.queue.submit([o]),o}dispatch1D(e,t,r,i,o,a={}){let s=fe(r,i);return this.dispatch({pipeline:e,bindGroups:t,workgroups:s,label:o},a)}dispatch2D(e,t,r,i,o,a,s,l={}){let u=Mr(r,i,o,a);return this.dispatch({pipeline:e,bindGroups:t,workgroups:u,label:s},l)}dispatch3D(e,t,r,i,o,a,s,l,u,m={}){let c=Ar(r,i,o,a,s,l);return this.dispatch({pipeline:e,bindGroups:t,workgroups:c,label:u},m)}blitRGBA8BufferToCanvas(e,t,r,i,o,a={}){this._rgba8Blitter||(this._rgba8Blitter=new Tr(this.device,this.queue)),this._rgba8Blitter.encode(e,t,r,i,o,a)}workgroups1D(e,t){return fe(e,t)}workgroups2D(e,t,r,i){return Mr(e,t,r,i)}workgroups3D(e,t,r,i,o,a){return Ar(e,t,r,i,o,a)}destroy(){this._rgba8Blitter?.destroy(),this._rgba8Blitter=null,this.readback.destroy(),this.kernels.destroy()}};var Lr=n=>n.startsWith("data:"),Fr=n=>{let e=n.match(/^data:([^,]*),([\s\S]*)$/);if(!e)throw new Error(`Invalid data URI: ${n.slice(0,64)}...`);let t=e[1]??"",r=e[2]??"",i=t.split(";").filter(u=>u.length>0),o=null,a=!1;for(let u of i)u==="base64"?a=!0:o=u;if(a){let u=atob(r),m=new Uint8Array(u.length);for(let c=0;c<u.length;c++)m[c]=u.charCodeAt(c)&255;return{mimeType:o,data:m.buffer}}let s=decodeURIComponent(r),l=new Uint8Array(s.length);for(let u=0;u<s.length;u++)l[u]=s.charCodeAt(u)&255;return{mimeType:o,data:l.buffer}},No=n=>{let e=n.lastIndexOf("/");return e<0?"":n.slice(0,e+1)},Dr=(n,e)=>e.startsWith("http://")||e.startsWith("https://")||e.startsWith("blob:")||e.startsWith("/")||!n?e:n+e;var qt=n=>{let e=new DataView(n);if(e.byteLength<12)throw new Error("Invalid GLB: too small");let t=e.getUint32(0,!0),r=e.getUint32(4,!0),i=e.getUint32(8,!0);if(t!==1179937895)throw new Error("Invalid GLB: bad magic");if(r!==2)throw new Error(`Unsupported GLB version: ${r}`);if(i>e.byteLength)throw new Error("Invalid GLB: length exceeds buffer");let o=12,a=null,s=null;for(;o+8<=i;){let m=e.getUint32(o+0,!0),c=e.getUint32(o+4,!0);if(o+=8,o+m>i)throw new Error("Invalid GLB: chunk exceeds buffer length");let d=n.slice(o,o+m);c===1313821514?a=d:c===5130562&&!s&&(s=d),o+=m}if(!a)throw new Error("Invalid GLB: missing JSON chunk");let l=new TextDecoder("utf-8").decode(a);return{json:JSON.parse(l),binChunk:s}};var Kt={5120:{bytes:1,ctor:Int8Array,signed:!0,bits:8},5121:{bytes:1,ctor:Uint8Array,signed:!1,bits:8},5122:{bytes:2,ctor:Int16Array,signed:!0,bits:16},5123:{bytes:2,ctor:Uint16Array,signed:!1,bits:16},5124:{bytes:4,ctor:Int32Array,signed:!0,bits:32},5125:{bytes:4,ctor:Uint32Array,signed:!1,bits:32},5126:{bytes:4,ctor:Float32Array,signed:!0,bits:32}},sl=n=>{switch(n){case"SCALAR":return 1;case"VEC2":return 2;case"VEC3":return 3;case"VEC4":return 4;case"MAT2":return 4;case"MAT3":return 9;case"MAT4":return 16;default:return 1}},ll=(n,e)=>{let t=n.accessors?.[e];if(!t)throw new Error(`Invalid accessor index: ${e}`);return t},ui=(n,e)=>{let t=n.bufferViews?.[e];if(!t)throw new Error(`Invalid bufferView index: ${e}`);return t},ci=(n,e,t)=>{let r=_.allocBytes(t),i=new Uint8Array(n,e,t);return _.u8view(r,t).set(i),r},ul=(n,e)=>{let t=new Uint8Array(e);return t.set(_.u8view(n,e)),t},it=(n,e)=>{let t=n.json,r=ll(t,e),i=r.componentType,o=Kt[i];if(!o)throw new Error(`Unsupported accessor componentType: ${i}`);let a=r.count|0,s=r.type,l=sl(s),u=r.normalized===!0,m=o.bytes*l,c;if(r.bufferView===void 0)c=new o.ctor(new ArrayBuffer(a*l*o.bytes),0,a*l);else{let d=ui(t,r.bufferView);if(d.extensions?.EXT_meshopt_compression)throw new Error("EXT_meshopt_compression is not supported yet. Please provide an uncompressed glTF/GLB.");let f=n.buffers[d.buffer];if(!f)throw new Error(`Missing buffer[${d.buffer}]`);let p=(d.byteOffset??0)|0,b=(r.byteOffset??0)|0,g=p+b,x=d.byteStride??m;if(x<m)throw new Error(`Invalid bufferView.byteStride (${x}) < element byte size (${m})`);let M=x===m,h=g%o.bytes===0;if(M&&h)c=new o.ctor(f,g,a*l);else if(a<=0)c=new o.ctor(new ArrayBuffer(0),0,0);else{let w=o.bytes*l,S=(a-1)*x+w,B=ci(f,g,S),v=a*w,A=_.allocBytes(v);try{kt.deinterleave(A,B,a,l,o.bytes,x);let C=ul(A,v),k=new ArrayBuffer(v);new Uint8Array(k).set(C),c=new o.ctor(k,0,a*l)}finally{_.freeBytes(A,v),_.freeBytes(B,S)}}}if(r.sparse){let d=c.slice();cl(n,r,d,i,l),c=d}return{accessor:r,componentType:i,type:s,count:a,numComponents:l,normalized:u,array:c}},cl=(n,e,t,r,i)=>{let o=e.sparse,a=o.count|0;if(a<=0)return;let s=ui(n.json,o.indices.bufferView);if(s.extensions?.EXT_meshopt_compression)throw new Error("EXT_meshopt_compression sparse indices are not supported yet.");let l=n.buffers[s.buffer];if(!l)throw new Error(`Missing buffer[${s.buffer}] for sparse indices`);let u=(s.byteOffset??0)+(o.indices.byteOffset??0),m=o.indices.componentType,c=Kt[m];if(!c)throw new Error(`Unsupported sparse indices componentType: ${m}`);let d=c.bytes,f=ui(n.json,o.values.bufferView);if(f.extensions?.EXT_meshopt_compression)throw new Error("EXT_meshopt_compression sparse values are not supported yet.");let p=n.buffers[f.buffer];if(!p)throw new Error(`Missing buffer[${f.buffer}] for sparse values`);let b=(f.byteOffset??0)+(o.values.byteOffset??0),g=Kt[r];if(!g)throw new Error(`Unsupported sparse values componentType: ${r}`);let x=t.length,M=g.bytes,h=x*M,w=_.allocBytes(h);_.u8view(w,h).set(new Uint8Array(t.buffer,t.byteOffset,h));let S=a*d,B=ci(l,u,S),v=a*i*M,A=ci(p,b,v);try{kt.applySparse(w,x,r,i,B,m,A,a);let C=_.u8view(w,h);new Uint8Array(t.buffer,t.byteOffset,h).set(C)}finally{_.freeBytes(A,v),_.freeBytes(B,S),_.freeBytes(w,h)}},ke=(n,e)=>{let t=it(n,e),r=Kt[t.componentType];if(!r)throw new Error(`Unsupported componentType: ${t.componentType}`);if(t.componentType===5126&&!t.normalized)return t.array;let i=t.array.length*r.bytes,o=_.allocBytes(i);_.u8view(o,i).set(new Uint8Array(t.array.buffer,t.array.byteOffset,i));let a=_.allocF32(t.array.length);try{kt.convertToF32(a,o,t.array.length,t.componentType,t.normalized);let s=new Float32Array(t.array.length);return s.set(_.f32view(a,t.array.length)),s}finally{_.freeF32(a,t.array.length),_.freeBytes(o,i)}},Xt=(n,e)=>{let t=it(n,e),r=t.componentType,i=Kt[r];if(!i)throw new Error(`Unsupported componentType: ${r}`);if(r===5123&&!t.normalized)return t.array;let o=t.array.length*i.bytes,a=_.allocBytes(o);_.u8view(a,o).set(new Uint8Array(t.array.buffer,t.array.byteOffset,o));let s=t.array.length*2,l=_.allocBytes(s);try{kt.convertToU16(l,a,t.array.length,r);let u=new Uint16Array(t.array.length);return new Uint8Array(u.buffer).set(_.u8view(l,s)),u}finally{_.freeBytes(l,s),_.freeBytes(a,o)}},Ir=(n,e)=>{let t=it(n,e),r=t.componentType,i=Kt[r];if(!i)throw new Error(`Unsupported componentType: ${r}`);if(r===5125&&!t.normalized)return t.array;let o=t.array.length*i.bytes,a=_.allocBytes(o);_.u8view(a,o).set(new Uint8Array(t.array.buffer,t.array.byteOffset,o));let s=t.array.length*4,l=_.allocBytes(s);try{kt.convertToU32(l,a,t.array.length,r);let u=new Uint32Array(t.array.length);return new Uint8Array(u.buffer).set(_.u8view(l,s)),u}finally{_.freeBytes(l,s),_.freeBytes(a,o)}};var ml=(n,e)=>n?.onWarning?.(e),Vo=n=>{let e=n?.fetch??globalThis.fetch;if(!e)throw new Error("loadGltf(): fetch() is not available. Pass LoadGltfOptions.fetch or provide an ArrayBuffer source.");return e},mi=async(n,e)=>{let r=await Vo(e)(n);if(!r.ok)throw new Error(`Failed to fetch ${n}: ${r.status} ${r.statusText}`);return await r.arrayBuffer()},dl=async(n,e)=>{let r=await Vo(e)(n);if(!r.ok)throw new Error(`Failed to fetch ${n}: ${r.status} ${r.statusText}`);return await r.json()},cn=async(n,e,t,r)=>{let i=n.buffers??[],o=new Array(i.length);for(let a=0;a<i.length;a++){let s=i[a];if(!s.uri){if(!r)throw new Error(`buffers[${a}] has no uri but no GLB BIN chunk was provided`);o[a]=r;continue}if(Lr(s.uri)){o[a]=Fr(s.uri).data;continue}let l=Dr(e,s.uri);o[a]=await mi(l,t)}return o},mn=async(n,e,t,r)=>{let i=n.images??[],o=new Array(i.length);for(let a=0;a<i.length;a++){let s=i[a];if(s.uri){if(Lr(s.uri))o[a]=Fr(s.uri).data;else{let l=Dr(t,s.uri);o[a]=await mi(l,r)}continue}if(s.bufferView!==void 0){let l=n.bufferViews?.[s.bufferView];if(!l)throw new Error(`Invalid images[${a}].bufferView: ${s.bufferView}`);let u=e[l.buffer];if(!u)throw new Error(`Missing buffer[${l.buffer}] for images[${a}]`);let m=(l.byteOffset??0)|0,c=l.byteLength|0,d=new Uint8Array(c);d.set(new Uint8Array(u,m,c)),o[a]=d.buffer;continue}ml(r,`images[${a}] has neither uri nor bufferView; skipping`),o[a]=new ArrayBuffer(0)}return o},dn=async(n,e)=>{if(typeof n=="string"){let m=n,c=e?.baseUrl??No(m);if(m.toLowerCase().endsWith(".glb")){let b=await mi(m,e),{json:g,binChunk:x}=qt(b),M=await cn(g,c,e,x),h={json:g,buffers:M,baseUrl:c};return e?.loadImages&&(h.images=await mn(g,M,c,e)),h}let d=await dl(m,e),f=await cn(d,c,e,null),p={json:d,buffers:f,baseUrl:c};return e?.loadImages&&(p.images=await mn(d,f,c,e)),p}let t=n,r=new DataView(t),i=r.byteLength>=4?r.getUint32(0,!0):0,o=e?.baseUrl??"";if(i===1179937895){let{json:m,binChunk:c}=qt(t),d=await cn(m,o,e,c),f={json:m,buffers:d,baseUrl:o};return e?.loadImages&&(f.images=await mn(m,d,o,e)),f}let a=new TextDecoder("utf-8").decode(t),s=JSON.parse(a),l=await cn(s,o,e,null),u={json:s,buffers:l,baseUrl:o};return e?.loadImages&&(u.images=await mn(s,l,o,e)),u};var jo="@group(0) @binding(0) var samp: sampler; @group(0) @binding(1) var tex: texture_2d<f32>; struct VSOut { @builtin(position) pos: vec4f, @location(0) uv: vec2f }; @vertex fn vs_main(@builtin(vertex_index) idx: u32) -> VSOut { var positions = array<vec2f, 3>( vec2f(-1.0, -1.0), vec2f( 3.0, -1.0), vec2f(-1.0, 3.0) ); var uvs = array<vec2f, 3>( vec2f(0.0, 1.0), vec2f(2.0, 1.0), vec2f(0.0, -1.0) ); var o: VSOut; o.pos = vec4f(positions[idx], 0.0, 1.0); o.uv = uvs[idx]; return o; } @fragment fn fs_main(in: VSOut) -> @location(0) vec4f { return textureSample(tex, samp, in.uv); }";var fl=1,hl=()=>typeof globalThis.createImageBitmap=="function",bl=(n,e)=>{let t=Math.max(1,n|0,e|0);return(Math.floor(Math.log2(t))|0)+1},$o=new WeakMap,gl=n=>{let e=$o.get(n);if(e)return e;let t=n.createShaderModule({code:jo}),r=n.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]}),i=n.createPipelineLayout({bindGroupLayouts:[r]}),o=l=>n.createRenderPipeline({layout:i,vertex:{module:t,entryPoint:"vs_main"},fragment:{module:t,entryPoint:"fs_main",targets:[{format:l}]},primitive:{topology:"triangle-list"}}),a=n.createSampler({minFilter:"linear",magFilter:"linear"}),s={pipelineLinear:o("rgba8unorm"),pipelineSrgb:o("rgba8unorm-srgb"),sampler:a,bindGroupLayout:r};return $o.set(n,s),s},vt=class n{id=fl++;_source;_mipmaps;_mipmapColorSpace=null;samplerDesc;_gpuTexture=null;_viewLinear=null;_viewSrgb=null;_sampler=null;_uploadPromise=null;_uploadStarted=!1;_revision=0;_width=0;_height=0;constructor(e){this._source=e.source,this._mipmaps=e.mipmaps??!0,this.samplerDesc={addressModeU:e.sampler?.addressModeU??"repeat",addressModeV:e.sampler?.addressModeV??"repeat",addressModeW:e.sampler?.addressModeW??"repeat",magFilter:e.sampler?.magFilter??"linear",minFilter:e.sampler?.minFilter??"linear",mipmapFilter:e.sampler?.mipmapFilter??"linear",lodMinClamp:e.sampler?.lodMinClamp??0,lodMaxClamp:e.sampler?.lodMaxClamp??32}}get revision(){return this._revision}get width(){return this._width}get height(){return this._height}get uploaded(){return!!this._gpuTexture}static createFrom(e){return new n(e)}getSampler(e,t){if(this._sampler)return this._sampler;try{return this._sampler=e.createSampler(this.samplerDesc),this._sampler}catch(r){if(t)return t;throw r}}getView(e,t,r,i){return this._gpuTexture?r==="srgb"?this._viewSrgb??i:this._viewLinear??i:(this.ensureUploaded(e,t,r),i)}destroy(){this._gpuTexture?.destroy(),this._gpuTexture=null,this._viewLinear=null,this._viewSrgb=null,this._sampler=null,this._uploadStarted=!1,this._uploadPromise=null,this._mipmapColorSpace=null,this._revision++}ensureUploaded(e,t,r="linear"){this._uploadStarted||(this._uploadStarted=!0,this._mipmapColorSpace=r,this._uploadPromise=(async()=>{let i=null,o=null;try{i=await this.decodeBitmap();let a=i.width|0,s=i.height|0,l=this._mipmaps?bl(a,s):1;o=e.createTexture({size:{width:a,height:s},format:"rgba8unorm",mipLevelCount:l,usage:this._mipmaps?GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST,viewFormats:["rgba8unorm-srgb"]}),t.copyExternalImageToTexture({source:i},{texture:o},{width:a,height:s}),this._mipmaps&&l>1&&this.generateMipmaps(e,o,l,this._mipmapColorSpace??"linear");let u=o.createView({format:"rgba8unorm"}),m=o.createView({format:"rgba8unorm-srgb"});this._viewLinear=u,this._viewSrgb=m,this._width=a,this._height=s,this._gpuTexture=o,this._revision++}catch(a){this._uploadStarted=!1,this._uploadPromise=null,this._mipmapColorSpace=null;try{o?.destroy()}catch{}throw a}finally{if(i&&this._source.kind!=="bitmap")try{i.close?.()}catch{}}})(),this._uploadPromise.catch(i=>console.warn("Texture2D upload failed: ",i)))}async decodeBitmap(){let e=this._source;if(e.kind==="bitmap")return e.bitmap;if(!hl())throw new Error("createImageBitmap() is not available in this environment.");let t={premultiplyAlpha:"none",imageOrientation:"none",colorSpaceConversion:this._mipmapColorSpace==="srgb"?"default":"none"};if(e.kind==="url"){let i=await fetch(e.url);if(!i.ok)throw new Error(`Failed to fetch texture: ${i.status} ${i.statusText}`);let o=await i.blob();try{return await createImageBitmap(o,t)}catch{return await createImageBitmap(o)}}let r=new Blob([e.bytes],{type:e.mimeType??"application/octet-stream"});try{return await createImageBitmap(r,t)}catch{return await createImageBitmap(r)}}generateMipmaps(e,t,r,i){let o=gl(e),a=i==="srgb"?o.pipelineSrgb:o.pipelineLinear,s=i==="srgb"?"rgba8unorm-srgb":"rgba8unorm",l=e.createCommandEncoder();for(let u=1;u<r;u++){let m=t.createView({baseMipLevel:u-1,mipLevelCount:1,format:s}),c=t.createView({baseMipLevel:u,mipLevelCount:1,format:s}),d=e.createBindGroup({layout:o.bindGroupLayout,entries:[{binding:0,resource:o.sampler},{binding:1,resource:m}]}),f=l.beginRenderPass({colorAttachments:[{view:c,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]});f.setPipeline(a),f.setBindGroup(0,d),f.draw(3),f.end()}e.queue.submit([l.finish()])}};var xt=class{name;samplerCount;channelCount;samplersPtr;channelsPtr;startTime;endTime;_ownedF32Allocs;_ownedU32Allocs;_disposed=!1;constructor(e){this.name=e.name,this.samplerCount=e.samplerCount|0,this.channelCount=e.channelCount|0,this.samplersPtr=e.samplersPtr,this.channelsPtr=e.channelsPtr,this.startTime=e.startTime,this.endTime=e.endTime,this._ownedF32Allocs=e.ownedF32Allocs??null,this._ownedU32Allocs=e.ownedU32Allocs??null}get duration(){return Math.max(0,this.endTime-this.startTime)}sample(e){let t=N.global(),r={posPtr:t.posPtr,rotPtr:t.rotPtr,sclPtr:t.sclPtr};Gt.sampleClipTRS(r.posPtr,r.rotPtr,r.sclPtr,t.count|0,this.samplersPtr,this.samplerCount,this.channelsPtr,this.channelCount,e),t.markDirty()}dispose(){if(!this._disposed){if(this._disposed=!0,this._ownedF32Allocs)for(let e of this._ownedF32Allocs)e.ptr&&_.freeF32(e.ptr,e.len|0);if(this._ownedU32Allocs)for(let e of this._ownedU32Allocs)e.ptr&&_.freeU32(e.ptr,e.len|0);this._ownedF32Allocs=null,this._ownedU32Allocs=null}}},Er=class{clip;time=0;speed=1;loop=!0;playing=!0;constructor(e,t={}){this.clip=e,t.speed!==void 0&&(this.speed=t.speed),t.loop!==void 0&&(this.loop=t.loop),t.playing!==void 0&&(this.playing=t.playing),this.time=e.startTime}update(e){if(!this.playing)return;let t=this.clip.duration;if(t<=0){this.clip.sample(this.clip.startTime);return}if(this.time+=e*this.speed,this.loop){let r=this.clip.startTime,i=this.clip.endTime;for(;this.time<r;)this.time+=t;for(;this.time>=i;)this.time-=t}else this.time=Math.max(this.clip.startTime,Math.min(this.time,this.clip.endTime));this.clip.sample(this.time)}},Pt=class{name;joints;jointCount;jointIndicesPtr;invBindPtr;_disposed=!1;constructor(e,t,r){this.name=e,this.joints=t,this.jointCount=t.length|0,this.jointIndicesPtr=_.allocU32(this.jointCount);let i=_.u32view(this.jointIndicesPtr,this.jointCount);for(let a=0;a<this.jointCount;a++)i[a]=t[a].index>>>0;this.invBindPtr=_.allocF32(this.jointCount*16);let o=_.f32view(this.invBindPtr,this.jointCount*16);if(r&&r.length===this.jointCount*16)o.set(r);else for(let a=0;a<this.jointCount;a++){let s=a*16;o[s+0]=1,o[s+1]=0,o[s+2]=0,o[s+3]=0,o[s+4]=0,o[s+5]=1,o[s+6]=0,o[s+7]=0,o[s+8]=0,o[s+9]=0,o[s+10]=1,o[s+11]=0,o[s+12]=0,o[s+13]=0,o[s+14]=0,o[s+15]=1}}createInstance(e){return new pn(this,e)}dispose(){this._disposed||(this._disposed=!0,this.jointIndicesPtr&&_.freeU32(this.jointIndicesPtr,this.jointCount),this.invBindPtr&&_.freeF32(this.invBindPtr,this.jointCount*16))}},pn=class{skin;meshTransform;bindMatrixPtr=0;boneBuffer=null;bindGroup=null;constructor(e,t){this.skin=e,this.meshTransform=t,this.bindMatrixPtr=_.allocF32(16);let r=_.f32view(this.bindMatrixPtr,16),i=t.worldMatrix;for(let o=0;o<16;o++)r[o]=i[o]??(o%5===0?1:0)}get jointCount(){return this.skin.jointCount}ensureGpuResources(e,t){if(this.boneBuffer&&this.bindGroup)return;let r=this.skin.jointCount*16*4;this.boneBuffer=e.createBuffer({size:r,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.bindGroup=e.createBindGroup({layout:t,entries:[{binding:0,resource:{buffer:this.boneBuffer}}]})}dispose(){this.boneBuffer?.destroy(),this.boneBuffer=null,this.bindGroup=null,this.bindMatrixPtr&&(_.freeF32(this.bindMatrixPtr,16),this.bindMatrixPtr=0)}};var Or=class n{transform;type;_projectionMatrix=null;_viewMatrix=null;_viewProjectionMatrix=null;_projectionDirty=!0;constructor(e){this.type=e,this.transform=new pe}get viewMatrix(){let e=this.transform.worldMatrix;return this._viewMatrix=ze.invert(e),this._viewMatrix}get viewProjectionMatrix(){let e=this.getProjectionMatrix(),t=this.viewMatrix;return this._viewProjectionMatrix=ze.mul(e,t),this._viewProjectionMatrix}get position(){return this.transform.worldPosition}get up(){let e=this.transform.worldMatrix;return[e[4],e[5],e[6]]}lookAt(e,t,r){let i=typeof e=="number"?[e,t,r]:e;return this.lookAtWithUp(i,[0,1,0])}lookAtWithUp(e,t){let r=this.transform.worldPosition,i=Ge.normalize(Ge.sub(e,r)),o=[t[0],t[1],t[2]];Math.abs(Ge.dot(i,o))>.999&&(Math.abs(i[1])<.9?o=[0,1,0]:o=[1,0,0]);let a=Ge.normalize(Ge.cross(i,o)),s=Ge.cross(a,i),l=[a[0],a[1],a[2],0,s[0],s[1],s[2],0,-i[0],-i[1],-i[2],0,0,0,0,1],u=n.matrixToQuaternion(l);return this.transform.setRotation(u[0],u[1],u[2],u[3]),this}static matrixToQuaternion(e){let t=e[0]+e[5]+e[10],r,i,o,a;if(t>0){let s=.5/Math.sqrt(t+1);r=.25/s,i=(e[6]-e[9])*s,o=(e[8]-e[2])*s,a=(e[1]-e[4])*s}else if(e[0]>e[5]&&e[0]>e[10]){let s=2*Math.sqrt(1+e[0]-e[5]-e[10]);r=(e[6]-e[9])/s,i=.25*s,o=(e[4]+e[1])/s,a=(e[8]+e[2])/s}else if(e[5]>e[10]){let s=2*Math.sqrt(1+e[5]-e[0]-e[10]);r=(e[8]-e[2])/s,i=(e[4]+e[1])/s,o=.25*s,a=(e[9]+e[6])/s}else{let s=2*Math.sqrt(1+e[10]-e[0]-e[5]);r=(e[1]-e[4])/s,i=(e[8]+e[2])/s,o=(e[9]+e[6])/s,a=.25*s}return[i,o,a,r]}markProjectionDirty(){this._projectionDirty=!0}},wt=class extends Or{_fov;_aspect;_near;_far;constructor(e={}){super("perspective"),this._fov=e.fov??60,this._aspect=e.aspect??16/9,this._near=e.near??.1,this._far=e.far??1e3}get fov(){return this._fov}set fov(e){e!==this._fov&&(this._fov=e,this.markProjectionDirty())}get aspect(){return this._aspect}set aspect(e){e!==this._aspect&&(this._aspect=e,this.markProjectionDirty())}get near(){return this._near}set near(e){e!==this._near&&(this._near=e,this.markProjectionDirty())}get far(){return this._far}set far(e){e!==this._far&&(this._far=e,this.markProjectionDirty())}updateAspect(e,t){return this._aspect=e/t,this.markProjectionDirty(),this}getProjectionMatrix(){if(this._projectionDirty||!this._projectionMatrix){let e=this._fov*Math.PI/180;this._projectionMatrix=ze.perspective(e,this._aspect,this._near,this._far),this._projectionDirty=!1}return this._projectionMatrix}},St=class extends Or{_left;_right;_top;_bottom;_near;_far;constructor(e={}){super("orthographic"),this._left=e.left??-10,this._right=e.right??10,this._top=e.top??10,this._bottom=e.bottom??-10,this._near=e.near??.1,this._far=e.far??1e3}get left(){return this._left}set left(e){e!==this._left&&(this._left=e,this.markProjectionDirty())}get right(){return this._right}set right(e){e!==this._right&&(this._right=e,this.markProjectionDirty())}get top(){return this._top}set top(e){e!==this._top&&(this._top=e,this.markProjectionDirty())}get bottom(){return this._bottom}set bottom(e){e!==this._bottom&&(this._bottom=e,this.markProjectionDirty())}get near(){return this._near}set near(e){e!==this._near&&(this._near=e,this.markProjectionDirty())}get far(){return this._far}set far(e){e!==this._far&&(this._far=e,this.markProjectionDirty())}updateFromCanvas(e,t,r=1){let i=e/2/r,o=t/2/r;return this._left=-i,this._right=i,this._top=o,this._bottom=-o,this.markProjectionDirty(),this}getProjectionMatrix(){return(this._projectionDirty||!this._projectionMatrix)&&(this._projectionMatrix=this.computeOrthographicMatrix(),this._projectionDirty=!1),this._projectionMatrix}computeOrthographicMatrix(){let e=1/(this._left-this._right),t=1/(this._bottom-this._top),r=1/(this._near-this._far);return[-2*e,0,0,0,0,-2*t,0,0,0,0,r,0,(this._left+this._right)*e,(this._top+this._bottom)*t,this._near*r,1]}};var Y=(n,e)=>{n?.onWarning?.(e)},yl=(n,e,t)=>{if(!n)return 0;let r=new Set,i=l=>{if(!l)return;let u=(l.texCoord??0)|0;r.add(u)};i(n.pbrMetallicRoughness?.baseColorTexture),i(n.pbrMetallicRoughness?.metallicRoughnessTexture),i(n.normalTexture),i(n.occlusionTexture),i(n.emissiveTexture);let o=n.extensions?.KHR_materials_pbrSpecularGlossiness;i(o?.diffuseTexture),i(o?.specularGlossinessTexture);let a=n.pbrMetallicRoughness?.baseColorTexture?.texCoord??o?.diffuseTexture?.texCoord,s=typeof a=="number"?a|0:0;if(typeof a!="number"&&r.size>0&&(s=Math.max(...Array.from(r.values()))),(s<0||s>1)&&(Y(e,`${t}: TEXCOORD_${s} requested by material, but WasmGPU only supports TEXCOORD_0 or TEXCOORD_1; using TEXCOORD_0.`),s=0),r.size>1){let l=Array.from(r.values()).sort((u,m)=>u-m).join(", ");Y(e,`${t}: material references multiple texCoord sets (${l}). WasmGPU uses TEXCOORD_${s} for all textures on this primitive.`)}return s},qo=9728,Ko=9729,vl=9984,xl=9985,Pl=9986,wl=9987,Sl=33071,Cl=33648,_l=10497,Ho=n=>{switch(n){case Sl:return"clamp-to-edge";case Cl:return"mirror-repeat";case _l:default:return"repeat"}},Bl=n=>{switch(n){case qo:return"nearest";case Ko:default:return"linear"}},Ml=n=>{switch(n){case qo:return{minFilter:"nearest",mipmapFilter:"nearest",useMipmaps:!1};case Ko:return{minFilter:"linear",mipmapFilter:"nearest",useMipmaps:!1};case vl:return{minFilter:"nearest",mipmapFilter:"nearest",useMipmaps:!0};case xl:return{minFilter:"linear",mipmapFilter:"nearest",useMipmaps:!0};case Pl:return{minFilter:"nearest",mipmapFilter:"linear",useMipmaps:!0};case wl:default:return{minFilter:"linear",mipmapFilter:"linear",useMipmaps:!0}}},Al=n=>{if(!n)return;let e=n.toLowerCase();if(e.endsWith(".png"))return"image/png";if(e.endsWith(".jpg")||e.endsWith(".jpeg"))return"image/jpeg";if(e.endsWith(".webp"))return"image/webp";if(e.endsWith(".gif"))return"image/gif"},Ul=(n,e)=>e?.sceneIndex!==void 0?e.sceneIndex|0:n.scene!==void 0?n.scene|0:0,kl=n=>{let e=n.extensions?.KHR_lights_punctual;return e||null},Gl=n=>{let e=n.extensions?.KHR_lights_punctual;return e||null},Tl=n=>!!n.extensions?.KHR_materials_unlit,fn=0,hn=0,Rl=()=>{fn!==0&&hn!==0||(fn=_.allocF32(16),hn=_.allocF32(10))},Ll=(n,e)=>{Rl();let t=_.f32view(fn,16);for(let i=0;i<16;i++)t[i]=e[i]??(i%5===0?1:0);ne.decomposeTRS(hn,fn);let r=_.f32view(hn,10);n.setPosition(r[0],r[1],r[2]),n.setRotation(r[3],r[4],r[5],r[6]),n.setScale(r[7],r[8],r[9])},gi=0,di=0,yi=0,pi=0,vi=0,fi=0,hi=n=>{let e=Math.max(1,n|0);return e--,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,e|=e>>16,e++,e},Fl=(n,e)=>{di<n&&(di=hi(n),gi=_.allocF32(di)),fi<n&&(fi=hi(n),vi=_.allocF32(fi)),e>0&&pi<e&&(pi=hi(e),yi=_.allocU32(pi))},Dl=(n,e)=>{let t=n.length/3|0,r=e?e.length|0:0;Fl(n.length,r),_.f32view(gi,n.length).set(n);let i=e&&r>0?yi:0;e&&r>0&&_.u32view(yi,r).set(e),Li.computeVertexNormals(vi,gi,t,i,r);let o=new Float32Array(n.length);return o.set(_.f32view(vi,n.length)),o},bi=n=>{let e=new Float32Array(n);for(let t=0;t<e.length;t+=4){let r=e[t+0]??0,i=e[t+1]??0,o=e[t+2]??0,a=e[t+3]??0,s=r+i+o+a;if(s>0){let l=1/s;e[t+0]=r*l,e[t+1]=i*l,e[t+2]=o*l,e[t+3]=a*l}else e[t+0]=1,e[t+1]=0,e[t+2]=0,e[t+3]=0}return e},Il=(n,e)=>{let t=new Float32Array(n),r=new Float32Array(e);for(let i=0;i<t.length;i+=4){let o=t[i+0]??0,a=t[i+1]??0,s=t[i+2]??0,l=t[i+3]??0,u=r[i+0]??0,m=r[i+1]??0,c=r[i+2]??0,d=r[i+3]??0,f=o+a+s+l+u+m+c+d;if(f>0){let p=1/f;t[i+0]=o*p,t[i+1]=a*p,t[i+2]=s*p,t[i+3]=l*p,r[i+0]=u*p,r[i+1]=m*p,r[i+2]=c*p,r[i+3]=d*p}else t[i+0]=1,t[i+1]=0,t[i+2]=0,t[i+3]=0,r[i+0]=0,r[i+1]=0,r[i+2]=0,r[i+3]=0}return{weights0:t,weights1:r}},El=n=>{let e=[];for(let t=0;t+2<n.length;t++){let r=n[t],i=n[t+1],o=n[t+2];r===i||i===o||r===o||((t&1)===0?e.push(r,i,o):e.push(i,r,o))}return new Uint32Array(e)},Ol=n=>{let e=[];if(n.length<3)return new Uint32Array(0);let t=n[0];for(let r=1;r+1<n.length;r++){let i=n[r],o=n[r+1];t===i||i===o||t===o||e.push(t,i,o)}return new Uint32Array(e)},zl=(n,e,t,r,i,o)=>{if(t===void 0)return new xe({});let a=r.get(t);if(a)return a;let s=e.materials?.[t];if(!s){let U=new xe({});return r.set(t,U),U}let l=(U,L)=>{if(U===void 0)return null;let E=i.get(U);if(E)return E;let z=e.textures?.[U];if(!z)return Y(o,`glTF texture index ${U} missing (usage=${L}).`),null;let O=z.source,I=O!==void 0?e.images?.[O]:void 0;if(O===void 0||!I)return Y(o,`glTF texture ${U} has no valid source image (usage=${L}).`),null;let j=z.sampler!==void 0?e.samplers?.[z.sampler]:void 0,Z=Ho(j?.wrapS),ae=Ho(j?.wrapT),ue=Bl(j?.magFilter),{minFilter:Je,mipmapFilter:se,useMipmaps:ce}=Ml(j?.minFilter),J=null,Ie=n.images?.[O],we=I.mimeType??Al(I.uri);if(Ie)J={kind:"bytes",bytes:Ie,mimeType:we};else if(I.bufferView!==void 0){let he=e.bufferViews?.[I.bufferView],Oe=he?n.buffers[he.buffer]:void 0;if(he&&Oe){let lt=(he.byteOffset??0)|0;J={kind:"bytes",bytes:Oe.slice(lt,lt+he.byteLength),mimeType:we}}else Y(o,`glTF image bufferView ${I.bufferView} missing (texture=${U}, usage=${L}).`)}else if(I.uri)if(Lr(I.uri)){let he=Fr(I.uri);J={kind:"bytes",bytes:he.data,mimeType:we??he.mimeType??void 0}}else J={kind:"url",url:Dr(n.baseUrl,I.uri),mimeType:we};if(!J)return Y(o,`Could not resolve image source for texture=${U} (usage=${L}).`),null;let Ee=vt.createFrom({source:J,mipmaps:ce,sampler:{addressModeU:Z,addressModeV:ae,magFilter:ue,minFilter:Je,mipmapFilter:se}});return i.set(U,Ee),Ee},u=(U,L)=>{if(!U)return null;let E=(U.texCoord??0)|0;return E>1&&Y(o,`Texture texCoord=${E} not supported yet (usage=${L}); expected 0 or 1.`),U.extensions?.KHR_texture_transform&&Y(o,`KHR_texture_transform not supported yet (usage=${L}); ignoring.`),l(U.index,L)},m=s.alphaMode??"OPAQUE",c=m==="MASK"?s.alphaCutoff??.5:0,d=m==="BLEND"?"transparent":"opaque",f=s.doubleSided?"none":"back",p=s.pbrMetallicRoughness,b=s.extensions?.KHR_materials_pbrSpecularGlossiness;!p&&b&&(Y(o,`Material '${s.name??t}' uses KHR_materials_pbrSpecularGlossiness; approximating using diffuse as baseColor. Specular/glossiness are not fully supported yet.`),b.specularGlossinessTexture&&Y(o,`Material '${s.name??t}' has specularGlossinessTexture; currently ignored (highlights/roughness may look off).`));let g=p?.baseColorFactor??b?.diffuseFactor??[1,1,1,1],x=u(p?.baseColorTexture??b?.diffuseTexture,"baseColor"),M=1,h=1;p?(M=p.metallicFactor??1,h=p.roughnessFactor??1):b&&(M=0,h=1-(b.glossinessFactor??1),h<0&&(h=0),h>1&&(h=1));let w=p?u(p.metallicRoughnessTexture,"metallicRoughness"):null,S=u(s.normalTexture,"normal"),B=u(s.occlusionTexture,"occlusion"),v=u(s.emissiveTexture,"emissive"),A=s.normalTexture?.scale??1,C=s.occlusionTexture?.strength??1,k=s.emissiveFactor??[0,0,0],R=s.extensions?.KHR_materials_emissive_strength?.emissiveStrength??1,T=Tl(s),F=d==="opaque",D;return T?D=new Se({color:[g[0]??1,g[1]??1,g[2]??1],opacity:g[3]??1,baseColorTexture:x,alphaCutoff:c,blendMode:d,cullMode:f,depthWrite:F}):D=new xe({color:[g[0]??1,g[1]??1,g[2]??1],opacity:g[3]??1,metallic:M,roughness:h,emissive:[k[0]??0,k[1]??0,k[2]??0],emissiveIntensity:R,baseColorTexture:x,metallicRoughnessTexture:w,normalTexture:S,occlusionTexture:B,emissiveTexture:v,normalScale:A,occlusionStrength:C,alphaCutoff:c,blendMode:d,cullMode:f,depthWrite:F}),r.set(t,D),D},Wl=(n,e,t,r,i)=>{let o=t.attributes,a=o.POSITION;if(a===void 0)return Y(i,"Primitive missing POSITION; skipping"),null;let s=ke(n,a),l=null,u=o.NORMAL;u!==void 0&&(l=ke(n,u));let m=null,c=o.TEXCOORD_0;c!==void 0&&(m=ke(n,c));let d=null,f=null,p=null,b=null,g=o.JOINTS_0,x=o.WEIGHTS_0,M=o.JOINTS_1,h=o.WEIGHTS_1;if(g!==void 0&&x!==void 0){let B=Xt(n,g),v=ke(n,x);if(M!==void 0&&h!==void 0){let A=Xt(n,M),C=ke(n,h);if(A.length===B.length&&C.length===v.length){let k=Il(v,C);d=B,f=k.weights0,p=A,b=k.weights1}else Y(i,"Primitive has JOINTS_1/WEIGHTS_1 but lengths don't match JOINTS_0/WEIGHTS_0; ignoring additional influences"),d=B,f=bi(v)}else M!==void 0||h!==void 0?(Y(i,"Primitive has JOINTS_1/WEIGHTS_1 mismatch; ignoring additional influences"),d=B,f=bi(v)):(d=B,f=bi(v))}else(g!==void 0||x!==void 0)&&Y(i,"Primitive has JOINTS_0/WEIGHTS_0 mismatch; ignoring skinning attributes for this primitive");let w=t.mode??4,S=null;if(t.indices!==void 0)S=Ir(n,t.indices);else{let B=s.length/3|0,v=new Uint32Array(B);for(let A=0;A<B;A++)v[A]=A>>>0;S=w===4?null:v}if(w===5){let B=S??new Uint32Array(0);S=El(B)}else if(w===6){let B=S??new Uint32Array(0);S=Ol(B)}else if(w!==4)return Y(i,`Unsupported primitive mode=${w} (only triangles/strip/fan supported); skipping primitive`),null;return!l&&r&&(l=Dl(s,S)),new X({positions:s,normals:l??void 0,uvs:m??void 0,joints:d??void 0,weights:f??void 0,joints1:p??void 0,weights1:b??void 0,indices:S??void 0})},Nl=(n,e,t,r,i,o,a,s)=>{if(t.mesh===void 0)return[];let l=e.meshes?.[t.mesh];if(!l)return Y(s,`nodes[].mesh=${t.mesh} missing; skipping mesh node`),[];let u=[],m=s.computeMissingNormals!==!1;for(let c=0;c<l.primitives.length;c++){let d=l.primitives[c];if(d.extensions?.KHR_draco_mesh_compression){Y(s,`Mesh ${l.name??t.mesh} primitive ${c}: KHR_draco_mesh_compression not supported; skipping primitive`);continue}let f=`${t.mesh??-1}:${c}`,p=a.get(f),b=`${l.name??`mesh_${t.mesh}`}_${c}`,g=d.material!==void 0?e.materials?.[d.material]:void 0,x=yl(g,s,`Mesh '${l.name??t.mesh}' primitive ${c}`);if(p||(p=Wl(n,e,d,m,s),a.set(f,p)),!p)continue;let M=zl(n,e,d.material,i,o,s),h=new Me(p,M);h.name=t.name??l.name??`gltf_mesh_${t.mesh}_${c}`,h.transform.setParent(r),u.push(h)}return u},Vl=(n,e,t,r)=>{if(e.camera===void 0)return null;let i=n.cameras?.[e.camera];if(!i)return Y(r,`nodes[].camera=${e.camera} missing; skipping camera`),null;let o;if(i.type==="perspective"){let a=i.perspective;if(!a)return Y(r,`camera[${e.camera}] missing perspective block; skipping`),null;o=new wt({fov:a.yfov,near:a.znear,far:a.zfar??1e3})}else{let a=i.orthographic;if(!a)return Y(r,`camera[${e.camera}] missing orthographic block; skipping`),null;o=new St({left:-a.xmag,right:a.xmag,top:a.ymag,bottom:-a.ymag,near:a.znear,far:a.zfar})}return o.transform.setParent(t),o},jl=(n,e)=>{let t=n.color??[1,1,1],r=n.intensity??1;if(n.type==="directional"){let i=e.worldMatrix,o=i[8]??0,a=i[9]??0,s=i[10]??-1,l=-o,u=-a,m=-s,c=1/(Math.hypot(l,u,m)||1);return new Ye({direction:[l*c,u*c,m*c],color:[t[0]??1,t[1]??1,t[2]??1],intensity:r})}if(n.type==="point"){let i=e.worldPosition;return new Ve({position:[i[0]??0,i[1]??0,i[2]??0],color:[t[0]??1,t[1]??1,t[2]??1],intensity:r,range:n.range??10})}return null},$l=(n,e,t,r)=>{let i=e.skins??[],o=[];for(let a=0;a<i.length;a++){let s=i[a],l=[];for(let d of s.joints){let f=t[d];if(!f){Y(r,`skin[${a}] joint node ${d} missing transform`);continue}l.push(f)}let u;s.inverseBindMatrices!==void 0&&(u=ke(n,s.inverseBindMatrices));let m=s.skeleton!==void 0?t[s.skeleton]:void 0,c=new Pt(s.name??`skin_${a}`,l,u??null);o.push({name:s.name,joints:l,inverseBindMatrices:u,skeleton:m,runtime:c})}return o},Hl=(n,e,t,r)=>{let i=e.animations??[],o=[],a=l=>{switch(l){case"STEP":return 0;case"CUBICSPLINE":return 2;default:return 1}},s=l=>{switch(l){case"translation":return 0;case"rotation":return 1;case"scale":return 2;default:return-1}};for(let l=0;l<i.length;l++){let u=i[l],m=[],c=[],d=u.samplers.length|0,f=d>0?_.allocU32(d*5):0,p=d>0?_.u32view(f,d*5):null,b=[],g=[];d>0&&g.push({ptr:f,len:d*5});let x=Number.POSITIVE_INFINITY,M=Number.NEGATIVE_INFINITY;for(let B=0;B<u.samplers.length;B++){let v=u.samplers[B],A=ke(n,v.input),C=it(n,v.output),k=ke(n,v.output);if(m.push({interpolation:v.interpolation??"LINEAR",input:A,output:k}),A.length>0&&(x=Math.min(x,A[0]),M=Math.max(M,A[A.length-1])),p){let G=_.allocF32(A.length);_.f32view(G,A.length).set(A),b.push({ptr:G,len:A.length});let R=_.allocF32(k.length);_.f32view(R,k.length).set(k),b.push({ptr:R,len:k.length});let T=B*5;p[T+0]=G>>>0,p[T+1]=(A.length|0)>>>0,p[T+2]=R>>>0,p[T+3]=(C.numComponents|0)>>>0,p[T+4]=a(v.interpolation??"LINEAR")>>>0}}let h=[];for(let B=0;B<u.channels.length;B++){let v=u.channels[B],A=v.target.node,C=A!==void 0?t[A]??null:null,k={sampler:v.sampler|0,targetNode:C,path:v.target.path};c.push(k);let G=s(k.path);C&&G>=0&&h.push({sampler:k.sampler|0,targetIndex:C.index>>>0,pathCode:G})}let w=null,S=h.length|0;if(d>0&&S>0){let B=_.allocU32(S*3),v=_.u32view(B,S*3);g.push({ptr:B,len:S*3});for(let A=0;A<S;A++){let C=h[A],k=A*3;v[k+0]=C.sampler>>>0,v[k+1]=C.targetIndex>>>0,v[k+2]=C.pathCode>>>0}Number.isFinite(x)||(x=0),Number.isFinite(M)||(M=0),w=new xt({name:u.name??`anim_${l}`,samplerCount:d,channelCount:S,samplersPtr:f,channelsPtr:B,startTime:x,endTime:M,ownedF32Allocs:b,ownedU32Allocs:g})}else{for(let B of b)_.freeF32(B.ptr,B.len);for(let B of g)_.freeU32(B.ptr,B.len)}o.push({name:u.name,samplers:m,channels:c,clip:w})}return o},bn=(n,e={})=>{let t=n.json,r=e.targetScene??new Xe,i=e.addToScene!==!1,o=t.nodes??[],a=new Array(o.length);for(let v=0;v<o.length;v++){let A=o[v],C=new pe;if(A.matrix&&A.matrix.length>=16)Ll(C,A.matrix);else{let k=A.translation??[0,0,0],G=A.rotation??[0,0,0,1],R=A.scale??[1,1,1];C.setPosition(k[0],k[1],k[2]),C.setRotation(G[0],G[1],G[2],G[3]),C.setScale(R[0],R[1],R[2])}a[v]=C}for(let v=0;v<o.length;v++){let A=o[v],C=a[v];for(let k of A.children??[]){let G=a[k];G?G.setParent(C):Y(e,`Node ${v} child ${k} missing transform`)}}let s=$l(n,t,a,e),l=new Map,u=new Map,m=new Map,c=[],d=[],f=[],p=kl(t),b=(v,A)=>{let C=o[v];if(!C)return;let k=a[v];if(!k)return;let G=Nl(n,t,C,k,l,u,m,e),R=C.skin!==void 0?C.skin|0:A;if(R!==void 0){let T=s[R];if(!T)Y(e,`nodes[${v}].skin=${R} missing; skipping skin binding`);else for(let F of G){if(F.geometry.joints===null||F.geometry.weights===null){Y(e,`Mesh '${F.name}' is skinned (node.skin) but is missing JOINTS_0/WEIGHTS_0; it will render unskinned.`);continue}F.skin=T.runtime.createInstance(F.transform)}}for(let T of G)c.push(T),i&&r.add(T);if(e.importCameras){let T=Vl(t,C,k,e);T&&d.push(T)}if(e.importLights&&p){let T=Gl(C);if(T){let F=p.lights[T.light];if(!F)Y(e,`KHR_lights_punctual node references missing light ${T.light}`);else{let D=jl(F,k);D?(f.push(D),i&&r.addLight(D)):Y(e,`Light '${C.name??`index ${v}`}' has unsupported type '${F.type}' and was skipped.`)}}}for(let T of C.children??[])b(T,R)},g=Ul(t,e),M=t.scenes?.[g]?.nodes??[];for(let v of M)b(v,void 0);let h=Hl(n,t,a,e),w=h.map(v=>v.clip).filter(v=>v!==null),S=Array.from(new Set(c.map(v=>v.geometry))),B=Array.from(new Set(c.map(v=>v.material)));return{scene:r,meshes:c,nodeTransforms:a,lights:f,cameras:d,skins:s,animations:h,clips:w,destroy(){if(i)for(let v of c)r.remove(v);for(let v of c)v.destroy();for(let v of h)v.clip?.dispose();for(let v of s)v.runtime.dispose();for(let v of S)v.destroy();for(let v of u.values())v.destroy();for(let v of B)v.destroy();for(let v of a)v.dispose()}}};var Fe=(n,e,t,r)=>{let i=Math.max(1,e),o=Math.max(1,t),a=n.viewProjectionMatrix,s=r[0]??0,l=r[1]??0,u=r[2]??0,m=a[0]*s+a[4]*l+a[8]*u+a[12],c=a[1]*s+a[5]*l+a[9]*u+a[13],d=a[2]*s+a[6]*l+a[10]*u+a[14],f=a[3]*s+a[7]*l+a[11]*u+a[15];if(!Number.isFinite(f)||Math.abs(f)<=1e-8)return null;let p=1/f,b=m*p,g=c*p,x=d*p,M=(b*.5+.5)*i,h=(1-(g*.5+.5))*o,w=f>0,S=b>=-1&&b<=1&&g>=-1&&g<=1&&x>=0&&x<=1;return{x:M,y:h,ndcX:b,ndcY:g,ndcZ:x,clipW:f,inFront:w,insideClip:S,visible:w&&S}},Xo=(n,e)=>{if(e.length<17)throw new Error("writeCameraSignature: expected Float64Array length >= 17.");e[0]=n.type==="perspective"?1:2;let t=n.viewProjectionMatrix;for(let r=0;r<16;r++)e[r+1]=t[r]??0},Yo=(n,e,t=1e-6)=>{if(n.length!==e.length)return!1;for(let r=0;r<n.length;r++)if(Math.abs(n[r]-e[r])>t)return!1;return!0},Yt=(n,e,t)=>{let r=Math.max(1,e),i=Math.max(1,t),o=n??{kind:"screen",corner:"bottom-left",offsetPx:[16,-16]},a=o.offsetPx?.[0]??0,s=o.offsetPx?.[1]??0;if(typeof o.x=="number"||typeof o.y=="number"){let u=(o.x??0)+a,m=(o.y??0)+s;return[u,m]}let l=o.corner??"bottom-left";return l==="top-left"?[0+a,0+s]:l==="top-right"?[r+a,0+s]:l==="bottom-right"?[r+a,i+s]:[0+a,i+s]};var ql=()=>typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now(),Kl=(n,e)=>{if(e){if(Array.isArray(e)){for(let t=0;t<e.length;t++)n.add(e[t]);return}n.add(e)}},Qt=class{canvas;parent;root;interactionThrottleMs;autoUpdate;layers=new Map;dirtyReasons=new Set(["layout"]);resizeObserver=null;winResizeListener=null;winScrollListener=null;rafId=null;currentCamera=null;currentScene=null;dpr=1;width=1;height=1;lastLeft=Number.NaN;lastTop=Number.NaN;lastUpdateMs=Number.NaN;interactionActive=!1;pendingInteractionFlush=!1;controlsUnsubChange=null;controlsUnsubInteraction=null;cameraSigA=new Float64Array(17);cameraSigB=new Float64Array(17);hasCameraSig=!1;constructor(e){if(typeof document>"u")throw new Error("OverlaySystem requires a DOM environment.");this.canvas=e.canvas,this.parent=e.parent??this.canvas.parentElement??document.body,this.interactionThrottleMs=Math.max(0,Math.round(e.interactionThrottleMs??24)),this.autoUpdate=e.autoUpdate??!0,this.parent!==document.body&&this.parent!==document.documentElement&&getComputedStyle(this.parent).position==="static"&&(this.parent.style.position="relative");let t=document.createElement("div");t.className=e.className??"wasmgpu-overlay-root",t.style.position=this.parent===document.body||this.parent===document.documentElement?"fixed":"absolute",t.style.pointerEvents="none",t.style.overflow="hidden",t.style.contain="layout style paint",t.style.left="0",t.style.top="0",t.style.width="1px",t.style.height="1px",t.style.zIndex=String(e.zIndex??20),this.parent.appendChild(t),this.root=t,this.currentCamera=e.camera??null,this.currentScene=e.scene??null,this.bindControls(e.controls??null),this.setupResizeEvents(),this.syncRootBounds(),this.invalidate("layout")}get layerCount(){return this.layers.size}get isInteractionActive(){return this.interactionActive}setView(e,t=null){return this.currentCamera=e,this.currentScene=t??null,this.invalidate("camera"),this}bindControls(e){if(this.controlsUnsubChange?.(),this.controlsUnsubInteraction?.(),this.controlsUnsubChange=null,this.controlsUnsubInteraction=null,!e)return this;let t=e;return typeof t.onChange=="function"&&(this.controlsUnsubChange=t.onChange(()=>this.invalidate("camera"))),typeof t.onInteractionState=="function"&&(this.controlsUnsubInteraction=t.onInteractionState(r=>this.setInteractionActive(r))),this}addLayer(e){if(this.layers.has(e.id))throw new Error(`OverlaySystem: duplicate layer id '${e.id}'.`);return this.layers.set(e.id,e),e.setSystem?.(this),e.attach(this.root),this.invalidate("manual"),this}removeLayer(e){let t=this.layers.get(e);return t?(t.setSystem?.(null),t.detach(),this.layers.delete(e),this.invalidate("manual"),this):this}clearLayers(){for(let e of this.layers.values())e.setSystem?.(null),e.detach();return this.layers.clear(),this.invalidate("manual"),this}invalidate(e="manual"){this.dirtyReasons.add(e),this.requestFrame()}setInteractionActive(e){return this.interactionActive===e?this:(this.interactionActive=e,e||(this.pendingInteractionFlush=!0),this.invalidate("interaction"),this)}update(e={}){e.camera!==void 0&&(this.currentCamera=e.camera),e.scene!==void 0&&(this.currentScene=e.scene),Kl(this.dirtyReasons,e.reasons),this.syncRootBounds();let t=this.currentCamera;if(!t)return!1;let r=e.nowMs??ql();Xo(t,this.cameraSigB),(!this.hasCameraSig||!Yo(this.cameraSigA,this.cameraSigB,1e-6))&&(this.cameraSigA.set(this.cameraSigB),this.hasCameraSig=!0,this.dirtyReasons.add("camera"));let i=!!e.force;if(this.dirtyReasons.size===0&&!this.pendingInteractionFlush&&!i||this.interactionActive&&this.interactionThrottleMs>0&&!i&&Number.isFinite(this.lastUpdateMs)&&r-this.lastUpdateMs<this.interactionThrottleMs)return!1;let o=new Set(this.dirtyReasons);this.pendingInteractionFlush&&o.add("interaction");for(let a of this.layers.values())a.update({camera:t,scene:this.currentScene??null,width:this.width,height:this.height,dpr:this.dpr,nowMs:r,reasons:o,root:this.root});return this.lastUpdateMs=r,this.pendingInteractionFlush=!1,this.dirtyReasons.clear(),!0}destroy(){if(this.cancelFrame(),this.controlsUnsubChange?.(),this.controlsUnsubInteraction?.(),this.controlsUnsubChange=null,this.controlsUnsubInteraction=null,this.resizeObserver){try{this.resizeObserver.disconnect()}catch{}this.resizeObserver=null}this.winResizeListener&&window.removeEventListener("resize",this.winResizeListener),this.winScrollListener&&window.removeEventListener("scroll",this.winScrollListener,!0),this.winResizeListener=null,this.winScrollListener=null,this.clearLayers(),this.root.remove()}requestFrame(){!this.autoUpdate||this.rafId!==null||typeof requestAnimationFrame=="function"&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null,this.update()}))}cancelFrame(){this.rafId!==null&&(typeof cancelAnimationFrame=="function"&&cancelAnimationFrame(this.rafId),this.rafId=null)}setupResizeEvents(){let e=()=>{this.syncRootBounds(),this.invalidate("viewport")};this.winResizeListener=e,this.winScrollListener=e,window.addEventListener("resize",e),window.addEventListener("scroll",e,!0),typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(e),this.resizeObserver.observe(this.canvas))}syncRootBounds(){let e=this.canvas.getBoundingClientRect(),t=this.parent===document.body||this.parent===document.documentElement?{left:0,top:0}:this.parent.getBoundingClientRect(),r=e.left-t.left+(this.parent.scrollLeft??0),i=e.top-t.top+(this.parent.scrollTop??0),o=Math.max(1,Math.round(e.width||this.canvas.clientWidth||1)),a=Math.max(1,Math.round(e.height||this.canvas.clientHeight||1)),s=Math.max(1,window.devicePixelRatio||1),l=!Number.isFinite(this.lastLeft)||!Number.isFinite(this.lastTop)||Math.abs(r-this.lastLeft)>.5||Math.abs(i-this.lastTop)>.5,u=o!==this.width||a!==this.height||Math.abs(s-this.dpr)>1e-6;!l&&!u||(this.lastLeft=r,this.lastTop=i,this.width=o,this.height=a,this.dpr=s,this.root.style.left=`${r}px`,this.root.style.top=`${i}px`,this.root.style.width=`${o}px`,this.root.style.height=`${a}px`,this.dirtyReasons.add(l?"layout":"viewport"))}};var Qo=[[1,0,0],[0,1,0],[0,0,1]],Xl=(n,e)=>{let t=Math.hypot(n,e);return t<=1e-8?[0,0]:[n/t,e/t]},Zt=class{id;anchor;lengthWorld;sizePx;lineWidthPx;labels;colors;labelOffsetPx;font;root=null;container=null;lines=[];labelEls=[];_system=null;constructor(e={}){this.id=e.id??"overlay-axis-triad",this.anchor=e.anchor??{kind:"screen",corner:"bottom-left",offsetPx:[26,-26]},this.lengthWorld=Math.max(1e-6,e.lengthWorld??1),this.sizePx=Math.max(8,e.sizePx??56),this.lineWidthPx=Math.max(1,e.lineWidthPx??2),this.labels=e.labels??["X","Y","Z"],this.colors=e.colors??["#ff5f56","#3fd77a","#4ca7ff"],this.labelOffsetPx=Math.max(0,e.labelOffsetPx??8),this.font=e.font??"11px monospace"}setSystem(e){this._system=e}attach(e){this.root=e;let t=document.createElement("div");t.style.position="absolute",t.style.inset="0",t.style.pointerEvents="none",e.appendChild(t),this.container=t,this.lines=[],this.labelEls=[];for(let r=0;r<3;r++){let i=document.createElement("div");i.style.position="absolute",i.style.transformOrigin="0 50%",i.style.background=this.colors[r],t.appendChild(i),this.lines.push(i);let o=document.createElement("div");o.style.position="absolute",o.style.font=this.font,o.style.color=this.colors[r],o.style.whiteSpace="nowrap",o.textContent=this.labels[r],t.appendChild(o),this.labelEls.push(o)}}detach(){this.container?.remove(),this.root=null,this.container=null,this.lines=[],this.labelEls=[]}update(e){if(!(!this.container||!this.root)){if(this.anchor?.kind==="world"){this.updateWorld(e,this.anchor);return}this.updateScreen(e)}}updateWorld(e,t){let r=Fe(e.camera,e.width,e.height,t.position);if(!r||!r.inFront){this.hideAll();return}for(let i=0;i<3;i++){let o=Qo[i],a=Fe(e.camera,e.width,e.height,[t.position[0]+o[0]*this.lengthWorld,t.position[1]+o[1]*this.lengthWorld,t.position[2]+o[2]*this.lengthWorld]);if(!a||!a.inFront){this.lines[i].style.display="none",this.labelEls[i].style.display="none";continue}this.drawLine(this.lines[i],r.x,r.y,a.x,a.y,this.colors[i],this.lineWidthPx),this.drawLabel(this.labelEls[i],a.x,a.y,this.colors[i])}}updateScreen(e){let[t,r]=Yt(this.anchor?.kind==="screen"?this.anchor:{kind:"screen",corner:"bottom-left",offsetPx:[26,-26]},e.width,e.height),i=e.camera.viewMatrix;for(let o=0;o<3;o++){let a=Qo[o],s=i[0]*a[0]+i[4]*a[1]+i[8]*a[2],l=i[1]*a[0]+i[5]*a[1]+i[9]*a[2],[u,m]=Xl(s,-l),c=t+u*this.sizePx,d=r+m*this.sizePx;this.drawLine(this.lines[o],t,r,c,d,this.colors[o],this.lineWidthPx),this.drawLabel(this.labelEls[o],c,d,this.colors[o])}}drawLine(e,t,r,i,o,a,s){let l=i-t,u=o-r,m=Math.hypot(l,u);if(!Number.isFinite(m)||m<=1e-5){e.style.display="none";return}let c=Math.atan2(u,l);e.style.display="",e.style.background=a,e.style.left=`${t}px`,e.style.top=`${r}px`,e.style.width=`${m}px`,e.style.height=`${Math.max(1,s)}px`,e.style.transform=`translateY(${-.5*Math.max(1,s)}px) rotate(${c}rad)`}drawLabel(e,t,r,i){e.style.display="",e.style.left=`${t+this.labelOffsetPx}px`,e.style.top=`${r-this.labelOffsetPx}px`,e.style.color=i}hideAll(){for(let e=0;e<this.lines.length;e++)this.lines[e].style.display="none";for(let e=0;e<this.labelEls.length;e++)this.labelEls[e].style.display="none"}};var $e=class{constructor(e,t,r){this.parent=e;this.create=t;this.maxNodes=r}nodes=[];used=0;beginFrame(){this.used=0}acquire(){if(this.used<this.nodes.length){let t=this.nodes[this.used++];return t.style.display="",t}if(this.nodes.length>=this.maxNodes)throw new Error(`DOMNodePool: exceeded max node budget (${this.maxNodes}).`);let e=this.create();return this.parent.appendChild(e),this.nodes.push(e),this.used++,e}endFrame(){for(let e=this.used;e<this.nodes.length;e++)this.nodes[e].style.display="none"}get size(){return this.nodes.length}clear(e=!1){this.used=0;for(let t=0;t<this.nodes.length;t++)e?this.nodes[t].remove():this.nodes[t].style.display="none";e&&(this.nodes.length=0)}};var gn=(n,e,t)=>Math.max(e,Math.min(t,n)),Zo=n=>{if(!Number.isFinite(n))return"nan";let e=Math.abs(n);return e>=1e4||e>0&&e<.001?n.toExponential(2):`${Math.round(n*1e3)/1e3}`},Jo=n=>{let e=Math.max(1e-9,Math.abs(n)),t=Math.floor(Math.log10(e)),r=Math.pow(10,t),i=e/r;return(i<=1?1:i<=2?2:i<=5?5:10)*r},Yl=n=>n==="xy"?{u:[1,0,0],v:[0,1,0]}:n==="xz"?{u:[1,0,0],v:[0,0,1]}:{u:[0,1,0],v:[0,0,1]},Ql=(n,e)=>n==="xy"?{uMin:e.boxMin[0],uMax:e.boxMax[0],vMin:e.boxMin[1],vMax:e.boxMax[1]}:n==="xz"?{uMin:e.boxMin[0],uMax:e.boxMax[0],vMin:e.boxMin[2],vMax:e.boxMax[2]}:{uMin:e.boxMin[1],uMax:e.boxMax[1],vMin:e.boxMin[2],vMax:e.boxMax[2]},yn=(n,e,t,r)=>n==="xy"?[e[0]+t,e[1]+r,e[2]]:n==="xz"?[e[0]+t,e[1],e[2]+r]:[e[0],e[1]+t,e[2]+r],ea=(n,e,t,r,i,o,a)=>{let s=r-e,l=i-t,u=Math.hypot(s,l);if(!Number.isFinite(u)||u<=1e-5){n.style.display="none";return}n.style.display="",n.style.left=`${e}px`,n.style.top=`${t}px`,n.style.width=`${u}px`,n.style.height=`${Math.max(1,a)}px`,n.style.background=o,n.style.transform=`translateY(${-.5*Math.max(1,a)}px) rotate(${Math.atan2(l,s)}rad)`},Zl=(n,e)=>Math.abs(n)<=e?0:n,vn=(n,e,t)=>Math.abs(n-e)<=t,wn=(n,e)=>Math.max(1e-9,Math.abs(n)*1e-9,Math.abs(e)*1e-6),xn=(n,e,t)=>{if(!Number.isFinite(e)||e<=t)return!1;let r=n/e;return Math.abs(r-Math.round(r))<=1e-4},Pn=(n,e,t)=>{let r=Math.max(0,e-n),i=wn(r,t);if(t<=i)return 0;let o=0,a=Math.ceil((n+i)/t)*t,s=e-i;for(let l=0;l<1e6&&a<=s;l++,a+=t)a>n+i&&a<e-i&&o++;return o},ta=(n,e,t)=>{let r=Math.max(0,e-n),i=wn(r,t);if(r<=i)return[n];let o=[n];if(t>i){let a=Math.ceil((n+i)/t)*t,s=e-i;for(let l=0;l<1e6&&a<=s;l++,a+=t)a<=n+i||a>=e-i||o.push(Zl(a,i))}return o.push(e),o},Jt=class{id;plane;origin;extentMode;fixedUMin;fixedUMax;fixedVMin;fixedVMax;targetMinorSpacingPx;majorStepFactor;minLabelSpacingPx;maxLines;maxLabels;minorColor;majorColor;axisColor;labelColor;lineWidthMinorPx;lineWidthMajorPx;font;container=null;linePool=null;labelPool=null;constructor(e={}){this.id=e.id??"overlay-grid",this.plane=e.plane??"xy",this.origin=e.origin??[0,0,0],this.extentMode=e.extentMode??"scene-fit",this.fixedUMin=e.fixedUMin??-10,this.fixedUMax=e.fixedUMax??10,this.fixedVMin=e.fixedVMin??-10,this.fixedVMax=e.fixedVMax??10,this.targetMinorSpacingPx=Math.max(6,e.targetMinorSpacingPx??30),this.majorStepFactor=Math.max(2,Math.round(e.majorStepFactor??5)),this.minLabelSpacingPx=Math.max(8,e.minLabelSpacingPx??58),this.maxLines=Math.max(4,Math.round(e.maxLines??160)),this.maxLabels=Math.max(2,Math.round(e.maxLabels??60)),this.minorColor=e.minorColor??"rgba(180, 210, 255, 0.17)",this.majorColor=e.majorColor??"rgba(180, 210, 255, 0.36)",this.axisColor=e.axisColor??"rgba(220, 235, 255, 0.8)",this.labelColor=e.labelColor??"rgba(220, 235, 255, 0.9)",this.lineWidthMinorPx=Math.max(1,e.lineWidthMinorPx??1),this.lineWidthMajorPx=Math.max(1,e.lineWidthMajorPx??2),this.font=e.font??"11px monospace"}attach(e){let t=document.createElement("div");t.style.position="absolute",t.style.inset="0",t.style.pointerEvents="none",e.appendChild(t),this.container=t,this.linePool=new $e(t,()=>{let r=document.createElement("div");return r.style.position="absolute",r.style.transformOrigin="0 50%",r},this.maxLines),this.labelPool=new $e(t,()=>{let r=document.createElement("div");return r.style.position="absolute",r.style.color=this.labelColor,r.style.font=this.font,r.style.whiteSpace="nowrap",r},this.maxLabels)}detach(){this.linePool?.clear(!0),this.labelPool?.clear(!0),this.linePool=null,this.labelPool=null,this.container?.remove(),this.container=null}update(e){if(!this.container||!this.linePool||!this.labelPool)return;let{uMin:t,uMax:r,vMin:i,vMax:o}=this.resolveExtent(e),a=Math.max(1e-6,r-t),s=Math.max(1e-6,o-i),l=this.estimatePixelsPerUnitAxes(e),u=Math.max(l.u,l.v),m=Jo(this.targetMinorSpacingPx/Math.max(1e-6,u)),c=(a>1e-9?2:1)+(s>1e-9?2:1),d=Math.max(0,this.maxLines-c),f=Pn(t,r,m),p=Pn(i,o,m);for(let U=0;U<32&&f+p>d;U++)m=Jo(m*1.5),f=Pn(t,r,m),p=Pn(i,o,m);let b=m*this.majorStepFactor,g=b*l.u,x=b*l.v,M=Math.max(1,Math.ceil(this.minLabelSpacingPx/Math.max(1e-6,g))),h=Math.max(1,Math.ceil(this.minLabelSpacingPx/Math.max(1e-6,x))),w=ta(t,r,m),S=ta(i,o,m),B=wn(a,m),v=wn(s,m),A=Math.max(B,Math.abs(b)*1e-6),C=Math.max(v,Math.abs(b)*1e-6),k=Math.max(B,Math.abs(m)*.001),G=Math.max(v,Math.abs(m)*.001),R=w.reduce((U,L)=>U+(xn(L,b,A)?1:0),0),T=S.reduce((U,L)=>U+(xn(L,b,C)?1:0),0);for(let U=0;U<32;U++){let L=R>0?Math.ceil(R/M):0,E=T>0?Math.ceil(T/h):0;if(L+E<=this.maxLabels)break;L>=E?M++:h++}this.linePool.beginFrame(),this.labelPool.beginFrame();let F=0;for(let U=0;U<w.length;U++){let L=w[U],E=this.projectFrontClippedSegment(e,yn(this.plane,this.origin,L,i),yn(this.plane,this.origin,L,o));if(!E)continue;let z=E.p0,O=E.p1,I=xn(L,b,A),j=Math.abs(L)<=k,Z=vn(L,t,B)||vn(L,r,B),ae=this.linePool.acquire();if(ea(ae,z.x,z.y,O.x,O.y,j?this.axisColor:I||Z?this.majorColor:this.minorColor,I||j||Z?this.lineWidthMajorPx:this.lineWidthMinorPx),I&&F%M===0){let ue=this.labelPool.acquire();ue.textContent=Zo(L),ue.style.left=`${z.x+4}px`,ue.style.top=`${z.y+2}px`}I&&F++}let D=0;for(let U=0;U<S.length;U++){let L=S[U],E=this.projectFrontClippedSegment(e,yn(this.plane,this.origin,t,L),yn(this.plane,this.origin,r,L));if(!E)continue;let z=E.p0,O=E.p1,I=xn(L,b,C),j=Math.abs(L)<=G,Z=vn(L,i,v)||vn(L,o,v),ae=this.linePool.acquire();if(ea(ae,z.x,z.y,O.x,O.y,j?this.axisColor:I||Z?this.majorColor:this.minorColor,I||j||Z?this.lineWidthMajorPx:this.lineWidthMinorPx),I&&D%h===0){let ue=this.labelPool.acquire();ue.textContent=Zo(L),ue.style.left=`${z.x+4}px`,ue.style.top=`${z.y+2}px`}I&&D++}this.linePool.endFrame(),this.labelPool.endFrame()}projectFrontClippedSegment(e,t,r){let i=this.getCameraNear(e.camera),o=-(i>0?i+Math.max(i*1e-4,1e-6):0),a=e.camera.viewMatrix,s=[t[0],t[1],t[2]],l=[r[0],r[1],r[2]],u=this.transformPoint(a,s),m=this.transformPoint(a,l);if(u[2]>o||m[2]>o){if(u[2]>o&&m[2]>o)return null;if(u[2]>o){let f=m[2]-u[2];if(!Number.isFinite(f)||Math.abs(f)<=1e-8)return null;let p=gn((o-u[2])/f,0,1);s=[s[0]+(l[0]-s[0])*p,s[1]+(l[1]-s[1])*p,s[2]+(l[2]-s[2])*p],u=[u[0]+(m[0]-u[0])*p,u[1]+(m[1]-u[1])*p,o]}if(m[2]>o){let f=u[2]-m[2];if(!Number.isFinite(f)||Math.abs(f)<=1e-8)return null;let p=gn((o-m[2])/f,0,1);l=[l[0]+(s[0]-l[0])*p,l[1]+(s[1]-l[1])*p,l[2]+(s[2]-l[2])*p],m=[m[0]+(u[0]-m[0])*p,m[1]+(u[1]-m[1])*p,o]}}let c=Fe(e.camera,e.width,e.height,s),d=Fe(e.camera,e.width,e.height,l);return!c||!d||!c.inFront||!d.inFront||!Number.isFinite(c.x)||!Number.isFinite(c.y)||!Number.isFinite(d.x)||!Number.isFinite(d.y)?null:{p0:c,p1:d}}getCameraNear(e){let t=e.near;return typeof t!="number"||!Number.isFinite(t)?0:Math.max(0,t)}transformPoint(e,t){let r=t[0]??0,i=t[1]??0,o=t[2]??0;return[e[0]*r+e[4]*i+e[8]*o+e[12],e[1]*r+e[5]*i+e[9]*o+e[13],e[2]*r+e[6]*i+e[10]*o+e[14]]}resolveExtent(e){if(this.extentMode==="fixed")return{uMin:Math.min(this.fixedUMin,this.fixedUMax),uMax:Math.max(this.fixedUMin,this.fixedUMax),vMin:Math.min(this.fixedVMin,this.fixedVMax),vMax:Math.max(this.fixedVMin,this.fixedVMax)};let t=e.scene;if(!t)return{uMin:-10,uMax:10,vMin:-10,vMax:10};let r=t.getBounds();if(r.empty)return{uMin:-10,uMax:10,vMin:-10,vMax:10};let i=Ql(this.plane,r),o=Math.max(.001,(i.uMax-i.uMin)*.1),a=Math.max(.001,(i.vMax-i.vMin)*.1);return{uMin:i.uMin-o,uMax:i.uMax+o,vMin:i.vMin-a,vMax:i.vMax+a}}estimatePixelsPerUnitAxes(e){let t=Yl(this.plane),r=Fe(e.camera,e.width,e.height,this.origin);if(!r||!r.inFront||r.ndcZ<0||r.ndcZ>1)return{u:1,v:1};let i=Fe(e.camera,e.width,e.height,[this.origin[0]+t.u[0],this.origin[1]+t.u[1],this.origin[2]+t.u[2]]),o=Fe(e.camera,e.width,e.height,[this.origin[0]+t.v[0],this.origin[1]+t.v[1],this.origin[2]+t.v[2]]),a=i&&i.inFront&&i.ndcZ>=0&&i.ndcZ<=1&&Number.isFinite(i.x)&&Number.isFinite(i.y)?Math.hypot(i.x-r.x,i.y-r.y):1,s=o&&o.inFront&&o.ndcZ>=0&&o.ndcZ<=1&&Number.isFinite(o.x)&&Number.isFinite(o.y)?Math.hypot(o.x-r.x,o.y-r.y):1;return{u:gn(a,1e-6,1e9),v:gn(s,1e-6,1e9)}}};var ra=n=>n<0?0:n>1?1:n,Sn=(n,e,t)=>n+(e-n)*t,Jl=n=>{if(!Number.isFinite(n))return"nan";let e=Math.abs(n);return e>=1e4||e>0&&e<.001?n.toExponential(3):`${Math.round(n*1e6)/1e6}`},xi=(n,e)=>{let t=Math.min(8,Math.max(2,e.length)),r=new Array(t);for(let l=0;l<t;l++){let u=e[Math.min(l,e.length-1)]??[0,0,0,1];r[l]=[u[0],u[1],u[2],u[3]]}let i=ra(n)*(t-1),o=Math.floor(i),a=Math.min(t-1,o+1),s=i-o;return o>=t-1?r[t-1]:[Sn(r[o][0],r[a][0],s),Sn(r[o][1],r[a][1],s),Sn(r[o][2],r[a][2],s),Sn(r[o][3],r[a][3],s)]},Ct=n=>[n.mode,n.clampMode,n.valueMode,n.componentCount,n.componentIndex,n.stride,n.offset,n.domainMin,n.domainMax,n.clampMin,n.clampMax,n.percentileLow,n.percentileHigh,n.logBase,n.symlogLinThresh,n.gamma,n.invert?1:0].join("|"),eu=(n,e)=>{let t=n;return typeof t.onVisualChange!="function"?null:t.onVisualChange(()=>e())??null},tu=(n,e)=>{if(n instanceof Ue){let o=ie(n.scaleTransform);if(n.colormap==="custom"){let s=n.colormapStops.slice();return{transform:o,signature:`pointcloud|custom|${Ct(o)}|${JSON.stringify(s)}`,sample:l=>xi(l,s)}}let a=n.getColormapForBinding();if(e&&!a.canSampleCPU)throw new Error("LegendLayer: bound point cloud colormap is GPU-only and cannot be sampled on CPU in strict parity mode.");return{transform:o,signature:`pointcloud|cm:${a.id}|f:${a.filter}|w:${a.width}|${Ct(o)}`,sample:s=>a.sampleCPU(s)}}if(n instanceof Re){let o=ie(n.scaleTransform);if(n.colorMode==="scalar"&&n.colormap==="custom"){let s=n.colormapStops.slice();return{transform:o,signature:`glyphfield|custom|${Ct(o)}|${JSON.stringify(s)}`,sample:l=>xi(l,s)}}let a=n.getColormapForBinding();if(e&&!a.canSampleCPU)throw new Error("LegendLayer: bound glyph colormap is GPU-only and cannot be sampled on CPU in strict parity mode.");return{transform:o,signature:`glyphfield|cm:${a.id}|f:${a.filter}|w:${a.width}|${Ct(o)}`,sample:s=>a.sampleCPU(s)}}if(n instanceof Ae){let o=ie(n.scaleTransform),a=n.getColormapForBinding();if(e&&!a.canSampleCPU)throw new Error("LegendLayer: bound data-material colormap is GPU-only and cannot be sampled on CPU in strict parity mode.");return{transform:o,signature:`datamaterial|cm:${a.id}|f:${a.filter}|w:${a.width}|${Ct(o)}`,sample:s=>a.sampleCPU(s)}}let t=n,r=ie(t.scaleTransform);if(t.colormapStops&&t.colormapStops.length>=2){let o=t.colormapStops.slice();return{transform:r,signature:`explicit|stops|${Ct(r)}|${JSON.stringify(o)}`,sample:a=>xi(a,o)}}let i=typeof t.colormap=="string"?H.builtin(t.colormap):t.colormap;if(e&&!i.canSampleCPU)throw new Error("LegendLayer: explicit colormap is GPU-only and cannot be sampled on CPU in strict parity mode.");return{transform:r,signature:`explicit|cm:${i.id}|f:${i.filter}|w:${i.width}|${Ct(r)}`,sample:o=>i.sampleCPU(o)}},er=class{id;source;strictParity;widthPx;heightPx;tickCount;font;formatValue;title;anchor;_system=null;unsubscribeSource=null;sourceDirty=!0;lastSignature=null;container=null;titleEl=null;gradientCanvas=null;gradientCtx=null;messageEl=null;tickMarkPool=null;tickLabelPool=null;constructor(e){this.id=e.id??"overlay-legend",this.source=e.source,this.strictParity=e.strictParity??!0,this.widthPx=Math.max(8,Math.round(e.widthPx??26)),this.heightPx=Math.max(32,Math.round(e.heightPx??240)),this.tickCount=Math.max(2,Math.round(e.tickCount??7)),this.font=e.font??"11px monospace",this.formatValue=e.formatValue??Jl,this.title=e.title??"Legend",this.anchor=e.anchor??{kind:"screen",corner:"top-right",offsetPx:[-16,16]},this.bindSource(this.source)}setSystem(e){this._system=e}setSource(e){this.source=e,this.bindSource(e),this.sourceDirty=!0,this._system?.invalidate("scale")}attach(e){let t=document.createElement("div");t.style.position="absolute",t.style.pointerEvents="none",t.style.padding="8px",t.style.border="1px solid rgba(190, 215, 255, 0.35)",t.style.background="rgba(7, 13, 24, 0.78)",t.style.borderRadius="6px",t.style.color="#e3eeff",t.style.font=this.font,e.appendChild(t),this.container=t;let r=document.createElement("div");r.textContent=this.title,r.style.marginBottom="6px",r.style.font=this.font,t.appendChild(r),this.titleEl=r;let i=document.createElement("div");i.style.position="relative",i.style.width=`${this.widthPx+64}px`,i.style.height=`${this.heightPx}px`,t.appendChild(i);let o=document.createElement("canvas");o.width=this.widthPx,o.height=this.heightPx,o.style.position="absolute",o.style.left="0",o.style.top="0",o.style.width=`${this.widthPx}px`,o.style.height=`${this.heightPx}px`,o.style.border="1px solid rgba(180, 210, 255, 0.35)",o.style.borderRadius="2px",i.appendChild(o),this.gradientCanvas=o,this.gradientCtx=o.getContext("2d");let a=document.createElement("div");a.style.position="absolute",a.style.left="0",a.style.top=`${this.heightPx+6}px`,a.style.color="rgba(255, 191, 191, 0.95)",a.style.maxWidth=`${this.widthPx+64}px`,i.appendChild(a),this.messageEl=a,this.tickMarkPool=new $e(i,()=>{let s=document.createElement("div");return s.style.position="absolute",s},this.tickCount),this.tickLabelPool=new $e(i,()=>{let s=document.createElement("div");return s.style.position="absolute",s.style.font=this.font,s.style.color="#e3eeff",s},this.tickCount)}detach(){this.unsubscribeSource?.(),this.unsubscribeSource=null,this.tickMarkPool?.clear(!0),this.tickLabelPool?.clear(!0),this.tickMarkPool=null,this.tickLabelPool=null,this.container?.remove(),this.container=null,this.titleEl=null,this.gradientCanvas=null,this.gradientCtx=null,this.messageEl=null}update(e){!this.container||(this.positionContainer(e),!(e.reasons.has("scale")||e.reasons.has("colormap")||e.reasons.has("manual")||e.reasons.has("viewport")||e.reasons.has("layout"))&&!this.sourceDirty)||(this.sourceDirty=!1,this.renderLegend())}positionContainer(e){if(!this.container)return;let[t,r]=Yt(this.anchor,e.width,e.height),i=this.anchor?.corner??"top-right",o=this.heightPx+32,a=this.widthPx+80,s=t,l=r;this.anchor?.x===void 0&&i.includes("right")&&(s-=a),this.anchor?.y===void 0&&i.includes("bottom")&&(l-=o),this.container.style.left=`${s}px`,this.container.style.top=`${l}px`}bindSource(e){this.unsubscribeSource?.(),this.unsubscribeSource=eu(e,()=>{this.sourceDirty=!0,this._system?.invalidate("scale")})}renderLegend(){if(!(!this.gradientCanvas||!this.gradientCtx||!this.tickMarkPool||!this.tickLabelPool))try{let e=tu(this.source,this.strictParity);e.signature!==this.lastSignature&&(this.lastSignature=e.signature,this.renderGradient(e),this.renderTicks(e)),this.messageEl&&(this.messageEl.textContent="")}catch(e){this.messageEl&&(this.messageEl.textContent=`${e instanceof Error?e.message:String(e)}`)}}renderGradient(e){if(!this.gradientCtx||!this.gradientCanvas)return;let t=this.gradientCanvas.width,r=this.gradientCanvas.height,i=this.gradientCtx.createImageData(t,r);for(let o=0;o<r;o++){let a=1-o/Math.max(1,r-1),s=e.sample(a),l=Math.max(0,Math.min(255,Math.round(s[0]*255))),u=Math.max(0,Math.min(255,Math.round(s[1]*255))),m=Math.max(0,Math.min(255,Math.round(s[2]*255))),c=Math.max(0,Math.min(255,Math.round(s[3]*255)));for(let d=0;d<t;d++){let f=(o*t+d)*4;i.data[f+0]=l,i.data[f+1]=u,i.data[f+2]=m,i.data[f+3]=c}}this.gradientCtx.putImageData(i,0,0)}renderTicks(e){if(!this.tickMarkPool||!this.tickLabelPool||!this.gradientCanvas)return;this.tickMarkPool.beginFrame(),this.tickLabelPool.beginFrame();let t=this.gradientCanvas.height;for(let r=0;r<this.tickCount;r++){let i=r/Math.max(1,this.tickCount-1),o=i*t,a=1-i,s=Zr(ra(a),e.transform),l=this.tickMarkPool.acquire();l.style.left=`${this.widthPx+4}px`,l.style.top=`${o}px`,l.style.width="8px",l.style.height="1px",l.style.background="#dce9ff";let u=this.tickLabelPool.acquire();u.style.left=`${this.widthPx+16}px`,u.style.top=`${o-6}px`,u.textContent=this.formatValue(s)}this.tickMarkPool.endFrame(),this.tickLabelPool.endFrame()}};var Ze={Idle:"idle",Marker:"marker",Distance:"distance",Angle:"angle"},na={Marker:"marker",Distance:"distance",Angle:"angle"},zr={Degrees:"deg",Radians:"rad"},ot=n=>[n[0],n[1],n[2],n[3]],Wr=n=>[n[0]??0,n[1]??0,n[2]??0],Pi=n=>n?{scalar:n.scalar??null,vector:n.vector?[n.vector[0],n.vector[1],n.vector[2],n.vector[3]]:null,packedPoint:n.packedPoint?[n.packedPoint[0],n.packedPoint[1],n.packedPoint[2],n.packedPoint[3]]:null}:null,ia=n=>n?{kind:n.kind,objectId:n.objectId,elementIndex:n.elementIndex,ndIndex:n.ndIndex?n.ndIndex.slice():null,attributes:Pi(n.attributes)}:null,re=n=>({position:Wr(n.position),pick:ia(n.pick)}),tr=n=>({position:Wr(n.worldPosition),pick:{kind:n.kind,objectId:n.objectId,elementIndex:n.elementIndex,ndIndex:n.ndIndex?n.ndIndex.slice():null,attributes:Pi(n.attributes)}}),rr=n=>{let e=Math.max(0,Math.min(255,Math.round(n[0]*255))),t=Math.max(0,Math.min(255,Math.round(n[1]*255))),r=Math.max(0,Math.min(255,Math.round(n[2]*255))),i=Math.max(0,Math.min(1,n[3]));return`rgba(${e}, ${t}, ${r}, ${i})`};var at=[{exponent:-12,symbol:"p",factor:1e-12},{exponent:-9,symbol:"n",factor:1e-9},{exponent:-6,symbol:"u",factor:1e-6},{exponent:-3,symbol:"m",factor:.001},{exponent:0,symbol:"",factor:1},{exponent:3,symbol:"k",factor:1e3},{exponent:6,symbol:"M",factor:1e6},{exponent:9,symbol:"G",factor:1e9},{exponent:12,symbol:"T",factor:1e12}],Cn=(n,e,t)=>{if(!Number.isFinite(n))return e;let r=Math.round(n);return r<e?e:r>t?t:r},ru=n=>n.includes(".")?n.replace(/(\.\d*?[1-9])0+$/g,"$1").replace(/\.0+$/g,""):n,me=(n,e)=>{if(!Number.isFinite(n))return"nan";let t=Math.abs(n),r=Cn(e,0,12);return t>=1e7||t>0&&t<1e-5?n.toExponential(Math.max(1,Math.min(6,r))):ru(n.toFixed(r))},nr=(n={})=>{let e=Number.isFinite(n.worldUnitsPerUnit)&&n.worldUnitsPerUnit>0?n.worldUnitsPerUnit:1,t=typeof n.symbol=="string"?n.symbol:"wu",r=Cn(n.decimals??3,0,12),i=!!n.autoMetric,o=n.angleUnit??zr.Degrees,a=Cn(n.angleDecimals??2,0,12);return{worldUnitsPerUnit:e,symbol:t,decimals:r,autoMetric:i,angleUnit:o,angleDecimals:a}},nu=n=>{let e=Math.abs(n);if(!Number.isFinite(e)||e<=0)return at[4];let t=Cn(Math.floor(Math.log10(e)/3)*3,at[0].exponent,at[at.length-1].exponent);for(let r=0;r<at.length;r++)if(at[r].exponent===t)return at[r];return at[4]},_n=(n,e={})=>{let t=nr(e);if(!Number.isFinite(n))return{worldDistance:n,value:Number.NaN,unitSymbol:t.symbol,text:`nan ${t.symbol}`};let r=n/t.worldUnitsPerUnit;if(!t.autoMetric){let l=`${me(r,t.decimals)} ${t.symbol}`.trim();return{worldDistance:n,value:r,unitSymbol:t.symbol,text:l}}let i=nu(r),o=r/i.factor,a=`${i.symbol}${t.symbol}`,s=`${me(o,t.decimals)} ${a}`.trim();return{worldDistance:n,value:o,unitSymbol:a,text:s}},Bn=(n,e={})=>{let t=nr(e);if(!Number.isFinite(n))return{radians:n,value:Number.NaN,unitSymbol:t.angleUnit,text:`nan ${t.angleUnit}`};if(t.angleUnit===zr.Radians){let o=`${me(n,t.angleDecimals)} rad`;return{radians:n,value:n,unitSymbol:"rad",text:o}}let r=n*(180/Math.PI),i=`${me(r,t.angleDecimals)} deg`;return{radians:n,value:r,unitSymbol:"deg",text:i}},Mn=(n,e=5)=>n?`[${me(n[0]??Number.NaN,e)}, ${me(n[1]??Number.NaN,e)}, ${me(n[2]??Number.NaN,e)}]`:"null";var iu=n=>!n||n.length===0?"null":`[${n.join(", ")}]`,ou=n=>{if(!n)return["attributes: null"];let e=[];return n.scalar!==void 0&&n.scalar!==null&&e.push(`scalar: ${me(n.scalar,6)}`),n.vector&&e.push(`vector: [${me(n.vector[0],4)}, ${me(n.vector[1],4)}, ${me(n.vector[2],4)}, ${me(n.vector[3],4)}]`),n.packedPoint&&e.push(`packedPoint: [${me(n.packedPoint[0],4)}, ${me(n.packedPoint[1],4)}, ${me(n.packedPoint[2],4)}, ${me(n.packedPoint[3],4)}]`),e.length===0&&e.push("attributes: {}"),e},oa=(n,e)=>!e||!e.hit?`${n}: miss`:[`${n}: hit`,`kind: ${e.kind}`,`objectId: ${e.objectId}`,`elementIndex: ${e.elementIndex}`,`world: ${Mn(e.worldPosition,5)}`,`ndIndex: ${iu(e.ndIndex)}`,...ou(e.attributes)].join(`
|
|
13
|
-
`),
|
|
21
|
+
`+t+this._fragmentShader}};var La=4+lt+4+32,Mu=La*4,_o=n=>fe({componentCount:4,componentIndex:3,stride:4,...n}),Ma=n=>n==="rgba"?0:1,Ra=new ArrayBuffer(4),Lu=new Float32Array(Ra),Ru=new Uint32Array(Ra),ut=(n,e)=>Math.imul((n^e>>>0)>>>0,16777619)>>>0,ri=(n,e)=>(Lu[0]=Number.isFinite(e)?e:0,ut(n,Ru[0]>>>0)),rt=class{transform=new we;name=null;visible=!0;boundsMin=[0,0,0];boundsMax=[0,0,0];boundsCenter=[0,0,0];boundsRadius=0;blendMode="additive";depthWrite=!1;depthTest=!0;_basePointSize=2;_minPointSize=1;_maxPointSize=16;_sizeAttenuation=1;_opacity=1;_colorMode="scalar";_colormap="viridis";_colormapStops=[[.267,.00487,.32942,1],[.99325,.90616,.14394,1]];_softness=.15;_scaleTransform;_CPUData=null;_colorsCPU=null;_keepCPUData=!1;_ndShape=null;_boundsSource="none";_scaleRevision=0;_visualChangeListeners=new Set;pointsBuffer=null;colorsBuffer=null;uniformBuffer=null;bindGroup=null;bindGroupKey=null;_pointCount=0;_uniformDirty=!0;_pointsDirty=!0;_colorsDirty=!0;_colorsExternal=!1;constructor(e){if(y(!!e&&!!e.scaleTransform,"PointCloud: scaleTransform is required."),this._scaleTransform=_o(e.scaleTransform),e.name!==void 0&&(this.name=e.name),e.visible!==void 0&&(this.visible=!!e.visible),e.blendMode!==void 0&&(this.blendMode=e.blendMode),e.depthWrite!==void 0&&(this.depthWrite=!!e.depthWrite),e.depthTest!==void 0&&(this.depthTest=!!e.depthTest),e.basePointSize!==void 0&&(this._basePointSize=e.basePointSize),e.minPointSize!==void 0&&(this._minPointSize=e.minPointSize),e.maxPointSize!==void 0&&(this._maxPointSize=e.maxPointSize),e.sizeAttenuation!==void 0&&(this._sizeAttenuation=e.sizeAttenuation),e.opacity!==void 0&&(this._opacity=e.opacity),e.colormap!==void 0&&(this._colormap=e.colormap),e.colormapStops!==void 0&&(this._colormapStops=Ze(e.colormapStops)),e.colorMode!==void 0?this._colorMode=e.colorMode:(e.colors||e.colorsBuffer)&&(this._colorMode="rgba"),e.softness!==void 0&&(this._softness=e.softness),e.keepCPUData!==void 0&&(this._keepCPUData=!!e.keepCPUData),e.ndShape!==void 0&&(this.ndShape=e.ndShape),this.applyExplicitBounds(e),e.data)this.setData(e.data,{keepCPUData:this._keepCPUData});else if(e.pointsBuffer){let t=re(e.pointsBuffer),r=e.pointCount??0;y(r>0,"PointCloud: pointCount is required when using pointsBuffer."),this.setPointsBuffer(t,r)}else e.pointCount!==void 0&&(this._pointCount=e.pointCount,this._pointsDirty=!1);e.colors?this.setColors(e.colors,{keepCPUData:this._keepCPUData}):e.colorsBuffer&&this.setColorsBuffer(re(e.colorsBuffer))}applyExplicitBounds(e){if(e.boundsMin&&e.boundsMax){let t=et(e.boundsMin,e.boundsMax);this.setBounds(t,"explicit"),e.boundsCenter&&(this.boundsCenter=[e.boundsCenter[0],e.boundsCenter[1],e.boundsCenter[2]]),e.boundsRadius!==void 0&&(this.boundsRadius=Math.max(0,e.boundsRadius));return}if(e.boundsCenter||e.boundsRadius!==void 0){let t=e.boundsCenter??[0,0,0],r=e.boundsRadius??0;this.setBounds(yt(t,r),"explicit")}}setBounds(e,t){this.boundsMin=[e.boxMin[0],e.boxMin[1],e.boxMin[2]],this.boundsMax=[e.boxMax[0],e.boxMax[1],e.boxMax[2]],this.boundsCenter=[e.sphereCenter[0],e.sphereCenter[1],e.sphereCenter[2]],this.boundsRadius=e.sphereRadius,this._boundsSource=t}clearComputedBoundsIfNeeded(){this._boundsSource==="computed"&&(this._boundsSource="none",this.boundsMin=[0,0,0],this.boundsMax=[0,0,0],this.boundsCenter=[0,0,0],this.boundsRadius=0)}clearColorsIfCountMismatch(){this._colorsCPU&&this._colorsCPU.length/4!==this._pointCount&&(this._colorsCPU=null,this._colorsDirty=!1,this.bindGroupKey=null)}get pointCount(){return this._pointCount}get occluderRevision(){let e=2166136261;return e=ut(e,this._pointCount>>>0),e=ut(e,this._scaleRevision>>>0),e=ut(e,this.blendMode==="opaque"?1:this.blendMode==="transparent"?2:3),e=ut(e,this.depthWrite?1:0),e=ut(e,this.depthTest?1:0),e=ut(e,this._pointsDirty?1:0),e=ut(e,this._colorsDirty?1:0),e=ut(e,this.pointsBuffer?1:0),e=ut(e,this.colorsBuffer?1:0),e=ut(e,Ma(this._colorMode)>>>0),e=ri(e,this._basePointSize),e=ri(e,this._minPointSize),e=ri(e,this._maxPointSize),e=ri(e,this._sizeAttenuation),e>>>0}get ndShape(){return this._ndShape?this._ndShape.slice():null}set ndShape(e){this._ndShape=br(e,"PointCloud: ndShape")}get scaleTransform(){return Ie(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=_o(e),this._uniformDirty=!0,this.emitVisualChange("scale")}applyScaleStats(e){let t=Ie(this._scaleTransform);Number.isFinite(e.min)&&(t.domainMin=e.min),Number.isFinite(e.max)&&(t.domainMax=e.max),e.percentileMin!==null&&e.percentileMax!==null&&(t.clampMin=e.percentileMin,t.clampMax=e.percentileMax),this._scaleTransform=_o(t),this._uniformDirty=!0,this.emitVisualChange("scale")}onVisualChange(e){return this._visualChangeListeners.add(e),()=>this._visualChangeListeners.delete(e)}getScaleSourceDescriptor(e=this._scaleRevision){return!this.pointsBuffer||this._pointCount<=0?null:{buffer:this.pointsBuffer,count:this._pointCount,componentCount:this._scaleTransform.componentCount,componentIndex:this._scaleTransform.componentIndex,valueMode:this._scaleTransform.valueMode,stride:this._scaleTransform.stride,offset:this._scaleTransform.offset,revision:e}}get basePointSize(){return this._basePointSize}set basePointSize(e){e!==this._basePointSize&&(this._basePointSize=e,this._uniformDirty=!0)}get minPointSize(){return this._minPointSize}set minPointSize(e){e!==this._minPointSize&&(this._minPointSize=e,this._uniformDirty=!0)}get maxPointSize(){return this._maxPointSize}set maxPointSize(e){e!==this._maxPointSize&&(this._maxPointSize=e,this._uniformDirty=!0)}get sizeAttenuation(){return this._sizeAttenuation}set sizeAttenuation(e){e!==this._sizeAttenuation&&(this._sizeAttenuation=e,this._uniformDirty=!0)}get opacity(){return this._opacity}set opacity(e){e!==this._opacity&&(this._opacity=e,this._uniformDirty=!0)}get colorMode(){return this._colorMode}set colorMode(e){e!==this._colorMode&&(this._colorMode=e,this._uniformDirty=!0,this.emitVisualChange("visual"))}get colormap(){return this._colormap}set colormap(e){this._colormap=e,this._uniformDirty=!0,this.bindGroupKey=null,this.emitVisualChange("colormap")}get colormapStops(){return this._colormapStops}set colormapStops(e){this._colormapStops=Ze(e),this._uniformDirty=!0,this.emitVisualChange("colormap")}getColormapKey(){let e=this._colormap;return e instanceof $?`cm:${e.id}`:`cm:${e}`}getColormapForBinding(){let e=this._colormap;return e instanceof $?e:e==="custom"?$.builtin("grayscale"):$.builtin(e)}get softness(){return this._softness}set softness(e){e!==this._softness&&(this._softness=e,this._uniformDirty=!0)}setData(e,t={}){y(e.length%4===0,"PointCloud: data length must be a multiple of 4 (x,y,z,scalar per point)."),this._CPUData=e,this._pointCount=e.length/4,this.clearColorsIfCountMismatch(),this._pointsDirty=!0,this._keepCPUData=t.keepCPUData??this._keepCPUData,this._scaleRevision++,this.clearComputedBoundsIfNeeded()}setPointsBuffer(e,t){y(t>0,"PointCloud: pointCount must be > 0."),this._CPUData=null,this._pointCount=t,this.clearColorsIfCountMismatch(),this.pointsBuffer=e,this._pointsDirty=!1,this._scaleRevision++,this.bindGroupKey=null,this.clearComputedBoundsIfNeeded()}setColors(e,t={}){y(e.length%4===0,"PointCloud: colors length must be a multiple of 4 (r,g,b,a per point)."),y(e.length/4===this._pointCount,"PointCloud: colors length must equal pointCount*4."),this._colorsCPU=new Float32Array(e),this._colorsExternal=!1,this._colorsDirty=!0,this._keepCPUData=t.keepCPUData??this._keepCPUData,this.bindGroupKey=null}setColorsBuffer(e){e&&y(this._pointCount>0,"PointCloud: pointCount must be > 0 when using colorsBuffer."),this.colorsBuffer=e,this._colorsCPU=null,this._colorsExternal=!!e,this._colorsDirty=!1,this.bindGroupKey=null}dropCPUData(){this._CPUData=null,this._colorsCPU=null}getPointRecord(e){let t=this._CPUData;if(!t||!Number.isInteger(e)||e<0||e>=this._pointCount)return null;let r=e*4,i=this._colorsCPU?[this._colorsCPU[r+0],this._colorsCPU[r+1],this._colorsCPU[r+2],this._colorsCPU[r+3]]:null;return{position:[t[r+0],t[r+1],t[r+2]],scalar:t[r+3],color:i,packed:[t[r+0],t[r+1],t[r+2],t[r+3]]}}mapLinearIndexToNd(e){return vr(this._ndShape,e)}computeBoundsFromCPUData(){let e=this._CPUData;if(!e||e.length<4)return;let t=this._pointCount|0;if(t<=0)return;let r=_.allocF32(e.length),i=_.allocF32(3),o=_.allocF32(3),a=_.allocF32(3),s=_.allocF32(1);try{_.f32view(r,e.length).set(e),Ht.pointcloudXYZS(i,o,a,s,r,t,4);let l=_.f32view(i,3),u=_.f32view(o,3),c=_.f32view(a,3),m=_.f32view(s,1)[0];this.setBounds(Zt([l[0],l[1],l[2]],[u[0],u[1],u[2]],[c[0],c[1],c[2]],m),"computed")}finally{_.freeF32(s,1),_.freeF32(a,3),_.freeF32(o,3),_.freeF32(i,3),_.freeF32(r,e.length)}}getLocalBounds(){return this._boundsSource==="none"&&this._CPUData&&this.computeBoundsFromCPUData(),this._boundsSource==="none"?kt(this._pointCount>0):Zt(this.boundsMin,this.boundsMax,this.boundsCenter,this.boundsRadius)}getWorldBounds(){return Mt(this.getLocalBounds(),this.transform.worldMatrix)}getBounds(){return this.getWorldBounds()}upload(e,t){if(this._pointsDirty)if(this.pointsBuffer&&!this._CPUData)this._pointsDirty=!1;else{let r=this._CPUData;if(!r)this._pointsDirty=!1;else{let i=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST;if(!this.pointsBuffer)this.pointsBuffer=ne(e,r,i);else try{t.writeBuffer(this.pointsBuffer,0,r.buffer,r.byteOffset,r.byteLength)}catch{this.pointsBuffer.destroy(),this.pointsBuffer=ne(e,r,i)}this._keepCPUData||(this._CPUData=null),this._pointsDirty=!1,this.bindGroupKey=null}}if(!this._colorsExternal&&this._colorsDirty){let r=this._colorsCPU;if(!r){this._colorsDirty=!1;return}let i=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST;if(!this.colorsBuffer)this.colorsBuffer=ne(e,r,i);else try{t.writeBuffer(this.colorsBuffer,0,r.buffer,r.byteOffset,r.byteLength)}catch{this.colorsBuffer.destroy(),this.colorsBuffer=ne(e,r,i)}this._keepCPUData||(this._colorsCPU=null),this._colorsDirty=!1,this.bindGroupKey=null}}getUniformBufferSize(){return Mu}getUniformData(){let e=new Float32Array(La),t=Math.max(0,this._basePointSize),r=Math.max(0,this._minPointSize),i=Math.max(r,this._maxPointSize),o=Math.max(0,this._sizeAttenuation);e[0]=t,e[1]=r,e[2]=i,e[3]=o,je(this._scaleTransform,e,4),e[24]=le(this._opacity),e[25]=le(this._softness),e[26]=typeof this._colormap=="string"&&this._colormap==="custom"?Math.min(8,Math.max(2,this._colormapStops.length)):0,e[27]=Ma(this._colorMode);let a=this._colormapStops,s=Math.min(8,Math.max(2,a.length));for(let l=0;l<8;l++){let u=a[Math.min(l,s-1)],c=28+l*4;e[c+0]=u[0],e[c+1]=u[1],e[c+2]=u[2],e[c+3]=u[3]}return e}get dirtyUniforms(){return this._uniformDirty}markUniformsClean(){this._uniformDirty=!1}emitVisualChange(e){for(let t of this._visualChangeListeners)try{t(e)}catch{}}destroy(){this.pointsBuffer?.destroy(),this.colorsBuffer?.destroy(),this.uniformBuffer?.destroy(),this.pointsBuffer=null,this.colorsBuffer=null,this.uniformBuffer=null,this.bindGroup=null,this.bindGroupKey=null,this._CPUData=null,this._colorsCPU=null,this._ndShape=null,this._pointCount=0,this._visualChangeListeners.clear(),this.transform.dispose()}};var Fa=60,Uu=Fa*4,ni=n=>fe({componentCount:4,componentIndex:0,stride:4,...n}),Ua=n=>{switch(n){case"rgba":return 0;case"scalar":return 1;case"solid":return 2}},Ia=new ArrayBuffer(4),Gu=new Float32Array(Ia),Au=new Uint32Array(Ia),nt=(n,e)=>Math.imul((n^e>>>0)>>>0,16777619)>>>0,Fu=(n,e)=>(Gu[0]=Number.isFinite(e)?e:0,nt(n,Au[0]>>>0)),Ga=(n=8,e=12)=>{let t=Math.max(3,n|0),r=Math.max(3,e|0),i=[],o=[],a=[],s=[];for(let u=0;u<=t;u++){let c=u/t,m=c*Math.PI,d=Math.sin(m),f=Math.cos(m);for(let p=0;p<=r;p++){let h=p/r,g=h*Math.PI*2,b=Math.sin(g),v=Math.cos(g)*d,x=f,T=b*d;i.push(v,x,T),o.push(v,x,T),a.push(h,1-c)}}let l=r+1;for(let u=0;u<t;u++)for(let c=0;c<r;c++){let m=u*l+c,d=m+1,f=m+l,p=f+1;s.push(m,d,f),s.push(d,p,f)}return new ae({positions:new Float32Array(i),normals:new Float32Array(o),uvs:new Float32Array(a),indices:new Uint32Array(s)})},Iu=(n=12)=>{let e=Math.max(3,n|0),t=[],r=[],i=[],o=[],a=-.5,s=.15,l=.2,u=.5,c=.05,m=.1,d=(S,R,G,L,U,F,D,k)=>{let A=t.length/3|0;return t.push(S,R,G),r.push(L,U,F),i.push(D,k),A},f=(S,R,G,L)=>{let U=[];for(let F=0;F<=e;F++){let D=F/e,k=D*Math.PI*2,A=Math.cos(k),I=Math.sin(k),O=A*R,N=I*R,z=A,E=I,H=G;L&&(z=0,E=0,H=G),U.push(d(O,N,S,z,E,H,D,S-a))}return U},p=f(a,c,0,!1),h=f(s,c,0,!1);for(let S=0;S<e;S++){let R=p[S],G=p[S+1],L=h[S],U=h[S+1];o.push(R,G,L),o.push(G,U,L)}let g=f(s,c,0,!1),b=f(l,m,0,!1),P=(c-m)/(l-s);for(let S=0;S<=e;S++){let G=S/e*Math.PI*2,L=Math.cos(G),U=Math.sin(G),F=L,D=U,k=P,A=1/Math.hypot(F,D,k);r[g[S]*3+0]=F*A,r[g[S]*3+1]=D*A,r[g[S]*3+2]=k*A,r[b[S]*3+0]=F*A,r[b[S]*3+1]=D*A,r[b[S]*3+2]=k*A}for(let S=0;S<e;S++){let R=g[S],G=g[S+1],L=b[S],U=b[S+1];o.push(R,G,L),o.push(G,U,L)}let v=f(l,m,0,!1),x=[],T=u-l,w=m/T;for(let S=0;S<=e;S++){let R=S/e,G=R*Math.PI*2,L=Math.cos(G),U=Math.sin(G),F=L,D=U,k=w,A=1/Math.hypot(F,D,k);x.push(d(0,0,u,F*A,D*A,k*A,R,u-a))}for(let S=0;S<=e;S++){let G=S/e*Math.PI*2,L=Math.cos(G),U=Math.sin(G),F=L,D=U,k=w,A=1/Math.hypot(F,D,k);r[v[S]*3+0]=F*A,r[v[S]*3+1]=D*A,r[v[S]*3+2]=k*A}for(let S=0;S<e;S++){let R=v[S],G=v[S+1],L=x[S];o.push(R,G,L)}let M=d(0,0,a,0,0,-1,.5,0),B=f(a,c,-1,!0);for(let S=0;S<e;S++){let R=B[S],G=B[S+1];o.push(M,G,R)}return new ae({positions:new Float32Array(t),normals:new Float32Array(r),uvs:new Float32Array(i),indices:new Uint32Array(o)})},ii=null,Aa=null,Du=n=>{switch(n){case"ellipsoid":return ii??=Ga(),ii;case"arrow":return Aa??=Iu(),Aa;default:return ii??=Ga(),ii}},ze=class{transform=new we;name=null;visible=!0;boundsMin=[0,0,0];boundsMax=[0,0,0];blendMode="opaque";cullMode="back";depthWrite=!0;depthTest=!0;boundsCenter=[0,0,0];boundsRadius=0;shape="ellipsoid";geometry;positionsBuffer=null;rotationsBuffer=null;scalesBuffer=null;attributesBuffer=null;uniformBuffer=null;bindGroup=null;bindGroupKey=null;_instanceCount=0;_positionsCPU=null;_rotationsCPU=null;_scalesCPU=null;_attributesCPU=null;_positionsPtr=0;_rotationsPtr=0;_scalesPtr=0;_attributesPtr=0;_usingWasmPtrs=!1;_usingExternalBuffers=!1;_keepCPUData=!1;_ndShape=null;_boundsSource="none";_dataDirty=!0;_uniformDirty=!0;_colorMode="rgba";_colormap="viridis";_colormapStops=[[.267,.00487,.32942,1],[.99325,.90616,.14394,1]];_scaleTransform=ni({});_scaleRevision=0;_visualChangeListeners=new Set;_opacity=1;_lit=!1;_solidColor=[1,1,1,1];constructor(e){y(!!e&&!!e.scaleTransform,"GlyphField: scaleTransform is required."),this._scaleTransform=ni(e.scaleTransform),e.name!==void 0&&(this.name=e.name),e.visible!==void 0&&(this.visible=!!e.visible),this.shape=e.shape??"ellipsoid",this.geometry=e.geometry??Du(this.shape),this.applyExplicitBounds(e),e.blendMode!==void 0&&(this.blendMode=e.blendMode),e.cullMode!==void 0&&(this.cullMode=e.cullMode),e.depthWrite!==void 0&&(this.depthWrite=!!e.depthWrite),e.depthTest!==void 0&&(this.depthTest=!!e.depthTest),e.colorMode!==void 0&&(this._colorMode=e.colorMode),e.colormap!==void 0&&(this._colormap=e.colormap),e.colormapStops!==void 0&&(this._colormapStops=Ze(e.colormapStops)),e.opacity!==void 0&&(this._opacity=e.opacity),e.lit!==void 0&&(this._lit=!!e.lit),e.solidColor!==void 0&&(this._solidColor=[e.solidColor[0],e.solidColor[1],e.solidColor[2],e.solidColor[3]]),e.keepCPUData!==void 0&&(this._keepCPUData=!!e.keepCPUData),e.ndShape!==void 0&&(this.ndShape=e.ndShape);let t=e.positionsBuffer?re(e.positionsBuffer):null,r=e.rotationsBuffer?re(e.rotationsBuffer):null,i=e.scalesBuffer?re(e.scalesBuffer):null,o=e.attributesBuffer?re(e.attributesBuffer):null;if(t||r||i||o){y(!!t&&!!r&&!!i,"GlyphField: positionsBuffer, rotationsBuffer, and scalesBuffer are required when using external buffers.");let a=e.instanceCount??0;y(a>0,"GlyphField: instanceCount is required when using external buffers."),this.setBuffers(t,r,i,o,a)}else if(e.positionsPtr||e.rotationsPtr||e.scalesPtr){y(!!e.positionsPtr&&!!e.rotationsPtr&&!!e.scalesPtr,"GlyphField: positionsPtr, rotationsPtr, and scalesPtr are required when using wasm pointers.");let a=e.instanceCount??0;y(a>0,"GlyphField: instanceCount is required when using wasm pointers."),this.setWasmSoA(e.positionsPtr,e.rotationsPtr,e.scalesPtr,e.attributesPtr??0,a)}else e.positions||e.rotations||e.scales||e.attributes?this.setCPUData(e.positions??null,e.rotations??null,e.scales??null,e.attributes??null,{keepCPUData:this._keepCPUData,instanceCount:e.instanceCount}):e.instanceCount!==void 0&&(this._instanceCount=e.instanceCount|0,this._dataDirty=!1)}applyExplicitBounds(e){if(e.boundsMin&&e.boundsMax){let t=et(e.boundsMin,e.boundsMax);this.setBounds(t,"explicit"),e.boundsCenter&&(this.boundsCenter=[e.boundsCenter[0],e.boundsCenter[1],e.boundsCenter[2]]),e.boundsRadius!==void 0&&(this.boundsRadius=Math.max(0,e.boundsRadius));return}if(e.boundsCenter||e.boundsRadius!==void 0){let t=e.boundsCenter??[0,0,0],r=e.boundsRadius??0;this.setBounds(yt(t,r),"explicit")}}setBounds(e,t){this.boundsMin=[e.boxMin[0],e.boxMin[1],e.boxMin[2]],this.boundsMax=[e.boxMax[0],e.boxMax[1],e.boxMax[2]],this.boundsCenter=[e.sphereCenter[0],e.sphereCenter[1],e.sphereCenter[2]],this.boundsRadius=e.sphereRadius,this._boundsSource=t}clearComputedBoundsIfNeeded(){this._boundsSource==="computed"&&(this._boundsSource="none",this.boundsMin=[0,0,0],this.boundsMax=[0,0,0],this.boundsCenter=[0,0,0],this.boundsRadius=0)}get instanceCount(){return this._instanceCount}get occluderRevision(){let e=2166136261;return e=nt(e,this._instanceCount>>>0),e=nt(e,this._scaleRevision>>>0),e=nt(e,this.blendMode==="opaque"?1:this.blendMode==="transparent"?2:3),e=nt(e,this.cullMode==="back"?1:this.cullMode==="front"?2:3),e=nt(e,this.depthWrite?1:0),e=nt(e,this.depthTest?1:0),e=nt(e,Ua(this._colorMode)>>>0),e=nt(e,this._dataDirty?1:0),e=nt(e,this.geometry.vertexCount>>>0),e=nt(e,this.geometry.indexCount>>>0),e=nt(e,this.attributesBuffer?1:0),e=Fu(e,this._opacity),e>>>0}get ndShape(){return this._ndShape?this._ndShape.slice():null}set ndShape(e){this._ndShape=br(e,"GlyphField: ndShape")}get scaleTransform(){return Ie(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=ni(e),this._uniformDirty=!0,this.emitVisualChange("scale")}applyScaleStats(e){let t=Ie(this._scaleTransform);Number.isFinite(e.min)&&(t.domainMin=e.min),Number.isFinite(e.max)&&(t.domainMax=e.max),e.percentileMin!==null&&e.percentileMax!==null&&(t.clampMin=e.percentileMin,t.clampMax=e.percentileMax),this._scaleTransform=ni(t),this._uniformDirty=!0,this.emitVisualChange("scale")}onVisualChange(e){return this._visualChangeListeners.add(e),()=>this._visualChangeListeners.delete(e)}getScaleSourceDescriptor(e=this._scaleRevision){return!this.attributesBuffer||this._instanceCount<=0?null:{buffer:this.attributesBuffer,count:this._instanceCount,componentCount:this._scaleTransform.componentCount,componentIndex:this._scaleTransform.componentIndex,valueMode:this._scaleTransform.valueMode,stride:this._scaleTransform.stride,offset:this._scaleTransform.offset,revision:e}}set instanceCount(e){let t=e|0;t!==this._instanceCount&&(y(t>=0,"GlyphField: instanceCount must be >= 0."),this._instanceCount=t,this._dataDirty=!0,this._scaleRevision++)}get colorMode(){return this._colorMode}set colorMode(e){e!==this._colorMode&&(this._colorMode=e,this._uniformDirty=!0)}get colormap(){return this._colormap}set colormap(e){this._colormap=e,this._uniformDirty=!0,this.bindGroupKey=null,this.emitVisualChange("colormap")}get colormapStops(){return this._colormapStops}set colormapStops(e){this._colormapStops=Ze(e),this._uniformDirty=!0,this.emitVisualChange("colormap")}getColormapKey(){let e=this._colormap;return e instanceof $?`cm:${e.id}`:`cm:${e}`}getColormapForBinding(){let e=this._colormap;return e instanceof $?e:e==="custom"?$.builtin("grayscale"):$.builtin(e)}get opacity(){return this._opacity}set opacity(e){e!==this._opacity&&(this._opacity=e,this._uniformDirty=!0)}get lit(){return this._lit}set lit(e){let t=!!e;t!==this._lit&&(this._lit=t,this._uniformDirty=!0)}get solidColor(){return this._solidColor}set solidColor(e){this._solidColor=[e[0],e[1],e[2],e[3]],this._uniformDirty=!0}markDataDirty(){this._usingExternalBuffers||(this._dataDirty=!0),this._scaleRevision++}markUniformsDirty(){this._uniformDirty=!0}getAttributeRecord(e){let t=this._attributesCPU;if(!t||!Number.isInteger(e)||e<0||e>=this._instanceCount)return null;let r=e*4;return[t[r+0],t[r+1],t[r+2],t[r+3]]}mapLinearIndexToNd(e){return vr(this._ndShape,e)}setCPUData(e,t,r,i,o={}){e&&y(e.length%4===0,"GlyphField: positions length must be a multiple of 4 (x,y,z,_ per instance)."),t&&y(t.length%4===0,"GlyphField: rotations length must be a multiple of 4 (qx,qy,qz,qw per instance)."),r&&y(r.length%4===0,"GlyphField: scales length must be a multiple of 4 (sx,sy,sz,_ per instance)."),i&&y(i.length%4===0,"GlyphField: attributes length must be a multiple of 4 (a0,a1,a2,a3 per instance).");let a=o.instanceCount!==void 0?o.instanceCount|0:e?e.length/4:t?t.length/4:r?r.length/4:i?i.length/4:0;y(a>=0,"GlyphField: instanceCount must be >= 0."),a>0&&y(!!e&&!!t&&!!r,"GlyphField: positions, rotations, and scales are required for CPU-backed glyph fields."),e&&y(e.length/4===a,"GlyphField: positions length does not match instanceCount."),t&&y(t.length/4===a,"GlyphField: rotations length does not match instanceCount."),r&&y(r.length/4===a,"GlyphField: scales length does not match instanceCount."),i&&y(i.length/4===a,"GlyphField: attributes length does not match instanceCount."),this._instanceCount=a,this._positionsCPU=e,this._rotationsCPU=t,this._scalesCPU=r,this._attributesCPU=i,this._positionsPtr=0,this._rotationsPtr=0,this._scalesPtr=0,this._attributesPtr=0,this._usingWasmPtrs=!1,this._usingExternalBuffers=!1,this._keepCPUData=o.keepCPUData??this._keepCPUData,this.clearComputedBoundsIfNeeded(),this._dataDirty=!0,this._scaleRevision++,this.bindGroupKey=null}setWasmSoA(e,t,r,i,o){let a=o|0;y(a>0,"GlyphField: instanceCount must be > 0."),this._instanceCount=a,this._positionsCPU=null,this._rotationsCPU=null,this._scalesCPU=null,this._attributesCPU=null,this._positionsPtr=e>>>0,this._rotationsPtr=t>>>0,this._scalesPtr=r>>>0,this._attributesPtr=i>>>0,this._usingWasmPtrs=!0,this._usingExternalBuffers=!1,this.clearComputedBoundsIfNeeded(),this._dataDirty=!0,this._scaleRevision++,this.bindGroupKey=null}setBuffers(e,t,r,i,o){let a=o|0;y(a>0,"GlyphField: instanceCount must be > 0."),this._instanceCount=a,this.positionsBuffer=e,this.rotationsBuffer=t,this.scalesBuffer=r,this.attributesBuffer=i,this._positionsCPU=null,this._rotationsCPU=null,this._scalesCPU=null,this._attributesCPU=null,this._positionsPtr=0,this._rotationsPtr=0,this._scalesPtr=0,this._attributesPtr=0,this._usingWasmPtrs=!1,this._usingExternalBuffers=!0,this.clearComputedBoundsIfNeeded(),this._dataDirty=!1,this._scaleRevision++,this.bindGroupKey=null}computeBoundsFromCPUData(){let e=this._positionsCPU,t=this._scalesCPU,r=this._instanceCount;if(!e||!t||r<=0)return;let i=this._rotationsCPU,o=_.allocF32(e.length),a=_.allocF32(t.length),s=0,l=_.allocF32(3),u=_.allocF32(3),c=_.allocF32(3),m=_.allocF32(3),d=_.allocF32(1);try{_.f32view(o,e.length).set(e),_.f32view(a,t.length).set(t),i&&(s=_.allocF32(i.length),_.f32view(s,i.length).set(i)),_.writeF32(l,3,this.geometry.boundsCenter),Ht.glyphInstances(u,c,m,d,o,a,s,r,l,this.geometry.boundsRadius);let f=_.f32view(u,3),p=_.f32view(c,3);this.setBounds(et([f[0],f[1],f[2]],[p[0],p[1],p[2]]),"computed")}finally{_.freeF32(d,1),_.freeF32(m,3),_.freeF32(c,3),_.freeF32(u,3),_.freeF32(l,3),s&&i&&_.freeF32(s,i.length),_.freeF32(a,t.length),_.freeF32(o,e.length)}}getLocalBounds(){return this._boundsSource==="none"&&this._positionsCPU&&this._scalesCPU&&this.computeBoundsFromCPUData(),this._boundsSource==="none"?kt(this._instanceCount>0):et(this.boundsMin,this.boundsMax)}getWorldBounds(){return Mt(this.getLocalBounds(),this.transform.worldMatrix)}getBounds(){return this.getWorldBounds()}upload(e,t){if(this._usingExternalBuffers||!this._dataDirty)return;if(this._instanceCount<=0){this._dataDirty=!1;return}let r=de.bytes(),i=this._instanceCount*16,o=(a,s,l,u)=>{if(!s&&!l)return a;let c=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,m=i,d=s??new Uint8Array(r.buffer,l>>>0,m);if(!a)return ne(e,d,c,u);try{t.writeBuffer(a,0,d.buffer,d.byteOffset,Math.min(d.byteLength,m))}catch{return a.destroy(),ne(e,d,c,u)}return a};this.positionsBuffer=o(this.positionsBuffer,this._positionsCPU,this._positionsPtr,"GlyphField.positions"),this.rotationsBuffer=o(this.rotationsBuffer,this._rotationsCPU,this._rotationsPtr,"GlyphField.rotations"),this.scalesBuffer=o(this.scalesBuffer,this._scalesCPU,this._scalesPtr,"GlyphField.scales"),this._attributesCPU||this._attributesPtr?this.attributesBuffer=o(this.attributesBuffer,this._attributesCPU,this._attributesPtr,"GlyphField.attributes"):this.attributesBuffer||(this.attributesBuffer=e.createBuffer({size:16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,label:"GlyphField.attributesDummy"})),this._keepCPUData||(this._positionsCPU=null,this._rotationsCPU=null,this._scalesCPU=null,this._attributesCPU=null),this._dataDirty=!1,this.bindGroupKey=null}getUniformBufferSize(){return Uu}getUniformData(){let e=new Float32Array(Fa);e.fill(0),je(this._scaleTransform,e,0),e[20]=le(this._opacity),e[21]=typeof this._colormap=="string"&&this._colormap==="custom"?Math.min(8,Math.max(2,this._colormapStops.length)):0,e[22]=Ua(this._colorMode),e[23]=this._lit?1:0,e[24]=this._solidColor[0],e[25]=this._solidColor[1],e[26]=this._solidColor[2],e[27]=this._solidColor[3];let t=this._colormapStops,r=Math.min(8,Math.max(2,t.length));for(let i=0;i<8;i++){let o=t[Math.min(i,r-1)],a=28+i*4;e[a+0]=o[0],e[a+1]=o[1],e[a+2]=o[2],e[a+3]=o[3]}return e}get dirtyUniforms(){return this._uniformDirty}markUniformsClean(){this._uniformDirty=!1}emitVisualChange(e){for(let t of this._visualChangeListeners)try{t(e)}catch{}}destroy(){this.positionsBuffer?.destroy(),this.rotationsBuffer?.destroy(),this.scalesBuffer?.destroy(),this.attributesBuffer?.destroy(),this.uniformBuffer?.destroy(),this.positionsBuffer=null,this.rotationsBuffer=null,this.scalesBuffer=null,this.attributesBuffer=null,this.uniformBuffer=null,this.bindGroup=null,this.bindGroupKey=null,this._positionsCPU=null,this._rotationsCPU=null,this._scalesCPU=null,this._attributesCPU=null,this._ndShape=null,this._instanceCount=0,this._visualChangeListeners.clear(),this.transform.dispose()}};var $e=class n{_meshes=[];_pointClouds=[];_glyphFields=[];_nodeLinks=[];_lights=[];_background;static MAX_LIGHTS=8;constructor(e={}){this._background=e.background??[0,0,0]}get background(){return this._background}set background(e){this._background=e}get meshes(){return this._meshes}get pointClouds(){return this._pointClouds}get glyphFields(){return this._glyphFields}get nodeLinks(){return this._nodeLinks}add(e){if(e instanceof tt){if(e.destroyed)throw new Error("Scene: cannot add a destroyed mesh.");this._meshes.includes(e)||(this._meshes.push(e),la(e,this))}else e instanceof rt?this._pointClouds.includes(e)||this._pointClouds.push(e):e instanceof ze?this._glyphFields.includes(e)||this._glyphFields.push(e):this._nodeLinks.includes(e)||this._nodeLinks.push(e);return this}remove(e){if(e instanceof tt){let t=this._meshes.indexOf(e);t!==-1&&this._meshes.splice(t,1),xo(e,this)}else if(e instanceof rt){let t=this._pointClouds.indexOf(e);t!==-1&&this._pointClouds.splice(t,1)}else if(e instanceof ze){let t=this._glyphFields.indexOf(e);t!==-1&&this._glyphFields.splice(t,1)}else{let t=this._nodeLinks.indexOf(e);t!==-1&&this._nodeLinks.splice(t,1)}return this}clear(){for(let e of this._meshes)xo(e,this);return this._meshes=[],this._pointClouds=[],this._glyphFields=[],this._nodeLinks=[],this}clearPointClouds(){return this._pointClouds=[],this}clearGlyphFields(){return this._glyphFields=[],this}clearNodeLinks(){return this._nodeLinks=[],this}get lights(){return this._lights}addLight(e){return this._lights.includes(e)||(this._lights.length>=n.MAX_LIGHTS&&e.type!=="ambient"&&console.warn(`Scene: Maximum of ${n.MAX_LIGHTS} non-ambient lights supported.`),this._lights.push(e)),this}removeLight(e){let t=this._lights.indexOf(e);return t!==-1&&this._lights.splice(t,1),this}clearLights(){return this._lights=[],this}findByName(e){return this._meshes.find(t=>t.name===e)}findAllByName(e){return this._meshes.filter(t=>t.name===e)}findPointCloudByName(e){return this._pointClouds.find(t=>t.name===e)}findAllPointCloudsByName(e){return this._pointClouds.filter(t=>t.name===e)}findGlyphFieldByName(e){return this._glyphFields.find(t=>t.name===e)}findAllGlyphFieldsByName(e){return this._glyphFields.filter(t=>t.name===e)}findNodeLinkByName(e){return this._nodeLinks.find(t=>t.name===e)}findAllNodeLinksByName(e){return this._nodeLinks.filter(t=>t.name===e)}get visibleMeshes(){return this._meshes.filter(e=>e.visible)}get visiblePointClouds(){return this._pointClouds.filter(e=>e.visible)}get visibleGlyphFields(){return this._glyphFields.filter(e=>e.visible)}get visibleNodeLinks(){return this._nodeLinks.filter(e=>e.visible)}get enabledLights(){return this._lights.filter(e=>e.enabled)}getAmbientColor(){let e=this._lights.find(t=>t.type==="ambient"&&t.enabled);return e?[e.color[0]*e.intensity,e.color[1]*e.intensity,e.color[2]*e.intensity]:[0,0,0]}getLightingData(){let e=this.getAmbientColor(),t=this.enabledLights.filter(r=>r.type!=="ambient").slice(0,n.MAX_LIGHTS);return{ambient:e,lights:t}}getBounds(e={}){let t=e.visibleOnly??!0,r=kt(!1),i=u=>{if(u.empty){u.partial&&(r.partial=!0);return}r=go(r,u)},o=t?this.visibleMeshes:this._meshes,a=t?this.visiblePointClouds:this._pointClouds,s=t?this.visibleGlyphFields:this._glyphFields,l=t?this.visibleNodeLinks:this._nodeLinks;for(let u of o)i(u.getWorldBounds());for(let u of a)i(u.getWorldBounds());for(let u of s)i(u.getWorldBounds());for(let u of l)i(u.getWorldBounds());return r}traverse(e){for(let t of this._meshes)e(t)}traverseVisible(e){for(let t of this._meshes)t.visible&&e(t)}traversePointClouds(e){for(let t of this._pointClouds)e(t)}traverseVisiblePointClouds(e){for(let t of this._pointClouds)t.visible&&e(t)}traverseGlyphFields(e){for(let t of this._glyphFields)e(t)}traverseVisibleGlyphFields(e){for(let t of this._glyphFields)t.visible&&e(t)}traverseNodeLinks(e){for(let t of this._nodeLinks)e(t)}traverseVisibleNodeLinks(e){for(let t of this._nodeLinks)t.visible&&e(t)}destroy(){let e=[...this._meshes];for(let t of e)this.remove(t);for(let t of e)t.destroy();for(let t of this._pointClouds)t.destroy();for(let t of this._glyphFields)t.destroy();for(let t of this._nodeLinks)t.destroy();this._meshes=[],this._pointClouds=[],this._glyphFields=[],this._nodeLinks=[],this._lights=[]}};var oi=n=>{let e=Math.sqrt(n[0]**2+n[1]**2+n[2]**2);return e<=0?[0,-1,0]:[n[0]/e,n[1]/e,n[2]/e]},nr=class{type;_color=[1,1,1];_intensity=1;_enabled=!0;constructor(e){this.type=e}get color(){return this._color}set color(e){this._color=e}get intensity(){return this._intensity}set intensity(e){this._intensity=e}get enabled(){return this._enabled}set enabled(e){this._enabled=e}},Bo=new WeakMap,Da=(n,e)=>{Bo.set(n,e)},Na=n=>{Bo.delete(n)},za=n=>{let e=Bo.get(n);return!e||e.disposed?null:e},Oa=(n,e)=>{let t=za(n);if(!t)return e;let r=t.worldPosition;return[r[0]??0,r[1]??0,r[2]??0]},Va=(n,e)=>{let t=za(n);if(!t)return e;let r=t.worldMatrix;return oi([-(r[8]??0),-(r[9]??0),-(r[10]??-1)])},ko=n=>n.position,ai=n=>n.direction,dn=class extends nr{constructor(e={}){super("ambient"),this._color=e.color??[1,1,1],this._intensity=e.intensity??.1}},Pt=class extends nr{_direction;constructor(e={}){super("directional"),this._direction=e.direction??[0,-1,0],this._color=e.color??[1,1,1],this._intensity=e.intensity??1}get direction(){return Va(this,this._direction)}set direction(e){this._direction=oi(e)}},Tt=class extends nr{_position;_range;constructor(e={}){super("point"),this._position=e.position??[0,0,0],this._color=e.color??[1,1,1],this._intensity=e.intensity??1,this._range=e.range??10}get position(){return Oa(this,this._position)}set position(e){this._position=e}get range(){return this._range}set range(e){this._range=e}},ct=class extends nr{_position;_direction;_range;_innerCone;_outerCone;constructor(e={}){super("spot"),this._position=e.position??[0,0,0],this._direction=oi(e.direction??[0,-1,0]),this._color=e.color??[1,1,1],this._intensity=e.intensity??1,this._range=e.range??10,this._innerCone=e.innerCone??Math.PI/8,this._outerCone=e.outerCone??Math.PI/6,this._innerCone>this._outerCone&&(this._innerCone=this._outerCone)}get position(){return Oa(this,this._position)}set position(e){this._position=e}get direction(){return Va(this,this._direction)}set direction(e){this._direction=oi(e)}get range(){return this._range}set range(e){this._range=e}get innerCone(){return this._innerCone}set innerCone(e){this._innerCone=Math.max(0,Math.min(e,this._outerCone))}get outerCone(){return this._outerCone}set outerCone(e){this._outerCone=Math.max(0,e),this._innerCone>this._outerCone&&(this._innerCone=this._outerCone)}};var $a=128,Nu=$a*4,si=n=>fe({componentCount:1,componentIndex:0,stride:1,offset:0,mode:"linear",clampMode:"range",domainMin:0,domainMax:1,clampMin:0,clampMax:1,gamma:1,invert:!1,...n??{}}),li=n=>fe({componentCount:1,componentIndex:0,stride:1,offset:0,mode:"linear",clampMode:"range",domainMin:0,domainMax:1,clampMin:0,clampMax:1,gamma:1,invert:!1,...n??{}}),ui=n=>n==="rgba"?0:n==="scalar"?1:2,Ea=n=>n==="points"?0:n==="spheres"?1:n==="ellipsoids"?2:3,Wa=n=>n==="lines"?0:1,ja=n=>n==="points"||n==="spheres"||n==="ellipsoids"||n==="cubes",Ha=n=>n==="lines"||n==="cylinders",ci=n=>n==="rgba"||n==="scalar"||n==="solid",zu=n=>new Uint8Array(new Uint8Array(n.buffer,n.byteOffset,n.byteLength)),qa=new ArrayBuffer(4),Ou=new Float32Array(qa),Vu=new Uint32Array(qa),Ge=(n,e)=>Math.imul((n^e>>>0)>>>0,16777619)>>>0,fn=(n,e)=>(Ou[0]=Number.isFinite(e)?e:0,Ge(n,Vu[0]>>>0)),Oe=class{transform=new we;name=null;visible=!0;blendMode="opaque";cullMode="back";depthWrite=!0;depthTest=!0;boundsMin=[0,0,0];boundsMax=[0,0,0];boundsCenter=[0,0,0];boundsRadius=0;nodePositionsBuffer=null;nodeScalarsBuffer=null;nodeColorsBuffer=null;nodeRadiiBuffer=null;edgesBuffer=null;edgeScalarsBuffer=null;edgeColorsBuffer=null;uniformBuffer=null;bindGroup=null;bindGroupKey=null;_nodeCount=0;_edgeCount=0;_nodePositionsCPU=null;_nodeScalarsCPU=null;_nodeColorsCPU=null;_nodeRadiiCPU=null;_edgesCPU=null;_edgeScalarsCPU=null;_edgeColorsCPU=null;_nodePositionsExternal=!1;_nodeScalarsExternal=!1;_nodeColorsExternal=!1;_nodeRadiiExternal=!1;_edgesExternal=!1;_edgeScalarsExternal=!1;_edgeColorsExternal=!1;_nodePositionsDirty=!0;_nodeScalarsDirty=!0;_nodeColorsDirty=!0;_nodeRadiiDirty=!0;_edgesDirty=!0;_edgeScalarsDirty=!0;_edgeColorsDirty=!0;_uniformDirty=!0;_boundsSource="none";_keepCPUData=!1;_ndShape=null;_nodeGeometryMode="points";_edgeGeometryMode="lines";_nodeColorMode="scalar";_edgeColorMode="solid";_nodeScaleTransform=si(void 0);_edgeScaleTransform=li(void 0);_nodeScaleRevision=0;_edgeScaleRevision=0;_nodeColormap="viridis";_edgeColormap="viridis";_nodeColormapStops=[[.267,.00487,.32942,1],[.99325,.90616,.14394,1]];_edgeColormapStops=[[.267,.00487,.32942,1],[.99325,.90616,.14394,1]];_nodeSolidColor=[1,1,1,1];_edgeSolidColor=[.8,.8,.8,1];_nodeSize=1;_minPointSize=1;_maxPointSize=32;_pointSizeAttenuation=1;_edgeSize=.06;_opacity=1;_lit=!1;_pendingWrites=[];_visualChangeListeners=new Set;constructor(e={}){this._nodeScaleTransform=si(e.nodeScaleTransform),this._edgeScaleTransform=li(e.edgeScaleTransform),e.nodeGeometryMode!==void 0&&y(ja(e.nodeGeometryMode),`NodeLink: invalid nodeGeometryMode '${String(e.nodeGeometryMode)}'.`),e.edgeGeometryMode!==void 0&&y(Ha(e.edgeGeometryMode),`NodeLink: invalid edgeGeometryMode '${String(e.edgeGeometryMode)}'.`),e.nodeColorMode!==void 0&&y(ci(e.nodeColorMode),`NodeLink: invalid nodeColorMode '${String(e.nodeColorMode)}'.`),e.edgeColorMode!==void 0&&y(ci(e.edgeColorMode),`NodeLink: invalid edgeColorMode '${String(e.edgeColorMode)}'.`),e.nodePositionsBuffer!==void 0&&y(e.nodeCount!==void 0,"NodeLink: nodeCount is required when nodePositionsBuffer is provided."),e.edgesBuffer!==void 0&&y(e.edgeCount!==void 0,"NodeLink: edgeCount is required when edgesBuffer is provided."),e.name!==void 0&&(this.name=e.name),e.visible!==void 0&&(this.visible=!!e.visible),e.blendMode!==void 0&&(this.blendMode=e.blendMode),e.cullMode!==void 0&&(this.cullMode=e.cullMode),e.depthWrite!==void 0&&(this.depthWrite=!!e.depthWrite),e.depthTest!==void 0&&(this.depthTest=!!e.depthTest),e.keepCPUData!==void 0&&(this._keepCPUData=!!e.keepCPUData),e.ndShape!==void 0&&(this.ndShape=e.ndShape),e.nodeGeometryMode!==void 0&&(this._nodeGeometryMode=e.nodeGeometryMode),e.edgeGeometryMode!==void 0&&(this._edgeGeometryMode=e.edgeGeometryMode),e.nodeColorMode!==void 0&&(this._nodeColorMode=e.nodeColorMode),e.edgeColorMode!==void 0&&(this._edgeColorMode=e.edgeColorMode),e.nodeColormap!==void 0&&(this._nodeColormap=e.nodeColormap),e.edgeColormap!==void 0&&(this._edgeColormap=e.edgeColormap),e.nodeColormapStops!==void 0&&(this._nodeColormapStops=Ze(e.nodeColormapStops)),e.edgeColormapStops!==void 0&&(this._edgeColormapStops=Ze(e.edgeColormapStops)),e.nodeSolidColor!==void 0&&(this._nodeSolidColor=[e.nodeSolidColor[0],e.nodeSolidColor[1],e.nodeSolidColor[2],e.nodeSolidColor[3]]),e.edgeSolidColor!==void 0&&(this._edgeSolidColor=[e.edgeSolidColor[0],e.edgeSolidColor[1],e.edgeSolidColor[2],e.edgeSolidColor[3]]),e.nodeSize!==void 0&&(this._nodeSize=Math.max(0,e.nodeSize)),e.minPointSize!==void 0&&(this._minPointSize=Math.max(0,e.minPointSize)),e.maxPointSize!==void 0&&(this._maxPointSize=Math.max(this._minPointSize,e.maxPointSize)),e.pointSizeAttenuation!==void 0&&(this._pointSizeAttenuation=Math.max(0,e.pointSizeAttenuation)),e.edgeSize!==void 0&&(this._edgeSize=Math.max(0,e.edgeSize)),e.opacity!==void 0&&(this._opacity=le(e.opacity)),e.lit!==void 0&&(this._lit=!!e.lit),this.applyExplicitBounds(e),e.nodePositions?this.setNodePositions(e.nodePositions,{stride:e.nodePositionsStride??3,keepCPUData:this._keepCPUData}):e.nodePositionsBuffer?this.setNodePositionsBuffer(re(e.nodePositionsBuffer),e.nodeCount??0):e.nodeCount!==void 0&&(this._nodeCount=Math.max(0,e.nodeCount|0)),e.edges?this.setEdges(e.edges,{keepCPUData:this._keepCPUData}):e.edgesBuffer?this.setEdgesBuffer(re(e.edgesBuffer),e.edgeCount??0):e.edgeCount!==void 0&&(this._edgeCount=Math.max(0,e.edgeCount|0)),e.nodeScalars?this.setNodeScalars(e.nodeScalars,{keepCPUData:this._keepCPUData}):e.nodeScalarsBuffer&&this.setNodeScalarsBuffer(re(e.nodeScalarsBuffer)),e.nodeColors?this.setNodeColors(e.nodeColors,{keepCPUData:this._keepCPUData}):e.nodeColorsBuffer&&this.setNodeColorsBuffer(re(e.nodeColorsBuffer)),e.nodeRadii?this.setNodeRadii(e.nodeRadii,{stride:e.nodeRadiiStride??3,keepCPUData:this._keepCPUData}):e.nodeRadiiBuffer&&this.setNodeRadiiBuffer(re(e.nodeRadiiBuffer)),e.edgeScalars?this.setEdgeScalars(e.edgeScalars,{keepCPUData:this._keepCPUData}):e.edgeScalarsBuffer&&this.setEdgeScalarsBuffer(re(e.edgeScalarsBuffer)),e.edgeColors?this.setEdgeColors(e.edgeColors,{keepCPUData:this._keepCPUData}):e.edgeColorsBuffer&&this.setEdgeColorsBuffer(re(e.edgeColorsBuffer))}applyExplicitBounds(e){if(e.boundsMin&&e.boundsMax){this.setBounds(et(e.boundsMin,e.boundsMax),"explicit"),e.boundsCenter&&(this.boundsCenter=[e.boundsCenter[0],e.boundsCenter[1],e.boundsCenter[2]]),e.boundsRadius!==void 0&&(this.boundsRadius=Math.max(0,e.boundsRadius));return}(e.boundsCenter||e.boundsRadius!==void 0)&&this.setBounds(yt(e.boundsCenter??[0,0,0],e.boundsRadius??0),"explicit")}setBounds(e,t){this.boundsMin=[e.boxMin[0],e.boxMin[1],e.boxMin[2]],this.boundsMax=[e.boxMax[0],e.boxMax[1],e.boxMax[2]],this.boundsCenter=[e.sphereCenter[0],e.sphereCenter[1],e.sphereCenter[2]],this.boundsRadius=e.sphereRadius,this._boundsSource=t}clearComputedBoundsIfNeeded(){this._boundsSource==="computed"&&(this._boundsSource="none",this.boundsMin=[0,0,0],this.boundsMax=[0,0,0],this.boundsCenter=[0,0,0],this.boundsRadius=0)}validateNodeArrayLength(e,t,r){return y(t===3||t===4,`NodeLink: ${r} stride must be 3 or 4.`),y(e%t===0,`NodeLink: ${r} length must be a multiple of ${t}.`),e/t|0}packVec4FromStride(e,t){if(t===4)return new Float32Array(e);let r=e.length/3,i=new Float32Array(r*4);for(let o=0;o<r;o++){let a=o*3,s=o*4;i[s+0]=e[a+0],i[s+1]=e[a+1],i[s+2]=e[a+2],i[s+3]=0}return i}queueWrite(e,t,r){this._pendingWrites.push({target:e,byteOffset:t,bytes:zu(r)}),this.bindGroupKey=null}flushQueuedWrites(e){for(let t of this._pendingWrites){let r=t.target==="nodePositions"?this.nodePositionsBuffer:t.target==="nodeScalars"?this.nodeScalarsBuffer:t.target==="nodeColors"?this.nodeColorsBuffer:t.target==="nodeRadii"?this.nodeRadiiBuffer:t.target==="edges"?this.edgesBuffer:t.target==="edgeScalars"?this.edgeScalarsBuffer:this.edgeColorsBuffer;r&&e.writeBuffer(r,t.byteOffset,t.bytes.buffer,t.bytes.byteOffset,t.bytes.byteLength)}this._pendingWrites.length=0}get nodeCount(){return this._nodeCount}get edgeCount(){return this._edgeCount}get occluderRevision(){let e=2166136261;return e=Ge(e,this._nodeCount>>>0),e=Ge(e,this._edgeCount>>>0),e=Ge(e,this._nodeScaleRevision>>>0),e=Ge(e,this._edgeScaleRevision>>>0),e=Ge(e,this.blendMode==="opaque"?1:this.blendMode==="transparent"?2:3),e=Ge(e,this.cullMode==="back"?1:this.cullMode==="front"?2:3),e=Ge(e,this.depthWrite?1:0),e=Ge(e,this.depthTest?1:0),e=Ge(e,Ea(this._nodeGeometryMode)>>>0),e=Ge(e,Wa(this._edgeGeometryMode)>>>0),e=Ge(e,ui(this._nodeColorMode)>>>0),e=Ge(e,ui(this._edgeColorMode)>>>0),e=Ge(e,this._nodePositionsDirty?1:0),e=Ge(e,this._nodeRadiiDirty?1:0),e=Ge(e,this._edgesDirty?1:0),e=fn(e,this._nodeSize),e=fn(e,this._edgeSize),e=fn(e,this._minPointSize),e=fn(e,this._maxPointSize),e=fn(e,this._pointSizeAttenuation),e>>>0}get ndShape(){return this._ndShape?this._ndShape.slice():null}set ndShape(e){this._ndShape=br(e,"NodeLink: ndShape")}get nodeGeometryMode(){return this._nodeGeometryMode}set nodeGeometryMode(e){y(ja(e),`NodeLink: invalid nodeGeometryMode '${String(e)}'.`),e!==this._nodeGeometryMode&&(this._nodeGeometryMode=e,this._uniformDirty=!0,this.emitVisualChange("visual"))}get edgeGeometryMode(){return this._edgeGeometryMode}set edgeGeometryMode(e){y(Ha(e),`NodeLink: invalid edgeGeometryMode '${String(e)}'.`),e!==this._edgeGeometryMode&&(this._edgeGeometryMode=e,this._uniformDirty=!0,this.emitVisualChange("visual"))}get nodeColorMode(){return this._nodeColorMode}set nodeColorMode(e){y(ci(e),`NodeLink: invalid nodeColorMode '${String(e)}'.`),e!==this._nodeColorMode&&(this._nodeColorMode=e,this._uniformDirty=!0,this.emitVisualChange("visual"))}get edgeColorMode(){return this._edgeColorMode}set edgeColorMode(e){y(ci(e),`NodeLink: invalid edgeColorMode '${String(e)}'.`),e!==this._edgeColorMode&&(this._edgeColorMode=e,this._uniformDirty=!0,this.emitVisualChange("visual"))}get nodeScaleTransform(){return Ie(this._nodeScaleTransform)}setNodeScaleTransform(e){this._nodeScaleTransform=si(e),this._uniformDirty=!0,this._nodeScaleRevision++,this.emitVisualChange("scale")}get edgeScaleTransform(){return Ie(this._edgeScaleTransform)}setEdgeScaleTransform(e){this._edgeScaleTransform=li(e),this._uniformDirty=!0,this._edgeScaleRevision++,this.emitVisualChange("scale")}applyNodeScaleStats(e){let t=Ie(this._nodeScaleTransform);Number.isFinite(e.min)&&(t.domainMin=e.min),Number.isFinite(e.max)&&(t.domainMax=e.max),e.percentileMin!==null&&e.percentileMax!==null&&(t.clampMin=e.percentileMin,t.clampMax=e.percentileMax),this._nodeScaleTransform=si(t),this._uniformDirty=!0,this._nodeScaleRevision++,this.emitVisualChange("scale")}applyEdgeScaleStats(e){let t=Ie(this._edgeScaleTransform);Number.isFinite(e.min)&&(t.domainMin=e.min),Number.isFinite(e.max)&&(t.domainMax=e.max),e.percentileMin!==null&&e.percentileMax!==null&&(t.clampMin=e.percentileMin,t.clampMax=e.percentileMax),this._edgeScaleTransform=li(t),this._uniformDirty=!0,this._edgeScaleRevision++,this.emitVisualChange("scale")}onVisualChange(e){return this._visualChangeListeners.add(e),()=>this._visualChangeListeners.delete(e)}getNodeScaleSourceDescriptor(e=this._nodeScaleRevision){return!this.nodeScalarsBuffer||this._nodeCount<=0?null:{buffer:this.nodeScalarsBuffer,count:this._nodeCount,componentCount:this._nodeScaleTransform.componentCount,componentIndex:this._nodeScaleTransform.componentIndex,valueMode:this._nodeScaleTransform.valueMode,stride:this._nodeScaleTransform.stride,offset:this._nodeScaleTransform.offset,revision:e}}getEdgeScaleSourceDescriptor(e=this._edgeScaleRevision){return!this.edgeScalarsBuffer||this._edgeCount<=0?null:{buffer:this.edgeScalarsBuffer,count:this._edgeCount,componentCount:this._edgeScaleTransform.componentCount,componentIndex:this._edgeScaleTransform.componentIndex,valueMode:this._edgeScaleTransform.valueMode,stride:this._edgeScaleTransform.stride,offset:this._edgeScaleTransform.offset,revision:e}}get nodeColormap(){return this._nodeColormap}set nodeColormap(e){this._nodeColormap=e,this._uniformDirty=!0,this.bindGroupKey=null,this.emitVisualChange("colormap")}get edgeColormap(){return this._edgeColormap}set edgeColormap(e){this._edgeColormap=e,this._uniformDirty=!0,this.bindGroupKey=null,this.emitVisualChange("colormap")}get nodeColormapStops(){return this._nodeColormapStops}set nodeColormapStops(e){this._nodeColormapStops=Ze(e),this._uniformDirty=!0,this.emitVisualChange("colormap")}get edgeColormapStops(){return this._edgeColormapStops}set edgeColormapStops(e){this._edgeColormapStops=Ze(e),this._uniformDirty=!0,this.emitVisualChange("colormap")}get nodeSolidColor(){return[this._nodeSolidColor[0],this._nodeSolidColor[1],this._nodeSolidColor[2],this._nodeSolidColor[3]]}set nodeSolidColor(e){this._nodeSolidColor=[e[0],e[1],e[2],e[3]],this._uniformDirty=!0,this.emitVisualChange("visual")}get edgeSolidColor(){return[this._edgeSolidColor[0],this._edgeSolidColor[1],this._edgeSolidColor[2],this._edgeSolidColor[3]]}set edgeSolidColor(e){this._edgeSolidColor=[e[0],e[1],e[2],e[3]],this._uniformDirty=!0,this.emitVisualChange("visual")}get nodeSize(){return this._nodeSize}set nodeSize(e){e!==this._nodeSize&&(this._nodeSize=Math.max(0,e),this._uniformDirty=!0,this.emitVisualChange("visual"))}get edgeSize(){return this._edgeSize}set edgeSize(e){e!==this._edgeSize&&(this._edgeSize=Math.max(0,e),this._uniformDirty=!0,this.emitVisualChange("visual"))}get opacity(){return this._opacity}set opacity(e){e!==this._opacity&&(this._opacity=le(e),this._uniformDirty=!0,this.emitVisualChange("visual"))}get lit(){return this._lit}set lit(e){let t=!!e;t!==this._lit&&(this._lit=t,this._uniformDirty=!0,this.emitVisualChange("visual"))}get minPointSize(){return this._minPointSize}set minPointSize(e){e!==this._minPointSize&&(this._minPointSize=Math.max(0,e),this._maxPointSize<this._minPointSize&&(this._maxPointSize=this._minPointSize),this._uniformDirty=!0,this.emitVisualChange("visual"))}get maxPointSize(){return this._maxPointSize}set maxPointSize(e){e!==this._maxPointSize&&(this._maxPointSize=Math.max(this._minPointSize,e),this._uniformDirty=!0,this.emitVisualChange("visual"))}get pointSizeAttenuation(){return this._pointSizeAttenuation}set pointSizeAttenuation(e){e!==this._pointSizeAttenuation&&(this._pointSizeAttenuation=Math.max(0,e),this._uniformDirty=!0,this.emitVisualChange("visual"))}setNodePositions(e,t={}){let r=t.stride??3,i=this.validateNodeArrayLength(e.length,r,"nodePositions");this._nodeCount=i,this._nodePositionsCPU=this.packVec4FromStride(e,r),this._nodePositionsExternal=!1,this._nodePositionsDirty=!0,this._keepCPUData=t.keepCPUData??this._keepCPUData,this.clearComputedBoundsIfNeeded(),this.bindGroupKey=null}updateNodePositions(e,t=0,r=3){let i=this.validateNodeArrayLength(e.length,r,"nodePositions patch"),o=t|0;y(o>=0,"NodeLink: updateNodePositions startNode must be >= 0."),y(o+i<=this._nodeCount,"NodeLink: updateNodePositions range exceeds nodeCount.");let a=this.packVec4FromStride(e,r);this._nodePositionsCPU&&this._nodePositionsCPU.set(a,o*4),this.nodePositionsBuffer?this.queueWrite("nodePositions",o*16,a):this._nodePositionsDirty=!0,this.clearComputedBoundsIfNeeded()}setNodePositionsBuffer(e,t){y(!!e,"NodeLink: nodePositionsBuffer is required."),y(Number.isInteger(t)&&t>=0,"NodeLink: nodeCount must be an integer >= 0."),this.nodePositionsBuffer=e,this._nodeCount=t|0,this._nodePositionsCPU=null,this._nodePositionsExternal=!0,this._nodePositionsDirty=!1,this.bindGroupKey=null}setNodeScalars(e,t={}){y(e.length===this._nodeCount,"NodeLink: nodeScalars length must equal nodeCount."),this._nodeScalarsCPU=new Float32Array(e),this._nodeScalarsExternal=!1,this._nodeScalarsDirty=!0,this._nodeScaleRevision++,this._keepCPUData=t.keepCPUData??this._keepCPUData}updateNodeScalars(e,t=0){let r=t|0;y(r>=0,"NodeLink: updateNodeScalars startNode must be >= 0."),y(r+e.length<=this._nodeCount,"NodeLink: updateNodeScalars range exceeds nodeCount."),this._nodeScalarsCPU&&this._nodeScalarsCPU.set(e,r),this.nodeScalarsBuffer?this.queueWrite("nodeScalars",r*4,e):this._nodeScalarsDirty=!0,this._nodeScaleRevision++}setNodeScalarsBuffer(e){this.nodeScalarsBuffer=e,this._nodeScalarsCPU=null,this._nodeScalarsExternal=!!e,this._nodeScalarsDirty=!1,this._nodeScaleRevision++,this.bindGroupKey=null}setNodeColors(e,t={}){y(e.length%4===0,"NodeLink: nodeColors length must be a multiple of 4."),y(e.length/4===this._nodeCount,"NodeLink: nodeColors length must equal nodeCount*4."),this._nodeColorsCPU=new Float32Array(e),this._nodeColorsExternal=!1,this._nodeColorsDirty=!0,this._keepCPUData=t.keepCPUData??this._keepCPUData}updateNodeColors(e,t=0){y(e.length%4===0,"NodeLink: updateNodeColors length must be a multiple of 4.");let r=t|0,i=e.length/4;y(r>=0,"NodeLink: updateNodeColors startNode must be >= 0."),y(r+i<=this._nodeCount,"NodeLink: updateNodeColors range exceeds nodeCount."),this._nodeColorsCPU&&this._nodeColorsCPU.set(e,r*4),this.nodeColorsBuffer?this.queueWrite("nodeColors",r*16,e):this._nodeColorsDirty=!0}setNodeColorsBuffer(e){this.nodeColorsBuffer=e,this._nodeColorsCPU=null,this._nodeColorsExternal=!!e,this._nodeColorsDirty=!1,this.bindGroupKey=null}setNodeRadii(e,t={}){let r=t.stride??3,i=this.validateNodeArrayLength(e.length,r,"nodeRadii");y(i===this._nodeCount,"NodeLink: nodeRadii count must equal nodeCount."),this._nodeRadiiCPU=this.packVec4FromStride(e,r),this._nodeRadiiExternal=!1,this._nodeRadiiDirty=!0,this._keepCPUData=t.keepCPUData??this._keepCPUData}updateNodeRadii(e,t=0,r=3){let i=this.validateNodeArrayLength(e.length,r,"nodeRadii patch"),o=t|0;y(o>=0,"NodeLink: updateNodeRadii startNode must be >= 0."),y(o+i<=this._nodeCount,"NodeLink: updateNodeRadii range exceeds nodeCount.");let a=this.packVec4FromStride(e,r);this._nodeRadiiCPU&&this._nodeRadiiCPU.set(a,o*4),this.nodeRadiiBuffer?this.queueWrite("nodeRadii",o*16,a):this._nodeRadiiDirty=!0}setNodeRadiiBuffer(e){this.nodeRadiiBuffer=e,this._nodeRadiiCPU=null,this._nodeRadiiExternal=!!e,this._nodeRadiiDirty=!1,this.bindGroupKey=null}setEdges(e,t={}){y(e instanceof Uint16Array||e instanceof Uint32Array,"NodeLink: edges must be a Uint16Array or Uint32Array."),y(e.length%2===0,"NodeLink: edges length must be a multiple of 2.");let r=e instanceof Uint32Array?e:new Uint32Array(e);for(let i=0;i<r.length;i++)y(r[i]<this._nodeCount,`NodeLink: edge index ${r[i]} is out of range.`);this._edgeCount=r.length/2|0,this._edgesCPU=new Uint32Array(r),this._edgesExternal=!1,this._edgesDirty=!0,this._keepCPUData=t.keepCPUData??this._keepCPUData}updateEdges(e,t=0){y(e instanceof Uint16Array||e instanceof Uint32Array,"NodeLink: updateEdges data must be a Uint16Array or Uint32Array."),y(e.length%2===0,"NodeLink: updateEdges length must be a multiple of 2.");let r=e instanceof Uint32Array?e:new Uint32Array(e),i=t|0,o=r.length/2|0;y(i>=0,"NodeLink: updateEdges startEdge must be >= 0."),y(i+o<=this._edgeCount,"NodeLink: updateEdges range exceeds edgeCount.");for(let a=0;a<r.length;a++)y(r[a]<this._nodeCount,`NodeLink: edge index ${r[a]} is out of range.`);this._edgesCPU&&this._edgesCPU.set(r,i*2),this.edgesBuffer?this.queueWrite("edges",i*8,r):this._edgesDirty=!0}setEdgesBuffer(e,t){y(!!e,"NodeLink: edgesBuffer is required."),y(Number.isInteger(t)&&t>=0,"NodeLink: edgeCount must be an integer >= 0."),this.edgesBuffer=e,this._edgeCount=t|0,this._edgesCPU=null,this._edgesExternal=!0,this._edgesDirty=!1,this.bindGroupKey=null}setEdgeScalars(e,t={}){y(e.length===this._edgeCount,"NodeLink: edgeScalars length must equal edgeCount."),this._edgeScalarsCPU=new Float32Array(e),this._edgeScalarsExternal=!1,this._edgeScalarsDirty=!0,this._edgeScaleRevision++,this._keepCPUData=t.keepCPUData??this._keepCPUData}updateEdgeScalars(e,t=0){let r=t|0;y(r>=0,"NodeLink: updateEdgeScalars startEdge must be >= 0."),y(r+e.length<=this._edgeCount,"NodeLink: updateEdgeScalars range exceeds edgeCount."),this._edgeScalarsCPU&&this._edgeScalarsCPU.set(e,r),this.edgeScalarsBuffer?this.queueWrite("edgeScalars",r*4,e):this._edgeScalarsDirty=!0,this._edgeScaleRevision++}setEdgeScalarsBuffer(e){this.edgeScalarsBuffer=e,this._edgeScalarsCPU=null,this._edgeScalarsExternal=!!e,this._edgeScalarsDirty=!1,this._edgeScaleRevision++,this.bindGroupKey=null}setEdgeColors(e,t={}){y(e.length%4===0,"NodeLink: edgeColors length must be a multiple of 4."),y(e.length/4===this._edgeCount,"NodeLink: edgeColors length must equal edgeCount*4."),this._edgeColorsCPU=new Float32Array(e),this._edgeColorsExternal=!1,this._edgeColorsDirty=!0,this._keepCPUData=t.keepCPUData??this._keepCPUData}updateEdgeColors(e,t=0){y(e.length%4===0,"NodeLink: updateEdgeColors length must be a multiple of 4.");let r=t|0,i=e.length/4;y(r>=0,"NodeLink: updateEdgeColors startEdge must be >= 0."),y(r+i<=this._edgeCount,"NodeLink: updateEdgeColors range exceeds edgeCount."),this._edgeColorsCPU&&this._edgeColorsCPU.set(e,r*4),this.edgeColorsBuffer?this.queueWrite("edgeColors",r*16,e):this._edgeColorsDirty=!0}setEdgeColorsBuffer(e){this.edgeColorsBuffer=e,this._edgeColorsCPU=null,this._edgeColorsExternal=!!e,this._edgeColorsDirty=!1,this.bindGroupKey=null}dropCPUData(){this._nodePositionsCPU=null,this._nodeScalarsCPU=null,this._nodeColorsCPU=null,this._nodeRadiiCPU=null,this._edgesCPU=null,this._edgeScalarsCPU=null,this._edgeColorsCPU=null}decodePickElement(e){if(!Number.isInteger(e)||e<0)return null;if(e<this._nodeCount)return{component:"node",componentIndex:e|0};let t=(e|0)-this._nodeCount;return t>=0&&t<this._edgeCount?{component:"edge",componentIndex:t}:null}mapLinearNodeIndexToNd(e){return vr(this._ndShape,e)}getNodeRecord(e){let t=this._nodePositionsCPU;if(!t||e<0||e>=this._nodeCount)return null;let r=e*4,i=this._nodeScalarsCPU?this._nodeScalarsCPU[e]:null,o=this._nodeColorsCPU?[this._nodeColorsCPU[r+0],this._nodeColorsCPU[r+1],this._nodeColorsCPU[r+2],this._nodeColorsCPU[r+3]]:null;return{position:[t[r+0],t[r+1],t[r+2]],scalar:i,color:o}}getEdgeRecord(e){let t=this._edgesCPU;if(!t||e<0||e>=this._edgeCount)return null;let r=e*2,i=t[r+0]|0,o=t[r+1]|0,a=this._edgeScalarsCPU?this._edgeScalarsCPU[e]:null,s=this._edgeColorsCPU?[this._edgeColorsCPU[e*4+0],this._edgeColorsCPU[e*4+1],this._edgeColorsCPU[e*4+2],this._edgeColorsCPU[e*4+3]]:null,l=null,u=null;if(this._nodePositionsCPU&&i<this._nodeCount&&o<this._nodeCount){let c=i*4,m=o*4;l=[this._nodePositionsCPU[c+0],this._nodePositionsCPU[c+1],this._nodePositionsCPU[c+2]],u=[this._nodePositionsCPU[m+0],this._nodePositionsCPU[m+1],this._nodePositionsCPU[m+2]]}return{src:i,dst:o,scalar:a,color:s,srcPosition:l,dstPosition:u}}computeBoundsFromCPUData(){if(!this._nodePositionsCPU||this._nodeCount<=0)return;let e=this._nodePositionsCPU,t=e[0],r=e[1],i=e[2],o=e[0],a=e[1],s=e[2];for(let d=1;d<this._nodeCount;d++){let f=d*4,p=e[f+0],h=e[f+1],g=e[f+2];p<t&&(t=p),h<r&&(r=h),g<i&&(i=g),p>o&&(o=p),h>a&&(a=h),g>s&&(s=g)}let l=(t+o)*.5,u=(r+a)*.5,c=(i+s)*.5,m=0;for(let d=0;d<this._nodeCount;d++){let f=d*4,p=e[f+0]-l,h=e[f+1]-u,g=e[f+2]-c,b=Math.sqrt(p*p+h*h+g*g);b>m&&(m=b)}this.setBounds(et([t,r,i],[o,a,s]),"computed"),this.boundsCenter=[l,u,c],this.boundsRadius=m}getLocalBounds(){return this._boundsSource==="none"&&this._nodePositionsCPU&&this.computeBoundsFromCPUData(),this._boundsSource==="none"?kt(this._nodeCount>0):yt(this.boundsCenter,this.boundsRadius)}getWorldBounds(){return Mt(this.getLocalBounds(),this.transform.worldMatrix)}getBounds(){return this.getWorldBounds()}upload(e,t){let r=(o,a,s)=>{if(!s||!a)return o;if(!o)return ne(e,a,GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST);try{return t.writeBuffer(o,0,a.buffer,a.byteOffset,a.byteLength),o}catch{return o.destroy(),ne(e,a,GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST)}},i=(o,a,s)=>{if(!s||!a)return o;if(!o)return ne(e,a,GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST);try{return t.writeBuffer(o,0,a.buffer,a.byteOffset,a.byteLength),o}catch{return o.destroy(),ne(e,a,GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST)}};this._nodePositionsExternal||(this.nodePositionsBuffer=r(this.nodePositionsBuffer,this._nodePositionsCPU,this._nodePositionsDirty)),this._nodeScalarsExternal||(this.nodeScalarsBuffer=r(this.nodeScalarsBuffer,this._nodeScalarsCPU,this._nodeScalarsDirty)),this._nodeColorsExternal||(this.nodeColorsBuffer=r(this.nodeColorsBuffer,this._nodeColorsCPU,this._nodeColorsDirty)),this._nodeRadiiExternal||(this.nodeRadiiBuffer=r(this.nodeRadiiBuffer,this._nodeRadiiCPU,this._nodeRadiiDirty)),this._edgesExternal||(this.edgesBuffer=i(this.edgesBuffer,this._edgesCPU,this._edgesDirty)),this._edgeScalarsExternal||(this.edgeScalarsBuffer=r(this.edgeScalarsBuffer,this._edgeScalarsCPU,this._edgeScalarsDirty)),this._edgeColorsExternal||(this.edgeColorsBuffer=r(this.edgeColorsBuffer,this._edgeColorsCPU,this._edgeColorsDirty)),this.flushQueuedWrites(t),this._keepCPUData||this.dropCPUData(),this._nodePositionsDirty=!1,this._nodeScalarsDirty=!1,this._nodeColorsDirty=!1,this._nodeRadiiDirty=!1,this._edgesDirty=!1,this._edgeScalarsDirty=!1,this._edgeColorsDirty=!1,this.bindGroupKey=null}getUniformBufferSize(){return Nu}getUniformData(){let e=new Float32Array($a);e.fill(0),e[0]=Math.max(0,this._nodeSize),e[1]=Math.max(0,this._edgeSize),e[2]=le(this._opacity),e[3]=this._lit?1:0,je(this._nodeScaleTransform,e,4),e[24]=ui(this._nodeColorMode),e[25]=typeof this._nodeColormap=="string"&&this._nodeColormap==="custom"?Math.min(8,Math.max(2,this._nodeColormapStops.length)):0,e[26]=Ea(this._nodeGeometryMode),e[27]=this.nodeRadiiBuffer?1:0,je(this._edgeScaleTransform,e,28),e[48]=ui(this._edgeColorMode),e[49]=typeof this._edgeColormap=="string"&&this._edgeColormap==="custom"?Math.min(8,Math.max(2,this._edgeColormapStops.length)):0,e[50]=Wa(this._edgeGeometryMode),e[52]=this._nodeSolidColor[0],e[53]=this._nodeSolidColor[1],e[54]=this._nodeSolidColor[2],e[55]=this._nodeSolidColor[3],e[56]=this._edgeSolidColor[0],e[57]=this._edgeSolidColor[1],e[58]=this._edgeSolidColor[2],e[59]=this._edgeSolidColor[3],e[60]=this._minPointSize,e[61]=this._maxPointSize,e[62]=this._pointSizeAttenuation;let t=this._nodeColormapStops;for(let i=0;i<8;i++){let o=t[Math.min(i,Math.max(1,t.length-1))],a=64+i*4;e[a+0]=o[0],e[a+1]=o[1],e[a+2]=o[2],e[a+3]=o[3]}let r=this._edgeColormapStops;for(let i=0;i<8;i++){let o=r[Math.min(i,Math.max(1,r.length-1))],a=96+i*4;e[a+0]=o[0],e[a+1]=o[1],e[a+2]=o[2],e[a+3]=o[3]}return e}get dirtyUniforms(){return this._uniformDirty}markUniformsClean(){this._uniformDirty=!1}getNodeColormapKey(){let e=this._nodeColormap;return e instanceof $?`cm:${e.id}`:`cm:${e}`}getEdgeColormapKey(){let e=this._edgeColormap;return e instanceof $?`cm:${e.id}`:`cm:${e}`}getNodeColormapForBinding(){let e=this._nodeColormap;return e instanceof $?e:e==="custom"?$.builtin("grayscale"):$.builtin(e)}getEdgeColormapForBinding(){let e=this._edgeColormap;return e instanceof $?e:e==="custom"?$.builtin("grayscale"):$.builtin(e)}destroy(){this.nodePositionsBuffer?.destroy(),this.nodeScalarsBuffer?.destroy(),this.nodeColorsBuffer?.destroy(),this.nodeRadiiBuffer?.destroy(),this.edgesBuffer?.destroy(),this.edgeScalarsBuffer?.destroy(),this.edgeColorsBuffer?.destroy(),this.uniformBuffer?.destroy(),this.nodePositionsBuffer=null,this.nodeScalarsBuffer=null,this.nodeColorsBuffer=null,this.nodeRadiiBuffer=null,this.edgesBuffer=null,this.edgeScalarsBuffer=null,this.edgeColorsBuffer=null,this.uniformBuffer=null,this.bindGroup=null,this.bindGroupKey=null,this.dropCPUData(),this._pendingWrites.length=0,this._visualChangeListeners.clear(),this._ndShape=null,this._nodeCount=0,this._edgeCount=0,this.transform.dispose()}emitVisualChange(e){for(let t of this._visualChangeListeners)try{t(e)}catch{}}};var Ka="struct Params { rtMetrics: vec4f, threshold: f32, _pad0: f32, _pad1: f32, _pad2: f32 }; @group(0) @binding(0) var<uniform> params: Params; @group(0) @binding(1) var sampLinear: sampler; @group(0) @binding(2) var sampPoint: sampler; @group(0) @binding(3) var sceneTex: texture_2d<f32>; @group(0) @binding(4) var edgesTex: texture_2d<f32>; @group(0) @binding(5) var blendTex: texture_2d<f32>; struct VertexOutput { @builtin(position) pos: vec4f, @location(0) uv: vec2f }; @vertex fn vs_fullscreen(@builtin(vertex_index) vi: u32) -> VertexOutput { var positions = array<vec2f, 3>( vec2f(-1.0, -1.0), vec2f(3.0, -1.0), vec2f(-1.0, 3.0) ); var uvs = array<vec2f, 3>( vec2f(0.0, 1.0), vec2f(2.0, 1.0), vec2f(0.0, -1.0) ); var out: VertexOutput; out.pos = vec4f(positions[vi], 0.0, 1.0); out.uv = uvs[vi]; return out; } fn luma(rgb: vec3f) -> f32 { return dot(rgb, vec3f(0.2126, 0.7152, 0.0722)); } @fragment fn fs_smaa_edges(in: VertexOutput) -> @location(0) vec4f { let t = params.rtMetrics.xy; let c = textureSampleLevel(sceneTex, sampPoint, in.uv, 0.0).rgb; let l = luma(c); let lLeft = luma(textureSampleLevel(sceneTex, sampPoint, in.uv + vec2f(-t.x, 0.0), 0.0).rgb); let lTop = luma(textureSampleLevel(sceneTex, sampPoint, in.uv + vec2f(0.0, -t.y), 0.0).rgb); let dLeft = abs(l - lLeft); let dTop = abs(l - lTop); let eV = select(0.0, 1.0, dLeft >= params.threshold); let eH = select(0.0, 1.0, dTop >= params.threshold); return vec4f(eV, eH, 0.0, 0.0); } fn edgeV(uv: vec2f) -> bool { return textureSampleLevel(edgesTex, sampPoint, uv, 0.0).r > 0.5; } fn edgeH(uv: vec2f) -> bool { return textureSampleLevel(edgesTex, sampPoint, uv, 0.0).g > 0.5; } @fragment fn fs_smaa_weights(in: VertexOutput) -> @location(0) vec4f { let t = params.rtMetrics.xy; let e = textureSampleLevel(edgesTex, sampPoint, in.uv, 0.0); var wLeft: f32 = 0.0; var wTop: f32 = 0.0; if (e.r > 0.5) { var up: i32 = 0; var down: i32 = 0; for (var s: i32 = 1; s <= 8; s = s + 1) { if (!edgeV(in.uv + vec2f(0.0, -t.y * f32(s)))) { break; } up = up + 1; } for (var s: i32 = 1; s <= 8; s = s + 1) { if (!edgeV(in.uv + vec2f(0.0, t.y * f32(s)))) { break; } down = down + 1; } let len = f32(up + down + 1); wLeft = clamp(len / 17.0, 0.0, 1.0) * 0.5; } if (e.g > 0.5) { var left: i32 = 0; var right: i32 = 0; for (var s: i32 = 1; s <= 8; s = s + 1) { if (!edgeH(in.uv + vec2f(-t.x * f32(s), 0.0))) { break; } left = left + 1; } for (var s: i32 = 1; s <= 8; s = s + 1) { if (!edgeH(in.uv + vec2f(t.x * f32(s), 0.0))) { break; } right = right + 1; } let len = f32(left + right + 1); wTop = clamp(len / 17.0, 0.0, 1.0) * 0.5; } return vec4f(wLeft, wTop, 0.0, 0.0); } @fragment fn fs_smaa_neighborhood(in: VertexOutput) -> @location(0) vec4f { let t = params.rtMetrics.xy; let c = textureSampleLevel(sceneTex, sampLinear, in.uv, 0.0); let w = textureSampleLevel(blendTex, sampPoint, in.uv, 0.0); let wL = w.r; let wT = w.g; let wR = textureSampleLevel(blendTex, sampPoint, in.uv + vec2f(t.x, 0.0), 0.0).r; let wB = textureSampleLevel(blendTex, sampPoint, in.uv + vec2f(0.0, t.y), 0.0).g; var bestW: f32 = 0.0; var dir: i32 = -1; if (wL > bestW) { bestW = wL; dir = 0; } if (wR > bestW) { bestW = wR; dir = 1; } if (wT > bestW) { bestW = wT; dir = 2; } if (wB > bestW) { bestW = wB; dir = 3; } if (bestW <= 0.0) { return c; } var n: vec4f = c; if (dir == 0) { n = textureSampleLevel(sceneTex, sampLinear, in.uv + vec2f(-t.x, 0.0), 0.0); } else if (dir == 1) { n = textureSampleLevel(sceneTex, sampLinear, in.uv + vec2f(t.x, 0.0), 0.0); } else if (dir == 2) { n = textureSampleLevel(sceneTex, sampLinear, in.uv + vec2f(0.0, -t.y), 0.0); } else { n = textureSampleLevel(sceneTex, sampLinear, in.uv + vec2f(0.0, t.y), 0.0); } return mix(c, n, bestW); }";var mi="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct PointData { position: vec3f, scalar: f32 }; @group(1) @binding(0) var<storage, read> points: array<PointData>; @group(1) @binding(4) var<storage, read> pointColors: array<vec4f>; struct PointCloudUniforms { sizeParams: vec4f, scaleSource: vec4f, scaleDomain: vec4f, scaleClamp: vec4f, scaleParams: vec4f, scaleFlags: vec4f, visual: vec4f, colors: array<vec4f, 8> }; @group(1) @binding(1) var<uniform> pc: PointCloudUniforms; @group(1) @binding(2) var colormapSampler: sampler; @group(1) @binding(3) var colormapTex: texture_1d<f32>; struct VertexOutput { @builtin(position) position: vec4f, @location(0) col: vec4f, @location(1) pointCoord: vec2f, }; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3f, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; fn srgbFromLinear(linear: vec3f) -> vec3f { let a = 0.055; let lo = 12.92 * linear; let hi = (1.0 + a) * pow(linear, vec3f(1.0 / 2.4)) - vec3f(a); let useHi = linear > vec3f(0.0031308); return select(lo, hi, useHi); } fn sampleCustomStops(t: f32, stopCount: u32) -> vec4f { let n = min(stopCount, 8u); let x = scale_clamp01(t) * f32(n - 1u); let i = u32(floor(x)); let f = x - f32(i); if (i >= n - 1u) { return pc.colors[n - 1u]; } return pc.colors[i] + f * (pc.colors[i + 1u] - pc.colors[i]); } fn colormap(tIn: f32) -> vec4f { let t = scale_clamp01(tIn); let stopCount = u32(pc.visual.z + 0.5); if (stopCount >= 2u) { return sampleCustomStops(t, stopCount); } return textureSampleLevel(colormapTex, colormapSampler, t, 0.0); } fn vec4Component(v: vec4f, idx: u32) -> f32 { if (idx == 0u) { return v.x; } if (idx == 1u) { return v.y; } if (idx == 2u) { return v.z; } return v.w; } fn shiftedValueVector(v: vec4f, offsetFloats: f32) -> vec4f { let o = min(3u, u32(offsetFloats + 0.5)); let i0 = min(3u, o + 0u); let i1 = min(3u, o + 1u); let i2 = min(3u, o + 2u); let i3 = min(3u, o + 3u); return vec4f(vec4Component(v, i0), vec4Component(v, i1), vec4Component(v, i2), vec4Component(v, i3)); } @vertex fn vs_main(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> VertexOutput { let p = points[instanceIndex]; let worldPos = model.model * vec4f(p.position, 1.0); let clip = camera.viewProj * worldPos; let baseSize = pc.sizeParams.x; let minSize = pc.sizeParams.y; let maxSize = pc.sizeParams.z; let atten = pc.sizeParams.w; var sizePx = baseSize; if (atten > 0.0) { let dist = distance(camera.position, worldPos.xyz); sizePx = baseSize * (atten / max(dist, 1e-6)); } sizePx = clamp(sizePx, minSize, maxSize); let uv = vec2f( f32((vertexIndex + 2u) / 3u % 2u), f32((vertexIndex + 1u) / 3u % 2u) ); let row0 = vec3f(camera.viewProj[0][0], camera.viewProj[1][0], camera.viewProj[2][0]); let row1 = vec3f(camera.viewProj[0][1], camera.viewProj[1][1], camera.viewProj[2][1]); let aspect = length(row1) / max(length(row0), 1e-6); let ndcSize = (sizePx * 2.0) / max(camera._pad0, 1.0); let offsetX = (uv.x - 0.5) * ndcSize / aspect * clip.w; let offsetY = -(uv.y - 0.5) * ndcSize * clip.w; let colorMode = u32(pc.visual.w + 0.5); var c: vec4f; if (colorMode == 0u) { c = pointColors[instanceIndex]; } else { let rawVec = shiftedValueVector(vec4f(p.position, p.scalar), pc.scaleDomain.z); let componentCount = u32(pc.scaleSource.x + 0.5); let componentIndex = u32(pc.scaleSource.y + 0.5); let valueMode = u32(pc.scaleSource.z + 0.5); let rawValue = scale_select_value(rawVec, componentCount, componentIndex, valueMode); let finiteRaw = scale_is_finite(rawValue); var t = scale_apply_transform(rawValue, vec4f(pc.scaleDomain.x, pc.scaleDomain.y, 0.0, pc.scaleDomain.w), pc.scaleClamp, pc.scaleParams, pc.scaleFlags); c = colormap(t); if (!finiteRaw) { c = vec4f(0.0, 0.0, 0.0, 0.0); } } let alpha = scale_clamp01(c.a) * scale_clamp01(pc.visual.x); var out: VertexOutput; out.position = clip + vec4f(offsetX, offsetY, 0.0, 0.0); out.pointCoord = uv * 2.0 - vec2f(1.0, 1.0); out.col = vec4f(srgbFromLinear(max(c.rgb, vec3f(0.0))), alpha); return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let uv = in.pointCoord; let r2 = dot(uv, uv); if (r2 > 1.0) { discard; } let falloff = (1.0 - r2); let alpha = falloff * falloff; return vec4f(in.col.rgb, in.col.a * alpha); }";var Xa="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } @group(1) @binding(0) var<storage, read> positions: array<vec4f>; @group(1) @binding(1) var<storage, read> rotations: array<vec4f>; @group(1) @binding(2) var<storage, read> scales: array<vec4f>; @group(1) @binding(3) var<storage, read> attributes: array<vec4f>; struct GlyphFieldUniforms { scaleSource: vec4f, scaleDomain: vec4f, scaleClamp: vec4f, scaleParams: vec4f, scaleFlags: vec4f, visual: vec4f, solidColor: vec4f, colors: array<vec4f, 8> }; @group(1) @binding(4) var<uniform> glyph: GlyphFieldUniforms; @group(1) @binding(5) var colormapSampler: sampler; @group(1) @binding(6) var colormapTex: texture_1d<f32>; struct VertexInput { @location(0) position: vec3f, @location(1) normal: vec3f }; struct VertexOutput { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) @interpolate(flat) attrib: vec4f }; struct CameraUniforms { viewProj: mat4x4f, position: vec3f, _pad0: f32 }; struct ModelUniforms { model: mat4x4f, normal: mat4x4f }; struct Light { position: vec4f, color: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; fn srgbFromLinear(linear: vec3f) -> vec3f { let a = 0.055; let lo = 12.92 * linear; let hi = (1.0 + a) * pow(linear, vec3f(1.0 / 2.4)) - vec3f(a); let useHi = linear > vec3f(0.0031308); return select(lo, hi, useHi); } fn rotateByQuat(v: vec3f, q: vec4f) -> vec3f { let u = q.xyz; let s = q.w; let t = 2.0 * cross(u, v); return v + s * t + cross(u, t); } fn sampleCustomStops(t: f32) -> vec4f { let count = u32(glyph.visual.y + 0.5); if (count <= 1u) { return glyph.colors[0u]; } let n = min(count, 8u); let x = scale_clamp01(t) * f32(n - 1u); let i = u32(floor(x)); let f = x - f32(i); if (i >= n - 1u) { return glyph.colors[n - 1u]; } return glyph.colors[i] + f * (glyph.colors[i + 1u] - glyph.colors[i]); } fn colormap(tIn: f32) -> vec4f { let t = scale_clamp01(tIn); let stopCount = u32(glyph.visual.y + 0.5); if (stopCount >= 2u) { return sampleCustomStops(t); } return textureSample(colormapTex, colormapSampler, t); } fn applyLighting(worldPos: vec3f, N: vec3f, baseColor: vec3f) -> vec3f { var Lo = lighting.ambient.rgb * baseColor; let lightCount = min(lighting.lightCount, 8u); for (var i = 0u; i < lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - worldPos; let distance = length(lightDir); L = select(vec3f(0.0, 1.0, 0.0), lightDir / distance, distance > 1e-6); attenuation = 1.0 / max(distance * distance, 1e-6); let range = light.params.x; if (range > 0.0) { let f = scale_clamp01(1.0 - distance / range); attenuation *= f * f; } } let NdotL = max(dot(N, L), 0.0); let radiance = light.color.rgb * light.color.a * attenuation; Lo += baseColor * radiance * NdotL; } return Lo; } fn vec4Component(v: vec4f, idx: u32) -> f32 { if (idx == 0u) { return v.x; } if (idx == 1u) { return v.y; } if (idx == 2u) { return v.z; } return v.w; } fn shiftedValueVector(v: vec4f, offsetFloats: f32) -> vec4f { let o = min(3u, u32(offsetFloats + 0.5)); let i0 = min(3u, o + 0u); let i1 = min(3u, o + 1u); let i2 = min(3u, o + 2u); let i3 = min(3u, o + 3u); return vec4f(vec4Component(v, i0), vec4Component(v, i1), vec4Component(v, i2), vec4Component(v, i3)); } @vertex fn vs_main(in: VertexInput, @builtin(instance_index) instanceIndex: u32) -> VertexOutput { let p4 = positions[instanceIndex]; let q = rotations[instanceIndex]; let s4 = scales[instanceIndex]; let a4 = attributes[instanceIndex]; let scl = s4.xyz; let localPos = rotateByQuat(in.position * scl, q) + p4.xyz; let worldPos4 = model.model * vec4f(localPos, 1.0); let worldPos = worldPos4.xyz; let invScale = 1.0 / max(abs(scl), vec3f(1e-6)); let localN = in.normal * invScale; let instN = rotateByQuat(localN, q); let worldN = normalize((model.normal * vec4f(instN, 0.0)).xyz); var out: VertexOutput; out.position = camera.viewProj * vec4f(worldPos, 1.0); out.worldPos = worldPos; out.normal = worldN; out.attrib = a4; return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { let colorMode = u32(round(glyph.visual.z)); let lit = glyph.visual.w > 0.5; var baseColor: vec3f; var alpha: f32 = 1.0; if (colorMode == 0u) { baseColor = in.attrib.rgb; alpha = in.attrib.a; } else if (colorMode == 1u) { let shifted = shiftedValueVector(in.attrib, glyph.scaleDomain.z); let componentCount = u32(glyph.scaleSource.x + 0.5); let componentIndex = u32(glyph.scaleSource.y + 0.5); let valueMode = u32(glyph.scaleSource.z + 0.5); let rawValue = scale_select_value(shifted, componentCount, componentIndex, valueMode); if (!scale_is_finite(rawValue)) { discard; } let t = scale_apply_transform(rawValue, vec4f(glyph.scaleDomain.x, glyph.scaleDomain.y, 0.0, glyph.scaleDomain.w), glyph.scaleClamp, glyph.scaleParams, glyph.scaleFlags); let cmap = colormap(t); baseColor = cmap.rgb; alpha = cmap.a; } else { baseColor = glyph.solidColor.rgb; alpha = glyph.solidColor.a; } baseColor = max(baseColor, vec3f(0.0)); alpha = scale_clamp01(alpha) * scale_clamp01(glyph.visual.x); var shaded = baseColor; if (lit) { shaded = applyLighting(in.worldPos, normalize(in.normal), baseColor); } return vec4f(srgbFromLinear(shaded), alpha); }";var di="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct CameraUniforms { viewProj: mat4x4f, position: vec3f, _pad0: f32 }; struct ModelUniforms { model: mat4x4f, normal: mat4x4f }; struct Light { position: vec4f, color: vec4f, params: vec4f }; struct LightingUniforms { ambient: vec4f, lightCount: u32, _pad0: u32, _pad1: u32, _pad2: u32, lights: array<Light, 8> }; struct NodeLinkUniforms { global: vec4f, nodeScaleSource: vec4f, nodeScaleDomain: vec4f, nodeScaleClamp: vec4f, nodeScaleParams: vec4f, nodeScaleFlags: vec4f, nodeVisual: vec4f, edgeScaleSource: vec4f, edgeScaleDomain: vec4f, edgeScaleClamp: vec4f, edgeScaleParams: vec4f, edgeScaleFlags: vec4f, edgeVisual: vec4f, nodeSolid: vec4f, edgeSolid: vec4f, pointParams: vec4f, nodeStops: array<vec4f, 8>, edgeStops: array<vec4f, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(0) @binding(2) var<uniform> lighting: LightingUniforms; @group(1) @binding(0) var<storage, read> nodePositions: array<vec4f>; @group(1) @binding(1) var<storage, read> nodeScalars: array<f32>; @group(1) @binding(2) var<storage, read> nodeColors: array<vec4f>; @group(1) @binding(3) var<storage, read> nodeRadii: array<vec4f>; @group(1) @binding(4) var<storage, read> edges: array<vec2u>; @group(1) @binding(5) var<storage, read> edgeScalars: array<f32>; @group(1) @binding(6) var<storage, read> edgeColors: array<vec4f>; @group(1) @binding(7) var<uniform> nl: NodeLinkUniforms; @group(1) @binding(8) var nodeColormapSampler: sampler; @group(1) @binding(9) var nodeColormapTex: texture_1d<f32>; @group(1) @binding(10) var edgeColormapSampler: sampler; @group(1) @binding(11) var edgeColormapTex: texture_1d<f32>; fn srgbFromLinear(linear: vec3f) -> vec3f { let a = 0.055; let lo = 12.92 * linear; let hi = (1.0 + a) * pow(linear, vec3f(1.0 / 2.4)) - vec3f(a); let useHi = linear > vec3f(0.0031308); return select(lo, hi, useHi); } fn sampleCustomStops(tIn: f32, stops: array<vec4f, 8>, stopCountIn: u32) -> vec4f { let n = min(8u, max(2u, stopCountIn)); let x = scale_clamp01(tIn) * f32(n - 1u); let i = u32(floor(x)); let f = x - f32(i); if (i >= n - 1u) { return stops[n - 1u]; } return stops[i] + f * (stops[i + 1u] - stops[i]); } fn sampleNodeColormap(t: f32) -> vec4f { let stopCount = u32(nl.nodeVisual.y + 0.5); if (stopCount >= 2u) { return sampleCustomStops(t, nl.nodeStops, stopCount); } return textureSampleLevel(nodeColormapTex, nodeColormapSampler, scale_clamp01(t), 0.0); } fn sampleEdgeColormap(t: f32) -> vec4f { let stopCount = u32(nl.edgeVisual.y + 0.5); if (stopCount >= 2u) { return sampleCustomStops(t, nl.edgeStops, stopCount); } return textureSampleLevel(edgeColormapTex, edgeColormapSampler, scale_clamp01(t), 0.0); } fn nodeColor(index: u32) -> vec4f { let mode = u32(round(nl.nodeVisual.x)); if (mode == 0u) { return nodeColors[index]; } if (mode == 1u) { let rawValue = nodeScalars[index]; if (!scale_is_finite(rawValue)) { return vec4f(0.0, 0.0, 0.0, 0.0); } let t = scale_apply_transform(rawValue, vec4f(nl.nodeScaleDomain.x, nl.nodeScaleDomain.y, 0.0, nl.nodeScaleDomain.w), nl.nodeScaleClamp, nl.nodeScaleParams, nl.nodeScaleFlags); return sampleNodeColormap(t); } return nl.nodeSolid; } fn edgeColor(index: u32) -> vec4f { let mode = u32(round(nl.edgeVisual.x)); if (mode == 0u) { return edgeColors[index]; } if (mode == 1u) { let rawValue = edgeScalars[index]; if (!scale_is_finite(rawValue)) { return vec4f(0.0, 0.0, 0.0, 0.0); } let t = scale_apply_transform(rawValue, vec4f(nl.edgeScaleDomain.x, nl.edgeScaleDomain.y, 0.0, nl.edgeScaleDomain.w), nl.edgeScaleClamp, nl.edgeScaleParams, nl.edgeScaleFlags); return sampleEdgeColormap(t); } return nl.edgeSolid; } fn applyLighting(worldPos: vec3f, N: vec3f, baseColor: vec3f) -> vec3f { var Lo = lighting.ambient.rgb * baseColor; let lightCount = min(lighting.lightCount, 8u); for (var i = 0u; i < lightCount; i++) { let light = lighting.lights[i]; var L: vec3f; var attenuation: f32 = 1.0; if (light.position.w == 0.0) { L = normalize(-light.position.xyz); } else { let lightDir = light.position.xyz - worldPos; let distance = length(lightDir); L = select(vec3f(0.0, 1.0, 0.0), lightDir / distance, distance > 1e-6); attenuation = 1.0 / max(distance * distance, 1e-6); let range = light.params.x; if (range > 0.0) { let f = scale_clamp01(1.0 - distance / range); attenuation *= f * f; } } let NdotL = max(dot(N, L), 0.0); let radiance = light.color.rgb * light.color.a * attenuation; Lo += baseColor * radiance * NdotL; } return Lo; } fn buildEdgeFrame(src: vec3f, dst: vec3f) -> mat3x3f { let yAxis = normalize(dst - src); var z = vec3f(0.0, 0.0, 1.0); if (abs(dot(z, yAxis)) > 0.99) { z = vec3f(1.0, 0.0, 0.0); } let xAxis = normalize(cross(z, yAxis)); let zAxis = normalize(cross(yAxis, xAxis)); return mat3x3f(xAxis, yAxis, zAxis); } struct NodeVertexOut { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) @interpolate(flat) nodeIndex: u32, @location(3) pointCoord: vec2f, @location(4) @interpolate(flat) isPoint: f32 }; struct EdgeVertexOut { @builtin(position) position: vec4f, @location(0) worldPos: vec3f, @location(1) normal: vec3f, @location(2) @interpolate(flat) edgeIndex: u32, @location(3) @interpolate(flat) litEnabled: f32 }; @vertex fn vs_node_points(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> NodeVertexOut { let p = nodePositions[instanceIndex].xyz; let worldPos4 = model.model * vec4f(p, 1.0); let clip = camera.viewProj * worldPos4; let baseSize = nl.global.x; let minSize = nl.pointParams.x; let maxSize = nl.pointParams.y; let atten = nl.pointParams.z; var sizePx = baseSize; if (atten > 0.0) { let dist = distance(camera.position, worldPos4.xyz); sizePx = baseSize * (atten / max(dist, 1e-6)); } sizePx = clamp(sizePx, minSize, maxSize); let uv = vec2f(f32((vertexIndex + 2u) / 3u % 2u), f32((vertexIndex + 1u) / 3u % 2u)); let row0 = vec3f(camera.viewProj[0][0], camera.viewProj[1][0], camera.viewProj[2][0]); let row1 = vec3f(camera.viewProj[0][1], camera.viewProj[1][1], camera.viewProj[2][1]); let aspect = length(row1) / max(length(row0), 1e-6); let ndcSize = (sizePx * 2.0) / max(camera._pad0, 1.0); let offsetX = (uv.x - 0.5) * ndcSize / aspect * clip.w; let offsetY = -(uv.y - 0.5) * ndcSize * clip.w; var out: NodeVertexOut; out.position = clip + vec4f(offsetX, offsetY, 0.0, 0.0); out.worldPos = worldPos4.xyz; out.normal = vec3f(0.0, 0.0, 1.0); out.nodeIndex = instanceIndex; out.pointCoord = uv * 2.0 - vec2f(1.0, 1.0); out.isPoint = 1.0; return out; } @vertex fn vs_node_solid(@location(0) position: vec3f, @location(1) normal: vec3f, @builtin(instance_index) instanceIndex: u32) -> NodeVertexOut { let center = nodePositions[instanceIndex].xyz; let mode = u32(round(nl.nodeVisual.z)); let useRadii = nl.nodeVisual.w > 0.5; var scaleVec = vec3f(max(nl.global.x, 1e-6)); if (useRadii) { let rv = max(nodeRadii[instanceIndex].xyz, vec3f(1e-6)); if (mode == 2u) { scaleVec = rv * max(nl.global.x, 1e-6); } else { scaleVec = vec3f(rv.x * max(nl.global.x, 1e-6)); } } let objPos = center + (position * scaleVec); let worldPos4 = model.model * vec4f(objPos, 1.0); let localN = normalize(normal / scaleVec); let worldN = normalize((model.normal * vec4f(localN, 0.0)).xyz); var out: NodeVertexOut; out.position = camera.viewProj * worldPos4; out.worldPos = worldPos4.xyz; out.normal = worldN; out.nodeIndex = instanceIndex; out.pointCoord = vec2f(0.0, 0.0); out.isPoint = 0.0; return out; } @vertex fn vs_edge_lines(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> EdgeVertexOut { let edge = edges[instanceIndex]; let src = nodePositions[edge.x].xyz; let dst = nodePositions[edge.y].xyz; let objPos = select(src, dst, (vertexIndex & 1u) == 1u); let worldPos4 = model.model * vec4f(objPos, 1.0); var out: EdgeVertexOut; out.position = camera.viewProj * worldPos4; out.worldPos = worldPos4.xyz; out.normal = vec3f(0.0, 1.0, 0.0); out.edgeIndex = instanceIndex; out.litEnabled = 0.0; return out; } @vertex fn vs_edge_cylinders(@location(0) position: vec3f, @location(1) normal: vec3f, @builtin(instance_index) instanceIndex: u32) -> EdgeVertexOut { let edge = edges[instanceIndex]; let src = nodePositions[edge.x].xyz; let dst = nodePositions[edge.y].xyz; let seg = dst - src; let segLen = max(length(seg), 1e-6); let basis = buildEdgeFrame(src, dst); let radius = max(nl.global.y, 1e-6); let local = vec3f(position.x * radius, position.y * segLen, position.z * radius); let objPos = ((src + dst) * 0.5) + (basis * local); let worldPos4 = model.model * vec4f(objPos, 1.0); let localN = normalize(basis * vec3f(normal.x, 0.0, normal.z)); let worldN = normalize((model.normal * vec4f(localN, 0.0)).xyz); var out: EdgeVertexOut; out.position = camera.viewProj * worldPos4; out.worldPos = worldPos4.xyz; out.normal = worldN; out.edgeIndex = instanceIndex; out.litEnabled = 1.0; return out; } @fragment fn fs_node(in: NodeVertexOut) -> @location(0) vec4f { var c = nodeColor(in.nodeIndex); if (in.isPoint > 0.5) { let r2 = dot(in.pointCoord, in.pointCoord); if (r2 > 1.0) { discard; } let falloff = (1.0 - r2); c = vec4f(c.rgb, c.a * (falloff * falloff)); } else if (nl.global.w > 0.5) { let litRgb = applyLighting(in.worldPos, normalize(in.normal), max(c.rgb, vec3f(0.0))); c = vec4f(litRgb, c.a); } c = vec4f(c.rgb, c.a * scale_clamp01(nl.global.z)); return vec4f(srgbFromLinear(max(c.rgb, vec3f(0.0))), c.a); } @fragment fn fs_edge(in: EdgeVertexOut) -> @location(0) vec4f { var c = edgeColor(in.edgeIndex); if (nl.global.w > 0.5 && in.litEnabled > 0.5) { let litRgb = applyLighting(in.worldPos, normalize(in.normal), max(c.rgb, vec3f(0.0))); c = vec4f(litRgb, c.a); } c = vec4f(c.rgb, c.a * scale_clamp01(nl.global.z)); return vec4f(srgbFromLinear(max(c.rgb, vec3f(0.0))), c.a); }";var Ya="enable primitive_index; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<uniform> pick: PickUniforms; struct VertexOutput { @builtin(position) position: vec4<f32> }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; @vertex fn vs_main(@location(0) position: vec3<f32>) -> VertexOutput { var out: VertexOutput; out.position = camera.viewProj * model.model * vec4<f32>(position, 1.0); return out; } @fragment fn fs_main(@builtin(position) fragCoord: vec4<f32>, @builtin(primitive_index) primitiveIndex: u32) -> FragmentOutput { var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + primitiveIndex); out.depth = fragCoord.z; return out; }";var Za="enable primitive_index; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; struct SkinBuffer { joints: array<mat4x4<f32>> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<uniform> pick: PickUniforms; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; struct VertexOutput { @builtin(position) position: vec4<f32> }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; @vertex fn vs_main(@location(0) position: vec3<f32>, @location(3) joints: vec4<u32>, @location(4) weights: vec4<f32> ) -> VertexOutput { var out: VertexOutput; let m = skin.joints[joints.x] * weights.x + skin.joints[joints.y] * weights.y + skin.joints[joints.z] * weights.z + skin.joints[joints.w] * weights.w; let localPos = m * vec4<f32>(position, 1.0); out.position = camera.viewProj * model.model * localPos; return out; } @fragment fn fs_main(@builtin(position) fragCoord: vec4<f32>, @builtin(primitive_index) primitiveIndex: u32) -> FragmentOutput { var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + primitiveIndex); out.depth = fragCoord.z; return out; }";var Qa="enable primitive_index; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; struct SkinBuffer { joints: array<mat4x4<f32>> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<uniform> pick: PickUniforms; @group(2) @binding(0) var<storage, read> skin: SkinBuffer; struct VertexOutput { @builtin(position) position: vec4<f32> }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; @vertex fn vs_main(@location(0) position: vec3<f32>, @location(3) joints0: vec4<u32>, @location(4) weights0: vec4<f32>, @location(5) joints1: vec4<u32>, @location(6) weights1: vec4<f32>) -> VertexOutput { var out: VertexOutput; let m = skin.joints[joints0.x] * weights0.x + skin.joints[joints0.y] * weights0.y + skin.joints[joints0.z] * weights0.z + skin.joints[joints0.w] * weights0.w + skin.joints[joints1.x] * weights1.x + skin.joints[joints1.y] * weights1.y + skin.joints[joints1.z] * weights1.z + skin.joints[joints1.w] * weights1.w; let localPos = m * vec4<f32>(position, 1.0); out.position = camera.viewProj * model.model * localPos; return out; } @fragment fn fs_main(@builtin(position) fragCoord: vec4<f32>, @builtin(primitive_index) primitiveIndex: u32) -> FragmentOutput { var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + primitiveIndex); out.depth = fragCoord.z; return out; }";var fi="struct PointData { position: vec3<f32>, scalar: f32 }; struct PointCloudUniforms { sizeParams: vec4<f32>, scalarParams: vec4<f32>, options: vec4<f32>, colors: array<vec4<f32>, 8> }; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<storage, read> points: array<PointData>; @group(1) @binding(1) var<uniform> pc: PointCloudUniforms; @group(2) @binding(0) var<uniform> pick: PickUniforms; struct VertexOutput { @builtin(position) position: vec4<f32>, @location(0) pointCoord: vec2<f32>, @location(1) @interpolate(flat) pointIndex: u32 }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; @vertex fn vs_main(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> VertexOutput { let p = points[instanceIndex]; let worldPos = model.model * vec4<f32>(p.position, 1.0); let clip = camera.viewProj * worldPos; let dist = distance(camera.position, worldPos.xyz); let baseSize = pc.sizeParams.x; let minSize = pc.sizeParams.y; let maxSize = pc.sizeParams.z; let atten = pc.sizeParams.w; var sizePx = baseSize; if (atten > 0.0) { sizePx = baseSize * (atten / max(dist, 1e-6)); } sizePx = clamp(sizePx, minSize, maxSize); var uv = vec2<f32>(0.0); if (vertexIndex == 0u) { uv = vec2<f32>(0.0, 0.0); } else if (vertexIndex == 1u) { uv = vec2<f32>(1.0, 0.0); } else if (vertexIndex == 2u) { uv = vec2<f32>(0.0, 1.0); } else if (vertexIndex == 3u) { uv = vec2<f32>(1.0, 0.0); } else if (vertexIndex == 4u) { uv = vec2<f32>(1.0, 1.0); } else if (vertexIndex == 5u) { uv = vec2<f32>(0.0, 1.0); } let row0 = vec3<f32>(camera.viewProj[0][0], camera.viewProj[1][0], camera.viewProj[2][0]); let row1 = vec3<f32>(camera.viewProj[0][1], camera.viewProj[1][1], camera.viewProj[2][1]); let aspect = length(row1) / max(length(row0), 1e-6); let ndcSize = (sizePx * 2.0) / max(camera._pad0, 1.0); let offsetX = (uv.x - 0.5) * ndcSize / aspect * clip.w; let offsetY = -(uv.y - 0.5) * ndcSize * clip.w; var out: VertexOutput; out.position = clip + vec4<f32>(offsetX, offsetY, 0.0, 0.0); out.pointCoord = uv; out.pointIndex = instanceIndex; return out; } @fragment fn fs_main(in: VertexOutput) -> FragmentOutput { let uv = in.pointCoord * 2.0 - vec2<f32>(1.0, 1.0); let r2 = dot(uv, uv); if (r2 > 1.0) { discard; } var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + in.pointIndex); out.depth = in.position.z; return out; }";var pi="@group(1) @binding(0) var<storage, read> positions: array<vec4<f32>>; @group(1) @binding(1) var<storage, read> rotations: array<vec4<f32>>; @group(1) @binding(2) var<storage, read> scales: array<vec4<f32>>; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(2) @binding(0) var<uniform> pick: PickUniforms; struct VertexInput { @location(0) position: vec3<f32> }; struct VertexOutput { @builtin(position) position: vec4<f32>, @location(0) @interpolate(flat) instanceIndex: u32 }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; fn rotateByQuat(v: vec3<f32>, q: vec4<f32>) -> vec3<f32> { let u = q.xyz; let s = q.w; let t = 2.0 * cross(u, v); return v + s * t + cross(u, t); } @vertex fn vs_main(in: VertexInput, @builtin(instance_index) instanceIndex: u32) -> VertexOutput { let p4 = positions[instanceIndex]; let q = rotations[instanceIndex]; let s4 = scales[instanceIndex]; let localPos = rotateByQuat(in.position * s4.xyz, q) + p4.xyz; let worldPos = model.model * vec4<f32>(localPos, 1.0); var out: VertexOutput; out.position = camera.viewProj * worldPos; out.instanceIndex = instanceIndex; return out; } @fragment fn fs_main(in: VertexOutput) -> FragmentOutput { var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + in.instanceIndex); out.depth = in.position.z; return out; }";var hi="struct CameraUniforms { viewProj: mat4x4f, position: vec3f, _pad0: f32 }; struct ModelUniforms { model: mat4x4f, normal: mat4x4f }; struct PickUniforms { objectId: u32, elementBase: u32, _pad0: u32, _pad1: u32 }; struct NodeLinkUniforms { global: vec4f, nodeScaleSource: vec4f, nodeScaleDomain: vec4f, nodeScaleClamp: vec4f, nodeScaleParams: vec4f, nodeScaleFlags: vec4f, nodeVisual: vec4f, edgeScaleSource: vec4f, edgeScaleDomain: vec4f, edgeScaleClamp: vec4f, edgeScaleParams: vec4f, edgeScaleFlags: vec4f, edgeVisual: vec4f, nodeSolid: vec4f, edgeSolid: vec4f, pointParams: vec4f, nodeStops: array<vec4f, 8>, edgeStops: array<vec4f, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<storage, read> nodePositions: array<vec4f>; @group(1) @binding(3) var<storage, read> nodeRadii: array<vec4f>; @group(1) @binding(4) var<storage, read> edges: array<vec2u>; @group(1) @binding(7) var<uniform> nl: NodeLinkUniforms; @group(2) @binding(0) var<uniform> pick: PickUniforms; struct PickOut { @builtin(position) position: vec4f, @location(0) @interpolate(flat) index: u32, @location(1) pointCoord: vec2f, @location(2) @interpolate(flat) isPoint: f32 }; struct FragmentOutput { @location(0) id: vec2<u32>, @location(1) depth: f32 }; fn buildEdgeFrame(src: vec3f, dst: vec3f) -> mat3x3f { let yAxis = normalize(dst - src); var fallbackAxis = vec3f(0.0, 0.0, 1.0); if (abs(dot(fallbackAxis, yAxis)) > 0.99) { fallbackAxis = vec3f(1.0, 0.0, 0.0); } let xAxis = normalize(cross(fallbackAxis, yAxis)); let zAxis = normalize(cross(yAxis, xAxis)); return mat3x3f(xAxis, yAxis, zAxis); } @vertex fn vs_pick_node_points(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> PickOut { let p = nodePositions[instanceIndex].xyz; let worldPos4 = model.model * vec4f(p, 1.0); let clip = camera.viewProj * worldPos4; let baseSize = nl.global.x; let minSize = nl.pointParams.x; let maxSize = nl.pointParams.y; let atten = nl.pointParams.z; var sizePx = baseSize; if (atten > 0.0) { let dist = distance(camera.position, worldPos4.xyz); sizePx = baseSize * (atten / max(dist, 1e-6)); } sizePx = clamp(sizePx, minSize, maxSize); let uv = vec2f(f32((vertexIndex + 2u) / 3u % 2u), f32((vertexIndex + 1u) / 3u % 2u)); let row0 = vec3f(camera.viewProj[0][0], camera.viewProj[1][0], camera.viewProj[2][0]); let row1 = vec3f(camera.viewProj[0][1], camera.viewProj[1][1], camera.viewProj[2][1]); let aspect = length(row1) / max(length(row0), 1e-6); let ndcSize = (sizePx * 2.0) / max(camera._pad0, 1.0); let offsetX = (uv.x - 0.5) * ndcSize / aspect * clip.w; let offsetY = -(uv.y - 0.5) * ndcSize * clip.w; var out: PickOut; out.position = clip + vec4f(offsetX, offsetY, 0.0, 0.0); out.index = instanceIndex; out.pointCoord = uv * 2.0 - vec2f(1.0, 1.0); out.isPoint = 1.0; return out; } @vertex fn vs_pick_node_solid(@location(0) position: vec3f, @builtin(instance_index) instanceIndex: u32) -> PickOut { let center = nodePositions[instanceIndex].xyz; let mode = u32(round(nl.nodeVisual.z)); let useRadii = nl.nodeVisual.w > 0.5; var scaleVec = vec3f(max(nl.global.x, 1e-6)); if (useRadii) { let rv = max(nodeRadii[instanceIndex].xyz, vec3f(1e-6)); if (mode == 2u) { scaleVec = rv * max(nl.global.x, 1e-6); } else { scaleVec = vec3f(rv.x * max(nl.global.x, 1e-6)); } } let objPos = center + (position * scaleVec); let worldPos4 = model.model * vec4f(objPos, 1.0); var out: PickOut; out.position = camera.viewProj * worldPos4; out.index = instanceIndex; out.pointCoord = vec2f(0.0, 0.0); out.isPoint = 0.0; return out; } @vertex fn vs_pick_edge_lines(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> PickOut { let edge = edges[instanceIndex]; let src = nodePositions[edge.x].xyz; let dst = nodePositions[edge.y].xyz; let objPos = select(src, dst, (vertexIndex & 1u) == 1u); let worldPos4 = model.model * vec4f(objPos, 1.0); var out: PickOut; out.position = camera.viewProj * worldPos4; out.index = instanceIndex; out.pointCoord = vec2f(0.0, 0.0); out.isPoint = 0.0; return out; } @vertex fn vs_pick_edge_cylinders(@location(0) position: vec3f, @builtin(instance_index) instanceIndex: u32) -> PickOut { let edge = edges[instanceIndex]; let src = nodePositions[edge.x].xyz; let dst = nodePositions[edge.y].xyz; let seg = dst - src; let segLen = max(length(seg), 1e-6); let basis = buildEdgeFrame(src, dst); let radius = max(nl.global.y, 1e-6); let local = vec3f(position.x * radius, position.y * segLen, position.z * radius); let objPos = ((src + dst) * 0.5) + (basis * local); let worldPos4 = model.model * vec4f(objPos, 1.0); var out: PickOut; out.position = camera.viewProj * worldPos4; out.index = instanceIndex; out.pointCoord = vec2f(0.0, 0.0); out.isPoint = 0.0; return out; } @fragment fn fs_pick(in: PickOut) -> FragmentOutput { if (in.isPoint > 0.5) { let r2 = dot(in.pointCoord, in.pointCoord); if (r2 > 1.0) { discard; } } var out: FragmentOutput; out.id = vec2<u32>(pick.objectId, pick.elementBase + in.index); out.depth = in.position.z; return out; }";var gi="struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; struct VertexOutput { @builtin(position) position: vec4<f32> }; @vertex fn vs_main(@location(0) position: vec3<f32>) -> VertexOutput { var out: VertexOutput; out.position = camera.viewProj * model.model * vec4<f32>(position, 1.0); return out; } @fragment fn fs_main(@builtin(position) fragCoord: vec4<f32>) -> @location(0) f32 { return fragCoord.z; }";var bi="@group(0) @binding(0) var srcTex: texture_2d<f32>; struct VSOut { @builtin(position) pos: vec4f }; @vertex fn vs_main(@builtin(vertex_index) idx: u32) -> VSOut { var positions = array<vec2f, 3>( vec2f(-1.0, -1.0), vec2f(3.0, -1.0), vec2f(-1.0, 3.0) ); var out: VSOut; out.pos = vec4f(positions[idx], 0.0, 1.0); return out; } @fragment fn fs_main(@builtin(position) fragCoord: vec4f) -> @location(0) f32 { let srcSize = textureDimensions(srcTex); let dstCoord = vec2i(i32(fragCoord.x), i32(fragCoord.y)); let base = dstCoord * 2; let x1 = min(base.x + 1, i32(srcSize.x) - 1); let y1 = min(base.y + 1, i32(srcSize.y) - 1); let d00 = textureLoad(srcTex, base, 0).x; let d10 = textureLoad(srcTex, vec2i(x1, base.y), 0).x; let d01 = textureLoad(srcTex, vec2i(base.x, y1), 0).x; let d11 = textureLoad(srcTex, vec2i(x1, y1), 0).x; return max(max(d00, d10), max(d01, d11)); }";var vi="struct PointData { position: vec3<f32>, scalar: f32 }; struct PointCloudUniforms { sizeParams: vec4<f32>, scalarParams: vec4<f32>, options: vec4<f32>, colors: array<vec4<f32>, 8> }; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<storage, read> points: array<PointData>; @group(1) @binding(1) var<uniform> pc: PointCloudUniforms; struct VertexOutput { @builtin(position) position: vec4<f32>, @location(0) pointCoord: vec2<f32> }; @vertex fn vs_main(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> VertexOutput { let p = points[instanceIndex]; let worldPos = model.model * vec4<f32>(p.position, 1.0); let clip = camera.viewProj * worldPos; let dist = distance(camera.position, worldPos.xyz); let baseSize = pc.sizeParams.x; let minSize = pc.sizeParams.y; let maxSize = pc.sizeParams.z; let atten = pc.sizeParams.w; var sizePx = baseSize; if (atten > 0.0) { sizePx = baseSize * (atten / max(dist, 1e-6)); } sizePx = clamp(sizePx, minSize, maxSize); var uv = vec2<f32>(0.0); if (vertexIndex == 0u) { uv = vec2<f32>(0.0, 0.0); } else if (vertexIndex == 1u) { uv = vec2<f32>(1.0, 0.0); } else if (vertexIndex == 2u) { uv = vec2<f32>(0.0, 1.0); } else if (vertexIndex == 3u) { uv = vec2<f32>(1.0, 0.0); } else if (vertexIndex == 4u) { uv = vec2<f32>(1.0, 1.0); } else if (vertexIndex == 5u) { uv = vec2<f32>(0.0, 1.0); } let row0 = vec3<f32>(camera.viewProj[0][0], camera.viewProj[1][0], camera.viewProj[2][0]); let row1 = vec3<f32>(camera.viewProj[0][1], camera.viewProj[1][1], camera.viewProj[2][1]); let aspect = length(row1) / max(length(row0), 1e-6); let ndcSize = (sizePx * 2.0) / max(camera._pad0, 1.0); let offsetX = (uv.x - 0.5) * ndcSize / aspect * clip.w; let offsetY = -(uv.y - 0.5) * ndcSize * clip.w; var out: VertexOutput; out.position = clip + vec4<f32>(offsetX, offsetY, 0.0, 0.0); out.pointCoord = uv; return out; } @fragment fn fs_main(in: VertexOutput, @builtin(position) fragCoord: vec4<f32>) -> @location(0) f32 { let uv = in.pointCoord * 2.0 - vec2<f32>(1.0, 1.0); let r2 = dot(uv, uv); if (r2 > 1.0) { discard; } return fragCoord.z; }";var yi="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn vec4Component(v: vec4f, idx: u32) -> f32 { if (idx == 0u) { return v.x; } if (idx == 1u) { return v.y; } if (idx == 2u) { return v.z; } return v.w; } fn shiftedValueVector(v: vec4f, offsetFloats: f32) -> vec4f { let o = min(3u, u32(offsetFloats + 0.5)); let i0 = min(3u, o + 0u); let i1 = min(3u, o + 1u); let i2 = min(3u, o + 2u); let i3 = min(3u, o + 3u); return vec4f(vec4Component(v, i0), vec4Component(v, i1), vec4Component(v, i2), vec4Component(v, i3)); } @group(1) @binding(0) var<storage, read> positions: array<vec4<f32>>; @group(1) @binding(1) var<storage, read> rotations: array<vec4<f32>>; @group(1) @binding(2) var<storage, read> scales: array<vec4<f32>>; @group(1) @binding(3) var<storage, read> attributes: array<vec4<f32>>; struct GlyphFieldUniforms { scaleSource: vec4f, scaleDomain: vec4f, scaleClamp: vec4f, scaleParams: vec4f, scaleFlags: vec4f, visual: vec4f, solidColor: vec4f, colors: array<vec4f, 8> }; @group(1) @binding(4) var<uniform> glyph: GlyphFieldUniforms; struct CameraUniforms { viewProj: mat4x4<f32>, position: vec3<f32>, _pad0: f32 }; struct ModelUniforms { model: mat4x4<f32>, normal: mat4x4<f32> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; struct VertexInput { @location(0) position: vec3<f32> }; struct VertexOutput { @builtin(position) position: vec4<f32>, @location(0) @interpolate(flat) attrib: vec4f }; fn rotateByQuat(v: vec3<f32>, q: vec4<f32>) -> vec3<f32> { let u = q.xyz; let s = q.w; let t = 2.0 * cross(u, v); return v + s * t + cross(u, t); } @vertex fn vs_main(in: VertexInput, @builtin(instance_index) instanceIndex: u32) -> VertexOutput { let p4 = positions[instanceIndex]; let q = rotations[instanceIndex]; let s4 = scales[instanceIndex]; let localPos = rotateByQuat(in.position * s4.xyz, q) + p4.xyz; let worldPos = model.model * vec4<f32>(localPos, 1.0); var out: VertexOutput; out.position = camera.viewProj * worldPos; out.attrib = attributes[instanceIndex]; return out; } @fragment fn fs_main(in: VertexOutput, @builtin(position) fragCoord: vec4<f32>) -> @location(0) f32 { let colorMode = u32(round(glyph.visual.z)); if (colorMode == 1u) { let shifted = shiftedValueVector(in.attrib, glyph.scaleDomain.z); let componentCount = u32(glyph.scaleSource.x + 0.5); let componentIndex = u32(glyph.scaleSource.y + 0.5); let valueMode = u32(glyph.scaleSource.z + 0.5); let rawValue = scale_select_value(shifted, componentCount, componentIndex, valueMode); if (!scale_is_finite(rawValue)) { discard; } } return fragCoord.z; }";var xi="struct CameraUniforms { viewProj: mat4x4f, position: vec3f, _pad0: f32 }; struct ModelUniforms { model: mat4x4f, normal: mat4x4f }; struct NodeLinkUniforms { global: vec4f, nodeScaleSource: vec4f, nodeScaleDomain: vec4f, nodeScaleClamp: vec4f, nodeScaleParams: vec4f, nodeScaleFlags: vec4f, nodeVisual: vec4f, edgeScaleSource: vec4f, edgeScaleDomain: vec4f, edgeScaleClamp: vec4f, edgeScaleParams: vec4f, edgeScaleFlags: vec4f, edgeVisual: vec4f, nodeSolid: vec4f, edgeSolid: vec4f, pointParams: vec4f, nodeStops: array<vec4f, 8>, edgeStops: array<vec4f, 8> }; @group(0) @binding(0) var<uniform> camera: CameraUniforms; @group(0) @binding(1) var<uniform> model: ModelUniforms; @group(1) @binding(0) var<storage, read> nodePositions: array<vec4f>; @group(1) @binding(3) var<storage, read> nodeRadii: array<vec4f>; @group(1) @binding(4) var<storage, read> edges: array<vec2u>; @group(1) @binding(7) var<uniform> nl: NodeLinkUniforms; struct OcclusionOut { @builtin(position) position: vec4f, @location(0) pointCoord: vec2f, @location(1) @interpolate(flat) isPoint: f32 }; fn buildEdgeFrame(src: vec3f, dst: vec3f) -> mat3x3f { let yAxis = normalize(dst - src); var fallbackAxis = vec3f(0.0, 0.0, 1.0); if (abs(dot(fallbackAxis, yAxis)) > 0.99) { fallbackAxis = vec3f(1.0, 0.0, 0.0); } let xAxis = normalize(cross(fallbackAxis, yAxis)); let zAxis = normalize(cross(yAxis, xAxis)); return mat3x3f(xAxis, yAxis, zAxis); } @vertex fn vs_node_points(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> OcclusionOut { let p = nodePositions[instanceIndex].xyz; let worldPos4 = model.model * vec4f(p, 1.0); let clip = camera.viewProj * worldPos4; let baseSize = nl.global.x; let minSize = nl.pointParams.x; let maxSize = nl.pointParams.y; let atten = nl.pointParams.z; var sizePx = baseSize; if (atten > 0.0) { let dist = distance(camera.position, worldPos4.xyz); sizePx = baseSize * (atten / max(dist, 1e-6)); } sizePx = clamp(sizePx, minSize, maxSize); let uv = vec2f(f32((vertexIndex + 2u) / 3u % 2u), f32((vertexIndex + 1u) / 3u % 2u)); let row0 = vec3f(camera.viewProj[0][0], camera.viewProj[1][0], camera.viewProj[2][0]); let row1 = vec3f(camera.viewProj[0][1], camera.viewProj[1][1], camera.viewProj[2][1]); let aspect = length(row1) / max(length(row0), 1e-6); let ndcSize = (sizePx * 2.0) / max(camera._pad0, 1.0); let offsetX = (uv.x - 0.5) * ndcSize / aspect * clip.w; let offsetY = -(uv.y - 0.5) * ndcSize * clip.w; var out: OcclusionOut; out.position = clip + vec4f(offsetX, offsetY, 0.0, 0.0); out.pointCoord = uv * 2.0 - vec2f(1.0, 1.0); out.isPoint = 1.0; return out; } @vertex fn vs_node_solid(@location(0) position: vec3f, @builtin(instance_index) instanceIndex: u32) -> OcclusionOut { let center = nodePositions[instanceIndex].xyz; let mode = u32(round(nl.nodeVisual.z)); let useRadii = nl.nodeVisual.w > 0.5; var scaleVec = vec3f(max(nl.global.x, 1e-6)); if (useRadii) { let rv = max(nodeRadii[instanceIndex].xyz, vec3f(1e-6)); if (mode == 2u) { scaleVec = rv * max(nl.global.x, 1e-6); } else { scaleVec = vec3f(rv.x * max(nl.global.x, 1e-6)); } } let objPos = center + (position * scaleVec); let worldPos4 = model.model * vec4f(objPos, 1.0); var out: OcclusionOut; out.position = camera.viewProj * worldPos4; out.pointCoord = vec2f(0.0, 0.0); out.isPoint = 0.0; return out; } @vertex fn vs_edge_lines(@builtin(vertex_index) vertexIndex: u32, @builtin(instance_index) instanceIndex: u32) -> OcclusionOut { let edge = edges[instanceIndex]; let src = nodePositions[edge.x].xyz; let dst = nodePositions[edge.y].xyz; let objPos = select(src, dst, (vertexIndex & 1u) == 1u); let worldPos4 = model.model * vec4f(objPos, 1.0); var out: OcclusionOut; out.position = camera.viewProj * worldPos4; out.pointCoord = vec2f(0.0, 0.0); out.isPoint = 0.0; return out; } @vertex fn vs_edge_cylinders(@location(0) position: vec3f, @builtin(instance_index) instanceIndex: u32) -> OcclusionOut { let edge = edges[instanceIndex]; let src = nodePositions[edge.x].xyz; let dst = nodePositions[edge.y].xyz; let seg = dst - src; let segLen = max(length(seg), 1e-6); let basis = buildEdgeFrame(src, dst); let radius = max(nl.global.y, 1e-6); let local = vec3f(position.x * radius, position.y * segLen, position.z * radius); let objPos = ((src + dst) * 0.5) + (basis * local); let worldPos4 = model.model * vec4f(objPos, 1.0); var out: OcclusionOut; out.position = camera.viewProj * worldPos4; out.pointCoord = vec2f(0.0, 0.0); out.isPoint = 0.0; return out; } @fragment fn fs_main(in: OcclusionOut, @builtin(position) fragCoord: vec4f) -> @location(0) f32 { if (in.isPoint > 0.5) { let r2 = dot(in.pointCoord, in.pointCoord); if (r2 > 1.0) { discard; } } return fragCoord.z; }";var Ja=new ArrayBuffer(4),nc=new Float32Array(Ja),ic=new Uint32Array(Ja),pn=class n{canvas;context;device;queue;format;depthTexture;depthView;width=0;height=0;smaaEnabled=!1;smaaSceneColorTexture=null;smaaSceneColorView=null;smaaEdgesTexture=null;smaaEdgesView=null;smaaBlendTexture=null;smaaBlendView=null;smaaParamsBuffer=null;smaaSamplerPoint=null;smaaSamplerLinear=null;smaaShaderModule=null;smaaEdgePipeline=null;smaaWeightPipeline=null;smaaNeighborhoodPipeline=null;smaaEdgeBindGroupLayout=null;smaaWeightBindGroupLayout=null;smaaNeighborhoodBindGroupLayout=null;smaaEdgeBindGroup=null;smaaWeightBindGroup=null;smaaNeighborhoodBindGroup=null;transmissionSceneColorTexture=null;transmissionSceneColorView=null;transmissionSourceTexture=null;transmissionSourceView=null;transmissionSourceRevision=0;globalBindGroupLayout;globalBindGroups=[];skinBindGroupLayout;cameraUniformBuffer;modelUniformBuffers=[];modelBufferIndex=0;MODEL_BUFFER_POOL_SIZE=64;lightingUniformBuffer;instanceBuffer=null;instanceBufferCapacityBytes=0;instanceBufferOffset=0;INSTANCE_STRIDE_BYTES=128;pipelineCache=new Map;shaderCache=new Map;drawItemPool=[];drawItemPoolUsed=0;opaqueDrawList=[];transparentDrawList=[];pointCloudBindGroupLayout=null;pointCloudDummyColorsBuffer=null;pointCloudDrawItemPool=[];pointCloudDrawItemPoolUsed=0;opaquePointCloudDrawList=[];transparentPointCloudDrawList=[];glyphFieldBindGroupLayout=null;glyphFieldDummyAttributesBuffer=null;glyphFieldDrawItemPool=[];glyphFieldDrawItemPoolUsed=0;opaqueGlyphFieldDrawList=[];transparentGlyphFieldDrawList=[];nodeLinkBindGroupLayout=null;nodeLinkDummyF32Buffer=null;nodeLinkDummyU32Buffer=null;nodeLinkDrawItemPool=[];nodeLinkDrawItemPoolUsed=0;opaqueNodeLinkDrawList=[];transparentNodeLinkDrawList=[];cullNodeLinkScratch=[];nodeLinkSphereGeometry=null;nodeLinkCubeGeometry=null;nodeLinkCylinderGeometry=null;cullGlyphFieldScratch=[];transparentMergedDrawList=[];cullPointCloudScratch=[];objectIds=new WeakMap;objectsById=new Map;nextObjectId=1;cameraUniformStagingPtr;lightingUniformStagingPtr;modelUniformStagingPtr;cameraUniformStagingView;lightingUniformStagingView;lightingCountView;modelUniformStagingView;_wasmBuffer=null;frustumCullingEnabled=!0;frustumCullingStatsEnabled=!1;occlusionCullingEnabled=!1;occlusionCullingStatsEnabled=!1;cullingStats={frustum:{tested:0,visible:0},occlusion:{tested:0,visible:0,occluded:0}};frameFrustumTested=0;frameFrustumVisible=0;cullCentersPtr=0;cullRadiiPtr=0;cullCapacity=0;cullMeshScratch=[];occlusionVisibleObjectIds=new Set;occlusionCandidateObjectIds=new Set;occlusionCandidateScratch=[];pendingOcclusionFrameState=null;latestOcclusionHierarchy=null;latestOcclusionHierarchySerial=0;occlusionHierarchyTexture=null;occlusionHierarchyMipViews=[];occlusionDepthTexture=null;occlusionDepthView=null;occlusionHierarchyLayout=null;occlusionWidth=0;occlusionHeight=0;occlusionReadbackSlots=[];occlusionCaptureSerial=0;occlusionReduceBindGroupLayout=null;occlusionReducePipeline=null;occlusionReduceBindGroups=new Map;OCCLUSION_READBACK_RING_SIZE=3;OCCLUSION_MAX_LONG_EDGE=256;OCCLUSION_NEAR_EPSILON=1e-5;OCCLUSION_MAX_SCREEN_COVERAGE=.2;OCCLUSION_DEPTH_BIAS=2e-4;OCCLUSION_VIEW_PROJ_EPSILON=1e-6;fallbackSampler;fallbackWhiteTexture;fallbackWhiteViewLinear;fallbackWhiteViewSrgb;fallbackNormalTexture;fallbackNormalViewLinear;fallbackMRTex;fallbackMRViewLinear;fallbackOcclusionTex;fallbackOcclusionViewLinear;fallbackAnisotropyTexture;fallbackAnisotropyViewLinear;gpuTimingSupported=!1;gpuTimingEnabled=!1;gpuQuerySet=null;gpuResolveBuffer=null;gpuResultBuffer=null;gpuResultPending=!1;_gpuTimeNs=null;dataMaterialDummyDataBuffer=null;pickBindGroupLayout=null;pickUniformBuffers=[];pickBindGroups=[];pickIdTexture=null;pickIdView=null;pickDepthTexture=null;pickDepthView=null;pickDepthPayloadTexture=null;pickDepthPayloadView=null;pickIdReadbackBuffer=null;pickDepthReadbackBuffer=null;pickIdReadbackCapacityBytes=0;pickDepthReadbackCapacityBytes=0;pickTail=Promise.resolve();destroyed=!1;constructor(e){this.canvas=e}static async create(e,t={}){let r=new n(e);return await r.init(t),r}async init(e){if(!navigator.gpu)throw new Error("WebGPU is not supported in this browser.");let t=await navigator.gpu.requestAdapter({powerPreference:e.powerPreference??"high-performance"});if(!t)throw new Error("Failed to get GPU adapter.");let r=[];t.features.has("timestamp-query")&&r.push("timestamp-query"),t.features.has("primitive-index")&&r.push("primitive-index");let i={};r.length>0&&(i.requiredFeatures=r);let o={};if(e.maxBufferSize!==void 0&&(o.maxBufferSize=e.maxBufferSize),e.maxStorageBufferBindingSize!==void 0&&(o.maxStorageBufferBindingSize=e.maxStorageBufferBindingSize),e.maxUniformBufferBindingSize!==void 0&&(o.maxUniformBufferBindingSize=e.maxUniformBufferBindingSize),Object.keys(o).length>0&&(i.requiredLimits=o),this.device=await t.requestDevice(i),this.gpuTimingSupported=this.device.features.has("timestamp-query"),this.queue=this.device.queue,this.context=this.canvas.getContext("webgpu"),!this.context)throw new Error("Failed to get WebGPU canvas context.");e.canvasFormat?this.format=e.canvasFormat:typeof navigator.gpu.getPreferredCanvasFormat=="function"?this.format=navigator.gpu.getPreferredCanvasFormat():this.format="rgba8unorm",this.smaaEnabled=e.antialias??!1,this.smaaEnabled&&this.createSmaaResources(),this.createGlobalBindGroupLayout(),this.createSkinBindGroupLayout(),this.createUniformBuffers(),this.createFallbackTextures(),this.resize(),this.frustumCullingEnabled=e.frustumCulling??!0,this.frustumCullingStatsEnabled=e.frustumCullingStats??!1,this.occlusionCullingEnabled=e.occlusionCulling??!1,this.occlusionCullingStatsEnabled=e.occlusionCullingStats??!1,this.occlusionCullingEnabled&&this.ensureOcclusionResources()}get gpu(){return{device:this.device,queue:this.queue,format:this.format}}get gpuTimeNs(){return this._gpuTimeNs}get isGpuTimingSupported(){return this.gpuTimingSupported}enableGpuTiming(e){let t=!!e;t&&this.gpuTimingSupported&&!this.gpuQuerySet&&this.createGpuTimingResources(),this.gpuTimingEnabled=t&&this.gpuTimingSupported}createGpuTimingResources(){if(this.gpuTimingSupported&&!this.gpuQuerySet)try{this.gpuQuerySet=this.device.createQuerySet({type:"timestamp",count:2}),this.gpuResolveBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),this.gpuResultBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ})}catch(e){this.gpuQuerySet=null,this.gpuResolveBuffer?.destroy(),this.gpuResolveBuffer=null,this.gpuResultBuffer?.destroy(),this.gpuResultBuffer=null,this.gpuTimingSupported=!1,this.gpuTimingEnabled=!1,console.warn("Renderer: failed to initialize GPU timing resources:",e)}}tryReadGpuTiming(){if(!this.gpuResultPending)return;let e=this.gpuResultBuffer;e&&e.mapState==="unmapped"&&(this.gpuResultPending=!1,e.mapAsync(GPUMapMode.READ).then(()=>{try{let t=e.getMappedRange(),r=new BigUint64Array(t),i=r[0],a=r[1]-i,s=a>0n?Number(a):0;this._gpuTimeNs=Number.isFinite(s)?s:0}catch{}finally{try{e.unmap()}catch{}}}).catch(()=>{try{e.unmap()}catch{}}))}resize(){let e=Math.max(1,window.devicePixelRatio||1),t=Math.max(1,Math.floor(this.canvas.clientWidth*e)),r=Math.max(1,Math.floor(this.canvas.clientHeight*e));t===this.width&&r===this.height||(this.width=t,this.height=r,this.canvas.width=t,this.canvas.height=r,this.context.configure({device:this.device,format:this.format,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_DST,alphaMode:"opaque"}),this.depthTexture&&this.depthTexture.destroy(),this.depthTexture=Dn(this.device,this.width,this.height),this.depthView=this.depthTexture.createView(),this.transmissionSceneColorTexture?.destroy(),this.transmissionSourceTexture?.destroy(),this.transmissionSceneColorTexture=null,this.transmissionSceneColorView=null,this.transmissionSourceTexture=null,this.transmissionSourceView=null,this.transmissionSourceRevision++,this.smaaEnabled&&this.resizeSmaaTargets(),this.resizePickTargets(),this.invalidateOcclusionResources())}get aspectRatio(){return this.width/this.height}refreshWasmStagingViews(){let e=_.memory().buffer;(e!==this._wasmBuffer||!this.cameraUniformStagingView||this.cameraUniformStagingView.byteOffset!==this.cameraUniformStagingPtr||!this.lightingUniformStagingView||this.lightingUniformStagingView.byteOffset!==this.lightingUniformStagingPtr||!this.modelUniformStagingView||this.modelUniformStagingView.byteOffset!==this.modelUniformStagingPtr)&&(this._wasmBuffer=e,this.cameraUniformStagingView=_.f32view(this.cameraUniformStagingPtr,20),this.lightingUniformStagingView=_.f32view(this.lightingUniformStagingPtr,8+$e.MAX_LIGHTS*16),this.lightingCountView=_.u32view(this.lightingUniformStagingPtr+16,1),this.modelUniformStagingView=_.f32view(this.modelUniformStagingPtr,32))}getObjectId(e){let t=this.objectIds.get(e);return t!==void 0||(t=this.nextObjectId++,this.objectIds.set(e,t),this.objectsById.set(t,e)),t}acquireDrawItem(){let e=this.drawItemPoolUsed++,t=this.drawItemPool[e];return t||(t={mesh:null,geometry:null,material:null,pipeline:null,pipelineId:0,materialId:0,geometryId:0,vertexSourceId:0,skinned:!1,skinned8:!1,mirrored:!1,sortKey:0},this.drawItemPool[e]=t),t}acquirePointCloudDrawItem(){let e=this.pointCloudDrawItemPoolUsed++,t=this.pointCloudDrawItemPool[e];return t||(t={cloud:null,pipeline:null,pipelineId:0,cloudId:0,sortKey:0},this.pointCloudDrawItemPool[e]=t),t}acquireGlyphFieldDrawItem(){let e=this.glyphFieldDrawItemPoolUsed++;return e>=this.glyphFieldDrawItemPool.length&&this.glyphFieldDrawItemPool.push({}),this.glyphFieldDrawItemPool[e]}acquireNodeLinkDrawItem(){let e=this.nodeLinkDrawItemPoolUsed++;return e>=this.nodeLinkDrawItemPool.length&&this.nodeLinkDrawItemPool.push({}),this.nodeLinkDrawItemPool[e]}ensureCullingCapacity(e){if(e<=this.cullCapacity)return;let t=Math.max(1,this.cullCapacity);for(;t<e;)t*=2;this.cullCentersPtr=_.allocF32(t*3),this.cullRadiiPtr=_.allocF32(t),this.cullCapacity=t}prepareSceneFrameBase(e,t){this.modelBufferIndex=0,this.instanceBufferOffset=0,this.frameFrustumTested=0,this.frameFrustumVisible=0,this.pendingOcclusionFrameState=null,this.cameraUniformStagingPtr=W.allocF32(20),this.lightingUniformStagingPtr=W.allocF32(8+$e.MAX_LIGHTS*16),this.modelUniformStagingPtr=W.allocF32(32),"aspect"in t&&(t.aspect=this.aspectRatio),we.updateAll(),this.writeCameraUniforms(t),this.writeLightingUniforms(e),this.buildDrawLists(e,t),this.buildPointCloudDrawLists(e,t),this.buildGlyphFieldDrawLists(e,t),this.buildNodeLinkDrawLists(e,t)}applyRenderCullingAndStats(e){if(this.cullingStats.frustum.tested=this.frustumCullingStatsEnabled?this.frameFrustumTested:0,this.cullingStats.frustum.visible=this.frustumCullingStatsEnabled?this.frameFrustumVisible:0,this.cullingStats.occlusion.tested=0,this.cullingStats.occlusion.visible=0,this.cullingStats.occlusion.occluded=0,!this.occlusionCullingEnabled||(this.pendingOcclusionFrameState=this.buildOcclusionFrameState(),!this.pendingOcclusionFrameState))return;let t=this.getValidOcclusionHierarchy(e,this.pendingOcclusionFrameState.signature);t&&this.applyOcclusionFiltering(e,this.pendingOcclusionFrameState.candidates,t)}render(e,t){this.resize();let r=this.context.getCurrentTexture(),i=r.createView();this.prepareSceneFrameBase(e,t),this.applyRenderCullingAndStats(t);let o=this.device.createCommandEncoder(),a=this.gpuTimingEnabled&&this.gpuQuerySet?{querySet:this.gpuQuerySet,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1}:void 0,s=this.gpuTimingEnabled&&this.gpuQuerySet?{querySet:this.gpuQuerySet,beginningOfPassWriteIndex:0}:void 0,l=this.gpuTimingEnabled&&this.gpuQuerySet?{querySet:this.gpuQuerySet,endOfPassWriteIndex:1}:void 0,u=this.hasOpticalTransmissionDrawItems();if(this.smaaEnabled){(!this.smaaSceneColorView||!this.smaaEdgesView||!this.smaaBlendView)&&this.resizeSmaaTargets(),u&&this.ensureTransmissionTargets(!1);let c=o.beginRenderPass({colorAttachments:[{view:this.smaaSceneColorView,clearValue:{r:e.background[0],g:e.background[1],b:e.background[2],a:1},loadOp:"clear",storeOp:"store"}],depthStencilAttachment:{view:this.depthView,depthClearValue:1,depthLoadOp:"clear",depthStoreOp:"store"},...u&&s?{timestampWrites:s}:a?{timestampWrites:a}:{}});if(this.executeDrawList(c,this.opaqueDrawList),this.executeGlyphFieldDrawList(c,this.opaqueGlyphFieldDrawList),this.executePointCloudDrawList(c,this.opaquePointCloudDrawList),this.executeNodeLinkDrawList(c,this.opaqueNodeLinkDrawList),u||this.executeTransparentMergedDrawList(c),c.end(),u){o.copyTextureToTexture({texture:this.smaaSceneColorTexture},{texture:this.transmissionSourceTexture},{width:this.width,height:this.height,depthOrArrayLayers:1});let m=o.beginRenderPass({colorAttachments:[{view:this.smaaSceneColorView,loadOp:"load",storeOp:"store"}],depthStencilAttachment:{view:this.depthView,depthLoadOp:"load",depthStoreOp:"store"},...l?{timestampWrites:l}:{}});this.executeTransparentMergedDrawList(m),m.end()}a&&this.gpuResolveBuffer&&this.gpuResultBuffer&&(o.resolveQuerySet(this.gpuQuerySet,0,2,this.gpuResolveBuffer,0),this.gpuResultBuffer.mapState==="unmapped"&&(o.copyBufferToBuffer(this.gpuResolveBuffer,0,this.gpuResultBuffer,0,16),this.gpuResultPending=!0)),this.executeSmaa(o,i)}else{u&&this.ensureTransmissionTargets(!0);let c=u?this.transmissionSceneColorView:i,m=o.beginRenderPass({colorAttachments:[{view:c,clearValue:{r:e.background[0],g:e.background[1],b:e.background[2],a:1},loadOp:"clear",storeOp:"store"}],depthStencilAttachment:{view:this.depthView,depthClearValue:1,depthLoadOp:"clear",depthStoreOp:"store"},...u&&s?{timestampWrites:s}:a?{timestampWrites:a}:{}});if(this.executeDrawList(m,this.opaqueDrawList),this.executeGlyphFieldDrawList(m,this.opaqueGlyphFieldDrawList),this.executePointCloudDrawList(m,this.opaquePointCloudDrawList),this.executeNodeLinkDrawList(m,this.opaqueNodeLinkDrawList),u||this.executeTransparentMergedDrawList(m),m.end(),u){o.copyTextureToTexture({texture:this.transmissionSceneColorTexture},{texture:this.transmissionSourceTexture},{width:this.width,height:this.height,depthOrArrayLayers:1});let d=o.beginRenderPass({colorAttachments:[{view:this.transmissionSceneColorView,loadOp:"load",storeOp:"store"}],depthStencilAttachment:{view:this.depthView,depthLoadOp:"load",depthStoreOp:"store"},...l?{timestampWrites:l}:{}});this.executeTransparentMergedDrawList(d),d.end(),o.copyTextureToTexture({texture:this.transmissionSceneColorTexture},{texture:r},{width:this.width,height:this.height,depthOrArrayLayers:1})}a&&this.gpuResolveBuffer&&this.gpuResultBuffer&&(o.resolveQuerySet(this.gpuQuerySet,0,2,this.gpuResolveBuffer,0),this.gpuResultBuffer.mapState==="unmapped"&&(o.copyBufferToBuffer(this.gpuResolveBuffer,0,this.gpuResultBuffer,0,16),this.gpuResultPending=!0))}this.queue.submit([o.finish()]),this.tryReadGpuTiming(),this.occlusionCullingEnabled&&this.captureOcclusionHierarchy(t)}warmup(e,t){this.resize(),this.prepareSceneFrameBase(e,t),this.occlusionCullingEnabled&&this.ensureOcclusionResources(),this.hasOpticalTransmissionDrawItems()&&this.ensureTransmissionTargets(!this.smaaEnabled),this.warmMeshDrawList(this.opaqueDrawList),this.warmMeshDrawList(this.transparentDrawList),this.warmPointCloudDrawList(this.opaquePointCloudDrawList),this.warmPointCloudDrawList(this.transparentPointCloudDrawList),this.warmGlyphFieldDrawList(this.opaqueGlyphFieldDrawList),this.warmGlyphFieldDrawList(this.transparentGlyphFieldDrawList),this.warmNodeLinkDrawList(this.opaqueNodeLinkDrawList),this.warmNodeLinkDrawList(this.transparentNodeLinkDrawList)}schedulePick(e){let t=this.pickTail.then(e,e);return this.pickTail=t.then(()=>{},()=>{}),t}pick(e,t,r,i,o={}){return this.schedulePick(()=>this.runPick(e,t,r,i))}pickRect(e,t,r,i,o,a,s={}){return this.schedulePick(()=>this.runPickRect(e,t,r,i,o,a,s))}pickLasso(e,t,r,i={}){return this.schedulePick(()=>this.runPickLasso(e,t,r,i))}clamp(e,t,r){return e<t?t:e>r?r:e}alignTo256(e){return e+255&-256}getPickMaxHits(e){let t=e.maxHits;return Number.isFinite(t)?Math.max(1,Math.floor(t)):1e4}toFramebufferPixel(e,t,r){let i=Math.max(1,r|0),o=e/Math.max(1,t)*i,a=Math.floor(o);return a<0?0:a>=i?i-1:a}toClientBounds(e,t,r,i,o,a){let s=this.clamp(e,0,o),l=this.clamp(t,0,a),u=this.clamp(r,0,o),c=this.clamp(i,0,a);return{x:s,y:l,width:Math.max(0,u-s),height:Math.max(0,c-l)}}resolveSinglePixel(e,t,r,i){if(!Number.isFinite(e)||!Number.isFinite(t)||e<0||t<0||e>=r||t>=i)return null;let o=this.toFramebufferPixel(e,r,this.width),a=this.toFramebufferPixel(t,i,this.height);return{px:o,py:a}}resolveRectPickQuery(e,t,r,i,o,a,s){let l=Math.min(e,r),u=Math.min(t,i),c=Math.max(e,r),m=Math.max(t,i),d=this.toClientBounds(l,u,c,m,a,s),f=Math.abs(e-r)<=1e-6,p=Math.abs(t-i)<=1e-6;if(f&&p){let T=this.resolveSinglePixel(e,t,a,s);return T?{mode:"rect",bounds:d,x:T.px,y:T.py,width:1,height:1,maxHits:o,lasso:null}:{mode:"rect",bounds:d,x:0,y:0,width:0,height:0,maxHits:o,lasso:null}}if(d.width<=0||d.height<=0)return{mode:"rect",bounds:d,x:0,y:0,width:0,height:0,maxHits:o,lasso:null};let h=Math.max(d.x,d.x+d.width-1e-6),g=Math.max(d.y,d.y+d.height-1e-6),b=this.toFramebufferPixel(d.x,a,this.width),P=this.toFramebufferPixel(d.y,s,this.height),v=this.toFramebufferPixel(h,a,this.width),x=this.toFramebufferPixel(g,s,this.height);return{mode:"rect",bounds:d,x:Math.min(b,v),y:Math.min(P,x),width:Math.abs(v-b)+1,height:Math.abs(x-P)+1,maxHits:o,lasso:null}}resolveLassoPickQuery(e,t,r,i){if(!Array.isArray(e)||e.length<3)return{mode:"lasso",bounds:{x:0,y:0,width:0,height:0},x:0,y:0,width:0,height:0,maxHits:t,lasso:null};let o=1/0,a=1/0,s=-1/0,l=-1/0;for(let v=0;v<e.length;v++){let x=e[v];!Number.isFinite(x.x)||!Number.isFinite(x.y)||(x.x<o&&(o=x.x),x.y<a&&(a=x.y),x.x>s&&(s=x.x),x.y>l&&(l=x.y))}if(!Number.isFinite(o)||!Number.isFinite(a)||!Number.isFinite(s)||!Number.isFinite(l))return{mode:"lasso",bounds:{x:0,y:0,width:0,height:0},x:0,y:0,width:0,height:0,maxHits:t,lasso:null};let u=this.toClientBounds(o,a,s,l,r,i);if(u.width<=0||u.height<=0)return{mode:"lasso",bounds:u,x:0,y:0,width:0,height:0,maxHits:t,lasso:null};let c=[],m=1/0,d=1/0,f=-1/0,p=-1/0;for(let v=0;v<e.length;v++){let x=e[v];if(!Number.isFinite(x.x)||!Number.isFinite(x.y))continue;let T=x.x/Math.max(1,r)*Math.max(1,this.width),w=x.y/Math.max(1,i)*Math.max(1,this.height);c.push({x:T,y:w}),T<m&&(m=T),w<d&&(d=w),T>f&&(f=T),w>p&&(p=w)}if(c.length<3||!Number.isFinite(m)||!Number.isFinite(d)||!Number.isFinite(f)||!Number.isFinite(p))return{mode:"lasso",bounds:u,x:0,y:0,width:0,height:0,maxHits:t,lasso:null};let h=this.clamp(Math.floor(m),0,Math.max(0,this.width-1)),g=this.clamp(Math.floor(d),0,Math.max(0,this.height-1)),b=this.clamp(Math.floor(f),0,Math.max(0,this.width-1)),P=this.clamp(Math.floor(p),0,Math.max(0,this.height-1));return b<h||P<g?{mode:"lasso",bounds:u,x:0,y:0,width:0,height:0,maxHits:t,lasso:null}:{mode:"lasso",bounds:u,x:h,y:g,width:b-h+1,height:P-g+1,maxHits:t,lasso:c}}preparePickFrame(e,t){this.prepareSceneFrameBase(e,t),(!this.pickIdView||!this.pickDepthView||!this.pickDepthPayloadView)&&this.resizePickTargets()}resolveRendererPickHit(e,t){let r=this.objectsById.get(t.objectId);if(!r)return null;let i=this.unprojectDepth(e,t.px,t.py,t.depth);return r instanceof tt?{kind:"mesh",object:r,objectId:t.objectId,elementIndex:t.elementIndex,worldPosition:i}:r instanceof rt?{kind:"pointcloud",object:r,objectId:t.objectId,elementIndex:t.elementIndex,worldPosition:i}:r instanceof ze?{kind:"glyphfield",object:r,objectId:t.objectId,elementIndex:t.elementIndex,worldPosition:i}:r instanceof Oe?{kind:"nodelink",object:r,objectId:t.objectId,elementIndex:t.elementIndex,worldPosition:i}:null}pointInPolygon(e,t,r){let i=!1;for(let o=0,a=r.length-1;o<r.length;a=o++){let s=r[o].x,l=r[o].y,u=r[a].x,c=r[a].y;l>t!=c>t&&e<(u-s)*(t-l)/(c-l||1e-12)+s&&(i=!i)}return i}async executePickRegion(e,t,r){if(r.width<=0||r.height<=0)return{mode:r.mode,hits:[],truncated:!1,bounds:r.bounds,sampledPixels:0};if(this.preparePickFrame(e,t),!this.pickIdView||!this.pickDepthView||!this.pickDepthPayloadView)return{mode:r.mode,hits:[],truncated:!1,bounds:r.bounds,sampledPixels:0};let i=this.ensurePickReadbackBuffers(r.width,r.height);if(!this.pickIdTexture||!this.pickDepthPayloadTexture||!this.pickIdReadbackBuffer||!this.pickDepthReadbackBuffer)return{mode:r.mode,hits:[],truncated:!1,bounds:r.bounds,sampledPixels:0};if(this.pickIdReadbackBuffer.mapState!=="unmapped")try{this.pickIdReadbackBuffer.unmap()}catch{}if(this.pickDepthReadbackBuffer.mapState!=="unmapped")try{this.pickDepthReadbackBuffer.unmap()}catch{}let o=this.device.createCommandEncoder(),a=o.beginRenderPass({colorAttachments:[{view:this.pickIdView,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"},{view:this.pickDepthPayloadView,clearValue:{r:1,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}],depthStencilAttachment:{view:this.pickDepthView,depthClearValue:1,depthLoadOp:"clear",depthStoreOp:"store"}});a.setScissorRect(r.x,r.y,r.width,r.height),this.executeMeshPickDrawList(a,this.opaqueDrawList),this.executeMeshPickDrawList(a,this.transparentDrawList),this.executeGlyphPickDrawList(a,this.opaqueGlyphFieldDrawList),this.executeGlyphPickDrawList(a,this.transparentGlyphFieldDrawList),this.executePointCloudPickDrawList(a,this.opaquePointCloudDrawList),this.executePointCloudPickDrawList(a,this.transparentPointCloudDrawList),this.executeNodeLinkPickDrawList(a,this.opaqueNodeLinkDrawList),this.executeNodeLinkPickDrawList(a,this.transparentNodeLinkDrawList),a.end(),o.copyTextureToBuffer({texture:this.pickIdTexture,origin:{x:r.x,y:r.y,z:0}},{buffer:this.pickIdReadbackBuffer,bytesPerRow:i.idBytesPerRow,rowsPerImage:r.height},{width:r.width,height:r.height,depthOrArrayLayers:1}),o.copyTextureToBuffer({texture:this.pickDepthPayloadTexture,origin:{x:r.x,y:r.y,z:0}},{buffer:this.pickDepthReadbackBuffer,bytesPerRow:i.depthBytesPerRow,rowsPerImage:r.height},{width:r.width,height:r.height,depthOrArrayLayers:1}),this.queue.submit([o.finish()]),await Promise.all([this.pickIdReadbackBuffer.mapAsync(GPUMapMode.READ,0,i.idSizeBytes),this.pickDepthReadbackBuffer.mapAsync(GPUMapMode.READ,0,i.depthSizeBytes)]);let s=!1,l=0,u=new Map;try{let m=new Uint32Array(this.pickIdReadbackBuffer.getMappedRange(0,i.idSizeBytes)),d=new Float32Array(this.pickDepthReadbackBuffer.getMappedRange(0,i.depthSizeBytes)),f=r.mode==="lasso"?r.lasso:null;e:for(let p=0;p<r.height;p++){let h=p*i.idBytesPerRow>>>2,g=p*i.depthBytesPerRow>>>2,b=r.y+p;for(let P=0;P<r.width;P++){let v=r.x+P;if(f&&!this.pointInPolygon(v+.5,b+.5,f))continue;l++;let x=h+P*2,T=m[x]>>>0;if(T===0)continue;let w=m[x+1]>>>0,M=d[g+P];if(!Number.isFinite(M)||M>=1)continue;let B=`${T}:${w}`,S=u.get(B);if(S)M<S.depth&&(S.depth=M,S.px=v,S.py=b);else{if(u.size>=r.maxHits){s=!0;break e}u.set(B,{objectId:T,elementIndex:w,depth:M,px:v,py:b})}}}}finally{try{this.pickIdReadbackBuffer.unmap()}catch{}try{this.pickDepthReadbackBuffer.unmap()}catch{}}let c=[];for(let m of u.values()){let d=this.resolveRendererPickHit(t,m);d&&c.push(d)}return{mode:r.mode,hits:c,truncated:s,bounds:r.bounds,sampledPixels:l}}async runPick(e,t,r,i){W.reset(),this.resize();let o=Math.max(1,this.canvas.clientWidth||this.width),a=Math.max(1,this.canvas.clientHeight||this.height),s=this.resolveSinglePixel(r,i,o,a);if(!s)return null;let l={mode:"rect",bounds:{x:r,y:i,width:0,height:0},x:s.px,y:s.py,width:1,height:1,maxHits:1,lasso:null},u=await this.executePickRegion(e,t,l);return u.hits.length>0?u.hits[0]:null}async runPickRect(e,t,r,i,o,a,s){W.reset(),this.resize();let l=Math.max(1,this.canvas.clientWidth||this.width),u=Math.max(1,this.canvas.clientHeight||this.height),c=this.resolveRectPickQuery(r,i,o,a,this.getPickMaxHits(s),l,u);return this.executePickRegion(e,t,c)}async runPickLasso(e,t,r,i){W.reset(),this.resize();let o=Math.max(1,this.canvas.clientWidth||this.width),a=Math.max(1,this.canvas.clientHeight||this.height),s=this.resolveLassoPickQuery(r,this.getPickMaxHits(i),o,a);return this.executePickRegion(e,t,s)}destroy(){if(!this.destroyed){this.destroyed=!0,this.destroyOcclusionTextures(),this.depthTexture?.destroy(),this.smaaSceneColorTexture?.destroy(),this.smaaEdgesTexture?.destroy(),this.smaaBlendTexture?.destroy(),this.transmissionSceneColorTexture?.destroy(),this.transmissionSourceTexture?.destroy(),this.smaaSceneColorTexture=null,this.smaaSceneColorView=null,this.smaaEdgesTexture=null,this.smaaEdgesView=null,this.smaaBlendTexture=null,this.smaaBlendView=null,this.transmissionSceneColorTexture=null,this.transmissionSceneColorView=null,this.transmissionSourceTexture=null,this.transmissionSourceView=null,this.transmissionSourceRevision++,this.smaaParamsBuffer?.destroy(),this.smaaParamsBuffer=null,this.smaaEdgeBindGroup=null,this.smaaWeightBindGroup=null,this.smaaNeighborhoodBindGroup=null,this.smaaEdgePipeline=null,this.smaaWeightPipeline=null,this.smaaNeighborhoodPipeline=null,this.smaaShaderModule=null,this.smaaEdgeBindGroupLayout=null,this.smaaWeightBindGroupLayout=null,this.smaaNeighborhoodBindGroupLayout=null,this.smaaSamplerPoint=null,this.smaaSamplerLinear=null,this.fallbackWhiteTexture?.destroy(),this.fallbackNormalTexture?.destroy(),this.fallbackMRTex?.destroy(),this.fallbackOcclusionTex?.destroy(),this.fallbackAnisotropyTexture?.destroy(),this.cameraUniformBuffer?.destroy();for(let e of this.modelUniformBuffers)e.destroy();for(let e of this.pickUniformBuffers)e.destroy();this.modelUniformBuffers=[],this.pickUniformBuffers=[],this.pickBindGroups=[],this.pickBindGroupLayout=null,this.pickIdTexture?.destroy(),this.pickDepthTexture?.destroy(),this.pickDepthPayloadTexture?.destroy(),this.pickIdTexture=null,this.pickIdView=null,this.pickDepthTexture=null,this.pickDepthView=null,this.pickDepthPayloadTexture=null,this.pickDepthPayloadView=null,this.pickIdReadbackBuffer?.destroy(),this.pickDepthReadbackBuffer?.destroy(),this.pickIdReadbackBuffer=null,this.pickDepthReadbackBuffer=null,this.pickIdReadbackCapacityBytes=0,this.pickDepthReadbackCapacityBytes=0,this.pickTail=Promise.resolve();for(let e of this.occlusionReadbackSlots)e.buffer?.destroy(),e.buffer=null,e.capacityBytes=0,e.pending=null,e.metadata=null,e.data=null,e.state="idle";this.occlusionReadbackSlots=[],this.occlusionReduceBindGroups.clear(),this.occlusionReduceBindGroupLayout=null,this.occlusionReducePipeline=null,this.latestOcclusionHierarchy=null,this.latestOcclusionHierarchySerial=0,this.pendingOcclusionFrameState=null,this.lightingUniformBuffer?.destroy(),this.instanceBuffer?.destroy(),this.instanceBuffer=null,this.instanceBufferCapacityBytes=0,this.globalBindGroups=[],this.pipelineCache.clear(),this.shaderCache.clear(),this.pointCloudBindGroupLayout=null,this.pointCloudDummyColorsBuffer?.destroy(),this.pointCloudDummyColorsBuffer=null,this.glyphFieldBindGroupLayout=null,this.nodeLinkBindGroupLayout=null,this.glyphFieldDummyAttributesBuffer?.destroy(),this.glyphFieldDummyAttributesBuffer=null,this.nodeLinkDummyF32Buffer?.destroy(),this.nodeLinkDummyU32Buffer?.destroy(),this.nodeLinkDummyF32Buffer=null,this.nodeLinkDummyU32Buffer=null,this.nodeLinkSphereGeometry=null,this.nodeLinkCubeGeometry=null,this.nodeLinkCylinderGeometry=null,this.gpuQuerySet?.destroy(),this.gpuQuerySet=null,this.gpuResolveBuffer?.destroy(),this.gpuResolveBuffer=null,this.gpuResultBuffer?.destroy(),this.gpuResultBuffer=null,this.gpuResultPending=!1,this._gpuTimeNs=null,this.dataMaterialDummyDataBuffer?.destroy(),this.dataMaterialDummyDataBuffer=null,this.objectsById.clear(),this.objectIds=new WeakMap,this.nextObjectId=1;try{this.context?.unconfigure?.()}catch{}try{this.device?.destroy?.()}catch{}}}createGlobalBindGroupLayout(){this.globalBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:80}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",minBindingSize:128}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:(8+$e.MAX_LIGHTS*16)*4}}]})}createSkinBindGroupLayout(){this.skinBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]})}createUniformBuffers(){this.cameraUniformBuffer=this.device.createBuffer({size:80,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.lightingUniformBuffer=this.device.createBuffer({size:(8+$e.MAX_LIGHTS*16)*4,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.modelUniformBuffers=[],this.globalBindGroups=[],this.pickUniformBuffers=[],this.pickBindGroups=[];let e=this.getPickBindGroupLayout();for(let t=0;t<this.MODEL_BUFFER_POOL_SIZE;t++){let r=this.device.createBuffer({size:128,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});this.modelUniformBuffers.push(r),this.globalBindGroups.push(this.device.createBindGroup({layout:this.globalBindGroupLayout,entries:[{binding:0,resource:{buffer:this.cameraUniformBuffer}},{binding:1,resource:{buffer:r}},{binding:2,resource:{buffer:this.lightingUniformBuffer}}]}));let i=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});this.pickUniformBuffers.push(i),this.pickBindGroups.push(this.device.createBindGroup({layout:e,entries:[{binding:0,resource:{buffer:i}}]}))}this.cameraUniformStagingPtr=0,this.lightingUniformStagingPtr=0,this.modelUniformStagingPtr=0,this._wasmBuffer=null}getPickBindGroupLayout(){return this.pickBindGroupLayout?this.pickBindGroupLayout:(this.pickBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:16}}]}),this.pickBindGroupLayout)}ensureModelBufferPool(e){let t=this.modelUniformBuffers.length;if(e<=t)return;let r=Math.max(1,t);for(;r<e;)r*=2;this.modelUniformBuffers.length=r,this.globalBindGroups.length=r,this.pickUniformBuffers.length=r,this.pickBindGroups.length=r;let i=this.getPickBindGroupLayout();for(let o=t;o<r;o++){let a=this.device.createBuffer({size:128,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});this.modelUniformBuffers[o]=a,this.globalBindGroups[o]=this.device.createBindGroup({layout:this.globalBindGroupLayout,entries:[{binding:0,resource:{buffer:this.cameraUniformBuffer}},{binding:1,resource:{buffer:a}},{binding:2,resource:{buffer:this.lightingUniformBuffer}}]});let s=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});this.pickUniformBuffers[o]=s,this.pickBindGroups[o]=this.device.createBindGroup({layout:i,entries:[{binding:0,resource:{buffer:s}}]})}}createFallbackTextures(){this.fallbackSampler=this.device.createSampler({addressModeU:"repeat",addressModeV:"repeat",magFilter:"linear",minFilter:"linear",mipmapFilter:"linear"});let e=(s,l)=>{let u=this.device.createTexture({size:{width:1,height:1},format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST,viewFormats:["rgba8unorm-srgb"]}),c=new Uint8Array(256);c[0]=s[0],c[1]=s[1],c[2]=s[2],c[3]=s[3],this.queue.writeTexture({texture:u},c,{bytesPerRow:256,rowsPerImage:1},{width:1,height:1});let m=u.createView({format:"rgba8unorm"}),d=l?u.createView({format:"rgba8unorm-srgb"}):m;return{tex:u,linear:m,srgb:d}},t=e([255,255,255,255],!0);this.fallbackWhiteTexture=t.tex,this.fallbackWhiteViewLinear=t.linear,this.fallbackWhiteViewSrgb=t.srgb;let r=e([128,128,255,255],!1);this.fallbackNormalTexture=r.tex,this.fallbackNormalViewLinear=r.linear;let i=e([0,255,255,255],!1);this.fallbackMRTex=i.tex,this.fallbackMRViewLinear=i.linear;let o=e([255,0,0,255],!1);this.fallbackOcclusionTex=o.tex,this.fallbackOcclusionViewLinear=o.linear;let a=e([255,128,255,255],!1);this.fallbackAnisotropyTexture=a.tex,this.fallbackAnisotropyViewLinear=a.linear}createSmaaResources(){if(this.smaaParamsBuffer)return;this.smaaParamsBuffer=this.device.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.smaaSamplerPoint=this.device.createSampler({addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge",magFilter:"nearest",minFilter:"nearest"}),this.smaaSamplerLinear=this.device.createSampler({addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge",magFilter:"linear",minFilter:"linear"});let e=Ka;this.smaaShaderModule=this.device.createShaderModule({code:e}),this.smaaEdgeBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:3,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]}),this.smaaWeightBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:4,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]}),this.smaaNeighborhoodBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:3,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:5,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]});let t=this.device.createPipelineLayout({bindGroupLayouts:[this.smaaEdgeBindGroupLayout]}),r=this.device.createPipelineLayout({bindGroupLayouts:[this.smaaWeightBindGroupLayout]}),i=this.device.createPipelineLayout({bindGroupLayouts:[this.smaaNeighborhoodBindGroupLayout]});this.smaaEdgePipeline=this.device.createRenderPipeline({layout:t,vertex:{module:this.smaaShaderModule,entryPoint:"vs_fullscreen"},fragment:{module:this.smaaShaderModule,entryPoint:"fs_smaa_edges",targets:[{format:"rgba8unorm"}]},primitive:{topology:"triangle-list",cullMode:"none"}}),this.smaaWeightPipeline=this.device.createRenderPipeline({layout:r,vertex:{module:this.smaaShaderModule,entryPoint:"vs_fullscreen"},fragment:{module:this.smaaShaderModule,entryPoint:"fs_smaa_weights",targets:[{format:"rgba8unorm"}]},primitive:{topology:"triangle-list",cullMode:"none"}}),this.smaaNeighborhoodPipeline=this.device.createRenderPipeline({layout:i,vertex:{module:this.smaaShaderModule,entryPoint:"vs_fullscreen"},fragment:{module:this.smaaShaderModule,entryPoint:"fs_smaa_neighborhood",targets:[{format:this.format}]},primitive:{topology:"triangle-list",cullMode:"none"}})}resizeSmaaTargets(){if(!this.smaaEnabled)return;this.smaaParamsBuffer||this.createSmaaResources(),this.smaaSceneColorTexture?.destroy(),this.smaaEdgesTexture?.destroy(),this.smaaBlendTexture?.destroy();let e=this.width|0,t=this.height|0;if(e<=0||t<=0)return;this.smaaSceneColorTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:this.format,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_SRC}),this.smaaSceneColorView=this.smaaSceneColorTexture.createView();let r="rgba8unorm";this.smaaEdgesTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:r,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),this.smaaEdgesView=this.smaaEdgesTexture.createView(),this.smaaBlendTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:r,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),this.smaaBlendView=this.smaaBlendTexture.createView();let i=new Float32Array(8);i[0]=1/e,i[1]=1/t,i[2]=e,i[3]=t,i[4]=.1,this.queue.writeBuffer(this.smaaParamsBuffer,0,i),this.smaaEdgeBindGroup=this.device.createBindGroup({layout:this.smaaEdgeBindGroupLayout,entries:[{binding:0,resource:{buffer:this.smaaParamsBuffer}},{binding:2,resource:this.smaaSamplerPoint},{binding:3,resource:this.smaaSceneColorView}]}),this.smaaWeightBindGroup=this.device.createBindGroup({layout:this.smaaWeightBindGroupLayout,entries:[{binding:0,resource:{buffer:this.smaaParamsBuffer}},{binding:2,resource:this.smaaSamplerPoint},{binding:4,resource:this.smaaEdgesView}]}),this.smaaNeighborhoodBindGroup=this.device.createBindGroup({layout:this.smaaNeighborhoodBindGroupLayout,entries:[{binding:0,resource:{buffer:this.smaaParamsBuffer}},{binding:1,resource:this.smaaSamplerLinear},{binding:2,resource:this.smaaSamplerPoint},{binding:3,resource:this.smaaSceneColorView},{binding:5,resource:this.smaaBlendView}]})}ensureTransmissionTargets(e){let t=this.transmissionSourceTexture!==null&&this.transmissionSourceView!==null,r=!e||this.transmissionSceneColorTexture!==null&&this.transmissionSceneColorView!==null;t&&r||this.resizeTransmissionTargets(e)}resizeTransmissionTargets(e){this.transmissionSceneColorTexture?.destroy(),this.transmissionSourceTexture?.destroy(),this.transmissionSceneColorTexture=null,this.transmissionSceneColorView=null,this.transmissionSourceTexture=null,this.transmissionSourceView=null;let t=this.width|0,r=this.height|0;if(t<=0||r<=0){this.transmissionSourceRevision++;return}e&&(this.transmissionSceneColorTexture=this.device.createTexture({size:{width:t,height:r,depthOrArrayLayers:1},format:this.format,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_SRC}),this.transmissionSceneColorView=this.transmissionSceneColorTexture.createView()),this.transmissionSourceTexture=this.device.createTexture({size:{width:t,height:r,depthOrArrayLayers:1},format:this.format,usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST}),this.transmissionSourceView=this.transmissionSourceTexture.createView(),this.transmissionSourceRevision++}resizePickTargets(){let e=this.width|0,t=this.height|0;e<=0||t<=0||(this.pickIdTexture?.destroy(),this.pickDepthTexture?.destroy(),this.pickDepthPayloadTexture?.destroy(),this.pickIdTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:"rg32uint",usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC}),this.pickIdView=this.pickIdTexture.createView(),this.pickDepthTexture=Dn(this.device,e,t),this.pickDepthView=this.pickDepthTexture.createView(),this.pickDepthPayloadTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:"r32float",usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC}),this.pickDepthPayloadView=this.pickDepthPayloadTexture.createView(),this.ensurePickReadbackBuffers(1,1))}ensurePickReadbackBuffers(e,t){let r=Math.max(1,e|0),i=Math.max(1,t|0),o=this.alignTo256(r*8),a=this.alignTo256(r*4),s=o*i,l=a*i;return(!this.pickIdReadbackBuffer||this.pickIdReadbackCapacityBytes<s)&&(this.pickIdReadbackBuffer?.destroy(),this.pickIdReadbackBuffer=this.device.createBuffer({size:s,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),this.pickIdReadbackCapacityBytes=s),(!this.pickDepthReadbackBuffer||this.pickDepthReadbackCapacityBytes<l)&&(this.pickDepthReadbackBuffer?.destroy(),this.pickDepthReadbackBuffer=this.device.createBuffer({size:l,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),this.pickDepthReadbackCapacityBytes=l),{idBytesPerRow:o,depthBytesPerRow:a,idSizeBytes:s,depthSizeBytes:l}}writePickUniform(e,t,r=0){e>=this.pickUniformBuffers.length&&this.ensureModelBufferPool(e+1);let i=new Uint32Array([t>>>0,r>>>0,0,0]);this.queue.writeBuffer(this.pickUniformBuffers[e],0,i.buffer,i.byteOffset,i.byteLength)}writeModelUniformSlot(e,t){e>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(e+1);let r=this.modelUniformBuffers[e],i=this.modelUniformStagingPtr,o=this.modelUniformStagingPtr+64;ie.invert(i,t),ie.transpose(o,i);let a=de.bytes();this.queue.writeBuffer(r,0,a,t,64),this.queue.writeBuffer(r,64,a,o,64)}unprojectDepth(e,t,r,i){let o=(t+.5)/Math.max(1,this.width)*2-1,a=1-(r+.5)/Math.max(1,this.height)*2,s=i,l=st.invert(e.viewProjectionMatrix),u=l[0]*o+l[4]*a+l[8]*s+l[12],c=l[1]*o+l[5]*a+l[9]*s+l[13],m=l[2]*o+l[6]*a+l[10]*s+l[14],d=l[3]*o+l[7]*a+l[11]*s+l[15];return!Number.isFinite(d)||Math.abs(d)<=1e-8?[0,0,0]:[u/d,c/d,m/d]}executeSmaa(e,t){if(!this.smaaEdgePipeline||!this.smaaWeightPipeline||!this.smaaNeighborhoodPipeline||!this.smaaEdgeBindGroup||!this.smaaWeightBindGroup||!this.smaaNeighborhoodBindGroup||!this.smaaEdgesView||!this.smaaBlendView)return;let r=e.beginRenderPass({colorAttachments:[{view:this.smaaEdgesView,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]});r.setPipeline(this.smaaEdgePipeline),r.setBindGroup(0,this.smaaEdgeBindGroup),r.draw(3),r.end();let i=e.beginRenderPass({colorAttachments:[{view:this.smaaBlendView,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]});i.setPipeline(this.smaaWeightPipeline),i.setBindGroup(0,this.smaaWeightBindGroup),i.draw(3),i.end();let o=e.beginRenderPass({colorAttachments:[{view:t,clearValue:{r:0,g:0,b:0,a:1},loadOp:"clear",storeOp:"store"}]});o.setPipeline(this.smaaNeighborhoodPipeline),o.setBindGroup(0,this.smaaNeighborhoodBindGroup),o.draw(3),o.end()}writeCameraUniforms(e){this.refreshWasmStagingViews();let t=e.getProjectionMatrix();this.modelUniformStagingView.set(t,0);let r=this.modelUniformStagingPtr+64;ie.invert(r,e.transform.worldMatrixPtr),ie.mul(this.cameraUniformStagingPtr,this.modelUniformStagingPtr,r);let i=K.global(),o=i.f32(),a=(i.worldPtr>>>2)+e.transform.index*16;this.cameraUniformStagingView[16]=o[a+12],this.cameraUniformStagingView[17]=o[a+13],this.cameraUniformStagingView[18]=o[a+14],this.cameraUniformStagingView[19]=this.height,this.queue.writeBuffer(this.cameraUniformBuffer,0,this.cameraUniformStagingView)}writeLightingUniforms(e){let{ambient:t,lights:r}=e.getLightingData();this.refreshWasmStagingViews();let i=this.lightingUniformStagingView;i.fill(0),i[0]=t[0],i[1]=t[1],i[2]=t[2],i[3]=1,this.lightingCountView[0]=r.length;let o=8;for(let a=0;a<r.length&&a<$e.MAX_LIGHTS;a++){let s=r[a];if(s instanceof Pt){let l=ai(s);i[o+0]=l[0],i[o+1]=l[1],i[o+2]=l[2],i[o+3]=0}else if(s instanceof Tt){let l=ko(s);i[o+0]=l[0],i[o+1]=l[1],i[o+2]=l[2],i[o+3]=1,i[o+12]=s.range}else if(s instanceof ct){let l=ko(s),u=ai(s);i[o+0]=l[0],i[o+1]=l[1],i[o+2]=l[2],i[o+3]=2,i[o+8]=u[0],i[o+9]=u[1],i[o+10]=u[2],i[o+12]=s.range,i[o+13]=Math.cos(s.innerCone),i[o+14]=Math.cos(s.outerCone)}if(i[o+4]=s.color[0],i[o+5]=s.color[1],i[o+6]=s.color[2],i[o+7]=s.intensity,s instanceof Pt){let l=ai(s);i[o+8]=l[0],i[o+9]=l[1],i[o+10]=l[2]}o+=16}this.queue.writeBuffer(this.lightingUniformBuffer,0,i)}recordFrustumCounts(e,t){this.frameFrustumTested+=e,this.frameFrustumVisible+=t}mixOcclusionHash(e,t){return Math.imul((e^t>>>0)>>>0,16777619)>>>0}blendModeHash(e){return e==="opaque"?1:e==="transparent"?2:3}cullModeHash(e){return e==="back"?1:e==="front"?2:3}mixOcclusionHashF32(e,t){return nc[0]=Number.isFinite(t)?t:0,this.mixOcclusionHash(e,ic[0]>>>0)}hashWorldMatrix(e){let t=_.f32view(e,16),r=2166136261;for(let i=0;i<16;i++)r=this.mixOcclusionHashF32(r,t[i]);return r>>>0}createOcclusionHierarchyLayout(e,t){let r=[],i=[],o=Math.max(1,e|0),a=Math.max(1,t|0);for(;r.push(o),i.push(a),!(o===1&&a===1);)o=Math.max(1,Math.floor(o/2)),a=Math.max(1,Math.floor(a/2));let s=r.length,l=new Uint32Array(s),u=new Uint32Array(s),c=new Uint32Array(s),m=0,d=0;for(let f=0;f<s;f++)l[f]=m>>>0,u[f]=d>>>0,c[f]=he(r[f]*4,256)>>>0,m+=r[f]*i[f],d+=c[f]*i[f];return{widths:Uint32Array.from(r),heights:Uint32Array.from(i),offsets:l,copyOffsets:u,rowBytes:c,mipCount:s,texelCount:m>>>0,totalBytes:d>>>0}}destroyOcclusionTextures(){this.occlusionHierarchyTexture?.destroy(),this.occlusionDepthTexture?.destroy(),this.occlusionHierarchyTexture=null,this.occlusionHierarchyMipViews=[],this.occlusionDepthTexture=null,this.occlusionDepthView=null,this.occlusionHierarchyLayout=null,this.occlusionWidth=0,this.occlusionHeight=0,this.occlusionReduceBindGroups.clear()}invalidateOcclusionResources(){this.destroyOcclusionTextures(),this.latestOcclusionHierarchy=null,this.latestOcclusionHierarchySerial=0,this.pendingOcclusionFrameState=null;for(let e of this.occlusionReadbackSlots)e.metadata=null,e.data=null,e.state==="ready"&&(e.state="idle")}ensureOcclusionResources(){if(!this.occlusionCullingEnabled)return;let e=this.width,t=this.height;if(e>=t){let i=Math.min(1,this.OCCLUSION_MAX_LONG_EDGE/Math.max(1,e));e=Math.max(1,Math.floor(e*i)),t=Math.max(1,Math.floor(t*i))}else{let i=Math.min(1,this.OCCLUSION_MAX_LONG_EDGE/Math.max(1,t));e=Math.max(1,Math.floor(e*i)),t=Math.max(1,Math.floor(t*i))}let r=this.createOcclusionHierarchyLayout(e,t);if(!(this.occlusionHierarchyTexture&&this.occlusionDepthTexture&&this.occlusionWidth===e&&this.occlusionHeight===t&&this.occlusionHierarchyLayout?.mipCount===r.mipCount)){this.destroyOcclusionTextures(),this.occlusionWidth=e,this.occlusionHeight=t,this.occlusionHierarchyLayout=r,this.occlusionHierarchyTexture=this.device.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:"r32float",mipLevelCount:r.mipCount,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_SRC}),this.occlusionHierarchyMipViews=[];for(let i=0;i<r.mipCount;i++)this.occlusionHierarchyMipViews.push(this.occlusionHierarchyTexture.createView({dimension:"2d",baseMipLevel:i,mipLevelCount:1}));for(this.occlusionDepthTexture=Dn(this.device,e,t),this.occlusionDepthView=this.occlusionDepthTexture.createView();this.occlusionReadbackSlots.length<this.OCCLUSION_READBACK_RING_SIZE;)this.occlusionReadbackSlots.push({buffer:null,capacityBytes:0,pending:null,state:"idle",metadata:null,data:null,serial:0})}}ensureOcclusionReadbackBuffer(e,t){e.buffer&&e.capacityBytes>=t||(e.buffer?.destroy(),e.buffer=this.device.createBuffer({size:Math.max(256,he(t,256)),usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),e.capacityBytes=Math.max(256,he(t,256)))}getIdleOcclusionReadbackSlot(){for(let e of this.occlusionReadbackSlots)if(!e.pending&&e.state!=="mapping")return e;return null}buildOcclusionFrameState(){let e=2166136261,t=this.occlusionCandidateScratch;t.length=0;let r=[],i=[],o=[],a=[],s=this.occlusionVisibleObjectIds;s.clear();for(let l of this.opaqueDrawList)this.isSafeMeshOccluder(l)&&(r.push(l),e=this.mixOcclusionHash(e,1),e=this.mixOcclusionHash(e,this.getObjectId(l.mesh)),e=this.mixOcclusionHash(e,this.getMeshOccluderToken(l))),!s.has(this.getObjectId(l.mesh))&&this.tryPushMeshOcclusionCandidate(l,t)&&s.add(this.getObjectId(l.mesh));for(let l of this.opaquePointCloudDrawList)this.isSafePointCloudOccluder(l)&&(i.push(l),e=this.mixOcclusionHash(e,2),e=this.mixOcclusionHash(e,this.getObjectId(l.cloud)),e=this.mixOcclusionHash(e,l.cloud.occluderRevision>>>0),e=this.mixOcclusionHash(e,this.hashWorldMatrix(l.cloud.transform.worldMatrixPtr))),!s.has(this.getObjectId(l.cloud))&&this.tryPushPointCloudOcclusionCandidate(l.cloud,t)&&s.add(this.getObjectId(l.cloud));for(let l of this.opaqueGlyphFieldDrawList)this.isSafeGlyphOccluder(l)&&(o.push(l),e=this.mixOcclusionHash(e,3),e=this.mixOcclusionHash(e,this.getObjectId(l.field)),e=this.mixOcclusionHash(e,l.field.occluderRevision>>>0),e=this.mixOcclusionHash(e,this.hashWorldMatrix(l.field.transform.worldMatrixPtr)),e=this.mixOcclusionHash(e,this.getObjectId(l.geometry))),!s.has(this.getObjectId(l.field))&&this.tryPushGlyphOcclusionCandidate(l.field,t)&&s.add(this.getObjectId(l.field));for(let l of this.opaqueNodeLinkDrawList)this.isSafeNodeLinkOccluder(l)&&(a.push(l),e=this.mixOcclusionHash(e,4),e=this.mixOcclusionHash(e,this.getObjectId(l.link)),e=this.mixOcclusionHash(e,l.link.occluderRevision>>>0),e=this.mixOcclusionHash(e,this.hashWorldMatrix(l.link.transform.worldMatrixPtr)),e=this.mixOcclusionHash(e,l.passKind==="node-points"?1:l.passKind==="node-solid"?2:l.passKind==="edge-lines"?3:4)),!s.has(this.getObjectId(l.link))&&this.tryPushNodeLinkOcclusionCandidate(l.link,t)&&s.add(this.getObjectId(l.link));return s.clear(),{signature:e>>>0,candidates:t,meshOccluders:r,pointCloudOccluders:i,glyphOccluders:o,nodeLinkOccluders:a}}tryPushMeshOcclusionCandidate(e,t){let r=e.mesh;if(e.skinned)return!1;let i=Jn(r);if(!(i.boundsRadius>0)||!Number.isFinite(i.boundsRadius))return!1;let o=i.boundsCenter;return!Number.isFinite(o[0])||!Number.isFinite(o[1])||!Number.isFinite(o[2])?!1:(t.push({kind:"mesh",object:r,objectId:this.getObjectId(r),worldMatrixPtr:r.transform.worldMatrixPtr,boundsCenter:[o[0],o[1],o[2]],boundsRadius:i.boundsRadius}),!0)}tryPushPointCloudOcclusionCandidate(e,t){if(!(e.boundsRadius>0)||!Number.isFinite(e.boundsRadius))return!1;let r=e.boundsCenter;return!Number.isFinite(r[0])||!Number.isFinite(r[1])||!Number.isFinite(r[2])?!1:(t.push({kind:"pointcloud",object:e,objectId:this.getObjectId(e),worldMatrixPtr:e.transform.worldMatrixPtr,boundsCenter:[r[0],r[1],r[2]],boundsRadius:e.boundsRadius}),!0)}tryPushGlyphOcclusionCandidate(e,t){if(!(e.boundsRadius>0)||!Number.isFinite(e.boundsRadius))return!1;let r=e.boundsCenter;return!Number.isFinite(r[0])||!Number.isFinite(r[1])||!Number.isFinite(r[2])?!1:(t.push({kind:"glyphfield",object:e,objectId:this.getObjectId(e),worldMatrixPtr:e.transform.worldMatrixPtr,boundsCenter:[r[0],r[1],r[2]],boundsRadius:e.boundsRadius}),!0)}tryPushNodeLinkOcclusionCandidate(e,t){if(!(e.boundsRadius>0)||!Number.isFinite(e.boundsRadius))return!1;let r=e.boundsCenter;return!Number.isFinite(r[0])||!Number.isFinite(r[1])||!Number.isFinite(r[2])?!1:(t.push({kind:"nodelink",object:e,objectId:this.getObjectId(e),worldMatrixPtr:e.transform.worldMatrixPtr,boundsCenter:[r[0],r[1],r[2]],boundsRadius:e.boundsRadius}),!0)}viewProjectionMatches(e,t){let r=_.f32view(e,16);if(t.length!==16)return!1;for(let i=0;i<16;i++)if(Math.abs(r[i]-t[i])>this.OCCLUSION_VIEW_PROJ_EPSILON)return!1;return!0}getValidOcclusionHierarchy(e,t){let r=this.latestOcclusionHierarchy;if(!r||!this.occlusionHierarchyLayout)return null;let i=r.metadata;return i.viewportWidth!==this.width||i.viewportHeight!==this.height||i.hierarchyWidth!==this.occlusionWidth||i.hierarchyHeight!==this.occlusionHeight||i.cameraType!==e.type||i.occluderSignature!==t||!this.viewProjectionMatches(this.cameraUniformStagingPtr,i.viewProjection)?null:r}applyOcclusionFiltering(e,t,r){if(t.length===0)return;this.ensureCullingCapacity(t.length);let i=W.alloc(t.length*4,4),o=W.allocF32(t.length*3),a=W.allocF32(t.length),s=_.u32view(i,t.length),l=_.f32view(o,t.length*3),u=_.f32view(a,t.length);for(let T=0;T<t.length;T++){let w=t[T];s[T]=w.worldMatrixPtr>>>0,l[T*3+0]=w.boundsCenter[0],l[T*3+1]=w.boundsCenter[1],l[T*3+2]=w.boundsCenter[2],u[T]=w.boundsRadius}We.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,i,o,a,t.length);let c=r.metadata.layout,m=W.allocF32(r.data.length);_.f32view(m,r.data.length).set(r.data);let d=W.alloc(c.offsets.byteLength,4),f=W.alloc(c.widths.byteLength,4),p=W.alloc(c.heights.byteLength,4);_.u32view(d,c.offsets.length).set(c.offsets),_.u32view(f,c.widths.length).set(c.widths),_.u32view(p,c.heights.length).set(c.heights);let h=W.alloc(t.length*4,4),g=W.alloc(12,4),b=We.spheresOcclusion(h,g,this.cullCentersPtr,this.cullRadiiPtr,t.length,this.cameraUniformStagingPtr,this.width,this.height,d,f,p,c.mipCount,m,r.data.length,this.OCCLUSION_NEAR_EPSILON,this.OCCLUSION_MAX_SCREEN_COVERAGE,this.OCCLUSION_DEPTH_BIAS);if(this.occlusionCullingStatsEnabled){let T=_.u32view(g,3);this.cullingStats.occlusion.tested=T[0]>>>0,this.cullingStats.occlusion.visible=T[1]>>>0,this.cullingStats.occlusion.occluded=T[2]>>>0}let P=this.occlusionVisibleObjectIds,v=this.occlusionCandidateObjectIds;P.clear(),v.clear();for(let T=0;T<t.length;T++)v.add(t[T].objectId);let x=_.u32view(h,b);for(let T=0;T<b;T++)P.add(t[x[T]].objectId);this.filterOpaqueDrawListInPlace(this.opaqueDrawList,T=>{let w=this.getObjectId(T.mesh);return!v.has(w)||P.has(w)}),this.filterOpaqueDrawListInPlace(this.opaquePointCloudDrawList,T=>{let w=this.getObjectId(T.cloud);return!v.has(w)||P.has(w)}),this.filterOpaqueDrawListInPlace(this.opaqueGlyphFieldDrawList,T=>{let w=this.getObjectId(T.field);return!v.has(w)||P.has(w)}),this.filterOpaqueDrawListInPlace(this.opaqueNodeLinkDrawList,T=>{let w=this.getObjectId(T.link);return!v.has(w)||P.has(w)}),P.clear(),v.clear()}filterOpaqueDrawListInPlace(e,t){let r=0;for(let i=0;i<e.length;i++){let o=e[i];t(o)&&(e[r++]=o)}e.length=r}isCoverageStableMeshMaterial(e){return e instanceof tr||e instanceof He?!1:e instanceof ke?e.alphaCutoff<=0:e instanceof J?e.alphaCutoff<=0&&!e.usesTransmissionLayout():!1}isSafeMeshOccluder(e){let t=e.material;return!(t.blendMode!=="opaque"||!t.depthWrite||!t.depthTest||this.isOpticallyTransmissiveMaterial(t)||!this.isCoverageStableMeshMaterial(t)||e.skinned)}getMeshOccluderToken(e){let t=e.mesh,r=e.material,i=2166136261;return i=this.mixOcclusionHash(i,this.getObjectId(e.geometry)),i=this.mixOcclusionHash(i,this.getObjectId(yo(t))),i=this.mixOcclusionHash(i,this.getObjectId(r)),i=this.mixOcclusionHash(i,this.blendModeHash(r.blendMode)),i=this.mixOcclusionHash(i,r.depthWrite?1:0),i=this.mixOcclusionHash(i,r.depthTest?1:0),i=this.mixOcclusionHash(i,this.cullModeHash(r.cullMode)),i=this.mixOcclusionHash(i,e.mirrored?1:0),i=this.mixOcclusionHash(i,e.skinned?1:0),i=this.mixOcclusionHash(i,Qn(t)?1:0),i=this.mixOcclusionHash(i,this.hashWorldMatrix(t.transform.worldMatrixPtr)),r instanceof ke&&(i=this.mixOcclusionHashF32(i,r.alphaCutoff)),r instanceof J&&(i=this.mixOcclusionHashF32(i,r.alphaCutoff),i=this.mixOcclusionHash(i,r.getFeatureMask()>>>0),i=this.mixOcclusionHash(i,r.usesTransmissionLayout()?1:0)),i>>>0}isSafePointCloudOccluder(e){return e.cloud.blendMode==="opaque"&&e.cloud.depthWrite&&e.cloud.depthTest}isSafeGlyphOccluder(e){return e.field.blendMode==="opaque"&&e.field.depthWrite&&e.field.depthTest}isSafeNodeLinkOccluder(e){return e.link.blendMode==="opaque"&&e.link.depthWrite&&e.link.depthTest}buildDrawLists(e,t){this.drawItemPoolUsed=0,this.opaqueDrawList.length=0,this.transparentDrawList.length=0;let r=this.cullMeshScratch;r.length=0;for(let h of e.meshes)h.destroyed||h.visible&&r.push(h);let i=r.length;if(i===0)return;let o=0,a=i,s=K.global(),l=s.f32(),u=s.u32(),c=t.transform.worldMatrixPtr>>>2,m=l[c+12],d=l[c+13],f=l[c+14];if(this.frustumCullingEnabled){this.ensureCullingCapacity(i);let h=W.alloc(i*4,4),g=W.allocF32(i*3),b=W.allocF32(i),P=u.subarray(h>>>2,(h>>>2)+i),v=l.subarray(g>>>2,(g>>>2)+i*3),x=l.subarray(b>>>2,(b>>>2)+i);for(let M=0;M<i;M++){let B=r[M],S=Jn(B),R=S.boundsCenter,G=M*3;P[M]=B.transform.worldMatrixPtr>>>0,v[G+0]=R[0],v[G+1]=R[1],v[G+2]=R[2],x[M]=S.boundsRadius}We.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,h,g,b,i);let T=W.allocF32(24);$t.writePlanesFromViewProjection(T,this.cameraUniformStagingPtr);let w=W.alloc(i*4,4);a=We.spheresFrustum(w,this.cullCentersPtr,this.cullRadiiPtr,i,T),o=w>>>2}this.recordFrustumCounts(i,a);let p=h=>{let g=h.geometry,b=h.material,P=h.skin!==null&&g.joints!==null&&g.weights!==null&&this.materialSupportsSkinning(b),v=P&&g.joints1!==null&&g.weights1!==null,x=h.transform.worldMatrixPtr>>>2,T=this.isMirroredWorldMatrix(l,x),w=this.isOpticallyTransmissiveMaterial(b),M=w&&b.blendMode!=="opaque",B=this.getOrCreatePipeline(b,!1,P,v,T,M),S=this.acquireDrawItem();if(S.mesh=h,S.geometry=g,S.material=b,S.pipeline=B,S.pipelineId=this.getObjectId(B),S.materialId=this.getObjectId(b),S.geometryId=this.getObjectId(g),S.vertexSourceId=this.getObjectId(yo(h)),S.skinned=P,S.skinned8=v,S.mirrored=T,S.sortKey=0,b.blendMode==="opaque"&&!w)this.opaqueDrawList.push(S);else{let R=l[x+12]-m,G=l[x+13]-d,L=l[x+14]-f;S.sortKey=R*R+G*G+L*L,this.transparentDrawList.push(S)}};if(this.frustumCullingEnabled){let h=o;for(let g=0;g<a;g++)p(r[u[h+g]])}else for(let h=0;h<i;h++)p(r[h]);this.opaqueDrawList.sort((h,g)=>h.pipelineId-g.pipelineId||h.materialId-g.materialId||h.vertexSourceId-g.vertexSourceId),this.transparentDrawList.sort((h,g)=>g.sortKey-h.sortKey||h.pipelineId-g.pipelineId||h.materialId-g.materialId||h.vertexSourceId-g.vertexSourceId)}isOpticallyTransmissiveMaterial(e){return e instanceof J?(e.extensions.transmission?.factor??0)>0:!1}hasOpticalTransmissionDrawItems(){for(let e of this.transparentDrawList)if(this.isOpticallyTransmissiveMaterial(e.material))return!0;return!1}buildPointCloudDrawLists(e,t){this.pointCloudDrawItemPoolUsed=0,this.opaquePointCloudDrawList.length=0,this.transparentPointCloudDrawList.length=0,this.transparentMergedDrawList.length=0,this.cullPointCloudScratch.length=0;for(let m of e.pointClouds)m.visible&&(m.pointCount<=0||this.cullPointCloudScratch.push(m));if(this.cullPointCloudScratch.length===0)return;let r=K.global(),i=r.f32(),o=r.u32(),a=this.cameraUniformStagingView,s=a[16],l=a[17],u=a[18],c=[];if(this.frustumCullingEnabled){let m=[],d=[];for(let f of this.cullPointCloudScratch)f.boundsRadius>0?m.push(f):d.push(f);if(m.length>0){this.ensureCullingCapacity(m.length);let f=m.length,p=W.alloc(f*4,4),h=W.allocF32(f*3),g=W.allocF32(f),b=o.subarray(p>>>2,(p>>>2)+f),P=i.subarray(h>>>2,(h>>>2)+f*3),v=i.subarray(g>>>2,(g>>>2)+f);for(let B=0;B<m.length;B++){let S=m[B],R=S.boundsCenter[0],G=S.boundsCenter[1],L=S.boundsCenter[2],U=B*3;b[B]=S.transform.worldMatrixPtr>>>0,P[U+0]=R,P[U+1]=G,P[U+2]=L,v[B]=S.boundsRadius}We.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,p,h,g,f);let x=W.allocF32(24);$t.writePlanesFromViewProjection(x,this.cameraUniformStagingPtr);let T=W.alloc(m.length*4,4),w=We.spheresFrustum(T,this.cullCentersPtr,this.cullRadiiPtr,m.length,x),M=T>>>2;for(let B=0;B<w;B++)c.push(m[o[M+B]])}for(let f of d)c.push(f)}else for(let m of this.cullPointCloudScratch)c.push(m);this.recordFrustumCounts(this.cullPointCloudScratch.length,c.length);for(let m of c){let d=this.getOrCreatePointCloudPipeline(m),f=this.getObjectId(d),p=this.getObjectId(m),h=this.acquirePointCloudDrawItem();if(h.cloud=m,h.pipeline=d,h.pipelineId=f,h.cloudId=p,m.blendMode==="opaque")h.sortKey=0,this.opaquePointCloudDrawList.push(h);else{let g=m.transform.worldMatrixPtr>>>2,b=m.boundsCenter[0],P=m.boundsCenter[1],v=m.boundsCenter[2],x=i[g+0]*b+i[g+4]*P+i[g+8]*v+i[g+12],T=i[g+1]*b+i[g+5]*P+i[g+9]*v+i[g+13],w=i[g+2]*b+i[g+6]*P+i[g+10]*v+i[g+14],M=x-s,B=T-l,S=w-u;h.sortKey=M*M+B*B+S*S,this.transparentPointCloudDrawList.push(h)}}this.opaquePointCloudDrawList.sort((m,d)=>m.pipelineId-d.pipelineId||m.cloudId-d.cloudId),this.transparentPointCloudDrawList.sort((m,d)=>d.sortKey-m.sortKey||m.pipelineId-d.pipelineId||m.cloudId-d.cloudId)}buildGlyphFieldDrawLists(e,t){this.glyphFieldDrawItemPoolUsed=0,this.opaqueGlyphFieldDrawList.length=0,this.transparentGlyphFieldDrawList.length=0,this.cullGlyphFieldScratch.length=0;for(let u of e.glyphFields)u.visible&&(u.instanceCount<=0||this.cullGlyphFieldScratch.push(u));if(this.cullGlyphFieldScratch.length===0)return;let r=K.global(),i=r.f32(),o=t.position[0],a=t.position[1],s=t.position[2],l=[];if(this.frustumCullingEnabled){let u=[],c=[];for(let m of this.cullGlyphFieldScratch)m.boundsRadius>0?u.push(m):c.push(m);if(u.length>0){this.ensureCullingCapacity(u.length);let m=u.length,d=W.alloc(m*4,4),f=W.allocF32(m*3),p=W.allocF32(m),h=r.u32().subarray(d>>>2,(d>>>2)+m),g=r.f32().subarray(f>>>2,(f>>>2)+m*3),b=r.f32().subarray(p>>>2,(p>>>2)+m);for(let M=0;M<u.length;M++){let B=u[M],S=B.boundsCenter[0],R=B.boundsCenter[1],G=B.boundsCenter[2],L=M*3;h[M]=B.transform.worldMatrixPtr>>>0,g[L+0]=S,g[L+1]=R,g[L+2]=G,b[M]=B.boundsRadius}We.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,d,f,p,m);let P=W.allocF32(24);$t.writePlanesFromViewProjection(P,this.cameraUniformStagingPtr);let v=W.alloc(u.length*4,4),x=We.spheresFrustum(v,this.cullCentersPtr,this.cullRadiiPtr,u.length,P),T=r.u32(),w=v>>>2;for(let M=0;M<x;M++)l.push(u[T[w+M]])}for(let m of c)l.push(m)}else for(let u of this.cullGlyphFieldScratch)l.push(u);this.recordFrustumCounts(this.cullGlyphFieldScratch.length,l.length);for(let u of l){let c=u.geometry,m=this.getOrCreateGlyphFieldPipeline(u),d=this.acquireGlyphFieldDrawItem();if(d.field=u,d.geometry=c,d.pipeline=m,d.pipelineId=this.getObjectId(m),d.geometryId=this.getObjectId(c),d.fieldId=this.getObjectId(u),u.blendMode==="opaque")d.sortKey=0,this.opaqueGlyphFieldDrawList.push(d);else{let f=u.transform.worldMatrixPtr>>>2,p=i[f+12]-o,h=i[f+13]-a,g=i[f+14]-s;d.sortKey=p*p+h*h+g*g,this.transparentGlyphFieldDrawList.push(d)}}this.opaqueGlyphFieldDrawList.length>0&&this.opaqueGlyphFieldDrawList.sort((u,c)=>{let m=u.pipelineId-c.pipelineId;if(m!==0)return m;let d=u.geometryId-c.geometryId;return d!==0?d:u.fieldId-c.fieldId}),this.transparentGlyphFieldDrawList.length>0&&this.transparentGlyphFieldDrawList.sort((u,c)=>{let m=c.sortKey-u.sortKey;if(m!==0)return m;let d=u.pipelineId-c.pipelineId;if(d!==0)return d;let f=u.geometryId-c.geometryId;return f!==0?f:u.fieldId-c.fieldId})}getNodeLinkNodeGeometry(e){return e==="cubes"?(this.nodeLinkCubeGeometry??=ae.box(1,1,1),this.nodeLinkCubeGeometry):(this.nodeLinkSphereGeometry??=ae.sphere(.5,16,12),this.nodeLinkSphereGeometry)}getNodeLinkEdgeCylinderGeometry(){return this.nodeLinkCylinderGeometry??=ae.cylinder(1,1,1,14,1,!1),this.nodeLinkCylinderGeometry}buildNodeLinkDrawLists(e,t){this.nodeLinkDrawItemPoolUsed=0,this.opaqueNodeLinkDrawList.length=0,this.transparentNodeLinkDrawList.length=0,this.cullNodeLinkScratch.length=0;for(let c of e.nodeLinks)c.visible&&(c.nodeCount<=0&&c.edgeCount<=0||this.cullNodeLinkScratch.push(c));if(this.cullNodeLinkScratch.length===0)return;let r=K.global(),i=r.f32(),o=t.position[0],a=t.position[1],s=t.position[2],l=[];if(this.frustumCullingEnabled){let c=[],m=[];for(let d of this.cullNodeLinkScratch)d.boundsRadius>0?c.push(d):m.push(d);if(c.length>0){this.ensureCullingCapacity(c.length);let d=c.length,f=W.alloc(d*4,4),p=W.allocF32(d*3),h=W.allocF32(d),g=r.u32().subarray(f>>>2,(f>>>2)+d),b=r.f32().subarray(p>>>2,(p>>>2)+d*3),P=r.f32().subarray(h>>>2,(h>>>2)+d);for(let B=0;B<c.length;B++){let S=c[B];g[B]=S.transform.worldMatrixPtr>>>0,b[B*3+0]=S.boundsCenter[0],b[B*3+1]=S.boundsCenter[1],b[B*3+2]=S.boundsCenter[2],P[B]=S.boundsRadius}We.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,f,p,h,d);let v=W.allocF32(24);$t.writePlanesFromViewProjection(v,this.cameraUniformStagingPtr);let x=W.alloc(c.length*4,4),T=We.spheresFrustum(x,this.cullCentersPtr,this.cullRadiiPtr,c.length,v),w=r.u32(),M=x>>>2;for(let B=0;B<T;B++)l.push(c[w[M+B]])}for(let d of m)l.push(d)}else for(let c of this.cullNodeLinkScratch)l.push(c);this.recordFrustumCounts(this.cullNodeLinkScratch.length,l.length);let u=(c,m,d)=>{let f=this.getOrCreateNodeLinkPipeline(c,m),p=this.acquireNodeLinkDrawItem();p.link=c,p.pipeline=f,p.pipelineId=this.getObjectId(f),p.linkId=this.getObjectId(c),p.passKind=m,p.geometry=d,p.geometryId=d?this.getObjectId(d):0;let h=c.transform.worldMatrixPtr>>>2,g=c.boundsCenter[0],b=c.boundsCenter[1],P=c.boundsCenter[2],v=i[h+0]*g+i[h+4]*b+i[h+8]*P+i[h+12],x=i[h+1]*g+i[h+5]*b+i[h+9]*P+i[h+13],T=i[h+2]*g+i[h+6]*b+i[h+10]*P+i[h+14],w=v-o,M=x-a,B=T-s;p.sortKey=w*w+M*M+B*B,c.blendMode==="opaque"?this.opaqueNodeLinkDrawList.push(p):this.transparentNodeLinkDrawList.push(p)};for(let c of l)c.nodeCount>0&&(c.nodeGeometryMode==="points"?u(c,"node-points",null):u(c,"node-solid",this.getNodeLinkNodeGeometry(c.nodeGeometryMode))),c.edgeCount>0&&(c.edgeGeometryMode==="lines"?u(c,"edge-lines",null):u(c,"edge-cylinders",this.getNodeLinkEdgeCylinderGeometry()));this.opaqueNodeLinkDrawList.sort((c,m)=>c.pipelineId-m.pipelineId||c.geometryId-m.geometryId||c.linkId-m.linkId),this.transparentNodeLinkDrawList.sort((c,m)=>m.sortKey-c.sortKey||c.pipelineId-m.pipelineId||c.geometryId-m.geometryId||c.linkId-m.linkId)}captureOcclusionHierarchy(e){let t=this.pendingOcclusionFrameState;if(!t||t.meshOccluders.length+t.pointCloudOccluders.length+t.glyphOccluders.length+t.nodeLinkOccluders.length<=0||(this.ensureOcclusionResources(),!this.occlusionHierarchyTexture||!this.occlusionDepthView||!this.occlusionHierarchyLayout))return;let i=this.getIdleOcclusionReadbackSlot();if(!i||(this.ensureOcclusionReadbackBuffer(i,this.occlusionHierarchyLayout.totalBytes),!i.buffer))return;this.modelBufferIndex=0;let o=this.device.createCommandEncoder(),a=o.beginRenderPass({colorAttachments:[{view:this.occlusionHierarchyMipViews[0],clearValue:{r:1,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}],depthStencilAttachment:{view:this.occlusionDepthView,depthClearValue:1,depthLoadOp:"clear",depthStoreOp:"store"}});this.executeOcclusionMeshDrawList(a,t.meshOccluders),this.executeOcclusionGlyphFieldDrawList(a,t.glyphOccluders),this.executeOcclusionPointCloudDrawList(a,t.pointCloudOccluders),this.executeOcclusionNodeLinkDrawList(a,t.nodeLinkOccluders),a.end();for(let l=1;l<this.occlusionHierarchyLayout.mipCount;l++){let u=o.beginRenderPass({colorAttachments:[{view:this.occlusionHierarchyMipViews[l],clearValue:{r:1,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]});u.setPipeline(this.getOrCreateOcclusionReducePipeline()),u.setBindGroup(0,this.getOrCreateOcclusionReduceBindGroup(l-1)),u.draw(3),u.end()}for(let l=0;l<this.occlusionHierarchyLayout.mipCount;l++)o.copyTextureToBuffer({texture:this.occlusionHierarchyTexture,mipLevel:l},{buffer:i.buffer,offset:this.occlusionHierarchyLayout.copyOffsets[l],bytesPerRow:this.occlusionHierarchyLayout.rowBytes[l],rowsPerImage:this.occlusionHierarchyLayout.heights[l]},{width:this.occlusionHierarchyLayout.widths[l],height:this.occlusionHierarchyLayout.heights[l],depthOrArrayLayers:1});let s={viewportWidth:this.width,viewportHeight:this.height,hierarchyWidth:this.occlusionWidth,hierarchyHeight:this.occlusionHeight,cameraType:e.type,occluderSignature:t.signature,viewProjection:new Float32Array(_.f32view(this.cameraUniformStagingPtr,16)),layout:this.occlusionHierarchyLayout};i.metadata=s,i.data=null,i.serial=++this.occlusionCaptureSerial,i.state="mapping",this.queue.submit([o.finish()]),i.pending=i.buffer.mapAsync(GPUMapMode.READ).then(()=>{if(!i.buffer||!i.metadata)return;let l=i.buffer.getMappedRange(),u=new Float32Array(i.metadata.layout.texelCount);for(let c=0;c<i.metadata.layout.mipCount;c++){let m=i.metadata.layout.widths[c],d=i.metadata.layout.heights[c],f=i.metadata.layout.offsets[c],p=i.metadata.layout.rowBytes[c],h=i.metadata.layout.copyOffsets[c];for(let g=0;g<d;g++){let b=new Float32Array(l,h+g*p,m);u.set(b,f+g*m)}}i.data=u,i.state="ready",i.metadata&&i.serial>=this.latestOcclusionHierarchySerial&&(this.latestOcclusionHierarchySerial=i.serial,this.latestOcclusionHierarchy={metadata:i.metadata,data:u})}).catch(()=>{i.data=null,i.metadata=null,i.state="idle"}).finally(()=>{try{i.buffer?.unmap()}catch{}i.state!=="ready"&&(i.state="idle"),i.pending=null})}executeOcclusionMeshDrawList(e,t){let r=null,i=null,o=-1;for(let a=0;a<t.length;a++){let s=t[a],l=s.geometry;(l!==i||s.vertexSourceId!==o)&&(l.upload(this.device),Qt(s.mesh,this.device,this.queue),i=l,o=s.vertexSourceId);let u=this.getOrCreateOcclusionMeshPipeline(s);u!==r&&(e.setPipeline(u),r=u);let c=this.modelBufferIndex++;this.writeModelUniformSlot(c,s.mesh.transform.worldMatrixPtr),e.setBindGroup(0,this.globalBindGroups[c]);let m=Qt(s.mesh,this.device,this.queue);e.setVertexBuffer(0,m.positionBuffer),l.isIndexed&&l.indexBuffer?(e.setIndexBuffer(l.indexBuffer,"uint32"),e.drawIndexed(l.indexCount)):e.draw(l.vertexCount)}}executeOcclusionPointCloudDrawList(e,t){let r=null;for(let i=0;i<t.length;i++){let a=t[i].cloud;if(this.ensurePointCloudBindGroup(a),!a.bindGroup)continue;let s=this.modelBufferIndex++;this.writeModelUniformSlot(s,a.transform.worldMatrixPtr),e.setPipeline(this.getOrCreateOcclusionPointCloudPipeline()),e.setBindGroup(0,this.globalBindGroups[s]),a!==r&&(e.setBindGroup(1,a.bindGroup),r=a),e.draw(6,a.pointCount)}}executeOcclusionGlyphFieldDrawList(e,t){let r=null,i=null,o=null;for(let a=0;a<t.length;a++){let s=t[a],l=s.field;if(this.ensureGlyphFieldBindGroup(l),!l.bindGroup)continue;let u=this.getOrCreateOcclusionGlyphFieldPipeline(l);u!==o&&(e.setPipeline(u),o=u),s.geometry!==r&&(s.geometry.upload(this.device),e.setVertexBuffer(0,s.geometry.positionBuffer),r=s.geometry);let c=this.modelBufferIndex++;this.writeModelUniformSlot(c,l.transform.worldMatrixPtr),e.setBindGroup(0,this.globalBindGroups[c]),l!==i&&(e.setBindGroup(1,l.bindGroup),i=l),s.geometry.isIndexed&&s.geometry.indexBuffer?(e.setIndexBuffer(s.geometry.indexBuffer,"uint32"),e.drawIndexed(s.geometry.indexCount,l.instanceCount)):e.draw(s.geometry.vertexCount,l.instanceCount)}}executeOcclusionNodeLinkDrawList(e,t){let r=null,i=null,o=null;for(let a=0;a<t.length;a++){let s=t[a],l=s.link;if(this.ensureNodeLinkBindGroup(l),!l.bindGroup)continue;let u=this.getOrCreateOcclusionNodeLinkPipeline(l,s.passKind);u!==o&&(e.setPipeline(u),o=u),s.geometry&&s.geometry!==i&&(s.geometry.upload(this.device),e.setVertexBuffer(0,s.geometry.positionBuffer),i=s.geometry);let c=this.modelBufferIndex++;if(this.writeModelUniformSlot(c,l.transform.worldMatrixPtr),e.setBindGroup(0,this.globalBindGroups[c]),l!==r&&(e.setBindGroup(1,l.bindGroup),r=l),s.passKind==="node-points")e.draw(6,l.nodeCount);else if(s.passKind==="edge-lines")e.draw(2,l.edgeCount);else if(s.passKind==="node-solid"){if(!s.geometry)continue;s.geometry.isIndexed&&s.geometry.indexBuffer?(e.setIndexBuffer(s.geometry.indexBuffer,"uint32"),e.drawIndexed(s.geometry.indexCount,l.nodeCount)):e.draw(s.geometry.vertexCount,l.nodeCount)}else{if(!s.geometry)continue;s.geometry.isIndexed&&s.geometry.indexBuffer?(e.setIndexBuffer(s.geometry.indexBuffer,"uint32"),e.drawIndexed(s.geometry.indexCount,l.edgeCount)):e.draw(s.geometry.vertexCount,l.edgeCount)}}}warmMeshDrawList(e){let t=null,r=null,i=-1;for(let o=0;o<e.length;){let a=e[o],s=a.material,l=a.geometry,u=a.vertexSourceId,c=o+1;for(;c<e.length;){let f=e[c];if(f.pipeline!==a.pipeline||f.material!==s||f.vertexSourceId!==u)break;c++}let m=c-o;if((l!==r||u!==i)&&(l.upload(this.device),Qt(a.mesh,this.device,this.queue),r=l,i=u),s!==t&&(this.ensureMaterialBindGroup(s),t=s),m>1&&!a.skinned&&!Qn(a.mesh)&&this.materialSupportsInstancing(s)&&e===this.opaqueDrawList)this.getOrCreatePipeline(s,!0,!1,!1,a.mirrored),this.warmInstancedRunResources(e,o,m);else if(a.skinned)for(let f=o;f<c;f++){let p=e[f].mesh.skin;p&&this.warmSkinResources(p)}o=c}}warmSkinResources(e){if(!e)return;e.ensureGpuResources(this.device,this.skinBindGroupLayout);let t=e.jointCount|0,r=W.allocF32(t*16);Gt.computeJointMatricesTo(r,e.skin.jointIndicesPtr,t,e.skin.invBindPtr,K.global().worldPtr,e.bindMatrixPtr);let i=de.bytes();this.queue.writeBuffer(e.boneBuffer,0,i,r,t*64)}warmInstancedRunResources(e,t,r){let i=W.alloc(r*4,4),o=K.global().u32(),a=i>>>2;for(let d=0;d<r;d++)o[a+d]=e[t+d].mesh.transform.worldMatrixPtr>>>0;let s=W.allocF32(r*32);At.packModelNormalMat4FromPtrs(s,i,r);let l=r*this.INSTANCE_STRIDE_BYTES,u=this.instanceBufferOffset,c=u+l;this.ensureInstanceBuffer(c);let m=de.bytes();this.queue.writeBuffer(this.instanceBuffer,u,m,s,l),this.instanceBufferOffset=c}warmPointCloudDrawList(e){for(let t of e){let r=t.cloud;r.visible&&(r.pointCount<=0||this.ensurePointCloudBindGroup(r))}}warmGlyphFieldDrawList(e){for(let t of e){let r=t.field;r.visible&&(r.instanceCount<=0||(t.geometry.upload(this.device),this.ensureGlyphFieldBindGroup(r)))}}warmNodeLinkDrawList(e){for(let t of e)this.ensureNodeLinkBindGroup(t.link),t.geometry&&t.geometry.upload(this.device)}executeDrawList(e,t){let r=null,i=null,o=null,a=-1;for(let s=0;s<t.length;){let l=t[s],u=l.pipeline,c=l.material,m=l.geometry,d=l.vertexSourceId,f=s+1;for(;f<t.length;){let g=t[f];if(g.pipeline!==u||g.material!==c||g.vertexSourceId!==d)break;f++}let p=f-s;if((m!==o||d!==a)&&m.upload(this.device),c!==i&&this.ensureMaterialBindGroup(c),u!==r&&(e.setPipeline(u),r=u),c!==i&&(e.setBindGroup(1,c.bindGroup),i=c),m!==o||d!==a){let g=Qt(l.mesh,this.device,this.queue);e.setVertexBuffer(0,g.positionBuffer),e.setVertexBuffer(1,g.normalBuffer),e.setVertexBuffer(2,m.uvBuffer),e.setVertexBuffer(3,m.uv1Buffer);let b=c instanceof J;b&&e.setVertexBuffer(4,m.tangentBuffer),l.skinned&&(b?e.setVertexBuffer(5,m.skinInfluenceBuffer):(e.setVertexBuffer(4,m.jointsBuffer),e.setVertexBuffer(5,m.weightsBuffer),l.skinned8&&(e.setVertexBuffer(6,m.joints1Buffer),e.setVertexBuffer(7,m.weights1Buffer)))),m.isIndexed&&e.setIndexBuffer(m.indexBuffer,"uint32"),o=m,a=d}if(p>1&&!l.skinned&&!Qn(l.mesh)&&this.materialSupportsInstancing(c)&&t===this.opaqueDrawList){let g=this.getOrCreatePipeline(c,!0,!1,!1,l.mirrored);g!==r&&(e.setPipeline(g),r=g),this.drawInstancedRun(e,m,c,t,s,p)}else for(let g=s;g<f;g++){this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let b=this.modelBufferIndex++,P=this.modelUniformBuffers[b],v=this.globalBindGroups[b],x=de.bytes(),T=t[g].mesh,w=l.skinned?T.skin:null;if(w){w.ensureGpuResources(this.device,this.skinBindGroupLayout);let R=w.jointCount|0,G=W.allocF32(R*16);Gt.computeJointMatricesTo(G,w.skin.jointIndicesPtr,R,w.skin.invBindPtr,K.global().worldPtr,w.bindMatrixPtr),this.queue.writeBuffer(w.boneBuffer,0,x,G,R*64),e.setBindGroup(2,w.bindGroup)}let M=T.transform.worldMatrixPtr,B=this.modelUniformStagingPtr,S=this.modelUniformStagingPtr+64;ie.invert(B,M),ie.transpose(S,B),this.queue.writeBuffer(P,0,x,M,64),this.queue.writeBuffer(P,64,x,S,64),e.setBindGroup(0,v),m.isIndexed?e.drawIndexed(m.indexCount):e.draw(m.vertexCount)}s=f}}executePointCloudDrawList(e,t){if(t.length===0)return;let r=de.bytes(),i=ie,o=null;for(let a=0;a<t.length;a++){let s=t[a],l=s.cloud;if(!l.visible||l.pointCount<=0||(this.ensurePointCloudBindGroup(l),!l.bindGroup))continue;s.pipeline!==o&&(e.setPipeline(s.pipeline),o=s.pipeline),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let u=this.modelBufferIndex++,c=this.modelUniformBuffers[u],m=this.globalBindGroups[u],d=l.transform.worldMatrixPtr,f=this.modelUniformStagingPtr,p=this.modelUniformStagingPtr+64;i.invert(f,d),i.transpose(p,f),this.queue.writeBuffer(c,0,r,d,64),this.queue.writeBuffer(c,64,r,p,64),e.setBindGroup(0,m),e.setBindGroup(1,l.bindGroup),e.draw(6,l.pointCount)}}executeGlyphFieldDrawList(e,t){if(t.length===0)return;let r=de.bytes(),i=null,o=null,a=null;for(let s=0;s<t.length;s++){let l=t[s],u=l.field,c=l.geometry;if(!u.visible||u.instanceCount<=0||(this.ensureGlyphFieldBindGroup(u),!u.bindGroup))continue;l.pipeline!==i&&(e.setPipeline(l.pipeline),i=l.pipeline,o=null,a=null),c!==o&&(c.upload(this.device),e.setVertexBuffer(0,c.positionBuffer),e.setVertexBuffer(1,c.normalBuffer),c.isIndexed&&e.setIndexBuffer(c.indexBuffer,"uint32"),o=c),u!==a&&(e.setBindGroup(1,u.bindGroup),a=u),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let m=this.modelBufferIndex++,d=this.modelUniformBuffers[m],f=this.globalBindGroups[m],p=u.transform.worldMatrixPtr,h=this.modelUniformStagingPtr,g=this.modelUniformStagingPtr+64;ie.invert(h,p),ie.transpose(g,h),this.queue.writeBuffer(d,0,r,p,64),this.queue.writeBuffer(d,64,r,g,64),e.setBindGroup(0,f),c.isIndexed?e.drawIndexed(c.indexCount,u.instanceCount):e.draw(c.vertexCount,u.instanceCount)}}executeNodeLinkDrawList(e,t){if(t.length===0)return;let r=de.bytes(),i=null,o=null,a=null;for(let s=0;s<t.length;s++){let l=t[s],u=l.link;if(this.ensureNodeLinkBindGroup(u),!u.bindGroup)continue;l.pipeline!==i&&(e.setPipeline(l.pipeline),i=l.pipeline,o=null,a=null),l.geometry&&l.geometry!==o&&(l.geometry.upload(this.device),e.setVertexBuffer(0,l.geometry.positionBuffer),e.setVertexBuffer(1,l.geometry.normalBuffer),l.geometry.isIndexed&&e.setIndexBuffer(l.geometry.indexBuffer,"uint32"),o=l.geometry),u!==a&&(e.setBindGroup(1,u.bindGroup),a=u),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let c=this.modelBufferIndex++,m=this.modelUniformBuffers[c],d=this.globalBindGroups[c],f=u.transform.worldMatrixPtr,p=this.modelUniformStagingPtr,h=this.modelUniformStagingPtr+64;if(ie.invert(p,f),ie.transpose(h,p),this.queue.writeBuffer(m,0,r,f,64),this.queue.writeBuffer(m,64,r,h,64),e.setBindGroup(0,d),l.passKind==="node-points")e.draw(6,u.nodeCount);else if(l.passKind==="edge-lines")e.draw(2,u.edgeCount);else if(l.passKind==="node-solid"){if(!l.geometry)continue;l.geometry.isIndexed?e.drawIndexed(l.geometry.indexCount,u.nodeCount):e.draw(l.geometry.vertexCount,u.nodeCount)}else{if(!l.geometry)continue;l.geometry.isIndexed?e.drawIndexed(l.geometry.indexCount,u.edgeCount):e.draw(l.geometry.vertexCount,u.edgeCount)}}}executeTransparentMergedDrawList(e){this.transparentMergedDrawList.length=0;for(let f of this.transparentDrawList)this.transparentMergedDrawList.push(f);for(let f of this.transparentGlyphFieldDrawList)this.transparentMergedDrawList.push(f);for(let f of this.transparentPointCloudDrawList)this.transparentMergedDrawList.push(f);for(let f of this.transparentNodeLinkDrawList)this.transparentMergedDrawList.push(f);if(this.transparentMergedDrawList.length===0)return;let t=f=>"mesh"in f?0:"field"in f?1:"cloud"in f?2:3;this.transparentMergedDrawList.sort((f,p)=>{let h=p.sortKey-f.sortKey;if(h!==0)return h;let g=f.pipelineId-p.pipelineId;if(g!==0)return g;let b="mesh"in f,P="mesh"in p;if(b&&P){let S=f,R=p;return S.materialId-R.materialId||S.geometryId-R.geometryId||S.vertexSourceId-R.vertexSourceId||(S.skinned?1:0)-(R.skinned?1:0)||(S.skinned8?1:0)-(R.skinned8?1:0)}let v="cloud"in f,x="cloud"in p;if(v&&x){let S=f,R=p;return S.cloudId-R.cloudId}let T="field"in f,w="field"in p;if(T&&w){let S=f,R=p;return S.geometryId-R.geometryId||S.fieldId-R.fieldId}let M="link"in f,B="link"in p;if(M&&B){let S=f,R=p;return S.geometryId-R.geometryId||S.linkId-R.linkId}return t(f)-t(p)});let r=de.bytes(),i=null,o=null,a=null,s=-1,l=!1,u=!1,c=null,m=null,d=null;for(let f=0;f<this.transparentMergedDrawList.length;f++){let p=this.transparentMergedDrawList[f];if("mesh"in p){let h=p,g=h.mesh,b=h.geometry,P=h.material;if(h.pipeline!==i&&(e.setPipeline(h.pipeline),i=h.pipeline,o=null,a=null,s=-1,l=!1,u=!1,c=null,m=null,d=null),b!==a&&b.upload(this.device),P!==o&&this.ensureMaterialBindGroup(P),P!==o&&(e.setBindGroup(1,P.bindGroup),o=P),b!==a||h.vertexSourceId!==s||h.skinned!==l||h.skinned8!==u){let S=Qt(g,this.device,this.queue);e.setVertexBuffer(0,S.positionBuffer),e.setVertexBuffer(1,S.normalBuffer),e.setVertexBuffer(2,b.uvBuffer),e.setVertexBuffer(3,b.uv1Buffer);let R=P instanceof J;R&&e.setVertexBuffer(4,b.tangentBuffer),h.skinned&&(R?e.setVertexBuffer(5,b.skinInfluenceBuffer):(e.setVertexBuffer(4,b.jointsBuffer),e.setVertexBuffer(5,b.weightsBuffer),h.skinned8&&(e.setVertexBuffer(6,b.joints1Buffer),e.setVertexBuffer(7,b.weights1Buffer)))),b.isIndexed&&e.setIndexBuffer(b.indexBuffer,"uint32"),a=b,s=h.vertexSourceId,l=h.skinned,u=h.skinned8}if(h.skinned){let S=g.skin;if(S){S.ensureGpuResources(this.device,this.skinBindGroupLayout);let R=S.jointCount|0,G=W.allocF32(R*16);Gt.computeJointMatricesTo(G,S.skin.jointIndicesPtr,R,S.skin.invBindPtr,K.global().worldPtr,S.bindMatrixPtr),this.queue.writeBuffer(S.boneBuffer,0,r,G,R*64),e.setBindGroup(2,S.bindGroup)}}this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let v=this.modelBufferIndex++,x=this.modelUniformBuffers[v],T=this.globalBindGroups[v],w=g.transform.worldMatrixPtr,M=this.modelUniformStagingPtr,B=this.modelUniformStagingPtr+64;ie.invert(M,w),ie.transpose(B,M),this.queue.writeBuffer(x,0,r,w,64),this.queue.writeBuffer(x,64,r,B,64),e.setBindGroup(0,T),b.isIndexed?e.drawIndexed(b.indexCount):e.draw(b.vertexCount);continue}if("field"in p){let h=p,g=h.field,b=h.geometry;if(!g.visible||g.instanceCount<=0||(this.ensureGlyphFieldBindGroup(g),!g.bindGroup))continue;h.pipeline!==i&&(e.setPipeline(h.pipeline),i=h.pipeline,o=null,a=null,s=-1,l=!1,u=!1,c=null,m=null),b!==a&&(b.upload(this.device),e.setVertexBuffer(0,b.positionBuffer),e.setVertexBuffer(1,b.normalBuffer),b.isIndexed&&e.setIndexBuffer(b.indexBuffer,"uint32"),a=b),g!==m&&(e.setBindGroup(1,g.bindGroup),m=g,c=null,o=null,d=null),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let P=this.modelBufferIndex++,v=this.modelUniformBuffers[P],x=this.globalBindGroups[P],T=g.transform.worldMatrixPtr,w=this.modelUniformStagingPtr,M=this.modelUniformStagingPtr+64;ie.invert(w,T),ie.transpose(M,w),this.queue.writeBuffer(v,0,r,T,64),this.queue.writeBuffer(v,64,r,M,64),e.setBindGroup(0,x),b.isIndexed?e.drawIndexed(b.indexCount,g.instanceCount):e.draw(b.vertexCount,g.instanceCount);continue}if("cloud"in p){let h=p,g=h.cloud;if(!g.visible||g.pointCount<=0||(this.ensurePointCloudBindGroup(g),!g.bindGroup))continue;h.pipeline!==i&&(e.setPipeline(h.pipeline),i=h.pipeline,o=null,a=null,s=-1,l=!1,u=!1,c=null,m=null,d=null),g!==c&&(e.setBindGroup(1,g.bindGroup),c=g,m=null,o=null,d=null),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let b=this.modelBufferIndex++,P=this.modelUniformBuffers[b],v=this.globalBindGroups[b],x=g.transform.worldMatrixPtr,T=this.modelUniformStagingPtr,w=this.modelUniformStagingPtr+64;ie.invert(T,x),ie.transpose(w,T),this.queue.writeBuffer(P,0,r,x,64),this.queue.writeBuffer(P,64,r,w,64),e.setBindGroup(0,v),e.draw(6,g.pointCount);continue}if("link"in p){let h=p,g=h.link;if(this.ensureNodeLinkBindGroup(g),!g.bindGroup)continue;h.pipeline!==i&&(e.setPipeline(h.pipeline),i=h.pipeline,o=null,a=null,s=-1,l=!1,u=!1,c=null,m=null,d=null),h.geometry&&h.geometry!==a&&(h.geometry.upload(this.device),e.setVertexBuffer(0,h.geometry.positionBuffer),e.setVertexBuffer(1,h.geometry.normalBuffer),h.geometry.isIndexed&&e.setIndexBuffer(h.geometry.indexBuffer,"uint32"),a=h.geometry),g!==d&&(e.setBindGroup(1,g.bindGroup),d=g,c=null,m=null,o=null),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let b=this.modelBufferIndex++,P=this.modelUniformBuffers[b],v=this.globalBindGroups[b],x=g.transform.worldMatrixPtr,T=this.modelUniformStagingPtr,w=this.modelUniformStagingPtr+64;if(ie.invert(T,x),ie.transpose(w,T),this.queue.writeBuffer(P,0,r,x,64),this.queue.writeBuffer(P,64,r,w,64),e.setBindGroup(0,v),h.passKind==="node-points")e.draw(6,g.nodeCount);else if(h.passKind==="edge-lines")e.draw(2,g.edgeCount);else if(h.passKind==="node-solid"){if(!h.geometry)continue;h.geometry.isIndexed?e.drawIndexed(h.geometry.indexCount,g.nodeCount):e.draw(h.geometry.vertexCount,g.nodeCount)}else{if(!h.geometry)continue;h.geometry.isIndexed?e.drawIndexed(h.geometry.indexCount,g.edgeCount):e.draw(h.geometry.vertexCount,g.edgeCount)}continue}}}executeMeshPickDrawList(e,t){let r=de.bytes(),i=null,o=null,a=-1,s=!1,l=!1;for(let u=0;u<t.length;u++){let c=t[u],m=c.mesh,d=c.geometry;if(!m.visible)continue;let f=this.getOrCreatePickMeshPipeline(c.material,c.skinned,c.skinned8,c.mirrored);if(f!==i&&(e.setPipeline(f),i=f,o=null,a=-1,s=!1,l=!1),d!==o||c.vertexSourceId!==a||c.skinned!==s||c.skinned8!==l){d.upload(this.device);let x=Qt(m,this.device,this.queue);e.setVertexBuffer(0,x.positionBuffer),c.skinned&&(e.setVertexBuffer(3,d.jointsBuffer),e.setVertexBuffer(4,d.weightsBuffer),c.skinned8&&(e.setVertexBuffer(5,d.joints1Buffer),e.setVertexBuffer(6,d.weights1Buffer))),d.isIndexed&&e.setIndexBuffer(d.indexBuffer,"uint32"),o=d,a=c.vertexSourceId,s=c.skinned,l=c.skinned8}this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let p=this.modelBufferIndex++,h=this.modelUniformBuffers[p],g=this.globalBindGroups[p],b=m.transform.worldMatrixPtr,P=this.modelUniformStagingPtr,v=this.modelUniformStagingPtr+64;if(ie.invert(P,b),ie.transpose(v,P),this.queue.writeBuffer(h,0,r,b,64),this.queue.writeBuffer(h,64,r,v,64),this.writePickUniform(p,this.getObjectId(m),0),e.setBindGroup(0,g),e.setBindGroup(1,this.pickBindGroups[p]),c.skinned){let x=m.skin;if(x){x.ensureGpuResources(this.device,this.skinBindGroupLayout);let T=x.jointCount|0,w=W.allocF32(T*16);Gt.computeJointMatricesTo(w,x.skin.jointIndicesPtr,T,x.skin.invBindPtr,K.global().worldPtr,x.bindMatrixPtr),this.queue.writeBuffer(x.boneBuffer,0,r,w,T*64),e.setBindGroup(2,x.bindGroup)}}d.isIndexed?e.drawIndexed(d.indexCount):e.draw(d.vertexCount)}}executePointCloudPickDrawList(e,t){let r=de.bytes(),i=null,o=null;for(let a=0;a<t.length;a++){let s=t[a].cloud;if(!s.visible||s.pointCount<=0||(this.ensurePointCloudBindGroup(s),!s.bindGroup))continue;let l=this.getOrCreatePickPointCloudPipeline();l!==i&&(e.setPipeline(l),i=l,o=null),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let u=this.modelBufferIndex++,c=this.modelUniformBuffers[u],m=this.globalBindGroups[u],d=s.transform.worldMatrixPtr,f=this.modelUniformStagingPtr,p=this.modelUniformStagingPtr+64;ie.invert(f,d),ie.transpose(p,f),this.queue.writeBuffer(c,0,r,d,64),this.queue.writeBuffer(c,64,r,p,64),this.writePickUniform(u,this.getObjectId(s),0),e.setBindGroup(0,m),s!==o&&(e.setBindGroup(1,s.bindGroup),o=s),e.setBindGroup(2,this.pickBindGroups[u]),e.draw(6,s.pointCount)}}executeGlyphPickDrawList(e,t){let r=de.bytes(),i=null,o=null,a=null;for(let s=0;s<t.length;s++){let l=t[s],u=l.field,c=l.geometry;if(!u.visible||u.instanceCount<=0||(this.ensureGlyphFieldBindGroup(u),!u.bindGroup))continue;let m=this.getOrCreatePickGlyphFieldPipeline(u);m!==i&&(e.setPipeline(m),i=m,o=null,a=null),c!==o&&(c.upload(this.device),e.setVertexBuffer(0,c.positionBuffer),c.isIndexed&&e.setIndexBuffer(c.indexBuffer,"uint32"),o=c),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let d=this.modelBufferIndex++,f=this.modelUniformBuffers[d],p=this.globalBindGroups[d],h=u.transform.worldMatrixPtr,g=this.modelUniformStagingPtr,b=this.modelUniformStagingPtr+64;ie.invert(g,h),ie.transpose(b,g),this.queue.writeBuffer(f,0,r,h,64),this.queue.writeBuffer(f,64,r,b,64),this.writePickUniform(d,this.getObjectId(u),0),e.setBindGroup(0,p),u!==a&&(e.setBindGroup(1,u.bindGroup),a=u),e.setBindGroup(2,this.pickBindGroups[d]),c.isIndexed?e.drawIndexed(c.indexCount,u.instanceCount):e.draw(c.vertexCount,u.instanceCount)}}executeNodeLinkPickDrawList(e,t){let r=de.bytes(),i=null,o=null,a=null;for(let s=0;s<t.length;s++){let l=t[s],u=l.link;if(this.ensureNodeLinkBindGroup(u),!u.bindGroup)continue;let c=this.getOrCreatePickNodeLinkPipeline(l.passKind,u);c!==i&&(e.setPipeline(c),i=c,o=null,a=null),l.geometry&&l.geometry!==o&&(l.geometry.upload(this.device),e.setVertexBuffer(0,l.geometry.positionBuffer),l.geometry.isIndexed&&e.setIndexBuffer(l.geometry.indexBuffer,"uint32"),o=l.geometry),this.modelBufferIndex>=this.modelUniformBuffers.length&&this.ensureModelBufferPool(this.modelBufferIndex+1);let m=this.modelBufferIndex++,d=this.modelUniformBuffers[m],f=this.globalBindGroups[m],p=u.transform.worldMatrixPtr,h=this.modelUniformStagingPtr,g=this.modelUniformStagingPtr+64;ie.invert(h,p),ie.transpose(g,h),this.queue.writeBuffer(d,0,r,p,64),this.queue.writeBuffer(d,64,r,g,64);let b=l.passKind==="edge-lines"||l.passKind==="edge-cylinders"?u.nodeCount:0;if(this.writePickUniform(m,this.getObjectId(u),b),e.setBindGroup(0,f),u!==a&&(e.setBindGroup(1,u.bindGroup),a=u),e.setBindGroup(2,this.pickBindGroups[m]),l.passKind==="node-points")e.draw(6,u.nodeCount);else if(l.passKind==="edge-lines")e.draw(2,u.edgeCount);else if(l.passKind==="node-solid"){if(!l.geometry)continue;l.geometry.isIndexed?e.drawIndexed(l.geometry.indexCount,u.nodeCount):e.draw(l.geometry.vertexCount,u.nodeCount)}else{if(!l.geometry)continue;l.geometry.isIndexed?e.drawIndexed(l.geometry.indexCount,u.edgeCount):e.draw(l.geometry.vertexCount,u.edgeCount)}}}drawInstancedRun(e,t,r,i,o,a){let s=W.alloc(a*4,4),l=K.global().u32(),u=s>>>2;for(let h=0;h<a;h++)l[u+h]=i[o+h].mesh.transform.worldMatrixPtr>>>0;let c=W.allocF32(a*32);At.packModelNormalMat4FromPtrs(c,s,a);let m=a*this.INSTANCE_STRIDE_BYTES,d=this.instanceBufferOffset,f=d+m;this.ensureInstanceBuffer(f);let p=de.bytes();this.queue.writeBuffer(this.instanceBuffer,d,p,c,m),e.setBindGroup(0,this.globalBindGroups[0]),r instanceof J?(e.setVertexBuffer(4,t.tangentBuffer),e.setVertexBuffer(5,this.instanceBuffer,d,m)):e.setVertexBuffer(4,this.instanceBuffer,d,m),t.isIndexed?e.drawIndexed(t.indexCount,a):e.draw(t.vertexCount,a),this.instanceBufferOffset=f}getOcclusionReduceBindGroupLayout(){return this.occlusionReduceBindGroupLayout?this.occlusionReduceBindGroupLayout:(this.occlusionReduceBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"unfilterable-float",viewDimension:"2d"}}]}),this.occlusionReduceBindGroupLayout)}getOrCreateOcclusionReducePipeline(){if(this.occlusionReducePipeline)return this.occlusionReducePipeline;let e=this.shaderCache.get(bi);return e||(e=this.device.createShaderModule({code:bi}),this.shaderCache.set(bi,e)),this.occlusionReducePipeline=this.device.createRenderPipeline({layout:this.device.createPipelineLayout({bindGroupLayouts:[this.getOcclusionReduceBindGroupLayout()]}),vertex:{module:e,entryPoint:"vs_main",buffers:[]},fragment:{module:e,entryPoint:"fs_main",targets:[{format:"r32float"}]},primitive:{topology:"triangle-list",cullMode:"none"}}),this.occlusionReducePipeline}getOrCreateOcclusionReduceBindGroup(e){if(!this.occlusionHierarchyTexture)throw new Error("Renderer: occlusion hierarchy texture is not initialized.");let t=`occlusion-reduce:${this.getObjectId(this.occlusionHierarchyTexture)}:${e}`,r=this.occlusionReduceBindGroups.get(t);if(r)return r;let i=this.device.createBindGroup({layout:this.getOcclusionReduceBindGroupLayout(),entries:[{binding:0,resource:this.occlusionHierarchyMipViews[e]}]});return this.occlusionReduceBindGroups.set(t,i),i}getOrCreateOcclusionMeshPipeline(e){let t=this.getCullMode(e.material.cullMode),r=`occlusion:mesh:${t}:${e.mirrored?"cw":"ccw"}`,i=this.pipelineCache.get(r);if(i)return i;let o=this.shaderCache.get(gi);o||(o=this.device.createShaderModule({code:gi}),this.shaderCache.set(gi,o));let a=this.device.createRenderPipeline({layout:this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout]}),vertex:{module:o,entryPoint:"vs_main",buffers:[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}]},fragment:{module:o,entryPoint:"fs_main",targets:[{format:"r32float"}]},primitive:{topology:"triangle-list",cullMode:t,frontFace:e.mirrored?"cw":"ccw"},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(r,a),a}getOrCreateOcclusionPointCloudPipeline(){let e="occlusion:pointcloud",t=this.pipelineCache.get(e);if(t)return t;let r=this.shaderCache.get(vi);r||(r=this.device.createShaderModule({code:vi}),this.shaderCache.set(vi,r));let i=this.device.createRenderPipeline({layout:this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getPointCloudBindGroupLayout()]}),vertex:{module:r,entryPoint:"vs_main",buffers:[]},fragment:{module:r,entryPoint:"fs_main",targets:[{format:"r32float"}]},primitive:{topology:"triangle-list",cullMode:"none"},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(e,i),i}getOrCreateOcclusionGlyphFieldPipeline(e){let t=this.getCullMode(e.cullMode),r=`occlusion:glyphfield:${t}`,i=this.pipelineCache.get(r);if(i)return i;let o=this.shaderCache.get(yi);o||(o=this.device.createShaderModule({code:yi}),this.shaderCache.set(yi,o));let a=this.device.createRenderPipeline({layout:this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getGlyphFieldBindGroupLayout()]}),vertex:{module:o,entryPoint:"vs_main",buffers:[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}]},fragment:{module:o,entryPoint:"fs_main",targets:[{format:"r32float"}]},primitive:{topology:"triangle-list",cullMode:t},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(r,a),a}getOrCreateOcclusionNodeLinkPipeline(e,t){let r=`occlusion:nodelink:${t}:${e.cullMode}`,i=this.pipelineCache.get(r);if(i)return i;let o=this.shaderCache.get(xi);o||(o=this.device.createShaderModule({code:xi}),this.shaderCache.set(xi,o));let a="vs_node_points",s=[],l="triangle-list",u="none";t==="node-solid"?(a="vs_node_solid",s=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}],u=this.getCullMode(e.cullMode)):t==="edge-lines"?(a="vs_edge_lines",l="line-list"):t==="edge-cylinders"&&(a="vs_edge_cylinders",s=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}],u=this.getCullMode(e.cullMode));let c=this.device.createRenderPipeline({layout:this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getNodeLinkBindGroupLayout()]}),vertex:{module:o,entryPoint:a,buffers:s},fragment:{module:o,entryPoint:"fs_main",targets:[{format:"r32float"}]},primitive:{topology:l,cullMode:u},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(r,c),c}getOrCreatePipeline(e,t=!1,r=!1,i=!1,o=!1,a=!1){if(t&&r)throw new Error("Renderer: instanced + skinned pipelines are not supported (attribute layout conflict).");i&&!r&&(r=!0);let s=this.getPipelineCacheKey(e,t,r,i,o,a),l=this.pipelineCache.get(s);if(l)return l;let u=e instanceof J&&e.usesTransmissionLayout(),c=e.getShaderCode({instanced:t,skinned:r,skinned8:i,transmission:u}),m=this.shaderCache.get(c);m||(m=this.device.createShaderModule({code:c}),this.shaderCache.set(c,m));let d=e.createBindGroupLayout(this.device),f=[this.globalBindGroupLayout,d];r&&f.push(this.skinBindGroupLayout);let p=this.device.createPipelineLayout({bindGroupLayouts:f}),h,g=e instanceof J;return t&&g?h=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:11,offset:0,format:"float32x2"}]},{arrayStride:16,attributes:[{shaderLocation:12,offset:0,format:"float32x4"}]},{arrayStride:this.INSTANCE_STRIDE_BYTES,stepMode:"instance",attributes:[{shaderLocation:3,offset:0,format:"float32x4"},{shaderLocation:4,offset:16,format:"float32x4"},{shaderLocation:5,offset:32,format:"float32x4"},{shaderLocation:6,offset:48,format:"float32x4"},{shaderLocation:7,offset:64,format:"float32x4"},{shaderLocation:8,offset:80,format:"float32x4"},{shaderLocation:9,offset:96,format:"float32x4"},{shaderLocation:10,offset:112,format:"float32x4"}]}]:t?h=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:11,offset:0,format:"float32x2"}]},{arrayStride:this.INSTANCE_STRIDE_BYTES,stepMode:"instance",attributes:[{shaderLocation:3,offset:0,format:"float32x4"},{shaderLocation:4,offset:16,format:"float32x4"},{shaderLocation:5,offset:32,format:"float32x4"},{shaderLocation:6,offset:48,format:"float32x4"},{shaderLocation:7,offset:64,format:"float32x4"},{shaderLocation:8,offset:80,format:"float32x4"},{shaderLocation:9,offset:96,format:"float32x4"},{shaderLocation:10,offset:112,format:"float32x4"}]}]:i&&g?h=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:11,offset:0,format:"float32x2"}]},{arrayStride:16,attributes:[{shaderLocation:12,offset:0,format:"float32x4"}]},{arrayStride:48,attributes:[{shaderLocation:3,offset:0,format:"uint16x4"},{shaderLocation:4,offset:8,format:"float32x4"},{shaderLocation:5,offset:24,format:"uint16x4"},{shaderLocation:6,offset:32,format:"float32x4"}]}]:i?h=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:11,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:3,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:4,offset:0,format:"float32x4"}]},{arrayStride:8,attributes:[{shaderLocation:5,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:6,offset:0,format:"float32x4"}]}]:r&&g?h=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:11,offset:0,format:"float32x2"}]},{arrayStride:16,attributes:[{shaderLocation:12,offset:0,format:"float32x4"}]},{arrayStride:24,attributes:[{shaderLocation:3,offset:0,format:"uint16x4"},{shaderLocation:4,offset:8,format:"float32x4"}]}]:r?h=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:11,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:3,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:4,offset:0,format:"float32x4"}]}]:g?h=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:11,offset:0,format:"float32x2"}]},{arrayStride:16,attributes:[{shaderLocation:12,offset:0,format:"float32x4"}]}]:h=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:2,offset:0,format:"float32x2"}]},{arrayStride:8,attributes:[{shaderLocation:11,offset:0,format:"float32x2"}]}],l=this.device.createRenderPipeline({layout:p,vertex:{module:m,entryPoint:"vs_main",buffers:h},fragment:{module:m,entryPoint:"fs_main",targets:[{format:this.format,blend:this.getBlendState(e.blendMode)}]},primitive:{topology:"triangle-list",cullMode:this.getCullMode(e.cullMode),frontFace:o?"cw":"ccw"},depthStencil:{format:"depth24plus",depthWriteEnabled:a?!1:e.depthWrite,depthCompare:e.depthTest?"less":"always"}}),this.pipelineCache.set(s,l),l}getOrCreatePickMeshPipeline(e,t,r,i=!1){r&&!t&&(t=!0);let o=this.getCullMode(e.cullMode),a=`pick:mesh:${o}:${i?"cw":"ccw"}:${r?"skin8":t?"skin4":"noskin"}`,s=this.pipelineCache.get(a);if(s)return s;let l=r?Qa:t?Za:Ya,u=this.shaderCache.get(l);u||(u=this.device.createShaderModule({code:l}),this.shaderCache.set(l,u));let c=[this.globalBindGroupLayout,this.getPickBindGroupLayout()];t&&c.push(this.skinBindGroupLayout);let m=this.device.createPipelineLayout({bindGroupLayouts:c}),d;r?d=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:3,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:4,offset:0,format:"float32x4"}]},{arrayStride:8,attributes:[{shaderLocation:5,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:6,offset:0,format:"float32x4"}]}]:t?d=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:8,attributes:[{shaderLocation:3,offset:0,format:"uint16x4"}]},{arrayStride:16,attributes:[{shaderLocation:4,offset:0,format:"float32x4"}]}]:d=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}];let f=this.device.createRenderPipeline({layout:m,vertex:{module:u,entryPoint:"vs_main",buffers:d},fragment:{module:u,entryPoint:"fs_main",targets:[{format:"rg32uint"},{format:"r32float"}]},primitive:{topology:"triangle-list",cullMode:o,frontFace:i?"cw":"ccw"},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(a,f),f}getOrCreatePickPointCloudPipeline(){let e="pick:pointcloud",t=this.pipelineCache.get(e);if(t)return t;let r=this.shaderCache.get(fi);r||(r=this.device.createShaderModule({code:fi}),this.shaderCache.set(fi,r));let i=this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getPointCloudBindGroupLayout(),this.getPickBindGroupLayout()]}),o=this.device.createRenderPipeline({label:e,layout:i,vertex:{module:r,entryPoint:"vs_main",buffers:[]},fragment:{module:r,entryPoint:"fs_main",targets:[{format:"rg32uint"},{format:"r32float"}]},primitive:{topology:"triangle-list",cullMode:"none"},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(e,o),o}getOrCreatePickGlyphFieldPipeline(e){let t=this.getCullMode(e.cullMode),r=`pick:glyphfield:${t}`,i=this.pipelineCache.get(r);if(i)return i;let o=this.shaderCache.get(pi);o||(o=this.device.createShaderModule({code:pi}),this.shaderCache.set(pi,o));let a=this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getGlyphFieldBindGroupLayout(),this.getPickBindGroupLayout()]}),s=this.device.createRenderPipeline({label:r,layout:a,vertex:{module:o,entryPoint:"vs_main",buffers:[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}]},fragment:{module:o,entryPoint:"fs_main",targets:[{format:"rg32uint"},{format:"r32float"}]},primitive:{topology:"triangle-list",cullMode:t},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(r,s),s}getOrCreatePickNodeLinkPipeline(e,t){let r=e==="node-solid"||e==="edge-cylinders"?this.getCullMode(t.cullMode):"none",i=`pick:nodelink:${e}:${r}`,o=this.pipelineCache.get(i);if(o)return o;let a=this.shaderCache.get(hi);a||(a=this.device.createShaderModule({code:hi}),this.shaderCache.set(hi,a));let s=this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getNodeLinkBindGroupLayout(),this.getPickBindGroupLayout()]}),l="vs_pick_node_points",u=[],c="triangle-list";e==="node-solid"?(l="vs_pick_node_solid",u=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}],c="triangle-list"):e==="edge-lines"?(l="vs_pick_edge_lines",u=[],c="line-list"):e==="edge-cylinders"&&(l="vs_pick_edge_cylinders",u=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}],c="triangle-list");let m=this.device.createRenderPipeline({label:i,layout:s,vertex:{module:a,entryPoint:l,buffers:u},fragment:{module:a,entryPoint:"fs_pick",targets:[{format:"rg32uint"},{format:"r32float"}]},primitive:{topology:c,cullMode:r},depthStencil:{format:"depth24plus",depthWriteEnabled:!0,depthCompare:"less"}});return this.pipelineCache.set(i,m),m}getPipelineCacheKey(e,t,r,i,o,a=!1){let s=this.getObjectId(e.constructor),u=e.constructor===ke||e.constructor===J||e.constructor===He?`${s}`:`${s}_${this.getObjectId(e)}`,c=a?"no-depth-write":e.depthWrite?"depth-write":"no-depth-write",m=e instanceof J&&e.usesTransmissionLayout();return`${u}_${e.blendMode}_${e.cullMode}_${c}_${e.depthTest}_${m?"transmission":"standard"}_${o?"cw":"ccw"}_${t?"inst":"mesh"}_${i?"skin8":r?"skin4":"noskin"}`}isMirroredWorldMatrix(e,t){let r=e[t+0],i=e[t+4],o=e[t+8],a=e[t+1],s=e[t+5],l=e[t+9],u=e[t+2],c=e[t+6],m=e[t+10];return r*(s*m-l*c)-i*(a*m-l*u)+o*(a*c-s*u)<0}getBlendState(e){switch(e){case"opaque":return;case"transparent":return{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha",operation:"add"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha",operation:"add"}};case"additive":return{color:{srcFactor:"src-alpha",dstFactor:"one",operation:"add"},alpha:{srcFactor:"one",dstFactor:"one",operation:"add"}}}}getCullMode(e){switch(e){case"none":return"none";case"back":return"back";case"front":return"front"}}getMaterialBindGroupKey(e){if(e instanceof ke){let t=e.baseColorTexture;return`unlit:${t?.id??0}:${t?.revision??0}`}if(e instanceof J){let t=e.baseColorTexture,r=e.metallicRoughnessTexture,i=e.normalTexture,o=e.occlusionTexture,a=e.emissiveTexture,s=e.extensions,l=s.clearcoat,u=s.specular,c=s.sheen,m=s.iridescence,d=s.anisotropy,f=s.transmission,p=s.volume,h=s.diffuseTransmission,g=l?.texture??null,b=l?.roughnessTexture??null,P=l?.normalTexture??null,v=u?.texture??null,x=u?.colorTexture??null,T=c?.colorTexture??null,w=c?.roughnessTexture??null,M=m?.texture??null,B=m?.thicknessTexture??null,S=d?.texture??null,R=f?.texture??null,G=p?.thicknessTexture??null,L=h?.texture??null,U=h?.colorTexture??null;return`standard:${t?.id??0}:${t?.revision??0}:${r?.id??0}:${r?.revision??0}:${i?.id??0}:${i?.revision??0}:${o?.id??0}:${o?.revision??0}:${a?.id??0}:${a?.revision??0}:${g?.id??0}:${g?.revision??0}:${b?.id??0}:${b?.revision??0}:${P?.id??0}:${P?.revision??0}:${v?.id??0}:${v?.revision??0}:${x?.id??0}:${x?.revision??0}:${T?.id??0}:${T?.revision??0}:${w?.id??0}:${w?.revision??0}:${M?.id??0}:${M?.revision??0}:${B?.id??0}:${B?.revision??0}:${S?.id??0}:${S?.revision??0}:${R?.id??0}:${R?.revision??0}:${G?.id??0}:${G?.revision??0}:${L?.id??0}:${L?.revision??0}:${U?.id??0}:${U?.revision??0}:${this.transmissionSourceRevision}`}return e instanceof He?`data:${e.dataBuffer?this.getObjectId(e.dataBuffer):0}:${e.getColormapKey()}`:"custom"}ensureMaterialBindGroup(e){if(e.uniformBuffer||(e.uniformBuffer=this.device.createBuffer({size:e.getUniformBufferSize(),usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST})),e.dirty){let i=e.getUniformData();this.queue.writeBuffer(e.uniformBuffer,0,i.buffer,i.byteOffset,i.byteLength),e.markClean()}e instanceof He&&e.upload(this.device,this.queue);let t=this.getMaterialBindGroupKey(e);if(e.bindGroup&&e.bindGroupKey===t)return;let r=e.createBindGroupLayout(this.device);if(e instanceof ke){let i=e.baseColorTexture,o=i?i.getSampler(this.device,this.fallbackSampler):this.fallbackSampler,a=i?i.getView(this.device,this.queue,"srgb",this.fallbackWhiteViewSrgb):this.fallbackWhiteViewSrgb;e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:o},{binding:2,resource:a}]}),e.bindGroupKey=t;return}if(e instanceof J){let i=e.baseColorTexture,o=e.metallicRoughnessTexture,a=e.normalTexture,s=e.occlusionTexture,l=e.emissiveTexture,u=e.extensions,c=u.clearcoat,m=u.specular,d=u.sheen,f=u.iridescence,p=u.anisotropy,h=u.transmission,g=u.volume,b=u.diffuseTransmission,P=c?.texture??null,v=c?.roughnessTexture??null,x=c?.normalTexture??null,T=m?.texture??null,w=m?.colorTexture??null,M=d?.colorTexture??null,B=d?.roughnessTexture??null,S=f?.texture??null,R=f?.thicknessTexture??null,G=p?.texture??null,L=h?.texture??null,U=g?.thicknessTexture??null,F=b?.texture??null,D=b?.colorTexture??null,k=[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:i?i.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:2,resource:i?i.getView(this.device,this.queue,"srgb",this.fallbackWhiteViewSrgb):this.fallbackWhiteViewSrgb},{binding:3,resource:o?o.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:4,resource:o?o.getView(this.device,this.queue,"linear",this.fallbackMRViewLinear):this.fallbackMRViewLinear},{binding:5,resource:a?a.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:6,resource:a?a.getView(this.device,this.queue,"linear",this.fallbackNormalViewLinear):this.fallbackNormalViewLinear},{binding:7,resource:s?s.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:8,resource:s?s.getView(this.device,this.queue,"linear",this.fallbackOcclusionViewLinear):this.fallbackOcclusionViewLinear},{binding:9,resource:l?l.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:10,resource:l?l.getView(this.device,this.queue,"srgb",this.fallbackWhiteViewSrgb):this.fallbackWhiteViewSrgb},{binding:11,resource:P?P.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:12,resource:P?P.getView(this.device,this.queue,"linear",this.fallbackWhiteViewLinear):this.fallbackWhiteViewLinear},{binding:13,resource:v?v.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:14,resource:v?v.getView(this.device,this.queue,"linear",this.fallbackWhiteViewLinear):this.fallbackWhiteViewLinear},{binding:15,resource:x?x.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:16,resource:x?x.getView(this.device,this.queue,"linear",this.fallbackNormalViewLinear):this.fallbackNormalViewLinear},{binding:17,resource:T?T.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:18,resource:T?T.getView(this.device,this.queue,"linear",this.fallbackWhiteViewLinear):this.fallbackWhiteViewLinear},{binding:19,resource:w?w.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:20,resource:w?w.getView(this.device,this.queue,"srgb",this.fallbackWhiteViewSrgb):this.fallbackWhiteViewSrgb}];e.usesTransmissionLayout()?k.push({binding:21,resource:L?L.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:22,resource:L?L.getView(this.device,this.queue,"linear",this.fallbackWhiteViewLinear):this.fallbackWhiteViewLinear},{binding:23,resource:U?U.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:24,resource:U?U.getView(this.device,this.queue,"linear",this.fallbackWhiteViewLinear):this.fallbackWhiteViewLinear},{binding:25,resource:F?F.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:26,resource:F?F.getView(this.device,this.queue,"linear",this.fallbackWhiteViewLinear):this.fallbackWhiteViewLinear},{binding:27,resource:D?D.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:28,resource:D?D.getView(this.device,this.queue,"srgb",this.fallbackWhiteViewSrgb):this.fallbackWhiteViewSrgb},{binding:29,resource:this.fallbackSampler},{binding:30,resource:this.transmissionSourceView??this.fallbackWhiteViewLinear}):k.push({binding:21,resource:M?M.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:22,resource:M?M.getView(this.device,this.queue,"srgb",this.fallbackWhiteViewSrgb):this.fallbackWhiteViewSrgb},{binding:23,resource:B?B.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:24,resource:B?B.getView(this.device,this.queue,"linear",this.fallbackWhiteViewLinear):this.fallbackWhiteViewLinear},{binding:25,resource:S?S.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:26,resource:S?S.getView(this.device,this.queue,"linear",this.fallbackWhiteViewLinear):this.fallbackWhiteViewLinear},{binding:27,resource:R?R.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:28,resource:R?R.getView(this.device,this.queue,"linear",this.fallbackWhiteViewLinear):this.fallbackWhiteViewLinear},{binding:29,resource:G?G.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:30,resource:G?G.getView(this.device,this.queue,"linear",this.fallbackAnisotropyViewLinear):this.fallbackAnisotropyViewLinear}),e.bindGroup=this.device.createBindGroup({layout:r,entries:k}),e.bindGroupKey=t;return}if(e instanceof He){this.dataMaterialDummyDataBuffer||(this.dataMaterialDummyDataBuffer=this.device.createBuffer({size:4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.queue.writeBuffer(this.dataMaterialDummyDataBuffer,0,new Uint8Array(4)));let i=e.dataBuffer??this.dataMaterialDummyDataBuffer,o=e.getColormapForBinding().getGPUResources(this.device,this.queue);e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i}},{binding:2,resource:o.sampler},{binding:3,resource:o.view}]}),e.bindGroupKey=t;return}e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.uniformBuffer}}]}),e.bindGroupKey=t}materialSupportsInstancing(e){return e instanceof ke||e instanceof J}materialSupportsSkinning(e){return e instanceof ke||e instanceof J}ensureInstanceBuffer(e){if(this.instanceBuffer&&this.instanceBufferCapacityBytes>=e)return;this.instanceBuffer?.destroy();let t=this.instanceBufferCapacityBytes||this.INSTANCE_STRIDE_BYTES*256;for(;t<e;)t*=2;this.instanceBufferCapacityBytes=t,this.instanceBuffer=this.device.createBuffer({size:t,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}getPointCloudBindGroupLayout(){return this.pointCloudBindGroupLayout?this.pointCloudBindGroupLayout:(this.pointCloudBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:240}},{binding:2,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:3,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,texture:{sampleType:"float",viewDimension:"1d"}},{binding:4,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),this.pointCloudBindGroupLayout)}getPointCloudPipelineCacheKey(e){return["pointcloud",`blend=${e.blendMode}`,`depthTest=${e.depthTest?1:0}`,`depthWrite=${e.depthWrite?1:0}`,`fmt=${this.format}`].join("|")}getOrCreatePointCloudPipeline(e){let t=this.getPointCloudPipelineCacheKey(e),r=this.pipelineCache.get(t);if(r)return r;let i=this.shaderCache.get(mi);i||(i=this.device.createShaderModule({code:mi}),this.shaderCache.set(mi,i));let o=this.getPointCloudBindGroupLayout(),a=this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,o]}),s=this.getBlendState(e.blendMode),l=this.device.createRenderPipeline({label:t,layout:a,vertex:{module:i,entryPoint:"vs_main",buffers:[]},fragment:{module:i,entryPoint:"fs_main",targets:[{format:this.format,blend:s}]},primitive:{topology:"triangle-list",cullMode:"none"},depthStencil:e.depthTest?{format:"depth24plus",depthWriteEnabled:e.depthWrite,depthCompare:"less"}:void 0});return this.pipelineCache.set(t,l),l}getPointCloudBindGroupKey(e){let t=e.pointsBuffer,r=e.colorsBuffer,i=e.uniformBuffer;return`pointcloud:${t?this.getObjectId(t):0}:${r?this.getObjectId(r):0}:${i?this.getObjectId(i):0}:${e.getColormapKey()}`}ensurePointCloudBindGroup(e){if(e.upload(this.device,this.queue),!e.pointsBuffer||e.pointCount<=0)return;if(e.uniformBuffer||(e.uniformBuffer=this.device.createBuffer({size:e.getUniformBufferSize(),usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),e.bindGroupKey=null),e.dirtyUniforms){let o=e.getUniformData();this.queue.writeBuffer(e.uniformBuffer,0,o.buffer,o.byteOffset,o.byteLength),e.markUniformsClean()}if(!this.pointCloudDummyColorsBuffer){this.pointCloudDummyColorsBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});let o=new Float32Array([1,1,1,1]);this.queue.writeBuffer(this.pointCloudDummyColorsBuffer,0,o.buffer,o.byteOffset,o.byteLength)}let t=this.getPointCloudBindGroupKey(e);if(e.bindGroup&&e.bindGroupKey===t)return;let r=this.getPointCloudBindGroupLayout(),i=e.getColormapForBinding().getGPUResources(this.device,this.queue);e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.pointsBuffer}},{binding:1,resource:{buffer:e.uniformBuffer}},{binding:2,resource:i.sampler},{binding:3,resource:i.view},{binding:4,resource:{buffer:e.colorsBuffer??this.pointCloudDummyColorsBuffer}}]}),e.bindGroupKey=t}getGlyphFieldBindGroupLayout(){return this.glyphFieldBindGroupLayout?this.glyphFieldBindGroupLayout:(this.glyphFieldBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:240}},{binding:5,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:6,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float",viewDimension:"1d"}}]}),this.glyphFieldBindGroupLayout)}getOrCreateGlyphFieldPipeline(e){let t=`glyphfield:${this.format}:${e.blendMode}:${e.depthWrite?1:0}:${e.depthTest?1:0}:${e.cullMode}`,r=this.pipelineCache.get(t);if(r)return r;let i=Xa,o=this.shaderCache.get(i);o||(o=this.device.createShaderModule({code:i}),this.shaderCache.set(i,o));let a=this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getGlyphFieldBindGroupLayout()]}),s=this.device.createRenderPipeline({layout:a,vertex:{module:o,entryPoint:"vs_main",buffers:[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]}]},fragment:{module:o,entryPoint:"fs_main",targets:[{format:this.format,blend:this.getBlendState(e.blendMode)}]},primitive:{topology:"triangle-list",cullMode:this.getCullMode(e.cullMode)},depthStencil:e.depthTest||e.depthWrite?{format:"depth24plus",depthWriteEnabled:e.depthWrite,depthCompare:e.depthTest?"less":"always"}:void 0});return this.pipelineCache.set(t,s),s}getGlyphFieldBindGroupKey(e){let t=e.positionsBuffer,r=e.rotationsBuffer,i=e.scalesBuffer,o=e.attributesBuffer,a=e.uniformBuffer;return`glyphfield:${t?this.getObjectId(t):0}:${r?this.getObjectId(r):0}:${i?this.getObjectId(i):0}:${o?this.getObjectId(o):0}:${a?this.getObjectId(a):0}:${e.getColormapKey()}`}ensureGlyphFieldBindGroup(e){if(e.upload(this.device,this.queue),!e.positionsBuffer||!e.rotationsBuffer||!e.scalesBuffer||e.instanceCount<=0)return;if(e.uniformBuffer||(e.uniformBuffer=this.device.createBuffer({size:e.getUniformBufferSize(),usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),e.bindGroupKey=null),e.dirtyUniforms){let o=e.getUniformData();this.queue.writeBuffer(e.uniformBuffer,0,o.buffer,o.byteOffset,o.byteLength),e.markUniformsClean()}e.attributesBuffer||(this.glyphFieldDummyAttributesBuffer||(this.glyphFieldDummyAttributesBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),e.attributesBuffer=this.glyphFieldDummyAttributesBuffer,e.bindGroupKey=null);let t=this.getGlyphFieldBindGroupKey(e);if(e.bindGroup&&e.bindGroupKey===t)return;let r=this.getGlyphFieldBindGroupLayout(),i=e.getColormapForBinding().getGPUResources(this.device,this.queue);e.bindGroup=this.device.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:e.positionsBuffer}},{binding:1,resource:{buffer:e.rotationsBuffer}},{binding:2,resource:{buffer:e.scalesBuffer}},{binding:3,resource:{buffer:e.attributesBuffer}},{binding:4,resource:{buffer:e.uniformBuffer}},{binding:5,resource:i.sampler},{binding:6,resource:i.view}]}),e.bindGroupKey=t}getNodeLinkBindGroupLayout(){return this.nodeLinkBindGroupLayout?this.nodeLinkBindGroupLayout:(this.nodeLinkBindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:6,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:7,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform",minBindingSize:512}},{binding:8,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:9,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float",viewDimension:"1d"}},{binding:10,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:11,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float",viewDimension:"1d"}}]}),this.nodeLinkBindGroupLayout)}getNodeLinkPipelineCacheKey(e,t){let r=t==="node-solid"||t==="edge-cylinders"?e.cullMode:"none";return["nodelink",t,`blend=${e.blendMode}`,`depthTest=${e.depthTest?1:0}`,`depthWrite=${e.depthWrite?1:0}`,`cull=${r}`,`fmt=${this.format}`].join("|")}getOrCreateNodeLinkPipeline(e,t){let r=this.getNodeLinkPipelineCacheKey(e,t),i=this.pipelineCache.get(r);if(i)return i;let o=this.shaderCache.get(di);o||(o=this.device.createShaderModule({code:di}),this.shaderCache.set(di,o));let a=this.device.createPipelineLayout({bindGroupLayouts:[this.globalBindGroupLayout,this.getNodeLinkBindGroupLayout()]}),s="vs_node_points",l="fs_node",u=[],c="triangle-list",m="none";t==="node-solid"?(s="vs_node_solid",l="fs_node",u=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]}],c="triangle-list",m=this.getCullMode(e.cullMode)):t==="edge-lines"?(s="vs_edge_lines",l="fs_edge",u=[],c="line-list",m="none"):t==="edge-cylinders"&&(s="vs_edge_cylinders",l="fs_edge",u=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]}],c="triangle-list",m=this.getCullMode(e.cullMode));let d=this.device.createRenderPipeline({label:r,layout:a,vertex:{module:o,entryPoint:s,buffers:u},fragment:{module:o,entryPoint:l,targets:[{format:this.format,blend:this.getBlendState(e.blendMode)}]},primitive:{topology:c,cullMode:m},depthStencil:e.depthTest||e.depthWrite?{format:"depth24plus",depthWriteEnabled:e.depthWrite,depthCompare:e.depthTest?"less":"always"}:void 0});return this.pipelineCache.set(r,d),d}getNodeLinkBindGroupKey(e){let t=e.nodePositionsBuffer,r=e.nodeScalarsBuffer,i=e.nodeColorsBuffer,o=e.nodeRadiiBuffer,a=e.edgesBuffer,s=e.edgeScalarsBuffer,l=e.edgeColorsBuffer,u=e.uniformBuffer;return`nodelink:${t?this.getObjectId(t):0}:${r?this.getObjectId(r):0}:${i?this.getObjectId(i):0}:${o?this.getObjectId(o):0}:${a?this.getObjectId(a):0}:${s?this.getObjectId(s):0}:${l?this.getObjectId(l):0}:${u?this.getObjectId(u):0}:${e.getNodeColormapKey()}:${e.getEdgeColormapKey()}`}ensureNodeLinkBindGroup(e){if(e.upload(this.device,this.queue),!e.nodePositionsBuffer)return;if(e.uniformBuffer||(e.uniformBuffer=this.device.createBuffer({size:e.getUniformBufferSize(),usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),e.bindGroupKey=null),e.dirtyUniforms){let o=e.getUniformData();this.queue.writeBuffer(e.uniformBuffer,0,o.buffer,o.byteOffset,o.byteLength),e.markUniformsClean()}this.nodeLinkDummyF32Buffer||(this.nodeLinkDummyF32Buffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),this.nodeLinkDummyU32Buffer||(this.nodeLinkDummyU32Buffer=this.device.createBuffer({size:8,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}));let t=this.getNodeLinkBindGroupKey(e);if(e.bindGroup&&e.bindGroupKey===t)return;let r=e.getNodeColormapForBinding().getGPUResources(this.device,this.queue),i=e.getEdgeColormapForBinding().getGPUResources(this.device,this.queue);e.bindGroup=this.device.createBindGroup({layout:this.getNodeLinkBindGroupLayout(),entries:[{binding:0,resource:{buffer:e.nodePositionsBuffer??this.nodeLinkDummyF32Buffer}},{binding:1,resource:{buffer:e.nodeScalarsBuffer??this.nodeLinkDummyF32Buffer}},{binding:2,resource:{buffer:e.nodeColorsBuffer??this.nodeLinkDummyF32Buffer}},{binding:3,resource:{buffer:e.nodeRadiiBuffer??this.nodeLinkDummyF32Buffer}},{binding:4,resource:{buffer:e.edgesBuffer??this.nodeLinkDummyU32Buffer}},{binding:5,resource:{buffer:e.edgeScalarsBuffer??this.nodeLinkDummyF32Buffer}},{binding:6,resource:{buffer:e.edgeColorsBuffer??this.nodeLinkDummyF32Buffer}},{binding:7,resource:{buffer:e.uniformBuffer}},{binding:8,resource:r.sampler},{binding:9,resource:r.view},{binding:10,resource:i.sampler},{binding:11,resource:i.view}]}),e.bindGroupKey=t}};var _r=class{constructor(e){this.capacity=e;this.values=new Float64Array(Math.max(1,e|0))}values;cursor=0;count=0;total=0;addSample(e){if(!Number.isFinite(e)||e<0)return;let t=this.cursor;this.total-=this.values[t],this.values[t]=e,this.total+=e,this.cursor=(t+1)%this.values.length,this.count<this.values.length&&this.count++}get(){return this.count>0?this.total/this.count:0}},St=(n,e)=>{if(!Number.isFinite(n))return"n/a";let t=Math.max(0,e|0);return n.toFixed(t)},wr=(n,e)=>{if(!Number.isFinite(n))return"n/a";let t=Math.abs(n);return t<1024?`${St(n,0)} B`:t<1024*1024?`${St(n/1024,e)} KiB`:`${St(n/(1024*1024),e)} MiB`},hn=class{element;textEl;graphCanvas;graphCtx;sources;fpsAvg;frameMsAvg;cpuMsAvg;gpuMsAvg;history;historyCursor=0;targetFps;updateIntervalMs;decimals;lastTextUpdateMs=0;lastDtSeconds=0;show;label;constructor(e={},t={}){if(typeof document>"u")throw new Error("PerformanceStats requires a DOM environment (document is undefined).");this.sources=e,this.targetFps=Math.max(1,t.targetFps??60),this.updateIntervalMs=Math.max(0,t.updateIntervalMs??250),this.decimals=Math.max(0,t.decimals??1);let r=Math.max(4,t.historyLength??60)|0;this.history=new Float32Array(r);let i=Math.max(1,Math.min(240,r));this.fpsAvg=new _r(i),this.frameMsAvg=new _r(i),this.cpuMsAvg=new _r(i),this.gpuMsAvg=new _r(i),this.show={showFps:t.showFps??!0,showFrameTime:t.showFrameTime??!0,showCpuTime:t.showCpuTime??!0,showGpuTime:t.showGpuTime??!0,showMemory:t.showMemory??!0,showCulling:t.showCulling??!1,graph:t.graph??!0},this.label=t.label??null;let o=t.canvas??null,a=t.parent??o?.parentElement??document.body,s=t.position??"top-left",l=Math.max(0,t.paddingPx??8),u=(t.zIndex??9999)|0,c=t.pointerEvents??"none",m=document.createElement("div");this.element=m,m.style.position=a===document.body||a===document.documentElement?"fixed":"absolute",m.style.zIndex=String(u),m.style.pointerEvents=c,m.style.padding=`${l}px`,m.style.background="rgba(0, 0, 0, 0.75)",m.style.color="#ffffff",m.style.fontFamily="ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace",m.style.fontSize="12px",m.style.lineHeight="1.2",m.style.whiteSpace="pre",m.style.userSelect="none",m.style.position==="absolute"&&getComputedStyle(a).position==="static"&&(a.style.position="relative"),s.includes("top")&&(m.style.top="0"),s.includes("bottom")&&(m.style.bottom="0"),s.includes("left")&&(m.style.left="0"),s.includes("right")&&(m.style.right="0");let d=document.createElement("pre");if(this.textEl=d,d.style.margin="0",d.style.padding="0",d.style.whiteSpace="pre",m.appendChild(d),this.show.graph){let f=Math.max(32,t.graphWidthPx??120)|0,p=Math.max(16,t.graphHeightPx??40)|0,h=document.createElement("canvas");h.style.display="block",h.style.marginTop="6px",h.style.width=`${f}px`,h.style.height=`${p}px`;let g=Math.max(1,globalThis.devicePixelRatio||1);h.width=Math.max(1,Math.floor(f*g)),h.height=Math.max(1,Math.floor(p*g));let b=h.getContext("2d");b&&b.scale(g,g),this.graphCanvas=h,this.graphCtx=b,m.appendChild(h)}else this.graphCanvas=null,this.graphCtx=null;a.appendChild(m),this.refreshText()}update(e,t=0){this.lastDtSeconds=e;let r=e*1e3,i=e>0?1/e:0;this.fpsAvg.addSample(i),this.frameMsAvg.addSample(r),this.cpuMsAvg.addSample(t);let o=this.sources.getGpuTimeNs?.()??null;o!==null&&Number.isFinite(o)&&this.gpuMsAvg.addSample(o/1e6),this.history[this.historyCursor]=i,this.historyCursor=(this.historyCursor+1)%this.history.length,this.drawGraph();let a=hr();(this.updateIntervalMs===0||a-this.lastTextUpdateMs>=this.updateIntervalMs)&&(this.lastTextUpdateMs=a,this.refreshText())}destroy(){this.element.remove()}drawGraph(){if(!this.graphCanvas||!this.graphCtx)return;let e=this.graphCtx,t=parseFloat(this.graphCanvas.style.width)||120,r=parseFloat(this.graphCanvas.style.height)||40;e.clearRect(0,0,t,r);let i=this.history.length,o=t/i,a=r/this.targetFps;for(let s=0;s<i;s++){let l=(this.historyCursor+s)%i,u=this.history[l],c=se(u*a,0,r),m=s*o,d=r-c;e.fillStyle="rgba(255, 255, 255, 0.85)",e.fillRect(m,d,Math.max(1,o-.5),c)}e.strokeStyle="rgba(255, 255, 255, 0.35)",e.strokeRect(.5,.5,t-1,r-1)}refreshText(){let e=this.decimals,t=[];this.label&&t.push(this.label);let r=this.fpsAvg.get(),i=this.frameMsAvg.get(),o=i>0?1e3/i:0,a=this.cpuMsAvg.get();if(this.show.showFps&&t.push(`FPS: ${St(r,1)}`),this.show.showFrameTime&&t.push(`Frame: ${St(i,e)} ms (\u2248${St(o,0)} Hz)`),this.show.showCpuTime){let s=Math.max(1e-4,this.lastDtSeconds)*1e3,l=se(a/s*100,0,1e3);t.push(`CPU: ${St(a,e)} ms (${St(l,0)}%)`)}if(this.show.showGpuTime){let s=this.sources.getGpuTimeNs?.()??null;if(s===null||!Number.isFinite(s))t.push("GPU: n/a");else{let l=this.gpuMsAvg.get(),u=Math.max(1e-4,this.lastDtSeconds)*1e3,c=se(l/u*100,0,1e3);t.push(`GPU: ${St(l,e)} ms (${St(c,0)}%)`)}}if(this.show.showMemory){try{let l=W.usedBytes(),u=W.capBytes();t.push(`Frame arena: ${wr(l,e)} / ${wr(u,e)}`)}catch{}try{let l=_.memory().buffer.byteLength;t.push(`WASM memory: ${wr(l,e)}`)}catch{}let s=typeof performance<"u"?performance.memory:null;if(s&&typeof s.usedJSHeapSize=="number"){let l=s.usedJSHeapSize,u=typeof s.totalJSHeapSize=="number"?s.totalJSHeapSize:NaN;Number.isFinite(u)?t.push(`JS heap: ${wr(l,e)} / ${wr(u,e)}`):t.push(`JS heap: ${wr(l,e)}`)}}if(this.show.showCulling){let s=this.sources.getCullingStats?.()??null;s&&(t.push(`Frustum: visible ${s.frustum.visible} / tested ${s.frustum.tested}`),t.push(`Occlusion: visible ${s.occlusion.visible} / tested ${s.occlusion.tested} / occluded ${s.occlusion.occluded}`))}this.textEl.textContent=t.join(`
|
|
22
|
+
`)}};var V=n=>({binding:n.binding,visibility:n.visibility??GPUShaderStage.COMPUTE,buffer:{type:n.readOnly?"read-only-storage":"storage",hasDynamicOffset:n.hasDynamicOffset??!1,minBindingSize:n.minBindingSize}}),Me=n=>({binding:n.binding,visibility:n.visibility??GPUShaderStage.COMPUTE,buffer:{type:"uniform",hasDynamicOffset:n.hasDynamicOffset??!1,minBindingSize:n.minBindingSize}}),es=n=>{if(gr(n))return{buffer:n};if(n.buffer!==void 0&&n.device!==void 0)return{buffer:re(n)};let e=n;return{buffer:re(e.buffer),offset:e.offset,size:e.size}},oc=n=>{let e=[];if(Array.isArray(n)){for(let r of n)e.push({binding:r.binding,resource:es(r.resource)});return e}let t=Object.keys(n).map(r=>Number(r)).filter(r=>Number.isFinite(r));t.sort((r,i)=>r-i);for(let r of t){let i=n[r];i&&e.push({binding:r,resource:es(i)})}return e},Q=class{device;shaderCode;entryPoint;constants;pipeline;bindGroupLayouts;label;constructor(e,t){this.device=e,this.shaderCode=t.code,this.entryPoint=t.entryPoint??"main",this.constants=t.constants,this.label=t.label??null;let r=e.createShaderModule({code:t.code});if(t.bindGroups&&t.bindGroups.length>0){let i=t.bindGroups.map(a=>e.createBindGroupLayout({label:a.label,entries:a.entries})),o=e.createPipelineLayout({bindGroupLayouts:i});this.pipeline=e.createComputePipeline({label:t.label,layout:o,compute:{module:r,entryPoint:this.entryPoint,constants:this.constants}}),this.bindGroupLayouts=i}else this.pipeline=e.createComputePipeline({label:t.label,layout:"auto",compute:{module:r,entryPoint:this.entryPoint,constants:this.constants}}),this.bindGroupLayouts=[]}getBindGroupLayout(e){if(this.bindGroupLayouts.length>0){let t=this.bindGroupLayouts[e];return y(!!t,`Bind group layout ${e} not found (pipeline has ${this.bindGroupLayouts.length} explicit groups)`),t}return this.pipeline.getBindGroupLayout(e)}createBindGroup(e,t,r){let i=this.getBindGroupLayout(e),o=oc(t);return this.device.createBindGroup({label:r,layout:i,entries:o})}};var ts=(n,e=1,t=1)=>(y(ht(n),`workgroupSize.x must be a positive integer (got ${n})`),y(ht(e),`workgroupSize.y must be a positive integer (got ${e})`),y(ht(t),`workgroupSize.z must be a positive integer (got ${t})`),[n,e,t]),Br=(n,e=1,t=1)=>(y(Se(n),`workgroups.x must be an integer >= 0 (got ${n})`),y(Se(e),`workgroups.y must be an integer >= 0 (got ${e})`),y(Se(t),`workgroups.z must be an integer >= 0 (got ${t})`),[n,e,t]),Te=(n,e)=>(y(Number.isFinite(n),`invocations must be finite (got ${n})`),y(n>=0,`invocations must be >= 0 (got ${n})`),y(ht(e),`workgroupSizeX must be a positive integer (got ${e})`),n===0?[0,1,1]:[Ee(n,e),1,1]),gn=(n,e,t,r)=>{if(y(Number.isFinite(n)&&Number.isFinite(e),"width/height must be finite"),y(n>=0&&e>=0,`width/height must be >= 0 (got ${n}x${e})`),y(ht(t),`workgroupSizeX must be a positive integer (got ${t})`),y(ht(r),`workgroupSizeY must be a positive integer (got ${r})`),n===0||e===0)return[0,1,1];let i=Ee(n,t),o=Ee(e,r);return[i,o,1]},bn=(n,e,t,r,i,o)=>{if(y(Number.isFinite(n)&&Number.isFinite(e)&&Number.isFinite(t),"width/height/depth must be finite"),y(n>=0&&e>=0&&t>=0,`width/height/depth must be >= 0 (got ${n}x${e}x${t})`),y(ht(r),`workgroupSizeX must be a positive integer (got ${r})`),y(ht(i),`workgroupSizeY must be a positive integer (got ${i})`),y(ht(o),`workgroupSizeZ must be a positive integer (got ${o})`),n===0||e===0||t===0)return[0,1,1];let a=Ee(n,r),s=Ee(e,i),l=Ee(t,o);return[a,s,l]};var vn=n=>{if(Array.isArray(n)){let i=n[0]??0,o=n[1]??1,a=n[2]??1;return y(Se(i),`workgroups.x must be an integer >= 0 (got ${i})`),y(Se(o),`workgroups.y must be an integer >= 0 (got ${o})`),y(Se(a),`workgroups.z must be an integer >= 0 (got ${a})`),{x:i,y:o,z:a}}let e=n.x,t=n.y??1,r=n.z??1;return y(Se(e),`workgroups.x must be an integer >= 0 (got ${e})`),y(Se(t),`workgroups.y must be an integer >= 0 (got ${t})`),y(Se(r),`workgroups.z must be an integer >= 0 (got ${r})`),{x:e,y:t,z:r}},kr=(n,e)=>{let{x:t,y:r,z:i}=vn(e),o=n.limits.maxComputeWorkgroupsPerDimension;y(t<=o&&r<=o&&i<=o,`dispatchWorkgroups exceeds device.limits.maxComputeWorkgroupsPerDimension (${o})`)},rs=n=>n instanceof Q?n.pipeline:n,Mo=(n,e)=>{let t=n.beginComputePass({label:e.label}),r=rs(e.pipeline);if(t.setPipeline(r),e.bindGroups)for(let s=0;s<e.bindGroups.length;s++){let l=e.bindGroups[s];l&&t.setBindGroup(s,l)}let{x:i,y:o,z:a}=vn(e.workgroups);i>0&&o>0&&a>0&&t.dispatchWorkgroups(i,o,a),t.end()},yn=(n,e,t)=>{let r=n.beginComputePass({label:t}),i=null;for(let o of e){let a=rs(o.pipeline);if(a!==i&&(r.setPipeline(a),i=a),o.bindGroups)for(let c=0;c<o.bindGroups.length;c++){let m=o.bindGroups[c];m&&r.setBindGroup(c,m)}let{x:s,y:l,z:u}=vn(o.workgroups);s===0||l===0||u===0||(o.label&&r.pushDebugGroup(o.label),r.dispatchWorkgroups(s,l,u),o.label&&r.popDebugGroup())}r.end()};var Pi=class{device;usage;labelPrefix;buffersBySize=new Map;cursorBySize=new Map;constructor(e,t){this.device=e,this.usage=t.usage,this.labelPrefix=t.labelPrefix??"scratch"}acquire(e,t){y(Number.isInteger(e)&&e>=0,`ScratchBufferPool.acquire: byteLength must be an integer >= 0 (got ${e})`);let r=Math.max(4,he(e,4)),i=this.buffersBySize.get(r);i||(i=[],this.buffersBySize.set(r,i));let o=this.cursorBySize.get(r)??0,a;if(o<i.length)a=i[o];else{let s=t?`${this.labelPrefix}:${t}`:`${this.labelPrefix}:${r}`,l=o===0?s:`${s}:${o}`;a=this.device.createBuffer({label:l,size:r,usage:this.usage}),i.push(a)}return this.cursorBySize.set(r,o+1),a}reset(){for(let e of this.cursorBySize.keys())this.cursorBySize.set(e,0)}destroy(){for(let e of this.buffersBySize.values())for(let t of e)t.destroy();this.buffersBySize.clear(),this.cursorBySize.clear()}};var ns="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read_write> output: array<f32>; var<workgroup> share: array<f32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = -0x1.fffffep+127f; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = max(acc, input[i1]); } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = max(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var is="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<u32>; @group(0) @binding(1) var<storage, read_write> output: array<u32>; var<workgroup> share: array<u32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = 0u; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = max(acc, input[i1]); } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = max(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var os="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read_write> output: array<f32>; var<workgroup> share: array<f32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = 0x1.fffffep+127f; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = min(acc, input[i1]); } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = min(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var as="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<u32>; @group(0) @binding(1) var<storage, read_write> output: array<u32>; var<workgroup> share: array<u32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = 0xFFFFFFFFu; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = min(acc, input[i1]); } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = min(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var ss="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read_write> output: array<f32>; var<workgroup> share: array<f32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = 0.0; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = acc + input[i1]; } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = share[tid] + share[tid + stride]; } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var ls="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<u32>; @group(0) @binding(1) var<storage, read_write> output: array<u32>; var<workgroup> share: array<u32, 256>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var acc = 0u; if (i0 < n) { acc = input[i0]; } if (i1 < n) { acc = acc + input[i1]; } share[tid] = acc; workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = share[tid] + share[tid + stride]; } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var us="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; struct Pair { value: f32, index: u32 }; @group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read_write> output: array<Pair>; var<workgroup> share: array<Pair, 256>; fn isNan(val: f32) -> bool { let u = bitcast<u32>(val); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn invalidPair() -> Pair { return Pair(-0x1.fffffep+127f, 0xFFFFFFFFu); } fn better(a: Pair, b: Pair) -> Pair { let aNan = isNan(a.value); let bNan = isNan(b.value); if (aNan && bNan) { if (a.index <= b.index) { return a; } return b; } if (aNan) { return b; } if (bNan) { return a; } if (a.value > b.value) { return a; } if (b.value > a.value) { return b; } if (a.index <= b.index) { return a; } return b; } @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var a = invalidPair(); var b = invalidPair(); if (i0 < n) { a = Pair(input[i0], i0); } if (i1 < n) { b = Pair(input[i1], i1); } share[tid] = better(a, b); workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = better(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var cs="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; struct Pair { value: f32, index: u32 }; @group(0) @binding(0) var<storage, read> input: array<Pair>; @group(0) @binding(1) var<storage, read_write> output: array<Pair>; var<workgroup> share: array<Pair, 256>; fn isNan(val: f32) -> bool { let u = bitcast<u32>(val); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn invalidPair() -> Pair { return Pair(-0x1.fffffep+127f, 0xFFFFFFFFu); } fn better(a: Pair, b: Pair) -> Pair { let aNan = isNan(a.value); let bNan = isNan(b.value); if (aNan && bNan) { if (a.index <= b.index) { return a; } return b; } if (aNan) { return b; } if (bNan) { return a; } if (a.value > b.value) { return a; } if (b.value > a.value) { return b; } if (a.index <= b.index) { return a; } return b; } @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var a = invalidPair(); var b = invalidPair(); if (i0 < n) { a = input[i0]; } if (i1 < n) { b = input[i1]; } share[tid] = better(a, b); workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = better(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var ms="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; struct Pair { value: f32, index: u32 }; @group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read_write> output: array<Pair>; var<workgroup> share: array<Pair, 256>; fn isNan(val: f32) -> bool { let u = bitcast<u32>(val); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn invalidPair() -> Pair { return Pair(0x1.fffffep+127f, 0xFFFFFFFFu); } fn better(a: Pair, b: Pair) -> Pair { let aNan = isNan(a.value); let bNan = isNan(b.value); if (aNan && bNan) { if (a.index <= b.index) { return a; } return b; } if (aNan) { return b; } if (bNan) { return a; } if (a.value < b.value) { return a; } if (b.value < a.value) { return b; } if (a.index <= b.index) { return a; } return b; } @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var a = invalidPair(); var b = invalidPair(); if (i0 < n) { a = Pair(input[i0], i0); } if (i1 < n) { b = Pair(input[i1], i1); } share[tid] = better(a, b); workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = better(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var ds="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; struct Pair { value: f32, index: u32 }; @group(0) @binding(0) var<storage, read> input: array<Pair>; @group(0) @binding(1) var<storage, read_write> output: array<Pair>; var<workgroup> share: array<Pair, 256>; fn isNan(val: f32) -> bool { let u = bitcast<u32>(val); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn invalidPair() -> Pair { return Pair(0x1.fffffep+127f, 0xFFFFFFFFu); } fn better(a: Pair, b: Pair) -> Pair { let aNan = isNan(a.value); let bNan = isNan(b.value); if (aNan && bNan) { if (a.index <= b.index) { return a; } return b; } if (aNan) { return b; } if (bNan) { return a; } if (a.value < b.value) { return a; } if (b.value < a.value) { return b; } if (a.index <= b.index) { return a; } return b; } @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let i0 = base + tid; let i1 = i0 + WORKGROUP_SIZE; var a = invalidPair(); var b = invalidPair(); if (i0 < n) { a = input[i0]; } if (i1 < n) { b = input[i1]; } share[tid] = better(a, b); workgroupBarrier(); var stride = WORKGROUP_SIZE / 2u; loop { if (stride == 0u) { break; } if (tid < stride) { share[tid] = better(share[tid], share[tid + stride]); } workgroupBarrier(); stride = stride / 2u; } if (tid == 0u) { output[wid.x] = share[0]; } }";var fs="const WORKGROUP_SIZE: u32 = 256u; const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read> input: array<u32>; @group(0) @binding(1) var<storage, read_write> output: array<u32>; @group(0) @binding(2) var<storage, read_write> blockSums: array<u32>; var<workgroup> temp: array<u32, 512>; @compute @workgroup_size(256) fn main(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wid: vec3<u32>) { let tid = lid.x; let n = arrayLength(&input); let base = wid.x * ELEMENTS_PER_WORKGROUP; let ai = base + tid; let bi = ai + WORKGROUP_SIZE; temp[tid] = select(0u, input[ai], ai < n); temp[tid + WORKGROUP_SIZE] = select(0u, input[bi], bi < n); var offset = 1u; var d = WORKGROUP_SIZE; loop { workgroupBarrier(); if (d == 0u) { break; } if (tid < d) { let i1 = offset * ((tid * 2u) + 1u) - 1u; let i2 = offset * ((tid * 2u) + 2u) - 1u; temp[i2] = temp[i2] + temp[i1]; } offset = offset * 2u; d = d / 2u; } if (tid == 0u) { blockSums[wid.x] = temp[ELEMENTS_PER_WORKGROUP - 1u]; temp[ELEMENTS_PER_WORKGROUP - 1u] = 0u; } d = 1u; loop { offset = offset / 2u; workgroupBarrier(); if (d > WORKGROUP_SIZE) { break; } if (tid < d) { let i1 = offset * ((tid * 2u) + 1u) - 1u; let i2 = offset * ((tid * 2u) + 2u) - 1u; let t = temp[i1]; temp[i1] = temp[i2]; temp[i2] = temp[i2] + t; } d = d * 2u; } workgroupBarrier(); if (ai < n) { output[ai] = temp[tid]; } if (bi < n) { output[bi] = temp[tid + WORKGROUP_SIZE]; } }";var ps="const ELEMENTS_PER_WORKGROUP: u32 = 512u; @group(0) @binding(0) var<storage, read_write> data: array<u32>; @group(0) @binding(1) var<storage, read> blockOffsets: array<u32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&data); if (i >= n) { return; } let block = i / ELEMENTS_PER_WORKGROUP; let off = blockOffsets[block]; data[i] = data[i] + off; }";var hs="@group(0) @binding(0) var<storage, read_write> bins: array<atomic<u32>>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; if (i < arrayLength(&bins)) { atomicStore(&bins[i], 0u); } }";var gs="@group(0) @binding(0) var<storage, read> keys: array<u32>; @group(0) @binding(1) var<storage, read_write> bins: array<atomic<u32>>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&keys); if (i >= n) { return; } let k = keys[i]; let b = arrayLength(&bins); if (k < b) { _ = atomicAdd(&bins[k], 1u); } }";var bs="@group(0) @binding(0) var<storage, read> input: array<f32>; @group(0) @binding(1) var<storage, read> flags: array<u32>; @group(0) @binding(2) var<storage, read> prefix: array<u32>; @group(0) @binding(3) var<storage, read_write> output: array<f32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&flags); if (i >= n) { return; } if (flags[i] != 0u) { let dst = prefix[i]; output[dst] = input[i]; } }";var vs="@group(0) @binding(0) var<storage, read> input: array<u32>; @group(0) @binding(1) var<storage, read> flags: array<u32>; @group(0) @binding(2) var<storage, read> prefix: array<u32>; @group(0) @binding(3) var<storage, read_write> output: array<u32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&flags); if (i >= n) { return; } if (flags[i] != 0u) { let dst = prefix[i]; output[dst] = input[i]; } }";var ys="override BIT: u32 = 0u; @group(0) @binding(0) var<storage, read> keys: array<u32>; @group(0) @binding(1) var<storage, read_write> flags: array<u32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&keys); if (i >= n) { return; } let k = keys[i]; let isZero = ((k >> BIT) & 1u) == 0u; flags[i] = select(0u, 1u, isZero); }";var xs="override BIT: u32 = 0u; @group(0) @binding(0) var<storage, read> keysIn: array<u32>; @group(0) @binding(1) var<storage, read> prefix: array<u32>; @group(0) @binding(2) var<storage, read> zerosCount: array<u32>; @group(0) @binding(3) var<storage, read_write> keysOut: array<u32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&keysIn); if (i >= n) { return; } let k = keysIn[i]; let isZero = ((k >> BIT) & 1u) == 0u; let zeroPos = prefix[i]; let z = zerosCount[0]; let onePos = z + (i - zeroPos); let dst = select(onePos, zeroPos, isZero); keysOut[dst] = k; }";var Ps="@group(0) @binding(0) var<storage, read> src: array<f32>; @group(0) @binding(1) var<storage, read_write> dst: array<f32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&dst); if (i < n) { dst[i] = src[i]; } }";var Ts="@group(0) @binding(0) var<storage, read> src: array<u32>; @group(0) @binding(1) var<storage, read_write> dst: array<u32>; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; let n = arrayLength(&dst); if (i < n) { dst[i] = src[i]; } }";var Ss="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct Params { count: u32, componentCount: u32, componentIndex: u32, valueMode: u32, stride: u32, offset: u32, _pad0: u32, _pad1: u32 }; @group(0) @binding(0) var<storage, read> src: array<f32>; @group(0) @binding(1) var<storage, read_write> outValues: array<f32>; @group(0) @binding(2) var<storage, read_write> outFlags: array<u32>; @group(0) @binding(3) var<uniform> params: Params; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; if (i >= params.count) { return; } let cc = max(1u, min(4u, params.componentCount)); let ci = min(3u, params.componentIndex); let base = i * max(1u, params.stride) + params.offset; var x: f32 = src[base + 0u]; var y: f32 = 0.0; var z: f32 = 0.0; var w: f32 = 0.0; if (cc > 1u) { y = src[base + 1u]; } if (cc > 2u) { z = src[base + 2u]; } if (cc > 3u) { w = src[base + 3u]; } let raw = scale_select_value(vec4f(x, y, z, w), cc, ci, params.valueMode); if (scale_is_finite(raw)) { outValues[i] = raw; outFlags[i] = 1u; } else { outValues[i] = 0.0; outFlags[i] = 0u; } }";var Cs="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct Params { count: u32, binCount: u32, minValue: f32, maxValue: f32 }; @group(0) @binding(0) var<storage, read> values: array<f32>; @group(0) @binding(1) var<storage, read_write> bins: array<atomic<u32>>; @group(0) @binding(2) var<uniform> params: Params; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; if (i >= params.count) { return; } if (params.binCount == 0u) { return; } let minValue = params.minValue; let maxValue = params.maxValue; if (!(maxValue > minValue)) { return; } let v = values[i]; if (!scale_is_finite(v)) { return; } let t = clamp((v - minValue) / (maxValue - minValue), 0.0, 0.99999994); let b = min(params.binCount - 1u, u32(t * f32(params.binCount))); atomicAdd(&bins[b], 1u); }";var ws="fn scale_is_nan(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) != 0u; } fn scale_is_inf(v: f32) -> bool { let u = bitcast<u32>(v); return (u & 0x7F800000u) == 0x7F800000u && (u & 0x007FFFFFu) == 0u; } fn scale_is_finite(v: f32) -> bool { return !scale_is_nan(v) && !scale_is_inf(v); } fn scale_clamp01(x: f32) -> f32 { return clamp(x, 0.0, 1.0); } fn scale_log_base(x: f32, base: f32) -> f32 { let b = max(base, 1.000001); return log(x) / log(b); } fn scale_apply_mode(x: f32, modeId: u32, linthresh: f32, base: f32) -> f32 { if (modeId == 0u) { return x; } if (modeId == 1u) { return scale_log_base(max(x, 1e-20), base); } let lt = max(linthresh, 1e-20); let s = select(-1.0, 1.0, x >= 0.0); let y = scale_log_base(1.0 + abs(x) / lt, base); return s * y; } fn scale_select_value(v: vec4f, componentCountIn: u32, componentIndexIn: u32, valueMode: u32) -> f32 { let componentCount = max(1u, min(4u, componentCountIn)); let componentIndex = min(3u, componentIndexIn); if (valueMode == 1u) { if (componentCount == 1u) { return abs(v.x); } if (componentCount == 2u) { return length(v.xy); } if (componentCount == 3u) { return length(v.xyz); } return length(v); } if (componentIndex == 0u) { return v.x; } if (componentIndex == 1u) { return v.y; } if (componentIndex == 2u) { return v.z; } return v.w; } fn scale_apply_transform(rawValue: f32, domain: vec4f, clampConfig: vec4f, params: vec4f, flags: vec4f) -> f32 { if (!scale_is_finite(rawValue)) { return 0.0; } var v = rawValue; let clampMode = u32(domain.w + 0.5); let clampMin = clampConfig.x; let clampMax = clampConfig.y; if (clampMode != 0u && clampMax > clampMin) { v = clamp(v, clampMin, clampMax); } var d0 = domain.x; var d1 = domain.y; if (d1 <= d0 && clampMax > clampMin) { d0 = clampMin; d1 = clampMax; } let modeId = u32(params.x + 0.5); let base = params.y; let linthresh = params.z; let gamma = max(params.w, 1e-6); let a = scale_apply_mode(d0, modeId, linthresh, base); let b = scale_apply_mode(d1, modeId, linthresh, base); let x = scale_apply_mode(v, modeId, linthresh, base); let denom = max(1e-20, b - a); var t = scale_clamp01((x - a) / denom); t = pow(t, gamma); if (flags.x > 0.5) { t = 1.0 - t; } return scale_clamp01(t); } struct Params { count: u32, _pad0: u32, _pad1: u32, _pad2: u32, domain: vec4f, clampConfig: vec4f, scaleParams: vec4f, scaleFlags: vec4f }; @group(0) @binding(0) var<storage, read> values: array<f32>; @group(0) @binding(1) var<storage, read_write> outValues: array<f32>; @group(0) @binding(2) var<uniform> params: Params; @compute @workgroup_size(256) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; if (i >= params.count) { return; } let v = values[i]; if (!scale_is_finite(v)) { outValues[i] = 0.0; return; } outValues[i] = scale_apply_transform(v, params.domain, params.clampConfig, params.scaleParams, params.scaleFlags); }";var _s="struct LuBatchedParams { batch_count: u32, n: u32, elems_per_matrix: u32, _pad: u32, } @group(0) @binding(0) var<uniform> params: LuBatchedParams; @group(0) @binding(1) var<storage, read_write> matrices: array<f32>; @group(0) @binding(2) var<storage, read_write> ipiv: array<u32>; var<workgroup> wg_abs: array<f32, 128>; var<workgroup> wg_row: array<u32, 128>; var<workgroup> pivot_row: u32; @compute @workgroup_size(128, 1, 1) fn main(@builtin(workgroup_id) wg_id: vec3<u32>, @builtin(local_invocation_index) lid: u32) { let b = wg_id.x; if (b >= params.batch_count) { return; } let n = params.n; let stride = params.elems_per_matrix; let base = b * stride; let base_ipiv = b * n; for (var kk = 0u; kk < n; kk = kk + 1u) { var pv = -1.0; var pr = kk; var ii = kk + lid; while (ii < n) { let aik = matrices[base + ii * n + kk]; let av = abs(aik); if (av > pv || (av == pv && ii < pr)) { pv = av; pr = ii; } ii = ii + 128u; } wg_abs[lid] = pv; wg_row[lid] = pr; workgroupBarrier(); var s = 64u; while (s > 0u) { if (lid < s) { let i1 = lid + s; if (i1 < 128u) { let av0 = wg_abs[lid]; let av1 = wg_abs[i1]; let r0 = wg_row[lid]; let r1 = wg_row[i1]; if (av1 > av0 || (av1 == av0 && r1 < r0)) { wg_abs[lid] = av1; wg_row[lid] = r1; } } } workgroupBarrier(); s = s >> 1u; } if (lid == 0u) { pivot_row = wg_row[0]; ipiv[base_ipiv + kk] = pivot_row; } workgroupBarrier(); let piv = pivot_row; var jj = lid; while (jj < n) { let ia = base + kk * n + jj; let ib = base + piv * n + jj; let va = matrices[ia]; let vb = matrices[ib]; matrices[ia] = vb; matrices[ib] = va; jj = jj + 128u; } workgroupBarrier(); let p = matrices[base + kk * n + kk]; let col_len = n - kk - 1u; var t = lid; while (t < col_len) { let i = kk + 1u + t; let ik = base + i * n + kk; matrices[ik] = matrices[ik] / p; t = t + 128u; } workgroupBarrier(); let dim = n - kk - 1u; let total = dim * dim; t = lid; while (t < total) { let ii = t / dim; let jj2 = t % dim; let i = kk + 1u + ii; let j = kk + 1u + jj2; let lik = matrices[base + i * n + kk]; let ukj = matrices[base + kk * n + j]; let ij = base + i * n + j; matrices[ij] = matrices[ij] - lik * ukj; t = t + 128u; } workgroupBarrier(); } }";var Bs="const WG_SIZE: u32 = 128u; struct LuBlockedParams { batch_count: u32, n: u32, elems_per_matrix: u32, kk: u32, pw: u32, _pad0: u32, _pad1: u32, _pad2: u32, } @group(0) @binding(0) var<uniform> params: LuBlockedParams; @group(0) @binding(1) var<storage, read_write> matrices: array<f32>; @group(0) @binding(2) var<storage, read_write> ipiv: array<u32>; var<workgroup> wg_abs: array<f32, WG_SIZE>; var<workgroup> wg_row: array<u32, WG_SIZE>; var<workgroup> pivot_row: u32; @compute @workgroup_size(WG_SIZE, 1, 1) fn main(@builtin(workgroup_id) wg_id: vec3<u32>, @builtin(local_invocation_index) lid: u32) { let b = wg_id.x; if (b >= params.batch_count) { return; } let n = params.n; let base = b * params.elems_per_matrix; let base_ipiv = b * n; let kk = params.kk; let pw = params.pw; for (var j: u32 = 0u; j < pw; j = j + 1u) { let col = kk + j; if (col >= n) { break; } var pv: f32 = -1.0; var pr: u32 = col; var ii = col + lid; while (ii < n) { let aik = matrices[base + ii * n + col]; let av = abs(aik); if (av > pv || (av == pv && ii < pr)) { pv = av; pr = ii; } ii = ii + WG_SIZE; } wg_abs[lid] = pv; wg_row[lid] = pr; workgroupBarrier(); var s: u32 = WG_SIZE >> 1u; while (s > 0u) { if (lid < s) { let i1 = lid + s; let av0 = wg_abs[lid]; let av1 = wg_abs[i1]; let r0 = wg_row[lid]; let r1 = wg_row[i1]; if (av1 > av0 || (av1 == av0 && r1 < r0)) { wg_abs[lid] = av1; wg_row[lid] = r1; } } workgroupBarrier(); s = s >> 1u; } if (lid == 0u) { pivot_row = wg_row[0]; ipiv[base_ipiv + col] = pivot_row; } workgroupBarrier(); let piv = pivot_row; var jj: u32 = lid; while (jj < n) { let ia = base + col * n + jj; let ib = base + piv * n + jj; let va = matrices[ia]; let vb = matrices[ib]; matrices[ia] = vb; matrices[ib] = va; jj = jj + WG_SIZE; } workgroupBarrier(); let pivval = matrices[base + col * n + col]; var t: u32 = col + 1u + lid; while (t < n) { let idx = base + t * n + col; matrices[idx] = matrices[idx] / pivval; t = t + WG_SIZE; } workgroupBarrier(); let endc = min(n, kk + pw); let inner_cols = endc - (col + 1u); if (inner_cols > 0u) { let inner_rows = n - (col + 1u); let total = inner_rows * inner_cols; var u: u32 = lid; while (u < total) { let row_t = u / inner_cols; let col_t = u % inner_cols; let i = col + 1u + row_t; let c = col + 1u + col_t; let lik = matrices[base + i * n + col]; let ucj = matrices[base + col * n + c]; let idx = base + i * n + c; matrices[idx] = matrices[idx] - lik * ucj; u = u + WG_SIZE; } workgroupBarrier(); } } }";var ks="const MAX_PANEL_B: u32 = 16u; struct LuBlockedParams { batch_count: u32, n: u32, elems_per_matrix: u32, kk: u32, pw: u32, _pad0: u32, _pad1: u32, _pad2: u32, } @group(0) @binding(0) var<uniform> params: LuBlockedParams; @group(0) @binding(1) var<storage, read_write> matrices: array<f32>; @compute @workgroup_size(256, 1, 1) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let n = params.n; let kk = params.kk; let pw = params.pw; let trail_n = n - (kk + pw); if (trail_n == 0u || pw == 0u) { return; } let idx = gid.x; let b = idx / trail_n; if (b >= params.batch_count) { return; } let j = idx - b * trail_n; let col = (kk + pw) + j; let base = b * params.elems_per_matrix; var u_col: array<f32, MAX_PANEL_B>; for (var i: u32 = 0u; i < pw; i = i + 1u) { let row = kk + i; var sum_v = matrices[base + row * n + col]; for (var r: u32 = 0u; r < i; r = r + 1u) { let l_val = matrices[base + row * n + (kk + r)]; sum_v = sum_v - l_val * u_col[r]; } u_col[i] = sum_v; matrices[base + row * n + col] = sum_v; } }";var Ms="const TILE_M: u32 = 16u; const TILE_N: u32 = 8u; struct LuBlockedParams { batch_count: u32, n: u32, elems_per_matrix: u32, kk: u32, pw: u32, _pad0: u32, _pad1: u32, _pad2: u32, } @group(0) @binding(0) var<uniform> params: LuBlockedParams; @group(0) @binding(1) var<storage, read_write> matrices: array<f32>; var<workgroup> L_tile: array<f32, TILE_M>; var<workgroup> U_tile: array<f32, TILE_N>; @compute @workgroup_size(TILE_M, TILE_N, 1) fn main( @builtin(workgroup_id) wg_id: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>, @builtin(local_invocation_index) lid_idx: u32, ) { let b = wg_id.z; if (b >= params.batch_count) { return; } let n = params.n; let kk = params.kk; let pw = params.pw; let base = b * params.elems_per_matrix; let m_dim = n - (kk + pw); let n_dim = n - (kk + pw); if (m_dim == 0u || n_dim == 0u || pw == 0u) { return; } let global_i = wg_id.y * TILE_M + lid.x; let global_j = wg_id.x * TILE_N + lid.y; let valid = (global_i < m_dim) && (global_j < n_dim); var acc = 0.0; for (var k: u32 = 0u; k < pw; k = k + 1u) { if (lid_idx < TILE_M) { let i_g = wg_id.y * TILE_M + lid_idx; if (i_g < m_dim) { let row = (kk + pw) + i_g; L_tile[lid_idx] = matrices[base + row * n + (kk + k)]; } else { L_tile[lid_idx] = 0.0; } } else if (lid_idx < TILE_M + TILE_N) { let j_local = lid_idx - TILE_M; let j_g = wg_id.x * TILE_N + j_local; if (j_g < n_dim) { let col = (kk + pw) + j_g; U_tile[j_local] = matrices[base + (kk + k) * n + col]; } else { U_tile[j_local] = 0.0; } } workgroupBarrier(); acc = acc + L_tile[lid.x] * U_tile[lid.y]; workgroupBarrier(); } if (valid) { let row = (kk + pw) + global_i; let col = (kk + pw) + global_j; let idx = base + row * n + col; matrices[idx] = matrices[idx] - acc; } }";var Ls="struct LuBatchedParams { batch_count: u32, n: u32, elems_per_matrix: u32, _pad: u32, } fn cx_mul(a: vec2<f32>, b: vec2<f32>) -> vec2<f32> { return vec2<f32>(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } fn cx_div(a: vec2<f32>, b: vec2<f32>) -> vec2<f32> { let d = b.x * b.x + b.y * b.y; return vec2<f32>((a.x * b.x + a.y * b.y) / d, (a.y * b.x - a.x * b.y) / d); } fn cx_magsq(z: vec2<f32>) -> f32 { return z.x * z.x + z.y * z.y; } @group(0) @binding(0) var<uniform> params: LuBatchedParams; @group(0) @binding(1) var<storage, read_write> matrices: array<vec2<f32>>; @group(0) @binding(2) var<storage, read_write> ipiv: array<u32>; var<workgroup> wg_abs: array<f32, 128>; var<workgroup> wg_row: array<u32, 128>; var<workgroup> pivot_row: u32; @compute @workgroup_size(128, 1, 1) fn main(@builtin(workgroup_id) wg_id: vec3<u32>, @builtin(local_invocation_index) lid: u32) { let b = wg_id.x; if (b >= params.batch_count) { return; } let n = params.n; let stride = params.elems_per_matrix; let base = b * stride; let base_ipiv = b * n; for (var kk = 0u; kk < n; kk = kk + 1u) { var pv = -1.0; var pr = kk; var ii = kk + lid; while (ii < n) { let aik = matrices[base + ii * n + kk]; let ms = cx_magsq(aik); if (ms > pv || (ms == pv && ii < pr)) { pv = ms; pr = ii; } ii = ii + 128u; } wg_abs[lid] = pv; wg_row[lid] = pr; workgroupBarrier(); var s = 64u; while (s > 0u) { if (lid < s) { let i1 = lid + s; if (i1 < 128u) { let av0 = wg_abs[lid]; let av1 = wg_abs[i1]; let r0 = wg_row[lid]; let r1 = wg_row[i1]; if (av1 > av0 || (av1 == av0 && r1 < r0)) { wg_abs[lid] = av1; wg_row[lid] = r1; } } } workgroupBarrier(); s = s >> 1u; } if (lid == 0u) { pivot_row = wg_row[0]; ipiv[base_ipiv + kk] = pivot_row; } workgroupBarrier(); let piv = pivot_row; var jj = lid; while (jj < n) { let ia = base + kk * n + jj; let ib = base + piv * n + jj; let va = matrices[ia]; let vb = matrices[ib]; matrices[ia] = vb; matrices[ib] = va; jj = jj + 128u; } workgroupBarrier(); let p = matrices[base + kk * n + kk]; let col_len = n - kk - 1u; var t = lid; while (t < col_len) { let i = kk + 1u + t; let ik = base + i * n + kk; matrices[ik] = cx_div(matrices[ik], p); t = t + 128u; } workgroupBarrier(); let dim = n - kk - 1u; let total = dim * dim; t = lid; while (t < total) { let ii2 = t / dim; let jj2 = t % dim; let i = kk + 1u + ii2; let j = kk + 1u + jj2; let lik = matrices[base + i * n + kk]; let ukj = matrices[base + kk * n + j]; let ij = base + i * n + j; matrices[ij] = matrices[ij] - cx_mul(lik, ukj); t = t + 128u; } workgroupBarrier(); } }";var Rs="const WG_SIZE: u32 = 128u; struct LuBlockedParams { batch_count: u32, n: u32, elems_per_matrix: u32, kk: u32, pw: u32, _pad0: u32, _pad1: u32, _pad2: u32, } fn cx_mul(a: vec2<f32>, b: vec2<f32>) -> vec2<f32> { return vec2<f32>(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } fn cx_div(a: vec2<f32>, b: vec2<f32>) -> vec2<f32> { let d = b.x * b.x + b.y * b.y; return vec2<f32>((a.x * b.x + a.y * b.y) / d, (a.y * b.x - a.x * b.y) / d); } fn cx_magsq(z: vec2<f32>) -> f32 { return z.x * z.x + z.y * z.y; } @group(0) @binding(0) var<uniform> params: LuBlockedParams; @group(0) @binding(1) var<storage, read_write> matrices: array<vec2<f32>>; @group(0) @binding(2) var<storage, read_write> ipiv: array<u32>; var<workgroup> wg_abs: array<f32, WG_SIZE>; var<workgroup> wg_row: array<u32, WG_SIZE>; var<workgroup> pivot_row: u32; @compute @workgroup_size(WG_SIZE, 1, 1) fn main(@builtin(workgroup_id) wg_id: vec3<u32>, @builtin(local_invocation_index) lid: u32) { let b = wg_id.x; if (b >= params.batch_count) { return; } let n = params.n; let base = b * params.elems_per_matrix; let base_ipiv = b * n; let kk = params.kk; let pw = params.pw; for (var j: u32 = 0u; j < pw; j = j + 1u) { let col = kk + j; if (col >= n) { break; } var pv: f32 = -1.0; var pr: u32 = col; var ii = col + lid; while (ii < n) { let aik = matrices[base + ii * n + col]; let ms = cx_magsq(aik); if (ms > pv || (ms == pv && ii < pr)) { pv = ms; pr = ii; } ii = ii + WG_SIZE; } wg_abs[lid] = pv; wg_row[lid] = pr; workgroupBarrier(); var s: u32 = WG_SIZE >> 1u; while (s > 0u) { if (lid < s) { let i1 = lid + s; let av0 = wg_abs[lid]; let av1 = wg_abs[i1]; let r0 = wg_row[lid]; let r1 = wg_row[i1]; if (av1 > av0 || (av1 == av0 && r1 < r0)) { wg_abs[lid] = av1; wg_row[lid] = r1; } } workgroupBarrier(); s = s >> 1u; } if (lid == 0u) { pivot_row = wg_row[0]; ipiv[base_ipiv + col] = pivot_row; } workgroupBarrier(); let piv = pivot_row; var jj: u32 = lid; while (jj < n) { let ia = base + col * n + jj; let ib = base + piv * n + jj; let va = matrices[ia]; let vb = matrices[ib]; matrices[ia] = vb; matrices[ib] = va; jj = jj + WG_SIZE; } workgroupBarrier(); let pivval = matrices[base + col * n + col]; var t: u32 = col + 1u + lid; while (t < n) { let idx = base + t * n + col; matrices[idx] = cx_div(matrices[idx], pivval); t = t + WG_SIZE; } workgroupBarrier(); let endc = min(n, kk + pw); let inner_cols = endc - (col + 1u); if (inner_cols > 0u) { let inner_rows = n - (col + 1u); let total = inner_rows * inner_cols; var u: u32 = lid; while (u < total) { let row_t = u / inner_cols; let col_t = u % inner_cols; let i = col + 1u + row_t; let c = col + 1u + col_t; let lik = matrices[base + i * n + col]; let ucj = matrices[base + col * n + c]; let idx = base + i * n + c; matrices[idx] = matrices[idx] - cx_mul(lik, ucj); u = u + WG_SIZE; } workgroupBarrier(); } } }";var Us="const MAX_PANEL_B: u32 = 16u; struct LuBlockedParams { batch_count: u32, n: u32, elems_per_matrix: u32, kk: u32, pw: u32, _pad0: u32, _pad1: u32, _pad2: u32, } fn cx_mul(a: vec2<f32>, b: vec2<f32>) -> vec2<f32> { return vec2<f32>(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } @group(0) @binding(0) var<uniform> params: LuBlockedParams; @group(0) @binding(1) var<storage, read_write> matrices: array<vec2<f32>>; @compute @workgroup_size(256, 1, 1) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let n = params.n; let kk = params.kk; let pw = params.pw; let trail_n = n - (kk + pw); if (trail_n == 0u || pw == 0u) { return; } let idx = gid.x; let b = idx / trail_n; if (b >= params.batch_count) { return; } let j = idx - b * trail_n; let col = (kk + pw) + j; let base = b * params.elems_per_matrix; var u_col: array<vec2<f32>, MAX_PANEL_B>; for (var i: u32 = 0u; i < pw; i = i + 1u) { let row = kk + i; var sum_v = matrices[base + row * n + col]; for (var r: u32 = 0u; r < i; r = r + 1u) { let l_val = matrices[base + row * n + (kk + r)]; sum_v = sum_v - cx_mul(l_val, u_col[r]); } u_col[i] = sum_v; matrices[base + row * n + col] = sum_v; } }";var Gs="const TILE_M: u32 = 16u; const TILE_N: u32 = 8u; struct LuBlockedParams { batch_count: u32, n: u32, elems_per_matrix: u32, kk: u32, pw: u32, _pad0: u32, _pad1: u32, _pad2: u32, } fn cx_mul(a: vec2<f32>, b: vec2<f32>) -> vec2<f32> { return vec2<f32>(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } @group(0) @binding(0) var<uniform> params: LuBlockedParams; @group(0) @binding(1) var<storage, read_write> matrices: array<vec2<f32>>; var<workgroup> L_tile: array<vec2<f32>, TILE_M>; var<workgroup> U_tile: array<vec2<f32>, TILE_N>; @compute @workgroup_size(TILE_M, TILE_N, 1) fn main( @builtin(workgroup_id) wg_id: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>, @builtin(local_invocation_index) lid_idx: u32, ) { let b = wg_id.z; if (b >= params.batch_count) { return; } let n = params.n; let kk = params.kk; let pw = params.pw; let base = b * params.elems_per_matrix; let m_dim = n - (kk + pw); let n_dim = n - (kk + pw); if (m_dim == 0u || n_dim == 0u || pw == 0u) { return; } let global_i = wg_id.y * TILE_M + lid.x; let global_j = wg_id.x * TILE_N + lid.y; let valid = (global_i < m_dim) && (global_j < n_dim); var acc = vec2<f32>(0.0, 0.0); for (var k: u32 = 0u; k < pw; k = k + 1u) { if (lid_idx < TILE_M) { let i_g = wg_id.y * TILE_M + lid_idx; if (i_g < m_dim) { let row = (kk + pw) + i_g; L_tile[lid_idx] = matrices[base + row * n + (kk + k)]; } else { L_tile[lid_idx] = vec2<f32>(0.0, 0.0); } } else if (lid_idx < TILE_M + TILE_N) { let j_local = lid_idx - TILE_M; let j_g = wg_id.x * TILE_N + j_local; if (j_g < n_dim) { let col = (kk + pw) + j_g; U_tile[j_local] = matrices[base + (kk + k) * n + col]; } else { U_tile[j_local] = vec2<f32>(0.0, 0.0); } } workgroupBarrier(); acc = acc + cx_mul(L_tile[lid.x], U_tile[lid.y]); workgroupBarrier(); } if (valid) { let row = (kk + pw) + global_i; let col = (kk + pw) + global_j; let idx = base + row * n + col; matrices[idx] = matrices[idx] - acc; } }";var As="struct LuBatchedParams { batch_count: u32, n: u32, elems_per_matrix: u32, _pad: u32, } @group(0) @binding(0) var<uniform> params: LuBatchedParams; @group(0) @binding(1) var<storage, read> lu: array<f32>; @group(0) @binding(2) var<storage, read> rhs: array<f32>; @group(0) @binding(3) var<storage, read_write> x: array<f32>; @group(0) @binding(4) var<storage, read> ipiv: array<u32>; @compute @workgroup_size(1, 1, 1) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let b = gid.x; if (b >= params.batch_count) { return; } let n = params.n; let stride = params.elems_per_matrix; let base = b * stride; let baseRhs = b * n; let baseIpiv = b * n; for (var i = 0u; i < n; i = i + 1u) { x[baseRhs + i] = rhs[baseRhs + i]; } for (var kk = 0u; kk < n - 1u; kk = kk + 1u) { let p = ipiv[baseIpiv + kk]; if (p != kk) { let t = x[baseRhs + kk]; x[baseRhs + kk] = x[baseRhs + p]; x[baseRhs + p] = t; } } for (var i = 0u; i < n; i = i + 1u) { var sum = x[baseRhs + i]; for (var j = 0u; j < i; j = j + 1u) { sum = sum - lu[base + i * n + j] * x[baseRhs + j]; } x[baseRhs + i] = sum; } for (var ii = n; ii > 0u; ii = ii - 1u) { let i = ii - 1u; var sum = x[baseRhs + i]; for (var j = i + 1u; j < n; j = j + 1u) { sum = sum - lu[base + i * n + j] * x[baseRhs + j]; } x[baseRhs + i] = sum / lu[base + i * n + i]; } }";var Fs="const WG_SIZE: u32 = 64u; const BS: u32 = 32u; const MAX_N: u32 = 512u; const STRIDE_ITERS: u32 = 8u; struct LuBatchedParams { batch_count: u32, n: u32, elems_per_matrix: u32, _pad: u32, } @group(0) @binding(0) var<uniform> params: LuBatchedParams; @group(0) @binding(1) var<storage, read> lu: array<f32>; @group(0) @binding(2) var<storage, read> rhs: array<f32>; @group(0) @binding(3) var<storage, read_write> x: array<f32>; @group(0) @binding(4) var<storage, read> ipiv: array<u32>; var<workgroup> wg_x: array<f32, MAX_N>; var<workgroup> wg_partial: array<f32, WG_SIZE>; @compute @workgroup_size(WG_SIZE, 1, 1) fn main( @builtin(workgroup_id) wg_id: vec3<u32>, @builtin(local_invocation_index) lid: u32, ) { let b = wg_id.x; if (b >= params.batch_count) { return; } let n = params.n; let base = b * params.elems_per_matrix; let baseRhs = b * n; let baseIpiv = b * n; { for (var s: u32 = 0u; s < STRIDE_ITERS; s = s + 1u) { let t = lid + s * WG_SIZE; if (t < n) { wg_x[t] = rhs[baseRhs + t]; } } } workgroupBarrier(); if (lid == 0u) { for (var k: u32 = 0u; k < n; k = k + 1u) { let p = ipiv[baseIpiv + k]; if (p != k) { let tmp = wg_x[k]; wg_x[k] = wg_x[p]; wg_x[p] = tmp; } } } workgroupBarrier(); let n_blocks = (n + BS - 1u) / BS; for (var bi: u32 = 0u; bi < n_blocks; bi = bi + 1u) { let bs0 = bi * BS; let bs1 = min(bs0 + BS, n); for (var ii: u32 = bs0; ii < bs1; ii = ii + 1u) { var partial = 0.0; for (var s: u32 = 0u; s < STRIDE_ITERS; s = s + 1u) { let j = bs0 + lid + s * WG_SIZE; if (j < ii) { partial = partial + lu[base + ii * n + j] * wg_x[j]; } } wg_partial[lid] = partial; workgroupBarrier(); if (lid == 0u) { var sum = wg_partial[0]; for (var t: u32 = 1u; t < WG_SIZE; t = t + 1u) { sum = sum + wg_partial[t]; } wg_x[ii] = wg_x[ii] - sum; } workgroupBarrier(); } var k = bs1 + lid; while (k < n) { var update = 0.0; for (var j: u32 = bs0; j < bs1; j = j + 1u) { update = update + lu[base + k * n + j] * wg_x[j]; } wg_x[k] = wg_x[k] - update; k = k + WG_SIZE; } workgroupBarrier(); } for (var b_idx: u32 = 0u; b_idx < n_blocks; b_idx = b_idx + 1u) { let bi = n_blocks - 1u - b_idx; let bs0 = bi * BS; let bs1 = min(bs0 + BS, n); let bsz = bs1 - bs0; for (var ii_off: u32 = 0u; ii_off < bsz; ii_off = ii_off + 1u) { let ii = bs1 - 1u - ii_off; var partial = 0.0; for (var s: u32 = 0u; s < STRIDE_ITERS; s = s + 1u) { let j = ii + 1u + lid + s * WG_SIZE; if (j < bs1) { partial = partial + lu[base + ii * n + j] * wg_x[j]; } } wg_partial[lid] = partial; workgroupBarrier(); if (lid == 0u) { var sum = wg_partial[0]; for (var t: u32 = 1u; t < WG_SIZE; t = t + 1u) { sum = sum + wg_partial[t]; } let new_val = wg_x[ii] - sum; wg_x[ii] = new_val / lu[base + ii * n + ii]; } workgroupBarrier(); } var k = lid; while (k < bs0) { var update = 0.0; for (var j: u32 = bs0; j < bs1; j = j + 1u) { update = update + lu[base + k * n + j] * wg_x[j]; } wg_x[k] = wg_x[k] - update; k = k + WG_SIZE; } workgroupBarrier(); } { for (var s: u32 = 0u; s < STRIDE_ITERS; s = s + 1u) { let w = lid + s * WG_SIZE; if (w < n) { x[baseRhs + w] = wg_x[w]; } } } }";var Is="struct LuBatchedParams { batch_count: u32, n: u32, elems_per_matrix: u32, _pad: u32, } fn cx_mul(a: vec2<f32>, b: vec2<f32>) -> vec2<f32> { return vec2<f32>(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } fn cx_div(a: vec2<f32>, b: vec2<f32>) -> vec2<f32> { let d = b.x * b.x + b.y * b.y; return vec2<f32>((a.x * b.x + a.y * b.y) / d, (a.y * b.x - a.x * b.y) / d); } @group(0) @binding(0) var<uniform> params: LuBatchedParams; @group(0) @binding(1) var<storage, read> lu: array<vec2<f32>>; @group(0) @binding(2) var<storage, read> rhs: array<vec2<f32>>; @group(0) @binding(3) var<storage, read_write> x: array<vec2<f32>>; @group(0) @binding(4) var<storage, read> ipiv: array<u32>; @compute @workgroup_size(1, 1, 1) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let b = gid.x; if (b >= params.batch_count) { return; } let n = params.n; let stride = params.elems_per_matrix; let base = b * stride; let baseRhs = b * n; let baseIpiv = b * n; for (var i = 0u; i < n; i = i + 1u) { x[baseRhs + i] = rhs[baseRhs + i]; } for (var kk = 0u; kk < n - 1u; kk = kk + 1u) { let p = ipiv[baseIpiv + kk]; if (p != kk) { let t = x[baseRhs + kk]; x[baseRhs + kk] = x[baseRhs + p]; x[baseRhs + p] = t; } } for (var i = 0u; i < n; i = i + 1u) { var sum = x[baseRhs + i]; for (var j = 0u; j < i; j = j + 1u) { sum = sum - cx_mul(lu[base + i * n + j], x[baseRhs + j]); } x[baseRhs + i] = sum; } for (var ii = n; ii > 0u; ii = ii - 1u) { let i = ii - 1u; var sum = x[baseRhs + i]; for (var j = i + 1u; j < n; j = j + 1u) { sum = sum - cx_mul(lu[base + i * n + j], x[baseRhs + j]); } x[baseRhs + i] = cx_div(sum, lu[base + i * n + i]); } }";var Ds="const WG_SIZE: u32 = 64u; const BS: u32 = 32u; const MAX_N: u32 = 512u; const STRIDE_ITERS: u32 = 8u; struct LuBatchedParams { batch_count: u32, n: u32, elems_per_matrix: u32, _pad: u32, } fn cx_mul(a: vec2<f32>, b: vec2<f32>) -> vec2<f32> { return vec2<f32>(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } fn cx_div(a: vec2<f32>, b: vec2<f32>) -> vec2<f32> { let d = b.x * b.x + b.y * b.y; return vec2<f32>((a.x * b.x + a.y * b.y) / d, (a.y * b.x - a.x * b.y) / d); } @group(0) @binding(0) var<uniform> params: LuBatchedParams; @group(0) @binding(1) var<storage, read> lu: array<vec2<f32>>; @group(0) @binding(2) var<storage, read> rhs: array<vec2<f32>>; @group(0) @binding(3) var<storage, read_write> x: array<vec2<f32>>; @group(0) @binding(4) var<storage, read> ipiv: array<u32>; var<workgroup> wg_x: array<vec2<f32>, MAX_N>; var<workgroup> wg_partial: array<vec2<f32>, WG_SIZE>; @compute @workgroup_size(WG_SIZE, 1, 1) fn main( @builtin(workgroup_id) wg_id: vec3<u32>, @builtin(local_invocation_index) lid: u32, ) { let b = wg_id.x; if (b >= params.batch_count) { return; } let n = params.n; let base = b * params.elems_per_matrix; let baseRhs = b * n; let baseIpiv = b * n; { for (var s: u32 = 0u; s < STRIDE_ITERS; s = s + 1u) { let t = lid + s * WG_SIZE; if (t < n) { wg_x[t] = rhs[baseRhs + t]; } } } workgroupBarrier(); if (lid == 0u) { for (var k: u32 = 0u; k < n; k = k + 1u) { let p = ipiv[baseIpiv + k]; if (p != k) { let tmp = wg_x[k]; wg_x[k] = wg_x[p]; wg_x[p] = tmp; } } } workgroupBarrier(); let n_blocks = (n + BS - 1u) / BS; for (var bi: u32 = 0u; bi < n_blocks; bi = bi + 1u) { let bs0 = bi * BS; let bs1 = min(bs0 + BS, n); for (var ii: u32 = bs0; ii < bs1; ii = ii + 1u) { var partial = vec2<f32>(0.0, 0.0); for (var s: u32 = 0u; s < STRIDE_ITERS; s = s + 1u) { let j = bs0 + lid + s * WG_SIZE; if (j < ii) { partial = partial + cx_mul(lu[base + ii * n + j], wg_x[j]); } } wg_partial[lid] = partial; workgroupBarrier(); if (lid == 0u) { var sum = wg_partial[0]; for (var t: u32 = 1u; t < WG_SIZE; t = t + 1u) { sum = sum + wg_partial[t]; } wg_x[ii] = wg_x[ii] - sum; } workgroupBarrier(); } var k = bs1 + lid; while (k < n) { var update = vec2<f32>(0.0, 0.0); for (var j: u32 = bs0; j < bs1; j = j + 1u) { update = update + cx_mul(lu[base + k * n + j], wg_x[j]); } wg_x[k] = wg_x[k] - update; k = k + WG_SIZE; } workgroupBarrier(); } for (var b_idx: u32 = 0u; b_idx < n_blocks; b_idx = b_idx + 1u) { let bi = n_blocks - 1u - b_idx; let bs0 = bi * BS; let bs1 = min(bs0 + BS, n); let bsz = bs1 - bs0; for (var ii_off: u32 = 0u; ii_off < bsz; ii_off = ii_off + 1u) { let ii = bs1 - 1u - ii_off; var partial = vec2<f32>(0.0, 0.0); for (var s: u32 = 0u; s < STRIDE_ITERS; s = s + 1u) { let j = ii + 1u + lid + s * WG_SIZE; if (j < bs1) { partial = partial + cx_mul(lu[base + ii * n + j], wg_x[j]); } } wg_partial[lid] = partial; workgroupBarrier(); if (lid == 0u) { var sum = wg_partial[0]; for (var t: u32 = 1u; t < WG_SIZE; t = t + 1u) { sum = sum + wg_partial[t]; } let new_val = wg_x[ii] - sum; wg_x[ii] = cx_div(new_val, lu[base + ii * n + ii]); } workgroupBarrier(); } var k = lid; while (k < bs0) { var update = vec2<f32>(0.0, 0.0); for (var j: u32 = bs0; j < bs1; j = j + 1u) { update = update + cx_mul(lu[base + k * n + j], wg_x[j]); } wg_x[k] = wg_x[k] - update; k = k + WG_SIZE; } workgroupBarrier(); } { for (var s: u32 = 0u; s < STRIDE_ITERS; s = s + 1u) { let w = lid + s * WG_SIZE; if (w < n) { x[baseRhs + w] = wg_x[w]; } } } }";var Vc=n=>4,Ec=n=>n==="sum"?0:n==="min"?4294967295:0,Wc=n=>n==="sum"?0:n==="min"?2139095040:4286578688,jc=n=>n==="argmin"?{valueBits:2139095040,index:4294967295}:{valueBits:4286578688,index:4294967295},Hc=(n,e,t)=>{y(n%e===0,`${t}: byteLength (${n}) must be divisible by ${e}`)},Mr=class{device;queue;scratch;pipelines;luBatchedParamsBuffer;luBlockedParamsBuffer;constructor(e,t){this.device=e,this.queue=t,this.scratch=new Pi(e,{usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST,labelPrefix:"kernels:scratch"}),this.pipelines=new Map,this.luBatchedParamsBuffer=null,this.luBlockedParamsBuffer=null}destroy(){this.scratch.destroy(),this.pipelines.clear(),this.luBatchedParamsBuffer?.destroy(),this.luBatchedParamsBuffer=null,this.luBlockedParamsBuffer?.destroy(),this.luBlockedParamsBuffer=null}getLuBatchedParamsBuffer(){return this.luBatchedParamsBuffer||(this.luBatchedParamsBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,label:"kernels:luBatchedParams"})),this.luBatchedParamsBuffer}getLuBlockedParamsBuffer(){return this.luBlockedParamsBuffer||(this.luBlockedParamsBuffer=this.device.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,label:"kernels:luBlockedParams"})),this.luBlockedParamsBuffer}getPipeline(e,t){let r=this.pipelines.get(e);return r||(r=t(),this.pipelines.set(e,r)),r}bindSized(e,t){y(Number.isInteger(t)&&t>=0,`bindSized: sizeBytes must be an integer >= 0 (got ${t})`);let r=he(t,4);return{buffer:e,size:Math.max(4,r)}}resolveCount(e,t,r){Hc(e.byteLength,t,"resolveCount");let i=e.byteLength/t;return r===void 0?i:(y(Number.isInteger(r)&&r>=0,`count must be an integer >= 0 (got ${r})`),y(r<=i,`count (${r}) exceeds buffer element capacity (${i})`),r)}execute(e,t){if(e.length===0)return;let r=t?.encoder??this.device.createCommandEncoder();if(t?.validateLimits)for(let i of e)kr(this.device,i.workgroups);yn(r,e,t?.label),t?.encoder||(this.queue.submit([r.finish()]),this.scratch.reset())}writeScalarU32(e,t){let r=re(e),i=new Uint32Array([t>>>0]);this.queue.writeBuffer(r,0,i)}writeScalarF32(e,t){let r=re(e),i=new Float32Array([t]);this.queue.writeBuffer(r,0,i)}writeScalarF32Bits(e,t){let r=re(e),i=new Uint32Array([t>>>0]);this.queue.writeBuffer(r,0,i)}writeArgPairBits(e,t,r){let i=re(e),o=new Uint32Array([t>>>0,r>>>0]);this.queue.writeBuffer(i,0,o)}getReducePipeline(e,t){let r=`kernels:reduce:${e}:${t}`;return this.getPipeline(r,()=>new Q(this.device,{label:r,code:e==="f32"?t==="sum"?ss:t==="max"?ns:os:t==="sum"?ls:t==="max"?is:as,entryPoint:"main",bindGroups:[{label:`${r}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1})]}]}))}getArgReduceInitialPipeline(e){let t=`kernels:argreduce:init:${e}`;return this.getPipeline(t,()=>new Q(this.device,{label:t,code:e==="argmax"?us:ms,entryPoint:"main",bindGroups:[{label:`${t}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1})]}]}))}getArgReducePairsPipeline(e){let t=`kernels:argreduce:pairs:${e}`;return this.getPipeline(t,()=>{let r=e==="argmax"?cs:ds;return new Q(this.device,{label:t,code:r,entryPoint:"main",bindGroups:[{label:`${t}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1})]}]})})}encodeReduceScalar(e,t,r,i,o,a,s){y(Number.isInteger(o)&&o>0,"encodeReduceScalar expects inputCount > 0");let l=Vc(t),u=i,c=o,m=0;for(;;){let d=Ee(c,512),f=d<=1,p=f?a:this.scratch.acquire(d*l,`${s}:reduce:${m}`),h=this.getReducePipeline(t,r),g=h.createBindGroup(0,{0:this.bindSized(u,c*l),1:this.bindSized(p,d*l)},`${s}:reduce:${m}:bg`);if(e.push({pipeline:h,bindGroups:[g],workgroups:Br(d,1,1),label:`${s}:reduce:${m}`}),f)break;u=p,c=d,m++}}encodeArgReduceF32Scalar(e,t,r,i,o,a){y(Number.isInteger(i)&&i>0,"encodeArgReduceF32Scalar expects inputCount > 0");let s=r,l=i,u=4,c=0;for(;;){let m=Ee(l,512),d=m<=1,f=d?o:this.scratch.acquire(m*8,`${a}:argreduce:${c}`),p=c===0?this.getArgReduceInitialPipeline(t):this.getArgReducePairsPipeline(t),h=p.createBindGroup(0,{0:this.bindSized(s,l*u),1:this.bindSized(f,m*8)},`${a}:argreduce:${c}:bg`);if(e.push({pipeline:p,bindGroups:[h],workgroups:Br(m,1,1),label:`${a}:argreduce:${c}`}),d)break;s=f,l=m,u=8,c++}}getScanBlockExclusiveU32Pipeline(){let e="kernels:scan:blockExclusiveU32";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:fs,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1}),V({binding:2,readOnly:!1})]}]}))}getScanAddBlockOffsetsU32Pipeline(){let e="kernels:scan:addBlockOffsetsU32";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:ps,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[V({binding:0,readOnly:!1}),V({binding:1,readOnly:!0})]}]}))}encodeScanExclusiveU32Into(e,t,r,i,o){if(y(Number.isInteger(r)&&r>=0,`encodeScanExclusiveU32Into: count must be an integer >= 0 (got ${r})`),r===0)return;let a=Ee(r,512),s=this.scratch.acquire(a*4,`${o}:blockSums`);{let u=this.getScanBlockExclusiveU32Pipeline(),c=u.createBindGroup(0,{0:this.bindSized(t,r*4),1:this.bindSized(i,r*4),2:this.bindSized(s,a*4)},`${o}:scanBlocks:bg`);e.push({pipeline:u,bindGroups:[c],workgroups:Br(a,1,1),label:`${o}:scanBlocks`})}if(a<=1)return;let l=this.scratch.acquire(a*4,`${o}:blockOffsets`);this.encodeScanExclusiveU32Into(e,s,a,l,`${o}:scanBlockSums`);{let u=this.getScanAddBlockOffsetsU32Pipeline(),c=u.createBindGroup(0,{0:this.bindSized(i,r*4),1:this.bindSized(l,a*4)},`${o}:addOffsets:bg`);e.push({pipeline:u,bindGroups:[c],workgroups:Te(r,256),label:`${o}:addOffsets`})}}getHistogramClearPipeline(){let e="kernels:histogram:clearAtomicU32";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:hs,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[V({binding:0,readOnly:!1})]}]}))}getHistogramPipeline(){let e="kernels:histogram:u32";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:gs,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1})]}]}))}getCompactPipeline(e){let t=`kernels:compact:${e}`;return this.getPipeline(t,()=>new Q(this.device,{label:t,code:e==="u32"?vs:bs,entryPoint:"main",bindGroups:[{label:`${t}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!0}),V({binding:2,readOnly:!0}),V({binding:3,readOnly:!1})]}]}))}getRadixFlagsPipeline(e){let t=e|0,r=`kernels:radix:flags:bit${t}`;return this.getPipeline(r,()=>new Q(this.device,{label:r,code:ys,entryPoint:"main",constants:{BIT:t},bindGroups:[{label:`${r}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1})]}]}))}getRadixScatterPipeline(e){let t=e|0,r=`kernels:radix:scatter:bit${t}`;return this.getPipeline(r,()=>new Q(this.device,{label:r,code:xs,entryPoint:"main",constants:{BIT:t},bindGroups:[{label:`${r}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!0}),V({binding:2,readOnly:!0}),V({binding:3,readOnly:!1})]}]}))}getCopyF32Pipeline(){let e="kernels:copy:f32";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Ps,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1})]}]}))}getCopyU32Pipeline(){let e="kernels:copy:u32";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Ts,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1})]}]}))}getScaleExtractF32Pipeline(){let e="kernels:scale:extractF32";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Ss,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1}),V({binding:2,readOnly:!1}),Me({binding:3})]}]}))}getScaleHistogramF32Pipeline(){let e="kernels:scale:histogramF32";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Cs,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1}),Me({binding:2})]}]}))}getScaleRemapF32Pipeline(){let e="kernels:scale:remapF32";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:ws,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[V({binding:0,readOnly:!0}),V({binding:1,readOnly:!1}),Me({binding:2})]}]}))}getLuFactorRealPipeline(){let e="kernels:lu:factorReal";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:_s,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:16}),V({binding:1,readOnly:!1}),V({binding:2,readOnly:!1})]}]}))}getLuFactorRealLeadPipeline(){let e="kernels:lu:factorRealLead";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Bs,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:32}),V({binding:1,readOnly:!1}),V({binding:2,readOnly:!1})]}]}))}getLuFactorRealUpperPipeline(){let e="kernels:lu:factorRealUpper";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:ks,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:32}),V({binding:1,readOnly:!1})]}]}))}getLuFactorRealTrailingPipeline(){let e="kernels:lu:factorRealTrailing";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Ms,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:32}),V({binding:1,readOnly:!1})]}]}))}getLuSolveRealPipeline(){let e="kernels:lu:solveReal";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:As,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:16}),V({binding:1,readOnly:!0}),V({binding:2,readOnly:!0}),V({binding:3,readOnly:!1}),V({binding:4,readOnly:!0})]}]}))}getLuSolveRealSharedPipeline(){let e="kernels:lu:solveRealShared";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Fs,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:16}),V({binding:1,readOnly:!0}),V({binding:2,readOnly:!0}),V({binding:3,readOnly:!1}),V({binding:4,readOnly:!0})]}]}))}getLuFactorComplexLeadPipeline(){let e="kernels:lu:factorComplexLead";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Rs,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:32}),V({binding:1,readOnly:!1}),V({binding:2,readOnly:!1})]}]}))}getLuFactorComplexUpperPipeline(){let e="kernels:lu:factorComplexUpper";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Us,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:32}),V({binding:1,readOnly:!1})]}]}))}getLuFactorComplexTrailingPipeline(){let e="kernels:lu:factorComplexTrailing";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Gs,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:32}),V({binding:1,readOnly:!1})]}]}))}getLuFactorComplexSmallPipeline(){let e="kernels:lu:factorComplexSmall";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Ls,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:16}),V({binding:1,readOnly:!1}),V({binding:2,readOnly:!1})]}]}))}getLuSolveComplexLargePipeline(){let e="kernels:lu:solveComplexLarge";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Is,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:16}),V({binding:1,readOnly:!0}),V({binding:2,readOnly:!0}),V({binding:3,readOnly:!1}),V({binding:4,readOnly:!0})]}]}))}getLuSolveComplexPipeline(){let e="kernels:lu:solveComplex";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:Ds,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[Me({binding:0,minBindingSize:16}),V({binding:1,readOnly:!0}),V({binding:2,readOnly:!0}),V({binding:3,readOnly:!1}),V({binding:4,readOnly:!0})]}]}))}encodeCopyF32(e,t,r,i,o){if(y(Number.isInteger(r)&&r>=0,`encodeCopyF32: count must be an integer >= 0 (got ${r})`),r===0)return;let a=this.getCopyF32Pipeline(),s=a.createBindGroup(0,{0:this.bindSized(t,r*4),1:this.bindSized(i,r*4)},`${o}:copy:bg`);e.push({pipeline:a,bindGroups:[s],workgroups:Te(r,256),label:`${o}:copy`})}encodeCopyU32(e,t,r,i,o){if(y(Number.isInteger(r)&&r>=0,`encodeCopyU32: count must be an integer >= 0 (got ${r})`),r===0)return;let a=this.getCopyU32Pipeline(),s=a.createBindGroup(0,{0:this.bindSized(t,r*4),1:this.bindSized(i,r*4)},`${o}:copy:bg`);e.push({pipeline:a,bindGroups:[s],workgroups:Te(r,256),label:`${o}:copy`})}copyU32(e,t={}){let r=t.count;r===void 0&&(e instanceof oe?r=this.resolveCount(e,4,void 0):y(!1,"copyU32: opts.count is required when src is not a StorageBuffer")),y(Number.isInteger(r)&&r>=0,`copyU32: count must be an integer >= 0 (got ${r})`);let i=t.out??new oe(this.device,this.queue,{label:"copyU32:out",byteLength:r*4,copySrc:!0});y(i.byteLength>=r*4,"copyU32: out buffer is too small for requested count");let o=[];return this.encodeCopyU32(o,e,r,i,"copyU32"),this.execute(o,t),i}reduceU32(e,t,r={}){let i=this.resolveCount(e,4,r.count),o=r.out??new oe(this.device,this.queue,{label:`reduceU32:${t}`,byteLength:4,copySrc:!0});if(y(o.byteLength>=4,"reduceU32: out buffer must be at least 4 bytes"),i===0)return this.writeScalarU32(o,Ec(t)),o;let a=[];return this.encodeReduceScalar(a,"u32",t,e,i,o,`reduceU32:${t}`),this.execute(a,r),o}sumU32(e,t={}){return this.reduceU32(e,"sum",t)}minU32(e,t={}){return this.reduceU32(e,"min",t)}maxU32(e,t={}){return this.reduceU32(e,"max",t)}copyF32(e,t={}){let r=t.count;r===void 0&&(e instanceof oe?r=this.resolveCount(e,4,void 0):y(!1,"copyF32: opts.count is required when src is not a StorageBuffer")),y(Number.isInteger(r)&&r>=0,`copyF32: count must be an integer >= 0 (got ${r})`);let i=t.out??new oe(this.device,this.queue,{label:"copyF32:out",byteLength:r*4,copySrc:!0});y(i.byteLength>=r*4,"copyF32: out buffer is too small for requested count");let o=[];return this.encodeCopyF32(o,e,r,i,"copyF32"),this.execute(o,t),i}extractScaleValuesF32(e,t){y(!t.encoder,"extractScaleValuesF32 does not support opts.encoder");let r=t.count;y(Number.isInteger(r)&&r>=0,`extractScaleValuesF32: count must be an integer >= 0 (got ${r})`);let i=Math.max(1,Math.min(4,Math.floor(t.componentCount??1))),o=Math.max(0,Math.min(3,Math.floor(t.componentIndex??0))),a=Math.max(i,Math.floor(t.stride??i)),s=Math.max(0,Math.floor(t.offset??0)),l=t.valueMode??"component";y(l==="component"||l==="magnitude",`extractScaleValuesF32: invalid valueMode ${String(l)}`);let u=r>0?s+(r-1)*a+i:0,c=e instanceof oe?e.byteLength:re(e).size;y(u*4<=c,`extractScaleValuesF32: source range exceeds source buffer capacity (required ${u} f32, capacity ${Math.floor(c/4)} f32)`);let m=t.values??new oe(this.device,this.queue,{label:"scale:extract:values",byteLength:r*4,copySrc:!0}),d=t.flags??new oe(this.device,this.queue,{label:"scale:extract:flags",byteLength:r*4,copySrc:!0});if(y(m.byteLength>=r*4,"extractScaleValuesF32: values buffer too small for count"),y(d.byteLength>=r*4,"extractScaleValuesF32: flags buffer too small for count"),r===0)return{values:m,flags:d};let f=this.device.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,label:"scale:extract:params"});this.queue.writeBuffer(f,0,new Uint32Array([r>>>0,i>>>0,o>>>0,mn(l)>>>0,a>>>0,s>>>0,0,0]));let p=[],h=this.getScaleExtractF32Pipeline(),g=h.createBindGroup(0,{0:this.bindSized(e,u*4),1:this.bindSized(m,r*4),2:this.bindSized(d,r*4),3:{buffer:f,size:32}},"scale:extract:bg");return p.push({pipeline:h,bindGroups:[g],workgroups:Te(r,256),label:"scale:extract"}),this.execute(p,t),f.destroy(),{values:m,flags:d}}histogramF32(e,t,r){y(!r.encoder,"histogramF32 does not support opts.encoder"),y(Number.isInteger(t)&&t>=0,`histogramF32: binCount must be an integer >= 0 (got ${t})`);let i=this.resolveCount(e,4,r.count),o=r.bins??new oe(this.device,this.queue,{label:"histogramF32:bins",byteLength:t*4,copySrc:!0});y(o.byteLength>=t*4,"histogramF32: bins buffer is too small for binCount");let a=[];if(t>0&&(r.clear??!0)){let l=this.getHistogramClearPipeline(),u=l.createBindGroup(0,{0:this.bindSized(o,t*4)},"histogramF32:clear:bg");a.push({pipeline:l,bindGroups:[u],workgroups:Te(t,256),label:"histogramF32:clear"})}let s=null;if(i>0&&t>0&&Number.isFinite(r.minValue)&&Number.isFinite(r.maxValue)&&r.maxValue>r.minValue){s=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,label:"histogramF32:params"});let l=new ArrayBuffer(16),u=new DataView(l);u.setUint32(0,i>>>0,!0),u.setUint32(4,t>>>0,!0),u.setFloat32(8,r.minValue,!0),u.setFloat32(12,r.maxValue,!0),this.queue.writeBuffer(s,0,l);let c=this.getScaleHistogramF32Pipeline(),m=c.createBindGroup(0,{0:this.bindSized(e,i*4),1:this.bindSized(o,t*4),2:{buffer:s,size:16}},"histogramF32:hist:bg");a.push({pipeline:c,bindGroups:[m],workgroups:Te(i,256),label:"histogramF32:accum"})}return this.execute(a,r),s?.destroy(),o}remapScaleF32(e,t){y(!t.encoder,"remapScaleF32 does not support opts.encoder");let r=this.resolveCount(e,4,t.count),i=t.out??new oe(this.device,this.queue,{label:"scale:remap:out",byteLength:r*4,copySrc:!0});if(y(i.byteLength>=r*4,"remapScaleF32: out buffer is too small for requested count"),r===0)return i;let o=fe(t.transform),a=new Float32Array(20);je(o,a,0);let s=this.device.createBuffer({size:80,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,label:"scale:remap:params"}),l=new ArrayBuffer(80);new DataView(l).setUint32(0,r>>>0,!0);let c=new Float32Array(l);c[4]=a[4],c[5]=a[5],c[6]=0,c[7]=cn(o.clampMode),c[8]=a[8],c[9]=a[9],c[10]=a[10],c[11]=a[11],c[12]=un(o.mode),c[13]=a[13],c[14]=a[14],c[15]=a[15],c[16]=a[16],c[17]=0,c[18]=0,c[19]=0,this.queue.writeBuffer(s,0,l);let m=this.getScaleRemapF32Pipeline(),d=m.createBindGroup(0,{0:this.bindSized(e,r*4),1:this.bindSized(i,r*4),2:{buffer:s,size:80}},"scale:remap:bg");return this.execute([{pipeline:m,bindGroups:[d],workgroups:Te(r,256),label:"scale:remap"}],t),s.destroy(),i}reduceF32(e,t,r={}){let i=this.resolveCount(e,4,r.count),o=r.out??new oe(this.device,this.queue,{label:`reduceF32:${t}`,byteLength:4,copySrc:!0});if(y(o.byteLength>=4,"reduceF32: out buffer must be at least 4 bytes"),i===0)return this.writeScalarF32Bits(o,Wc(t)),o;let a=[];return this.encodeReduceScalar(a,"f32",t,e,i,o,`reduceF32:${t}`),this.execute(a,r),o}sumF32(e,t={}){return this.reduceF32(e,"sum",t)}minF32(e,t={}){return this.reduceF32(e,"min",t)}maxF32(e,t={}){return this.reduceF32(e,"max",t)}argminF32(e,t={}){return this.argReduceF32(e,"argmin",t)}argmaxF32(e,t={}){return this.argReduceF32(e,"argmax",t)}argReduceF32(e,t,r={}){let i=this.resolveCount(e,4,r.count),o=r.out??new oe(this.device,this.queue,{label:`argReduceF32:${t}`,byteLength:8,copySrc:!0});if(y(o.byteLength>=8,"argReduceF32: out buffer must be at least 8 bytes"),i===0){let s=jc(t);return this.writeArgPairBits(o,s.valueBits,s.index),o}let a=[];return this.encodeArgReduceF32Scalar(a,t,e,i,o,`argReduceF32:${t}`),this.execute(a,r),o}scanExclusiveU32(e,t={}){let r=this.resolveCount(e,4,t.count),i=t.out??new oe(this.device,this.queue,{label:"scanExclusiveU32",byteLength:r*4,copySrc:!0});if(y(i.byteLength>=r*4,"scanExclusiveU32: out buffer is too small for requested count"),r===0)return i;let o=[];return this.encodeScanExclusiveU32Into(o,e,r,i,"scanExclusiveU32"),this.execute(o,t),i}histogramU32(e,t,r={}){y(Number.isInteger(t)&&t>=0,`binCount must be an integer >= 0 (got ${t})`);let i=this.resolveCount(e,4,r.count),o=r.bins??new oe(this.device,this.queue,{label:"histogramU32:bins",byteLength:t*4,copySrc:!0});y(o.byteLength>=t*4,"histogramU32: bins buffer is too small for binCount");let a=[];if(t>0&&(r.clear??!0)){let s=this.getHistogramClearPipeline(),l=s.createBindGroup(0,{0:this.bindSized(o,t*4)},"histogramU32:clear:bg");a.push({pipeline:s,bindGroups:[l],workgroups:Te(t,256),label:"histogramU32:clear"})}if(i>0&&t>0){let s=this.getHistogramPipeline(),l=s.createBindGroup(0,{0:this.bindSized(e,i*4),1:this.bindSized(o,t*4)},"histogramU32:hist:bg");a.push({pipeline:s,bindGroups:[l],workgroups:Te(i,256),label:"histogramU32:accum"})}return this.execute(a,r),o}compactU32(e,t,r={}){return this.compactTyped(e,t,"u32",r)}compactF32(e,t,r={}){return this.compactTyped(e,t,"f32",r)}compactTyped(e,t,r,i){let o=this.resolveCount(t,4,i.count),a=this.resolveCount(e,4,i.count);y(a===o,"compact: input and flags counts must match");let s=i.out??new oe(this.device,this.queue,{label:`compact:${r}:out`,byteLength:o*4,copySrc:!0});y(s.byteLength>=o*4,"compact: out buffer is too small for requested count");let l=new oe(this.device,this.queue,{label:`compact:${r}:count`,byteLength:4,copySrc:!0});if(o===0)return this.writeScalarU32(l,0),{output:s,count:l};let u=this.scratch.acquire(o*4,`compact:${r}:prefix`),c=[];this.encodeScanExclusiveU32Into(c,t,o,u,`compact:${r}:scan`),this.encodeReduceScalar(c,"u32","sum",t,o,l,`compact:${r}:count`);{let m=this.getCompactPipeline(r),d=m.createBindGroup(0,{0:this.bindSized(e,o*4),1:this.bindSized(t,o*4),2:this.bindSized(u,o*4),3:this.bindSized(s,o*4)},`compact:${r}:compact:bg`);c.push({pipeline:m,bindGroups:[d],workgroups:Te(o,256),label:`compact:${r}:scatter`})}return this.execute(c,i),{output:s,count:l}}radixSortKeysU32(e,t={}){let r=this.resolveCount(e,4,t.count),i=t.inPlace??!1,o=i?e:t.out??new oe(this.device,this.queue,{label:"radixSortKeysU32:out",byteLength:r*4,copySrc:!0});if(i||y(o.byteLength>=r*4,"radixSortKeysU32: out buffer is too small for requested count"),r<=1){if(!i&&r===1){let h=[];this.encodeCopyU32(h,e,1,o,"radixSortKeysU32"),this.execute(h,t)}return o}let a=this.scratch.acquire(r*4,"radix:flags"),s=this.scratch.acquire(r*4,"radix:prefix"),l=this.scratch.acquire(4,"radix:zerosCount"),c=this.scratch.acquire(r*4,"radix:keysScratch"),m=o,d=e,f=c,p=[];for(let h=0;h<32;h++){{let g=this.getRadixFlagsPipeline(h),b=g.createBindGroup(0,{0:this.bindSized(d,r*4),1:this.bindSized(a,r*4)},`radix:bit${h}:flags:bg`);p.push({pipeline:g,bindGroups:[b],workgroups:Te(r,256),label:`radix:bit${h}:flags`})}this.encodeScanExclusiveU32Into(p,a,r,s,`radix:bit${h}:scan`),this.encodeReduceScalar(p,"u32","sum",a,r,l,`radix:bit${h}:zerosCount`);{let g=this.getRadixScatterPipeline(h),b=g.createBindGroup(0,{0:this.bindSized(d,r*4),1:this.bindSized(s,r*4),2:this.bindSized(l,4),3:this.bindSized(f,r*4)},`radix:bit${h}:scatter:bg`);p.push({pipeline:g,bindGroups:[b],workgroups:Te(r,256),label:`radix:bit${h}:scatter`})}d=f,f=f===c?m:c}return i?d!==e&&this.encodeCopyU32(p,d,r,e,"radixSortKeysU32:finalize"):d!==o&&this.encodeCopyU32(p,d,r,o,"radixSortKeysU32:finalize"),this.execute(p,t),o}luFactorF32Batched(e,t,r,i,o={}){if(y(!o.encoder,"luFactorF32Batched does not support opts.encoder"),y(Number.isInteger(r)&&r>=0,`luFactorF32Batched: batchCount must be an integer >= 0 (got ${r})`),y(Number.isInteger(i)&&i>=0,`luFactorF32Batched: n must be an integer >= 0 (got ${i})`),y(e!==t,"luFactorF32Batched: matrices and ipiv must be distinct StorageBuffer instances"),r===0||i===0)return;let a=i*i;y(Number.isFinite(a)&&a<=4294967295,"luFactorF32Batched: n*n overflow");let s=r*a*4,l=r*i*4;if(y(e.byteLength>=s,`luFactorF32Batched: matrices buffer too small (need ${s} bytes, have ${e.byteLength})`),y(t.byteLength>=l,`luFactorF32Batched: ipiv buffer too small (need ${l} bytes, have ${t.byteLength})`),i<160){let b=this.getLuBatchedParamsBuffer();this.queue.writeBuffer(b,0,new Uint32Array([r>>>0,i>>>0,a>>>0,0]));let P=this.getLuFactorRealPipeline(),v=P.createBindGroup(0,{0:{buffer:b,size:16},1:this.bindSized(e,s),2:this.bindSized(t,l)},"luFactorF32Batched:bg");this.execute([{pipeline:P,bindGroups:[v],workgroups:{x:r,y:1,z:1},label:"luFactorF32Batched"}],o);return}let u=this.getLuBlockedParamsBuffer(),c=this.getLuFactorRealLeadPipeline(),m=this.getLuFactorRealUpperPipeline(),d=this.getLuFactorRealTrailingPipeline(),f=c.createBindGroup(0,{0:{buffer:u,size:32},1:this.bindSized(e,s),2:this.bindSized(t,l)},"luFactorF32:lead:bg"),p=m.createBindGroup(0,{0:{buffer:u,size:32},1:this.bindSized(e,s)},"luFactorF32:upper:bg"),h=d.createBindGroup(0,{0:{buffer:u,size:32},1:this.bindSized(e,s)},"luFactorF32:trailing:bg"),g=16;for(let b=0;b<i;b+=g){let P=Math.min(g,i-b),v=i-(b+P);this.queue.writeBuffer(u,0,new Uint32Array([r>>>0,i>>>0,a>>>0,b>>>0,P>>>0,0,0,0]));let x=[{pipeline:c,bindGroups:[f],workgroups:{x:r,y:1,z:1},label:`luFactorF32:lead:kk${b}`}];if(v>0){let T=r*v;x.push({pipeline:m,bindGroups:[p],workgroups:Te(T,256),label:`luFactorF32:upper:kk${b}`});let w=v,M=v,B=16,S=8,R=Math.ceil(w/B),G=Math.ceil(M/S);x.push({pipeline:d,bindGroups:[h],workgroups:{x:G,y:R,z:r},label:`luFactorF32:trailing:kk${b}`})}this.execute(x,o)}}luSolveF32Batched(e,t,r,i,o,a,s={}){if(y(!s.encoder,"luSolveF32Batched does not support opts.encoder"),y(Number.isInteger(o)&&o>=0,`luSolveF32Batched: batchCount must be an integer >= 0 (got ${o})`),y(Number.isInteger(a)&&a>=0,`luSolveF32Batched: n must be an integer >= 0 (got ${a})`),y(e!==r&&e!==i&&e!==t&&r!==i&&r!==t&&i!==t,"luSolveF32Batched: lu, ipiv, rhs, and outX must be distinct StorageBuffer instances"),o===0||a===0)return;let l=a*a;y(Number.isFinite(l)&&l<=4294967295,"luSolveF32Batched: n*n overflow");let u=o*l*4,c=o*a*4,m=o*a*4;y(e.byteLength>=u,`luSolveF32Batched: lu buffer too small (need ${u} bytes, have ${e.byteLength})`),y(t.byteLength>=m,`luSolveF32Batched: ipiv buffer too small (need ${m} bytes, have ${t.byteLength})`),y(r.byteLength>=c,`luSolveF32Batched: rhs buffer too small (need ${c} bytes, have ${r.byteLength})`),y(i.byteLength>=c,`luSolveF32Batched: outX buffer too small (need ${c} bytes, have ${i.byteLength})`);let d=this.getLuBatchedParamsBuffer();this.queue.writeBuffer(d,0,new Uint32Array([o>>>0,a>>>0,l>>>0,0]));let f=a<=512?this.getLuSolveRealSharedPipeline():this.getLuSolveRealPipeline(),p=f.createBindGroup(0,{0:{buffer:d,size:16},1:this.bindSized(e,u),2:this.bindSized(r,c),3:this.bindSized(i,c),4:this.bindSized(t,m)},"luSolveF32Batched:bg");this.execute([{pipeline:f,bindGroups:[p],workgroups:{x:o,y:1,z:1},label:"luSolveF32Batched"}],s)}luFactorComplex64Batched(e,t,r,i,o={}){if(y(!o.encoder,"luFactorComplex64Batched does not support opts.encoder"),y(Number.isInteger(r)&&r>=0,`luFactorComplex64Batched: batchCount must be an integer >= 0 (got ${r})`),y(Number.isInteger(i)&&i>=0,`luFactorComplex64Batched: n must be an integer >= 0 (got ${i})`),y(e!==t,"luFactorComplex64Batched: matrices and ipiv must be distinct StorageBuffer instances"),r===0||i===0)return;let a=i*i;y(Number.isFinite(a)&&a<=4294967295,"luFactorComplex64Batched: n*n overflow");let s=r*a*8,l=r*i*4;if(y(e.byteLength>=s,`luFactorComplex64Batched: matrices buffer too small (need ${s} bytes, have ${e.byteLength})`),y(t.byteLength>=l,`luFactorComplex64Batched: ipiv buffer too small (need ${l} bytes, have ${t.byteLength})`),i<160){let b=this.getLuBatchedParamsBuffer();this.queue.writeBuffer(b,0,new Uint32Array([r>>>0,i>>>0,a>>>0,0]));let P=this.getLuFactorComplexSmallPipeline(),v=P.createBindGroup(0,{0:{buffer:b,size:16},1:this.bindSized(e,s),2:this.bindSized(t,l)},"luFactorComplex64Batched:bg");this.execute([{pipeline:P,bindGroups:[v],workgroups:{x:r,y:1,z:1},label:"luFactorComplex64Batched"}],o);return}let u=this.getLuBlockedParamsBuffer(),c=this.getLuFactorComplexLeadPipeline(),m=this.getLuFactorComplexUpperPipeline(),d=this.getLuFactorComplexTrailingPipeline(),f=c.createBindGroup(0,{0:{buffer:u,size:32},1:this.bindSized(e,s),2:this.bindSized(t,l)},"luFactorComplex64:lead:bg"),p=m.createBindGroup(0,{0:{buffer:u,size:32},1:this.bindSized(e,s)},"luFactorComplex64:upper:bg"),h=d.createBindGroup(0,{0:{buffer:u,size:32},1:this.bindSized(e,s)},"luFactorComplex64:trailing:bg"),g=16;for(let b=0;b<i;b+=g){let P=Math.min(g,i-b),v=i-(b+P);this.queue.writeBuffer(u,0,new Uint32Array([r>>>0,i>>>0,a>>>0,b>>>0,P>>>0,0,0,0]));let x=[{pipeline:c,bindGroups:[f],workgroups:{x:r,y:1,z:1},label:`luFactorComplex64:lead:kk${b}`}];if(v>0){let T=r*v;x.push({pipeline:m,bindGroups:[p],workgroups:Te(T,256),label:`luFactorComplex64:upper:kk${b}`});let w=v,M=v,B=16,S=8,R=Math.ceil(w/B),G=Math.ceil(M/S);x.push({pipeline:d,bindGroups:[h],workgroups:{x:G,y:R,z:r},label:`luFactorComplex64:trailing:kk${b}`})}this.execute(x,o)}}luSolveComplex64Batched(e,t,r,i,o,a,s={}){if(y(!s.encoder,"luSolveComplex64Batched does not support opts.encoder"),y(Number.isInteger(o)&&o>=0,`luSolveComplex64Batched: batchCount must be an integer >= 0 (got ${o})`),y(Number.isInteger(a)&&a>=0,`luSolveComplex64Batched: n must be an integer >= 0 (got ${a})`),y(e!==r&&e!==i&&e!==t&&r!==i&&r!==t&&i!==t,"luSolveComplex64Batched: lu, ipiv, rhs, and outX must be distinct StorageBuffer instances"),o===0||a===0)return;let l=a*a;y(Number.isFinite(l)&&l<=4294967295,"luSolveComplex64Batched: n*n overflow");let u=o*l*8,c=o*a*8,m=o*a*4;y(e.byteLength>=u,`luSolveComplex64Batched: lu buffer too small (need ${u} bytes, have ${e.byteLength})`),y(t.byteLength>=m,`luSolveComplex64Batched: ipiv buffer too small (need ${m} bytes, have ${t.byteLength})`),y(r.byteLength>=c,`luSolveComplex64Batched: rhs buffer too small (need ${c} bytes, have ${r.byteLength})`),y(i.byteLength>=c,`luSolveComplex64Batched: outX buffer too small (need ${c} bytes, have ${i.byteLength})`);let d=this.getLuBatchedParamsBuffer();this.queue.writeBuffer(d,0,new Uint32Array([o>>>0,a>>>0,l>>>0,0]));let f=a<=512?this.getLuSolveComplexPipeline():this.getLuSolveComplexLargePipeline(),p=f.createBindGroup(0,{0:{buffer:d,size:16},1:this.bindSized(e,u),2:this.bindSized(r,c),3:this.bindSized(i,c),4:this.bindSized(t,m)},"luSolveComplex64Batched:bg");this.execute([{pipeline:f,bindGroups:[p],workgroups:{x:o,y:1,z:1},label:"luSolveComplex64Batched"}],s)}};var Ns="struct Params { p0 : vec4f, p1 : vec4f } @group(0) @binding(0) var<uniform> params: Params; @group(0) @binding(1) var<storage, read> pixels: array<u32>; fn unpackRGBA8(x: u32) -> vec4f { let r = f32(x & 255u) / 255.0; let g = f32((x >> 8u) & 255u) / 255.0; let b = f32((x >> 16u) & 255u) / 255.0; let a = f32((x >> 24u) & 255u) / 255.0; return vec4f(r, g, b, a); } struct VSOut { @builtin(position) position: vec4f } @vertex fn vs_main(@builtin(vertex_index) vid: u32) -> VSOut { var pos = array<vec2f, 3>( vec2f(-1.0, -1.0), vec2f( 3.0, -1.0), vec2f(-1.0, 3.0) ); var out: VSOut; out.position = vec4f(pos[vid], 0.0, 1.0); return out; } @fragment fn fs_main(@builtin(position) pos: vec4f) -> @location(0) vec4f { let displayW = max(1.0, params.p0.x); let displayH = max(1.0, params.p0.y); let outW = max(1.0, params.p0.z); let outH = max(1.0, params.p0.w); let flipY = params.p1.x > 0.5; let xOut = clamp(i32(floor(pos.x * outW / displayW)), 0, i32(outW) - 1); var yOut = clamp(i32(floor(pos.y * outH / displayH)), 0, i32(outH) - 1); if (flipY) { yOut = i32(outH) - 1 - yOut; } let idx = u32(yOut) * u32(outW) + u32(xOut); return unpackRGBA8(pixels[idx]); }";var qc=()=>{let n=typeof navigator<"u"?navigator:null,e=n&&n.gpu?n.gpu:null;if(e&&typeof e.getPreferredCanvasFormat=="function")return e.getPreferredCanvasFormat();throw new Error("blitRGBA8BufferToCanvas: opts.format must be provided when navigator.gpu is unavailable.")},xn=class{device;queue;paramsStride;paramsCapacity;paramsBuffer;paramsF32;paramsIndex=0;pipelineByFormat=new Map;canvasState=new WeakMap;constructor(e,t,r={}){this.device=e,this.queue=t;let i=Math.max(256,e.limits.minUniformBufferOffsetAlignment);this.paramsStride=he(32,i),this.paramsCapacity=Math.max(1,r.uniformCapacity??256),this.paramsBuffer=e.createBuffer({label:"WasmGPU:compute:blitRGBA8:params",size:this.paramsStride*this.paramsCapacity,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.paramsF32=new Float32Array(8)}destroy(){this.paramsBuffer.destroy(),this.pipelineByFormat.clear()}encode(e,t,r,i,o,a={}){if(y(Se(i)&&Se(o),`outWidth/outHeight must be integers >= 0 (got ${i}x${o})`),i===0||o===0)return;let s=this.getOrCreateCanvasState(t),l=a.format??s.format??qc(),u=a.alphaMode??s.alphaMode??"opaque",c=a.autoResize??!0?this.autoResizeCanvas(t,s,a.dpr):this.syncCanvasSizeWithoutResize(t,s);(!s.configured||c||s.format!==l||s.alphaMode!==u)&&(s.context.configure({device:this.device,format:l,alphaMode:u}),s.configured=!0,s.format=l,s.alphaMode=u);let d=Math.max(1,t.width),f=Math.max(1,t.height);this.paramsF32[0]=d,this.paramsF32[1]=f,this.paramsF32[2]=i,this.paramsF32[3]=o,this.paramsF32[4]=a.flipY?1:0,this.paramsF32[5]=0,this.paramsF32[6]=0,this.paramsF32[7]=0;let p=this.allocParamsChunk();this.queue.writeBuffer(this.paramsBuffer,p,this.paramsF32.buffer,this.paramsF32.byteOffset,this.paramsF32.byteLength);let h=this.getPipeline(l),g=re(r),b=h.bindGroups.get(g);b||(b=this.device.createBindGroup({label:a.label?`${a.label}:bindGroup`:void 0,layout:h.bindGroupLayout,entries:[{binding:0,resource:{buffer:this.paramsBuffer,offset:0,size:32}},{binding:1,resource:{buffer:g}}]}),h.bindGroups.set(g,b));let P=s.context.getCurrentTexture().createView(),v=a.loadOp??"load",x=a.storeOp??"store",T=a.clearColor??{r:0,g:0,b:0,a:1},w=e.beginRenderPass({label:a.label,colorAttachments:[{view:P,clearValue:T,loadOp:v,storeOp:x}]});w.setPipeline(h.pipeline),w.setBindGroup(0,b,[p]),w.draw(3,1,0,0),w.end()}allocParamsChunk(){let e=this.paramsIndex++;return this.paramsIndex>=this.paramsCapacity&&(this.paramsIndex=0),e%this.paramsCapacity*this.paramsStride}getOrCreateCanvasState(e){let t=this.canvasState.get(e);if(t)return t;let r=e.getContext("webgpu");y(!!r,"blitRGBA8BufferToCanvas: failed to acquire a WebGPU canvas context");let i={context:r,width:Math.max(1,e.width),height:Math.max(1,e.height),format:null,alphaMode:"opaque",configured:!1};return this.canvasState.set(e,i),i}autoResizeCanvas(e,t,r){let i=r??Math.max(1,typeof window<"u"&&window.devicePixelRatio||1),o=Math.max(1,Math.floor(e.clientWidth*i)),a=Math.max(1,Math.floor(e.clientHeight*i));return o===t.width&&a===t.height?!1:(t.width=o,t.height=a,e.width=o,e.height=a,!0)}syncCanvasSizeWithoutResize(e,t){let r=Math.max(1,e.width),i=Math.max(1,e.height);return r===t.width&&i===t.height?!1:(t.width=r,t.height=i,!0)}getPipeline(e){let t=this.pipelineByFormat.get(e);if(t)return t;let r=this.device.createShaderModule({label:"WasmGPU:compute:blitRGBA8:shader",code:Ns}),i=this.device.createBindGroupLayout({label:"WasmGPU:compute:blitRGBA8:bgl",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform",hasDynamicOffset:!0,minBindingSize:32}},{binding:1,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),a={pipeline:this.device.createRenderPipeline({label:"WasmGPU:compute:blitRGBA8:pipeline",layout:this.device.createPipelineLayout({bindGroupLayouts:[i]}),vertex:{module:r,entryPoint:"vs_main"},fragment:{module:r,entryPoint:"fs_main",targets:[{format:e}]},primitive:{topology:"triangle-list",cullMode:"none"}}),bindGroupLayout:i,bindGroups:new WeakMap};return this.pipelineByFormat.set(e,a),a}};var Kc=n=>n instanceof oe?n.byteLength:Number(n.size),Xc=n=>{if(n instanceof oe)return n.usage;let e=n.usage;return typeof e=="number"?e:null},ir=class{device;queue;labelPrefix;slots=[];cursor=0;destroyed=!1;constructor(e,t,r={}){this.device=e,this.queue=t;let i=Math.max(1,r.slots??3);this.labelPrefix=r.labelPrefix??"WasmGPU:readback";for(let o=0;o<i;o++)this.slots.push(this.createSlot(4,o))}createSlot(e,t){let r=Math.max(4,he(e,4));return{buffer:this.device.createBuffer({label:`${this.labelPrefix}:slot${t}`,size:r,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),capacityBytes:r,tail:Promise.resolve()}}ensureNotDestroyed(){y(!this.destroyed,"ReadbackRing is destroyed")}assertSourceCanReadback(e){if(e instanceof oe){y(e.canReadback,"ReadbackRing requires the source StorageBuffer to be created with copySrc: true");return}let t=Xc(e);t!==null&&y((t&GPUBufferUsage.COPY_SRC)!==0,"ReadbackRing requires the source GPUBuffer to have GPUBufferUsage.COPY_SRC")}async read(e,t=0,r,i={}){this.ensureNotDestroyed(),y(this.slots.length>0,"ReadbackRing has no slots"),y(Se(t),`srcOffsetBytes must be an integer >= 0 (got ${t})`),y((t&3)===0,`srcOffsetBytes must be 4-byte aligned for readback (got ${t})`),this.assertSourceCanReadback(e);let o=Kc(e),a=o-t;y(a>=0,`srcOffsetBytes (${t}) exceeds source byteLength (${o})`);let s=r??a;y(Se(s),`sizeBytes must be an integer >= 0 (got ${s})`),y(s<=a,`sizeBytes (${s}) exceeds remaining bytes (${a})`);let l=Math.max(4,he(s,4));y(l<=a,`Aligned copy size (${l}) exceeds remaining bytes (${a}). copyBufferToBuffer requires multiples of 4.`);let u=this.cursor;this.cursor=(this.cursor+1)%this.slots.length;let c=this.slots[u],m=async()=>{if(this.ensureNotDestroyed(),c.buffer.mapState==="mapped"||c.buffer.mapState==="pending"){try{c.buffer.unmap()}catch{}y(c.buffer.mapState!=="mapped"&&c.buffer.mapState!=="pending","ReadbackRing internal error: staging buffer is still mapped")}if(l>c.capacityBytes){try{c.buffer.destroy()}catch{}let h=this.createSlot(l,u);c.buffer=h.buffer,c.capacityBytes=h.capacityBytes}let f=re(e),p=this.device.createCommandEncoder({label:i.label?`${i.label}:copyToStaging`:`${this.labelPrefix}:copyToStaging`});p.copyBufferToBuffer(f,t,c.buffer,0,l),this.queue.submit([p.finish()]);try{await c.buffer.mapAsync(GPUMapMode.READ,0,l);let g=c.buffer.getMappedRange(0,l).slice(0,s);return c.buffer.unmap(),g}catch(h){try{c.buffer.unmap()}catch{}throw h}},d=c.tail.then(m,m);return c.tail=d.then(()=>{},()=>{}),d}async readAs(e,t,r=0,i,o={}){let a=await this.read(t,r,i,o),s=e.BYTES_PER_ELEMENT;y(a.byteLength%s===0,`readAs: byteLength (${a.byteLength}) is not divisible by BYTES_PER_ELEMENT (${s})`);let l=a.byteLength/s;return new e(a,0,l)}readU32(e,t=0,r,i={}){y(Se(t),`elemOffset must be an integer >= 0 (got ${t})`);let o=t*4,a=r===void 0?void 0:r*4;return this.readAs(Uint32Array,e,o,a,i)}readF32(e,t=0,r,i={}){y(Se(t),`elemOffset must be an integer >= 0 (got ${t})`);let o=t*4,a=r===void 0?void 0:r*4;return this.readAs(Float32Array,e,o,a,i)}async readScalarU32(e,t=0,r={}){return(await this.readAs(Uint32Array,e,t,4,r))[0]>>>0}async readScalarF32(e,t=0,r={}){return(await this.readAs(Float32Array,e,t,4,r))[0]}destroy(){if(!this.destroyed){this.destroyed=!0;for(let e of this.slots){try{(e.buffer.mapState==="mapped"||e.buffer.mapState==="pending")&&e.buffer.unmap()}catch{}try{e.buffer.destroy()}catch{}e.tail=Promise.resolve()}this.slots.length=0}}};var Pn=class{device;queue;kernels;readback;ndarray=Ft;CPUndarray=Kt;GPUndarray=Xt;_rgba8Blitter=null;constructor(e,t,r={}){this.device=e,this.queue=t,this.kernels=new Mr(e,t),this.readback=new ir(e,t,r.readback)}createStorageBuffer(e){return new oe(this.device,this.queue,e)}createUniformBuffer(e){return new xr(this.device,this.queue,e)}createPipeline(e){return new Q(this.device,e)}createReadbackRing(e={}){return new ir(this.device,this.queue,e)}encodeDispatch(e,t,r=!1){r&&kr(this.device,t.workgroups),Mo(e,t)}encodeDispatchBatch(e,t,r,i=!1){if(i)for(let o of t)kr(this.device,o.workgroups);yn(e,t,r)}dispatch(e,t={}){let r=this.device.createCommandEncoder();this.encodeDispatch(r,e,t.validateLimits??!1);let i=r.finish();return t.submit!==!1&&this.queue.submit([i]),i}dispatchBatch(e,t,r={}){let i=this.device.createCommandEncoder();this.encodeDispatchBatch(i,e,t,r.validateLimits??!1);let o=i.finish();return r.submit!==!1&&this.queue.submit([o]),o}dispatch1D(e,t,r,i,o,a={}){let s=Te(r,i);return this.dispatch({pipeline:e,bindGroups:t,workgroups:s,label:o},a)}dispatch2D(e,t,r,i,o,a,s,l={}){let u=gn(r,i,o,a);return this.dispatch({pipeline:e,bindGroups:t,workgroups:u,label:s},l)}dispatch3D(e,t,r,i,o,a,s,l,u,c={}){let m=bn(r,i,o,a,s,l);return this.dispatch({pipeline:e,bindGroups:t,workgroups:m,label:u},c)}blitRGBA8BufferToCanvas(e,t,r,i,o,a={}){this._rgba8Blitter||(this._rgba8Blitter=new xn(this.device,this.queue)),this._rgba8Blitter.encode(e,t,r,i,o,a)}workgroups1D(e,t){return Te(e,t)}workgroups2D(e,t,r,i){return gn(e,t,r,i)}workgroups3D(e,t,r,i,o,a){return bn(e,t,r,i,o,a)}destroy(){this._rgba8Blitter?.destroy(),this._rgba8Blitter=null,this.readback.destroy(),this.kernels.destroy()}};var Tn=n=>n.startsWith("data:"),Sn=n=>{let e=n.match(/^data:([^,]*),([\s\S]*)$/);if(!e)throw new Error(`Invalid data URI: ${n.slice(0,64)}...`);let t=e[1]??"",r=e[2]??"",i=t.split(";").filter(u=>u.length>0),o=null,a=!1;for(let u of i)u==="base64"?a=!0:o=u;if(a){let u=atob(r),c=new Uint8Array(u.length);for(let m=0;m<u.length;m++)c[m]=u.charCodeAt(m)&255;return{mimeType:o,data:c.buffer}}let s=decodeURIComponent(r),l=new Uint8Array(s.length);for(let u=0;u<s.length;u++)l[u]=s.charCodeAt(u)&255;return{mimeType:o,data:l.buffer}},zs=n=>{let e=n.lastIndexOf("/");return e<0?"":n.slice(0,e+1)},Cn=(n,e)=>e.startsWith("http://")||e.startsWith("https://")||e.startsWith("blob:")||e.startsWith("/")||!n?e:n+e;var Lr=n=>{let e=new DataView(n);if(e.byteLength<12)throw new Error("Invalid GLB: too small");let t=e.getUint32(0,!0),r=e.getUint32(4,!0),i=e.getUint32(8,!0);if(t!==1179937895)throw new Error("Invalid GLB: bad magic");if(r!==2)throw new Error(`Unsupported GLB version: ${r}`);if(i>e.byteLength)throw new Error("Invalid GLB: length exceeds buffer");let o=12,a=null,s=null;for(;o+8<=i;){let c=e.getUint32(o+0,!0),m=e.getUint32(o+4,!0);if(o+=8,o+c>i)throw new Error("Invalid GLB: chunk exceeds buffer length");let d=n.slice(o,o+c);m===1313821514?a=d:m===5130562&&!s&&(s=d),o+=c}if(!a)throw new Error("Invalid GLB: missing JSON chunk");let l=new TextDecoder("utf-8").decode(a);return{json:JSON.parse(l),binChunk:s}};var Rr={5120:{bytes:1,ctor:Int8Array,signed:!0,bits:8},5121:{bytes:1,ctor:Uint8Array,signed:!1,bits:8},5122:{bytes:2,ctor:Int16Array,signed:!0,bits:16},5123:{bytes:2,ctor:Uint16Array,signed:!1,bits:16},5124:{bytes:4,ctor:Int32Array,signed:!0,bits:32},5125:{bytes:4,ctor:Uint32Array,signed:!1,bits:32},5126:{bytes:4,ctor:Float32Array,signed:!0,bits:32}},Yc=n=>{switch(n){case"SCALAR":return 1;case"VEC2":return 2;case"VEC3":return 3;case"VEC4":return 4;case"MAT2":return 4;case"MAT3":return 9;case"MAT4":return 16;default:return 1}},Zc=(n,e)=>{let t=n.accessors?.[e];if(!t)throw new Error(`Invalid accessor index: ${e}`);return t},Lo=(n,e)=>{let t=n.bufferViews?.[e];if(!t)throw new Error(`Invalid bufferView index: ${e}`);return t},Ro=(n,e,t)=>{let r=_.allocBytes(t),i=new Uint8Array(n,e,t);return _.u8view(r,t).set(i),r},Qc=(n,e)=>{let t=new Uint8Array(e);return t.set(_.u8view(n,e)),t},It=(n,e)=>{let t=n.json,r=Zc(t,e),i=r.componentType,o=Rr[i];if(!o)throw new Error(`Unsupported accessor componentType: ${i}`);let a=r.count|0,s=r.type,l=Yc(s),u=r.normalized===!0,c=o.bytes*l,m;if(r.bufferView===void 0)m=new o.ctor(new ArrayBuffer(a*l*o.bytes),0,a*l);else{let d=Lo(t,r.bufferView);if(d.extensions?.EXT_meshopt_compression)throw new Error("EXT_meshopt_compression is not supported yet. Please provide an uncompressed glTF/GLB.");let f=n.buffers[d.buffer];if(!f)throw new Error(`Missing buffer[${d.buffer}]`);let p=(d.byteOffset??0)|0,h=(r.byteOffset??0)|0,g=p+h,b=d.byteStride??c;if(b<c)throw new Error(`Invalid bufferView.byteStride (${b}) < element byte size (${c})`);let P=b===c,v=g%o.bytes===0;if(P&&v)m=new o.ctor(f,g,a*l);else if(a<=0)m=new o.ctor(new ArrayBuffer(0),0,0);else{let x=o.bytes*l,T=(a-1)*b+x,w=Ro(f,g,T),M=a*x,B=_.allocBytes(M);try{jt.deinterleave(B,w,a,l,o.bytes,b);let S=Qc(B,M),R=new ArrayBuffer(M);new Uint8Array(R).set(S),m=new o.ctor(R,0,a*l)}finally{_.freeBytes(B,M),_.freeBytes(w,T)}}}if(r.sparse){let d=m.slice();Jc(n,r,d,i,l),m=d}return{accessor:r,componentType:i,type:s,count:a,numComponents:l,normalized:u,array:m}},Jc=(n,e,t,r,i)=>{let o=e.sparse,a=o.count|0;if(a<=0)return;let s=Lo(n.json,o.indices.bufferView);if(s.extensions?.EXT_meshopt_compression)throw new Error("EXT_meshopt_compression sparse indices are not supported yet.");let l=n.buffers[s.buffer];if(!l)throw new Error(`Missing buffer[${s.buffer}] for sparse indices`);let u=(s.byteOffset??0)+(o.indices.byteOffset??0),c=o.indices.componentType,m=Rr[c];if(!m)throw new Error(`Unsupported sparse indices componentType: ${c}`);let d=m.bytes,f=Lo(n.json,o.values.bufferView);if(f.extensions?.EXT_meshopt_compression)throw new Error("EXT_meshopt_compression sparse values are not supported yet.");let p=n.buffers[f.buffer];if(!p)throw new Error(`Missing buffer[${f.buffer}] for sparse values`);let h=(f.byteOffset??0)+(o.values.byteOffset??0),g=Rr[r];if(!g)throw new Error(`Unsupported sparse values componentType: ${r}`);let b=t.length,P=g.bytes,v=b*P,x=_.allocBytes(v);_.u8view(x,v).set(new Uint8Array(t.buffer,t.byteOffset,v));let T=a*d,w=Ro(l,u,T),M=a*i*P,B=Ro(p,h,M);try{jt.applySparse(x,b,r,i,w,c,B,a);let S=_.u8view(x,v);new Uint8Array(t.buffer,t.byteOffset,v).set(S)}finally{_.freeBytes(B,M),_.freeBytes(w,T),_.freeBytes(x,v)}},Ae=(n,e)=>{let t=It(n,e),r=Rr[t.componentType];if(!r)throw new Error(`Unsupported componentType: ${t.componentType}`);if(t.componentType===5126&&!t.normalized)return t.array;let i=t.array.length*r.bytes,o=_.allocBytes(i);_.u8view(o,i).set(new Uint8Array(t.array.buffer,t.array.byteOffset,i));let a=_.allocF32(t.array.length);try{jt.convertToF32(a,o,t.array.length,t.componentType,t.normalized);let s=new Float32Array(t.array.length);return s.set(_.f32view(a,t.array.length)),s}finally{_.freeF32(a,t.array.length),_.freeBytes(o,i)}},Ur=(n,e)=>{let t=It(n,e),r=t.componentType,i=Rr[r];if(!i)throw new Error(`Unsupported componentType: ${r}`);if(r===5123&&!t.normalized)return t.array;let o=t.array.length*i.bytes,a=_.allocBytes(o);_.u8view(a,o).set(new Uint8Array(t.array.buffer,t.array.byteOffset,o));let s=t.array.length*2,l=_.allocBytes(s);try{jt.convertToU16(l,a,t.array.length,r);let u=new Uint16Array(t.array.length);return new Uint8Array(u.buffer).set(_.u8view(l,s)),u}finally{_.freeBytes(l,s),_.freeBytes(a,o)}},wn=(n,e)=>{let t=It(n,e),r=t.componentType,i=Rr[r];if(!i)throw new Error(`Unsupported componentType: ${r}`);if(r===5125&&!t.normalized)return t.array;let o=t.array.length*i.bytes,a=_.allocBytes(o);_.u8view(a,o).set(new Uint8Array(t.array.buffer,t.array.byteOffset,o));let s=t.array.length*4,l=_.allocBytes(s);try{jt.convertToU32(l,a,t.array.length,r);let u=new Uint32Array(t.array.length);return new Uint8Array(u.buffer).set(_.u8view(l,s)),u}finally{_.freeBytes(l,s),_.freeBytes(a,o)}};var em=(n,e)=>n?.onWarning?.(e),Os=n=>{let e=n?.fetch??globalThis.fetch;if(!e)throw new Error("loadGltf(): fetch() is not available. Pass LoadGltfOptions.fetch or provide an ArrayBuffer source.");return e},Uo=async(n,e)=>{let r=await Os(e)(n);if(!r.ok)throw new Error(`Failed to fetch ${n}: ${r.status} ${r.statusText}`);return await r.arrayBuffer()},tm=async(n,e)=>{let r=await Os(e)(n);if(!r.ok)throw new Error(`Failed to fetch ${n}: ${r.status} ${r.statusText}`);return await r.json()},Ti=async(n,e,t,r)=>{let i=n.buffers??[],o=new Array(i.length);for(let a=0;a<i.length;a++){let s=i[a];if(!s.uri){if(!r)throw new Error(`buffers[${a}] has no uri but no GLB BIN chunk was provided`);o[a]=r;continue}if(Tn(s.uri)){o[a]=Sn(s.uri).data;continue}let l=Cn(e,s.uri);o[a]=await Uo(l,t)}return o},Si=async(n,e,t,r)=>{let i=n.images??[],o=new Array(i.length);for(let a=0;a<i.length;a++){let s=i[a];if(s.uri){if(Tn(s.uri))o[a]=Sn(s.uri).data;else{let l=Cn(t,s.uri);o[a]=await Uo(l,r)}continue}if(s.bufferView!==void 0){let l=n.bufferViews?.[s.bufferView];if(!l)throw new Error(`Invalid images[${a}].bufferView: ${s.bufferView}`);let u=e[l.buffer];if(!u)throw new Error(`Missing buffer[${l.buffer}] for images[${a}]`);let c=(l.byteOffset??0)|0,m=l.byteLength|0,d=new Uint8Array(m);d.set(new Uint8Array(u,c,m)),o[a]=d.buffer;continue}em(r,`images[${a}] has neither uri nor bufferView; skipping`),o[a]=new ArrayBuffer(0)}return o},Ci=async(n,e)=>{if(typeof n=="string"){let c=n,m=e?.baseUrl??zs(c);if(c.toLowerCase().endsWith(".glb")){let h=await Uo(c,e),{json:g,binChunk:b}=Lr(h),P=await Ti(g,m,e,b),v={json:g,buffers:P,baseUrl:m};return e?.loadImages&&(v.images=await Si(g,P,m,e)),v}let d=await tm(c,e),f=await Ti(d,m,e,null),p={json:d,buffers:f,baseUrl:m};return e?.loadImages&&(p.images=await Si(d,f,m,e)),p}let t=n,r=new DataView(t),i=r.byteLength>=4?r.getUint32(0,!0):0,o=e?.baseUrl??"";if(i===1179937895){let{json:c,binChunk:m}=Lr(t),d=await Ti(c,o,e,m),f={json:c,buffers:d,baseUrl:o};return e?.loadImages&&(f.images=await Si(c,d,o,e)),f}let a=new TextDecoder("utf-8").decode(t),s=JSON.parse(a),l=await Ti(s,o,e,null),u={json:s,buffers:l,baseUrl:o};return e?.loadImages&&(u.images=await Si(s,l,o,e)),u};var Vs="@group(0) @binding(0) var samp: sampler; @group(0) @binding(1) var tex: texture_2d<f32>; struct VSOut { @builtin(position) pos: vec4f, @location(0) uv: vec2f }; @vertex fn vs_main(@builtin(vertex_index) idx: u32) -> VSOut { var positions = array<vec2f, 3>( vec2f(-1.0, -1.0), vec2f( 3.0, -1.0), vec2f(-1.0, 3.0) ); var uvs = array<vec2f, 3>( vec2f(0.0, 1.0), vec2f(2.0, 1.0), vec2f(0.0, -1.0) ); var o: VSOut; o.pos = vec4f(positions[idx], 0.0, 1.0); o.uv = uvs[idx]; return o; } @fragment fn fs_main(in: VSOut) -> @location(0) vec4f { return textureSample(tex, samp, in.uv); }";var nm=1,im=()=>typeof globalThis.createImageBitmap=="function",om=(n,e)=>{let t=Math.max(1,n|0,e|0);return(Math.floor(Math.log2(t))|0)+1},Es=new WeakMap,am=n=>{let e=Es.get(n);if(e)return e;let t=n.createShaderModule({code:Vs}),r=n.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}}]}),i=n.createPipelineLayout({bindGroupLayouts:[r]}),o=l=>n.createRenderPipeline({layout:i,vertex:{module:t,entryPoint:"vs_main"},fragment:{module:t,entryPoint:"fs_main",targets:[{format:l}]},primitive:{topology:"triangle-list"}}),a=n.createSampler({minFilter:"linear",magFilter:"linear"}),s={pipelineLinear:o("rgba8unorm"),pipelineSrgb:o("rgba8unorm-srgb"),sampler:a,bindGroupLayout:r};return Es.set(n,s),s},or=class n{id=nm++;_source;_mipmaps;_mipmapColorSpace=null;samplerDesc;_gpuTexture=null;_viewLinear=null;_viewSrgb=null;_sampler=null;_uploadPromise=null;_uploadStarted=!1;_revision=0;_width=0;_height=0;constructor(e){this._source=e.source,this._mipmaps=e.mipmaps??!0,this.samplerDesc={addressModeU:e.sampler?.addressModeU??"repeat",addressModeV:e.sampler?.addressModeV??"repeat",addressModeW:e.sampler?.addressModeW??"repeat",magFilter:e.sampler?.magFilter??"linear",minFilter:e.sampler?.minFilter??"linear",mipmapFilter:e.sampler?.mipmapFilter??"linear",lodMinClamp:e.sampler?.lodMinClamp??0,lodMaxClamp:e.sampler?.lodMaxClamp??32}}get revision(){return this._revision}get width(){return this._width}get height(){return this._height}get uploaded(){return!!this._gpuTexture}static createFrom(e){return new n(e)}getSampler(e,t){if(this._sampler)return this._sampler;try{return this._sampler=e.createSampler(this.samplerDesc),this._sampler}catch(r){if(t)return t;throw r}}getView(e,t,r,i){return this._gpuTexture?r==="srgb"?this._viewSrgb??i:this._viewLinear??i:(this.ensureUploaded(e,t,r),i)}destroy(){this._gpuTexture?.destroy(),this._gpuTexture=null,this._viewLinear=null,this._viewSrgb=null,this._sampler=null,this._uploadStarted=!1,this._uploadPromise=null,this._mipmapColorSpace=null,this._revision++}ensureUploaded(e,t,r="linear"){this._uploadStarted||(this._uploadStarted=!0,this._mipmapColorSpace=r,this._uploadPromise=(async()=>{let i=null,o=null;try{i=await this.decodeBitmap();let a=i.width|0,s=i.height|0,l=this._mipmaps?om(a,s):1;o=e.createTexture({size:{width:a,height:s},format:"rgba8unorm",mipLevelCount:l,usage:this._mipmaps?GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST,viewFormats:["rgba8unorm-srgb"]}),t.copyExternalImageToTexture({source:i},{texture:o},{width:a,height:s}),this._mipmaps&&l>1&&this.generateMipmaps(e,o,l,this._mipmapColorSpace??"linear");let u=o.createView({format:"rgba8unorm"}),c=o.createView({format:"rgba8unorm-srgb"});this._viewLinear=u,this._viewSrgb=c,this._width=a,this._height=s,this._gpuTexture=o,this._revision++}catch(a){this._uploadStarted=!1,this._uploadPromise=null,this._mipmapColorSpace=null;try{o?.destroy()}catch{}throw a}finally{if(i&&this._source.kind!=="bitmap")try{i.close?.()}catch{}}})(),this._uploadPromise.catch(i=>console.warn("Texture2D upload failed: ",i)))}async decodeBitmap(){let e=this._source;if(e.kind==="bitmap")return e.bitmap;if(!im())throw new Error("createImageBitmap() is not available in this environment.");let t={premultiplyAlpha:"none",imageOrientation:"none",colorSpaceConversion:this._mipmapColorSpace==="srgb"?"default":"none"};if(e.kind==="url"){let i=await fetch(e.url);if(!i.ok)throw new Error(`Failed to fetch texture: ${i.status} ${i.statusText}`);let o=await i.blob();try{return await createImageBitmap(o,t)}catch{return await createImageBitmap(o)}}let r=new Blob([e.bytes],{type:e.mimeType??"application/octet-stream"});try{return await createImageBitmap(r,t)}catch{return await createImageBitmap(r)}}generateMipmaps(e,t,r,i){let o=am(e),a=i==="srgb"?o.pipelineSrgb:o.pipelineLinear,s=i==="srgb"?"rgba8unorm-srgb":"rgba8unorm",l=e.createCommandEncoder();for(let u=1;u<r;u++){let c=t.createView({baseMipLevel:u-1,mipLevelCount:1,format:s}),m=t.createView({baseMipLevel:u,mipLevelCount:1,format:s}),d=e.createBindGroup({layout:o.bindGroupLayout,entries:[{binding:0,resource:o.sampler},{binding:1,resource:c}]}),f=l.beginRenderPass({colorAttachments:[{view:m,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]});f.setPipeline(a),f.setBindGroup(0,d),f.draw(3),f.end()}e.queue.submit([l.finish()])}};var sm=(n,e)=>{let t=n.length|0;if(t<=1)return{i0:0,i1:0,alpha:0,dt:0};if(e<=n[0])return{i0:0,i1:0,alpha:0,dt:n[1]-n[0]};if(e>=n[t-1])return{i0:t-1,i1:t-1,alpha:0,dt:n[t-1]-n[t-2]};let r=0,i=t-1;for(;r+1<i;){let l=r+i>>1;n[l]<=e?r=l:i=l}let o=r,a=r+1,s=n[a]-n[o];return s===0?{i0:o,i1:o,alpha:0,dt:0}:{i0:o,i1:a,alpha:le((e-n[o])/s),dt:s}},lm=n=>{let e=n*n,t=e*n;return[2*t-3*e+1,t-2*e+n,-2*t+3*e,t-e]},Ws=(n,e,t)=>{t.fill(0);let r=n.valueSize|0;if(r<=0)return;let{i0:i,i1:o,alpha:a,dt:s}=sm(n.input,e);switch(n.interpolation){case"STEP":{let l=i*r;for(let u=0;u<r;u++)t[u]=n.output[l+u]??0;return}case"CUBICSPLINE":{let[l,u,c,m]=lm(a),d=r*3,f=i*d,p=o*d,h=f+r,g=f+r*2,b=p,P=p+r;for(let v=0;v<r;v++){let x=n.output[h+v]??0,T=(n.output[g+v]??0)*s,w=n.output[P+v]??0,M=(n.output[b+v]??0)*s;t[v]=l*x+u*T+c*w+m*M}return}default:{let l=i*r,u=o*r;for(let c=0;c<r;c++){let m=n.output[l+c]??0,d=n.output[u+c]??0;t[c]=m+(d-m)*a}return}}},ar=class{name;samplerCount;channelCount;samplersPtr;channelsPtr;startTime;endTime;_ownedF32Allocs;_ownedU32Allocs;_weightSamplers;_weightChannels;_pointerSamplers;_pointerChannels;_disposed=!1;constructor(e){this.name=e.name,this.samplerCount=e.samplerCount|0,this.channelCount=e.channelCount|0,this.samplersPtr=e.samplersPtr,this.channelsPtr=e.channelsPtr,this.startTime=e.startTime,this.endTime=e.endTime,this._ownedF32Allocs=e.ownedF32Allocs??null,this._ownedU32Allocs=e.ownedU32Allocs??null,this._weightSamplers=e.weightSamplers??null,this._weightChannels=e.weightChannels??null,this._pointerSamplers=e.pointerSamplers??null,this._pointerChannels=e.pointerChannels??null}get duration(){return Math.max(0,this.endTime-this.startTime)}sample(e){if(this.channelCount>0){let t=K.global(),r={posPtr:t.posPtr,rotPtr:t.rotPtr,sclPtr:t.sclPtr};Gt.sampleClipTRS(r.posPtr,r.rotPtr,r.sclPtr,t.count|0,this.samplersPtr,this.samplerCount,this.channelsPtr,this.channelCount,e),t.markDirty()}if(this._weightSamplers&&this._weightChannels)for(let t of this._weightChannels){let r=this._weightSamplers[t.sampler];if(!(!r||t.meshes.length===0)){Ws(r,e,t.scratch);for(let i of t.meshes)aa(i,t.scratch)}}if(this._pointerSamplers&&this._pointerChannels)for(let t of this._pointerChannels){let r=this._pointerSamplers[t.sampler];r&&(Ws(r,e,t.scratch),t.setValue(t.scratch))}}dispose(){if(!this._disposed){if(this._disposed=!0,this._ownedF32Allocs)for(let e of this._ownedF32Allocs)e.ptr&&_.freeF32(e.ptr,e.len|0);if(this._ownedU32Allocs)for(let e of this._ownedU32Allocs)e.ptr&&_.freeU32(e.ptr,e.len|0);this._ownedF32Allocs=null,this._ownedU32Allocs=null,this._weightSamplers=null,this._weightChannels=null,this._pointerSamplers=null,this._pointerChannels=null}}},_n=class{clip;time=0;speed=1;loop=!0;playing=!0;constructor(e,t={}){this.clip=e,t.speed!==void 0&&(this.speed=t.speed),t.loop!==void 0&&(this.loop=t.loop),t.playing!==void 0&&(this.playing=t.playing),this.time=e.startTime}update(e){if(!this.playing)return;let t=this.clip.duration;if(t<=0){this.clip.sample(this.clip.startTime);return}if(this.time+=e*this.speed,this.loop){let r=this.clip.startTime,i=this.clip.endTime;for(;this.time<r;)this.time+=t;for(;this.time>=i;)this.time-=t}else this.time=Math.max(this.clip.startTime,Math.min(this.time,this.clip.endTime));this.clip.sample(this.time)}},sr=class{name;joints;jointCount;jointIndicesPtr;invBindPtr;_disposed=!1;constructor(e,t,r){this.name=e,this.joints=t,this.jointCount=t.length|0,this.jointIndicesPtr=_.allocU32(this.jointCount);let i=_.u32view(this.jointIndicesPtr,this.jointCount);for(let a=0;a<this.jointCount;a++)i[a]=t[a].index>>>0;this.invBindPtr=_.allocF32(this.jointCount*16);let o=_.f32view(this.invBindPtr,this.jointCount*16);if(r&&r.length===this.jointCount*16)o.set(r);else for(let a=0;a<this.jointCount;a++){let s=a*16;o[s+0]=1,o[s+1]=0,o[s+2]=0,o[s+3]=0,o[s+4]=0,o[s+5]=1,o[s+6]=0,o[s+7]=0,o[s+8]=0,o[s+9]=0,o[s+10]=1,o[s+11]=0,o[s+12]=0,o[s+13]=0,o[s+14]=0,o[s+15]=1}}createInstance(e){return new wi(this,e)}dispose(){this._disposed||(this._disposed=!0,this.jointIndicesPtr&&_.freeU32(this.jointIndicesPtr,this.jointCount),this.invBindPtr&&_.freeF32(this.invBindPtr,this.jointCount*16))}},wi=class{skin;meshTransform;bindMatrixPtr=0;boneBuffer=null;bindGroup=null;constructor(e,t){this.skin=e,this.meshTransform=t,this.bindMatrixPtr=_.allocF32(16);let r=_.f32view(this.bindMatrixPtr,16),i=t.worldMatrix;for(let o=0;o<16;o++)r[o]=i[o]??(o%5===0?1:0)}get jointCount(){return this.skin.jointCount}ensureGpuResources(e,t){if(this.boneBuffer&&this.bindGroup)return;let r=this.skin.jointCount*16*4;this.boneBuffer=e.createBuffer({size:r,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.bindGroup=e.createBindGroup({layout:t,entries:[{binding:0,resource:{buffer:this.boneBuffer}}]})}dispose(){this.boneBuffer?.destroy(),this.boneBuffer=null,this.bindGroup=null,this.bindMatrixPtr&&(_.freeF32(this.bindMatrixPtr,16),this.bindMatrixPtr=0)}};var Bn=class n{transform;type;_projectionMatrix=null;_viewMatrix=null;_viewProjectionMatrix=null;_projectionDirty=!0;constructor(e){this.type=e,this.transform=new we}get destroyed(){return this.transform.disposed}get viewMatrix(){let e=this.transform.worldMatrix;return this._viewMatrix=st.invert(e),this._viewMatrix}get viewProjectionMatrix(){let e=this.getProjectionMatrix(),t=this.viewMatrix;return this._viewProjectionMatrix=st.mul(e,t),this._viewProjectionMatrix}get position(){return this.transform.worldPosition}get up(){let e=this.transform.worldMatrix;return[e[4],e[5],e[6]]}lookAt(e,t,r){let i=typeof e=="number"?[e,t,r]:e;return this.lookAtWithUp(i,[0,1,0])}lookAtWithUp(e,t){let r=this.transform.worldPosition,i=Je.normalize(Je.sub(e,r)),o=[t[0],t[1],t[2]];Math.abs(Je.dot(i,o))>.999&&(Math.abs(i[1])<.9?o=[0,1,0]:o=[1,0,0]);let a=Je.normalize(Je.cross(i,o)),s=Je.cross(a,i),l=[a[0],a[1],a[2],0,s[0],s[1],s[2],0,-i[0],-i[1],-i[2],0,0,0,0,1],u=n.matrixToQuaternion(l);return this.transform.setRotation(u[0],u[1],u[2],u[3]),this}static matrixToQuaternion(e){let t=e[0]+e[5]+e[10],r,i,o,a;if(t>0){let s=.5/Math.sqrt(t+1);r=.25/s,i=(e[6]-e[9])*s,o=(e[8]-e[2])*s,a=(e[1]-e[4])*s}else if(e[0]>e[5]&&e[0]>e[10]){let s=2*Math.sqrt(1+e[0]-e[5]-e[10]);r=(e[6]-e[9])/s,i=.25*s,o=(e[4]+e[1])/s,a=(e[8]+e[2])/s}else if(e[5]>e[10]){let s=2*Math.sqrt(1+e[5]-e[0]-e[10]);r=(e[8]-e[2])/s,i=(e[4]+e[1])/s,o=.25*s,a=(e[9]+e[6])/s}else{let s=2*Math.sqrt(1+e[10]-e[0]-e[5]);r=(e[1]-e[4])/s,i=(e[8]+e[2])/s,o=(e[9]+e[6])/s,a=.25*s}return[i,o,a,r]}markProjectionDirty(){this._projectionDirty=!0}destroy(){this.transform.dispose()}},Dt=class extends Bn{_fov;_aspect;_near;_far;constructor(e={}){super("perspective"),this._fov=e.fov??60,this._aspect=e.aspect??16/9,this._near=e.near??.1,this._far=e.far??1e3}get fov(){return this._fov}set fov(e){e!==this._fov&&(this._fov=e,this.markProjectionDirty())}get aspect(){return this._aspect}set aspect(e){e!==this._aspect&&(this._aspect=e,this.markProjectionDirty())}get near(){return this._near}set near(e){e!==this._near&&(this._near=e,this.markProjectionDirty())}get far(){return this._far}set far(e){e!==this._far&&(this._far=e,this.markProjectionDirty())}updateAspect(e,t){return this._aspect=e/t,this.markProjectionDirty(),this}getProjectionMatrix(){if(this._projectionDirty||!this._projectionMatrix){let e=this._fov*Math.PI/180;this._projectionMatrix=st.perspective(e,this._aspect,this._near,this._far),this._projectionDirty=!1}return this._projectionMatrix}},Nt=class extends Bn{_left;_right;_top;_bottom;_near;_far;constructor(e={}){super("orthographic"),this._left=e.left??-10,this._right=e.right??10,this._top=e.top??10,this._bottom=e.bottom??-10,this._near=e.near??.1,this._far=e.far??1e3}get left(){return this._left}set left(e){e!==this._left&&(this._left=e,this.markProjectionDirty())}get right(){return this._right}set right(e){e!==this._right&&(this._right=e,this.markProjectionDirty())}get top(){return this._top}set top(e){e!==this._top&&(this._top=e,this.markProjectionDirty())}get bottom(){return this._bottom}set bottom(e){e!==this._bottom&&(this._bottom=e,this.markProjectionDirty())}get near(){return this._near}set near(e){e!==this._near&&(this._near=e,this.markProjectionDirty())}get far(){return this._far}set far(e){e!==this._far&&(this._far=e,this.markProjectionDirty())}updateFromCanvas(e,t,r=1){let i=e/2/r,o=t/2/r;return this._left=-i,this._right=i,this._top=o,this._bottom=-o,this.markProjectionDirty(),this}getProjectionMatrix(){return(this._projectionDirty||!this._projectionMatrix)&&(this._projectionMatrix=this.computeOrthographicMatrix(),this._projectionDirty=!1),this._projectionMatrix}computeOrthographicMatrix(){let e=1/(this._left-this._right),t=1/(this._bottom-this._top),r=1/(this._near-this._far);return[-2*e,0,0,0,0,-2*t,0,0,0,0,r,0,(this._left+this._right)*e,(this._top+this._bottom)*t,this._near*r,1]}};var um=n=>{let e=n?.extensions?.KHR_node_visibility;return typeof e?.visible=="boolean"?e.visible:!0},Io=class{index;name;transform;parentIndex;children;meshes;camera;light;_visible;_effectiveVisible;_parentNode;_childNodes;constructor(e,t,r){this.index=e,this.name=r?.name,this.transform=t,this.parentIndex=null,this.children=[...r?.children??[]],this.meshes=[],this.camera=null,this.light=null,this._visible=um(r),this._effectiveVisible=this._visible,this._parentNode=null,this._childNodes=[]}get visible(){return this._visible}set visible(e){this._visible=!!e,this.updateEffectiveVisibility()}get effectiveVisible(){return this._effectiveVisible}setParentNode(e){this._parentNode=e,e._childNodes.includes(this)||e._childNodes.push(this),this.updateEffectiveVisibility()}applyVisibility(){for(let e of this.meshes)e.visible=this._effectiveVisible;this.light&&(this.light.enabled=this._effectiveVisible)}updateEffectiveVisibility(){let e=this._visible&&(this._parentNode?.effectiveVisible??!0);this._effectiveVisible=e,this.applyVisibility();for(let t of this._childNodes)t.updateEffectiveVisibility()}},q=(n,e)=>{n?.onWarning?.(e)},Do=n=>{let e=n?.extensions?.KHR_texture_transform;return((e&&typeof e.texCoord=="number"?e.texCoord:n?.texCoord)??0)|0},qs=(n,e,t,r)=>{if(!n)return;let i=(p,h)=>{if(!p)return;let g=Do(p);if(g<0||g>1){q(t,`${r}: texture usage '${h}' references TEXCOORD_${g}, but WasmGPU supports TEXCOORD_0 and TEXCOORD_1; using TEXCOORD_0.`);return}e[`TEXCOORD_${g}`]===void 0&&q(t,`${r}: texture usage '${h}' references missing TEXCOORD_${g}; sampling will use zero coordinates.`)};i(n.pbrMetallicRoughness?.baseColorTexture,"baseColor"),i(n.pbrMetallicRoughness?.metallicRoughnessTexture,"metallicRoughness"),i(n.normalTexture,"normal"),i(n.occlusionTexture,"occlusion"),i(n.emissiveTexture,"emissive");let o=n.extensions?.KHR_materials_pbrSpecularGlossiness;i(o?.diffuseTexture,"diffuse"),i(o?.specularGlossinessTexture,"specularGlossiness");let a=n.extensions?.KHR_materials_clearcoat;i(a?.clearcoatTexture,"clearcoat"),i(a?.clearcoatRoughnessTexture,"clearcoatRoughness"),i(a?.clearcoatNormalTexture,"clearcoatNormal");let s=n.extensions?.KHR_materials_specular;i(s?.specularTexture,"specular"),i(s?.specularColorTexture,"specularColor");let l=n.extensions?.KHR_materials_sheen;i(l?.sheenColorTexture,"sheenColor"),i(l?.sheenRoughnessTexture,"sheenRoughness");let u=n.extensions?.KHR_materials_iridescence;i(u?.iridescenceTexture,"iridescence"),i(u?.iridescenceThicknessTexture,"iridescenceThickness");let c=n.extensions?.KHR_materials_anisotropy;i(c?.anisotropyTexture,"anisotropy");let m=n.extensions?.KHR_materials_transmission;i(m?.transmissionTexture,"transmission");let d=n.extensions?.KHR_materials_volume;i(d?.thicknessTexture,"volumeThickness");let f=n.extensions?.KHR_materials_diffuse_transmission;i(f?.diffuseTransmissionTexture,"diffuseTransmission"),i(f?.diffuseTransmissionColorTexture,"diffuseTransmissionColor")},Ks=9728,Xs=9729,cm=9984,mm=9985,dm=9986,fm=9987,pm=33071,hm=33648,gm=10497,js=n=>{switch(n){case pm:return"clamp-to-edge";case hm:return"mirror-repeat";case gm:default:return"repeat"}},bm=n=>{switch(n){case Ks:return"nearest";case Xs:default:return"linear"}},vm=n=>{switch(n){case Ks:return{minFilter:"nearest",mipmapFilter:"nearest",useMipmaps:!1};case Xs:return{minFilter:"linear",mipmapFilter:"nearest",useMipmaps:!1};case cm:return{minFilter:"nearest",mipmapFilter:"nearest",useMipmaps:!0};case mm:return{minFilter:"linear",mipmapFilter:"nearest",useMipmaps:!0};case dm:return{minFilter:"nearest",mipmapFilter:"linear",useMipmaps:!0};case fm:default:return{minFilter:"linear",mipmapFilter:"linear",useMipmaps:!0}}},ym=n=>{if(!n)return;let e=n.toLowerCase();if(e.endsWith(".png"))return"image/png";if(e.endsWith(".jpg")||e.endsWith(".jpeg"))return"image/jpeg";if(e.endsWith(".webp"))return"image/webp";if(e.endsWith(".gif"))return"image/gif"},xm=(n,e)=>e?.sceneIndex!==void 0?e.sceneIndex|0:n.scene!==void 0?n.scene|0:0,Ys=n=>{let e=n.extensions?.KHR_lights_punctual;return e||null},Pm=n=>{let e=n.extensions?.KHR_lights_punctual;return e||null},Zs=n=>!!n.extensions?.KHR_materials_unlit,_i=0,Bi=0,Tm=()=>{_i!==0&&Bi!==0||(_i=_.allocF32(16),Bi=_.allocF32(10))},Sm=(n,e)=>{Tm();let t=_.f32view(_i,16);for(let i=0;i<16;i++)t[i]=e[i]??(i%5===0?1:0);ie.decomposeTRS(Bi,_i);let r=_.f32view(Bi,10);n.setPosition(r[0],r[1],r[2]),n.setRotation(r[3],r[4],r[5],r[6]),n.setScale(r[7],r[8],r[9])},Cm=n=>{let e=n?.extensions?.KHR_xmp_json_ld;return typeof e?.packet=="number"?e.packet:null},Qs=(n,e)=>{let t=Cm(e);return t!==null&&t>=0&&t<n.length?n[t]:null},it=(n,e,t=[])=>({index:n,name:e?.name,extras:e?.extras,extensions:e?.extensions,xmp:Qs(t,e)}),wm=(n,e,t)=>({...it(n,e,t),primitives:e.primitives.map((r,i)=>({...it(i,r,t),material:r.material}))}),_m={KHR_lights_punctual:"supported",KHR_mesh_quantization:"supported",KHR_materials_unlit:"supported",KHR_materials_emissive_strength:"supported",KHR_materials_pbrSpecularGlossiness:"partial",KHR_materials_clearcoat:"supported",KHR_materials_transmission:"supported",KHR_materials_volume:"supported",KHR_materials_diffuse_transmission:"supported",KHR_materials_dispersion:"supported",KHR_materials_specular:"supported",KHR_materials_sheen:"supported",KHR_materials_iridescence:"supported",KHR_materials_anisotropy:"supported",KHR_materials_ior:"supported",KHR_materials_variants:"supported",KHR_node_visibility:"supported",KHR_animation_pointer:"supported",KHR_xmp_json_ld:"supported",KHR_draco_mesh_compression:"deferred",KHR_texture_basisu:"deferred",KHR_texture_transform:"supported",EXT_mesh_gpu_instancing:"deferred",EXT_meshopt_compression:"deferred",EXT_texture_webp:"deferred"},Bm=n=>{let e=[...n.extensionsUsed??[]],t=[...n.extensionsRequired??[]],r=new Set([...e,...t]),i={};for(let o of r)i[o]=_m[o]??"unsupported";return{used:e,required:t,support:i}},km=n=>{let e=n.extensions?.KHR_xmp_json_ld,t=Array.isArray(e?.packets)?[...e.packets]:[],r=Qs(t,n.asset);return{packets:t,packet:r}},Mm=(n=[])=>{let e=[...n],t=[],r=null,i=l=>{e.some(u=>u.index===l)||(e.push({index:l,name:`variant_${l}`}),e.sort((u,c)=>u.index-c.index))},o=l=>e.find(u=>u.name===l),a=()=>r===null?null:e.find(l=>l.index===r)?.name??`variant_${r}`,s=l=>{r=l;for(let u of t){if(u.mesh.destroyed)continue;let c=l!==null?u.variants.get(l)??u.baselineMaterial:u.baselineMaterial;u.mesh.material!==c&&(c.retain(),u.mesh.setMaterial(c))}};return{public:{get items(){return e.map(l=>({...l}))},get names(){return e.map(l=>l.name??`variant_${l.index}`)},get activeName(){return a()},get activeIndex(){return r},setActive(l){if(l===null){s(null);return}let u=o(l);if(!u)throw new Error(`glTF variants: unknown variant '${l}'.`);s(u.index)},setActiveIndex(l){if(l===null){s(null);return}if(!e.some(u=>u.index===l))throw new Error(`glTF variants: unknown variant index ${l}.`);s(l)},clear(){s(null)}},register(l,u,c=new Map){if(c.size===0)return;let m=Array.from(new Set([u,...c.values()]));for(let d of m)d.retain();t.push({mesh:l,baselineMaterial:u,variants:c,retainedMaterials:m});for(let d of c.keys())i(d);r!==null&&s(r)},destroy(){for(let l of t)for(let u of l.retainedMaterials)u.release();t.length=0}}},Lm=(n,e)=>{let t=n.extensions?.KHR_materials_variants;return(Array.isArray(t?.variants)?t.variants:[]).map((i,o)=>({...it(o,i,e),name:i?.name??`variant_${o}`}))},Rm=(n,e,t,r,i)=>{let o=n.scenes?.[e],a=r.packets;return{asset:it(0,n.asset,a),scene:o?it(e,o,a):null,nodes:(n.nodes??[]).map((s,l)=>it(l,s,a)),meshes:(n.meshes??[]).map((s,l)=>wm(l,s,a)),materials:(n.materials??[]).map((s,l)=>it(l,s,a)),textures:(n.textures??[]).map((s,l)=>it(l,s,a)),images:(n.images??[]).map((s,l)=>it(l,s,a)),cameras:(n.cameras??[]).map((s,l)=>it(l,s,a)),skins:(n.skins??[]).map((s,l)=>it(l,s,a)),animations:(n.animations??[]).map((s,l)=>it(l,s,a)),extensions:t,xmp:r,variants:i}},Um=(n,e,t,r)=>{let i=new Float32Array(e);if(!n||e<=0)return i;let o=n.length|0,a=Math.min(o,e);for(let s=0;s<a;s++)i[s]=Number(n[s]??0)||0;return o<e?q(t,`${r}: morph weights length ${o} is smaller than target count ${e}; padding with zeros.`):o>e&&q(t,`${r}: morph weights length ${o} exceeds target count ${e}; truncating extra values.`),i},Go=n=>{let e=new Float32Array(n);for(let t=0;t<e.length;t+=4){let r=e[t+0]??0,i=e[t+1]??0,o=e[t+2]??0,a=e[t+3]??0,s=r+i+o+a;if(s>0){let l=1/s;e[t+0]=r*l,e[t+1]=i*l,e[t+2]=o*l,e[t+3]=a*l}else e[t+0]=1,e[t+1]=0,e[t+2]=0,e[t+3]=0}return e},Gm=(n,e)=>{let t=new Float32Array(n),r=new Float32Array(e);for(let i=0;i<t.length;i+=4){let o=t[i+0]??0,a=t[i+1]??0,s=t[i+2]??0,l=t[i+3]??0,u=r[i+0]??0,c=r[i+1]??0,m=r[i+2]??0,d=r[i+3]??0,f=o+a+s+l+u+c+m+d;if(f>0){let p=1/f;t[i+0]=o*p,t[i+1]=a*p,t[i+2]=s*p,t[i+3]=l*p,r[i+0]=u*p,r[i+1]=c*p,r[i+2]=m*p,r[i+3]=d*p}else t[i+0]=1,t[i+1]=0,t[i+2]=0,t[i+3]=0,r[i+0]=0,r[i+1]=0,r[i+2]=0,r[i+3]=0}return{weights0:t,weights1:r}},Am=n=>{let e=[];for(let t=0;t+2<n.length;t++){let r=n[t],i=n[t+1],o=n[t+2];r===i||i===o||r===o||((t&1)===0?e.push(r,i,o):e.push(i,r,o))}return new Uint32Array(e)},Fm=n=>{let e=[];if(n.length<3)return new Uint32Array(0);let t=n[0];for(let r=1;r+1<n.length;r++){let i=n[r],o=n[r+1];t===i||i===o||t===o||e.push(t,i,o)}return new Uint32Array(e)},Im=n=>{if(!n||Zs(n))return[];let e=[],t=a=>{let s=a===1?1:0;e.includes(s)||e.push(s)},r=a=>{a&&t(Do(a))};r(n.normalTexture);let i=n.extensions?.KHR_materials_clearcoat;r(i?.clearcoatNormalTexture);let o=n.extensions?.KHR_materials_anisotropy;return o?.anisotropyTexture?r(o.anisotropyTexture):o&&e.length===0&&t(0),e},Js=(n,e,t,r,i,o)=>{if(t===void 0)return new J({});let a=r.get(t);if(a)return a.retain();let s=e.materials?.[t];if(!s){let Y=new J({});return r.set(t,Y),Y}let l=(Y,wt)=>{if(Y===void 0)return null;let ot=i.get(Y);if(ot)return ot;let Wt=e.textures?.[Y];if(!Wt)return q(o,`glTF texture index ${Y} missing (usage=${wt}).`),null;let at=Wt.source,Ye=at!==void 0?e.images?.[at]:void 0;if(at===void 0||!Ye)return q(o,`glTF texture ${Y} has no valid source image (usage=${wt}).`),null;let fr=Wt.sampler!==void 0?e.samplers?.[Wt.sampler]:void 0,Ki=js(fr?.wrapS),_l=js(fr?.wrapT),Bl=bm(fr?.magFilter),{minFilter:kl,mipmapFilter:Ml,useMipmaps:Ll}=vm(fr?.minFilter),pr=null,Ho=n.images?.[at],In=Ye.mimeType??ym(Ye.uri);if(Ho)pr={kind:"bytes",bytes:Ho,mimeType:In};else if(Ye.bufferView!==void 0){let _t=e.bufferViews?.[Ye.bufferView],qo=_t?n.buffers[_t.buffer]:void 0;if(_t&&qo){let Ko=(_t.byteOffset??0)|0;pr={kind:"bytes",bytes:qo.slice(Ko,Ko+_t.byteLength),mimeType:In}}else q(o,`glTF image bufferView ${Ye.bufferView} missing (texture=${Y}, usage=${wt}).`)}else if(Ye.uri)if(Tn(Ye.uri)){let _t=Sn(Ye.uri);pr={kind:"bytes",bytes:_t.data,mimeType:In??_t.mimeType??void 0}}else pr={kind:"url",url:Cn(n.baseUrl,Ye.uri),mimeType:In};if(!pr)return q(o,`Could not resolve image source for texture=${Y} (usage=${wt}).`),null;let $o=or.createFrom({source:pr,mipmaps:Ll,sampler:{addressModeU:Ki,addressModeV:_l,magFilter:Bl,minFilter:kl,mipmapFilter:Ml}});return i.set(Y,$o),$o},u=(Y,wt)=>Y?l(Y.index,wt):null,c=Y=>{if(!Y)return null;let ot=Y.extensions?.KHR_texture_transform,at=Do(Y)===1?1:0;return ot?{offset:[Number(ot.offset?.[0]??0),Number(ot.offset?.[1]??0)],rotation:Number(ot.rotation??0),scale:[Number(ot.scale?.[0]??1),Number(ot.scale?.[1]??1)],texCoord:at}:at===1?{texCoord:1}:null},m=s.alphaMode??"OPAQUE",d=m==="MASK"?s.alphaCutoff??.5:0,f=m==="BLEND"?"transparent":"opaque",p=s.doubleSided?"none":"back",h=s.pbrMetallicRoughness,g=s.extensions?.KHR_materials_pbrSpecularGlossiness;!h&&g&&(q(o,`Material '${s.name??t}' uses KHR_materials_pbrSpecularGlossiness; approximating using diffuse as baseColor. Specular/glossiness are not fully supported yet.`),g.specularGlossinessTexture&&q(o,`Material '${s.name??t}' has specularGlossinessTexture; currently ignored (highlights/roughness may look off).`));let b=h?.baseColorFactor??g?.diffuseFactor??[1,1,1,1],P=h?.baseColorTexture??g?.diffuseTexture,v=u(P,"baseColor"),x=c(P),T=1,w=1;h?(T=h.metallicFactor??1,w=h.roughnessFactor??1):g&&(T=0,w=1-(g.glossinessFactor??1),w<0&&(w=0),w>1&&(w=1));let M=h?.metallicRoughnessTexture,B=s.normalTexture,S=s.occlusionTexture,R=s.emissiveTexture,G=h?u(M,"metallicRoughness"):null,L=h?c(M):null,U=u(B,"normal"),F=c(B),D=u(S,"occlusion"),k=c(S),A=u(R,"emissive"),I=c(R),O=s.normalTexture?.scale??1,N=s.occlusionTexture?.strength??1,z=s.emissiveFactor??[0,0,0],E=s.extensions??{},H=E.KHR_materials_emissive_strength,j=H?.emissiveStrength??1,Z=E.KHR_materials_clearcoat,xe=E.KHR_materials_specular,te=E.KHR_materials_sheen,ce=E.KHR_materials_iridescence,be=E.KHR_materials_anisotropy,Xe=E.KHR_materials_transmission,Le=E.KHR_materials_volume,Re=E.KHR_materials_diffuse_transmission,ft=E.KHR_materials_dispersion,pt=E.KHR_materials_ior,dr=1,Fe={};if(Z&&(Fe.clearcoat={factor:Z.clearcoatFactor??0,texture:u(Z.clearcoatTexture,"clearcoat"),textureTransform:c(Z.clearcoatTexture),roughness:Z.clearcoatRoughnessFactor??0,roughnessTexture:u(Z.clearcoatRoughnessTexture,"clearcoatRoughness"),roughnessTextureTransform:c(Z.clearcoatRoughnessTexture),normalTexture:u(Z.clearcoatNormalTexture,"clearcoatNormal"),normalTextureTransform:c(Z.clearcoatNormalTexture),normalScale:Z.clearcoatNormalTexture?.scale??1}),xe){let Y=Array.isArray(xe.specularColorFactor)?xe.specularColorFactor:[1,1,1];Fe.specular={factor:xe.specularFactor??1,texture:u(xe.specularTexture,"specular"),textureTransform:c(xe.specularTexture),color:[Y[0]??1,Y[1]??1,Y[2]??1],colorTexture:u(xe.specularColorTexture,"specularColor"),colorTextureTransform:c(xe.specularColorTexture)}}if(te){let Y=Array.isArray(te.sheenColorFactor)?te.sheenColorFactor:[0,0,0];Fe.sheen={color:[Y[0]??0,Y[1]??0,Y[2]??0],colorTexture:u(te.sheenColorTexture,"sheenColor"),colorTextureTransform:c(te.sheenColorTexture),roughness:te.sheenRoughnessFactor??0,roughnessTexture:u(te.sheenRoughnessTexture,"sheenRoughness"),roughnessTextureTransform:c(te.sheenRoughnessTexture)}}if(ce&&(Fe.iridescence={factor:ce.iridescenceFactor??0,texture:u(ce.iridescenceTexture,"iridescence"),textureTransform:c(ce.iridescenceTexture),ior:ce.iridescenceIor??1.3,thicknessMinimum:ce.iridescenceThicknessMinimum??100,thicknessMaximum:ce.iridescenceThicknessMaximum??400,thicknessTexture:u(ce.iridescenceThicknessTexture,"iridescenceThickness"),thicknessTextureTransform:c(ce.iridescenceThicknessTexture)}),be&&(Fe.anisotropy={strength:be.anisotropyStrength??0,rotation:be.anisotropyRotation??0,texture:u(be.anisotropyTexture,"anisotropy"),textureTransform:c(be.anisotropyTexture)}),Xe&&(Fe.transmission={factor:Xe.transmissionFactor??0,texture:u(Xe.transmissionTexture,"transmission"),textureTransform:c(Xe.transmissionTexture)}),Le){let Y=Array.isArray(Le.attenuationColor)?Le.attenuationColor:[1,1,1];Fe.volume={thicknessFactor:Le.thicknessFactor??0,thicknessTexture:u(Le.thicknessTexture,"volumeThickness"),thicknessTextureTransform:c(Le.thicknessTexture),attenuationDistance:Le.attenuationDistance??1/0,attenuationColor:[Y[0]??1,Y[1]??1,Y[2]??1]}}if(Re){let Y=Array.isArray(Re.diffuseTransmissionColorFactor)?Re.diffuseTransmissionColorFactor:[1,1,1];Fe.diffuseTransmission={factor:Re.diffuseTransmissionFactor??0,texture:u(Re.diffuseTransmissionTexture,"diffuseTransmission"),textureTransform:c(Re.diffuseTransmissionTexture),color:[Y[0]??1,Y[1]??1,Y[2]??1],colorTexture:u(Re.diffuseTransmissionColorTexture,"diffuseTransmissionColor"),colorTextureTransform:c(Re.diffuseTransmissionColorTexture)}}ft&&(Fe.dispersion={dispersion:ft.dispersion??0}),pt&&(Fe.ior={ior:pt.ior??1.5}),H&&(Fe.emissiveStrength={strength:j});let Fn=Zs(s),Et=f==="opaque",Ut;return Fn?Ut=new ke({color:[b[0]??1,b[1]??1,b[2]??1],opacity:b[3]??1,baseColorTexture:v,baseColorTextureTransform:x,alphaCutoff:d,blendMode:f,cullMode:p,depthWrite:Et}):Ut=new J({color:[b[0]??1,b[1]??1,b[2]??1],opacity:b[3]??1,metallic:T,roughness:w,emissive:[z[0]??0,z[1]??0,z[2]??0],emissiveIntensity:dr,baseColorTexture:v,metallicRoughnessTexture:G,normalTexture:U,occlusionTexture:D,emissiveTexture:A,baseColorTextureTransform:x,metallicRoughnessTextureTransform:L,normalTextureTransform:F,occlusionTextureTransform:k,emissiveTextureTransform:I,normalScale:O,occlusionStrength:N,alphaCutoff:d,extensions:Object.keys(Fe).length>0?Fe:void 0,blendMode:f,cullMode:p,depthWrite:Et}),r.set(t,Ut),Ut},Dm=(n,e,t,r,i,o,a)=>{let s=t.extensions?.KHR_materials_variants,l=Array.isArray(s?.mappings)?s.mappings:[],u=new Map;for(let d of l){if(typeof d.material!="number"||!Number.isFinite(d.material)||!Array.isArray(d.variants))continue;let f=d.material|0;for(let p of d.variants)typeof p!="number"||!Number.isFinite(p)||u.set(p|0,f)}let c=new Map,m=new Map;for(let[d,f]of u){let p=m.get(f);p||(qs(e.materials?.[f],t.attributes,o,`${a} variant material ${f}`),p=Js(n,e,f,r,i,o),m.set(f,p)),c.set(d,p)}return{variants:c,ownedMaterials:[...m.values()]}},Nm=(n,e,t,r,i)=>{let o=t.attributes,a=o.POSITION;if(a===void 0)return q(i,"Primitive missing POSITION; skipping"),null;let s=Ae(n,a),l=null,u=o.NORMAL;u!==void 0&&(l=Ae(n,u));let c=null,m=o.TANGENT;m!==void 0&&(c=Ae(n,m));let d=null,f=o.TEXCOORD_0;f!==void 0&&(d=Ae(n,f));let p=null,h=o.TEXCOORD_1;h!==void 0&&(p=Ae(n,h));let g=null,b=null,P=null,v=null,x=o.JOINTS_0,T=o.WEIGHTS_0,w=o.JOINTS_1,M=o.WEIGHTS_1;if(x!==void 0&&T!==void 0){let U=Ur(n,x),F=Ae(n,T);if(w!==void 0&&M!==void 0){let D=Ur(n,w),k=Ae(n,M);if(D.length===U.length&&k.length===F.length){let A=Gm(F,k);g=U,b=A.weights0,P=D,v=A.weights1}else q(i,"Primitive has JOINTS_1/WEIGHTS_1 but lengths don't match JOINTS_0/WEIGHTS_0; ignoring additional influences"),g=U,b=Go(F)}else w!==void 0||M!==void 0?(q(i,"Primitive has JOINTS_1/WEIGHTS_1 mismatch; ignoring additional influences"),g=U,b=Go(F)):(g=U,b=Go(F))}else(x!==void 0||T!==void 0)&&q(i,"Primitive has JOINTS_0/WEIGHTS_0 mismatch; ignoring skinning attributes for this primitive");let B=t.mode??4,S=null;if(t.indices!==void 0)S=wn(n,t.indices);else{let U=s.length/3|0,F=new Uint32Array(U);for(let D=0;D<U;D++)F[D]=D>>>0;S=B===4?null:F}if(B===5){let U=S??new Uint32Array(0);S=Am(U)}else if(B===6){let U=S??new Uint32Array(0);S=Fm(U)}else if(B!==4)return q(i,`Unsupported primitive mode=${B} (only triangles/strip/fan supported); skipping primitive`),null;let R=[];if(t.targets&&t.targets.length>0)for(let U=0;U<t.targets.length;U++){let F=t.targets[U],D={},k=F.POSITION,A=F.NORMAL;if(k!==void 0){let I=Ae(n,k);I.length===s.length?D.positions=I:q(i,`Primitive morph target ${U} POSITION length ${I.length} does not match base POSITION length ${s.length}; ignoring POSITION deltas.`)}if(A!==void 0){let I=Ae(n,A);I.length===s.length?D.normals=I:q(i,`Primitive morph target ${U} NORMAL length ${I.length} does not match base NORMAL length ${s.length}; ignoring NORMAL deltas.`)}F.TANGENT!==void 0&&q(i,`Primitive morph target ${U} provides TANGENT deltas; WasmGPU ignores tangent morph data.`),!D.positions&&!D.normals&&q(i,`Primitive morph target ${U} has no supported POSITION or NORMAL deltas; preserving target slot with no runtime effect.`),R.push(D)}let G=Im(t.material!==void 0?e.materials?.[t.material]:void 0),L=G.length>0;if(!l&&(r||L)&&(l=Xn(s,S)),!c&&L){let U=G[0];if(G.length>1)q(i,"Primitive uses tangent-space textures on multiple texture coordinate sets; shader will fall back to derivative tangent space.");else{let F=U===1?p:d;l&&F?c=ta(s,l,F,S):q(i,`Primitive uses tangent-space material features but is missing NORMAL or TEXCOORD_${U}; shader will fall back to derivative tangent space.`)}}return new ae({positions:s,normals:l??void 0,tangents:c??void 0,uvs:d??void 0,uvs1:p??void 0,joints:g??void 0,weights:b??void 0,joints1:P??void 0,weights1:v??void 0,indices:S??void 0,morphTargets:R,authoredNormals:u!==void 0})},zm=(n,e,t,r,i,o,a,s,l,u)=>{if(r.mesh===void 0)return[];let c=e.meshes?.[r.mesh];if(!c)return q(u,`nodes[].mesh=${r.mesh} missing; skipping mesh node`),[];let m=[],d=u.computeMissingNormals!==!1;for(let f=0;f<c.primitives.length;f++){let p=c.primitives[f];if(p.extensions?.KHR_draco_mesh_compression){q(u,`Mesh ${c.name??r.mesh} primitive ${f}: KHR_draco_mesh_compression not supported; skipping primitive`);continue}let h=`${r.mesh??-1}:${f}`,g=s.has(h),b=s.get(h),P=`${c.name??`mesh_${r.mesh}`}_${f}`,v=p.material!==void 0?e.materials?.[p.material]:void 0;if(qs(v,p.attributes,u,`Mesh '${c.name??r.mesh}' primitive ${f}`),g||(b=Nm(n,e,p,d,u),s.set(h,b)),!b)continue;g&&b.retain();let x=Js(n,e,p.material,o,a,u),T=new tt(b,x);T.name=r.name??c.name??`gltf_mesh_${r.mesh}_${f}`,T.transform.setParent(i);let w=Um(r.weights??c.weights,b.morphTargets.length|0,u,`Mesh '${T.name}' primitive ${f}`);b.morphTargets.length>0&&vo(T,w),T.userData.gltf={nodeIndex:t,meshIndex:r.mesh,primitiveIndex:f,resolvedWeights:Array.from(w),extras:{node:r.extras,mesh:c.extras,primitive:p.extras,material:v?.extras},extensions:{node:r.extensions,mesh:c.extensions,primitive:p.extensions,material:v?.extensions}},m.push(T);let M=Dm(n,e,p,o,a,u,`Mesh '${c.name??r.mesh}' primitive ${f}`);l.register(T,T.material,M.variants);for(let B of M.ownedMaterials)B.release()}return m},Om=(n,e,t,r)=>{if(e.camera===void 0)return null;let i=n.cameras?.[e.camera];if(!i)return q(r,`nodes[].camera=${e.camera} missing; skipping camera`),null;let o;if(i.type==="perspective"){let a=i.perspective;if(!a)return q(r,`camera[${e.camera}] missing perspective block; skipping`),null;o=new Dt({fov:a.yfov*180/Math.PI,aspect:a.aspectRatio,near:a.znear,far:a.zfar??1e3})}else{let a=i.orthographic;if(!a)return q(r,`camera[${e.camera}] missing orthographic block; skipping`),null;o=new Nt({left:-a.xmag,right:a.xmag,top:a.ymag,bottom:-a.ymag,near:a.znear,far:a.zfar})}return o.transform.setParent(t),o},Vm=(n,e)=>{let t=n.color??[1,1,1],r=n.intensity??1;if(n.type==="directional"){let i=e.worldMatrix,o=i[8]??0,a=i[9]??0,s=i[10]??-1,l=-o,u=-a,c=-s,m=1/(Math.hypot(l,u,c)||1);return new Pt({direction:[l*m,u*m,c*m],color:[t[0]??1,t[1]??1,t[2]??1],intensity:r})}if(n.type==="point"){let i=e.worldPosition;return new Tt({position:[i[0]??0,i[1]??0,i[2]??0],color:[t[0]??1,t[1]??1,t[2]??1],intensity:r,range:n.range??0})}if(n.type==="spot"){let i=e.worldPosition,o=e.worldMatrix,a=-(o[8]??0),s=-(o[9]??0),l=-(o[10]??-1),u=1/(Math.hypot(a,s,l)||1);return new ct({position:[i[0]??0,i[1]??0,i[2]??0],direction:[a*u,s*u,l*u],color:[t[0]??1,t[1]??1,t[2]??1],intensity:r,range:n.range??0,innerCone:n.spot?.innerConeAngle??0,outerCone:n.spot?.outerConeAngle??Math.PI/4})}return null},Em=(n,e,t,r)=>{let i=e.skins??[],o=[];for(let a=0;a<i.length;a++){let s=i[a],l=[],u=!1;for(let p=0;p<s.joints.length;p++){let h=s.joints[p],g=t[h]?.transform;if(!g){q(r,`skin[${a}] joint slot ${p} references missing node ${h}; skipping skin runtime to avoid remapped joint indices.`),u=!0;continue}l.push(g)}let c;s.inverseBindMatrices!==void 0&&(c=Ae(n,s.inverseBindMatrices));let m=c;c&&c.length!==s.joints.length*16&&(q(r,`skin[${a}] inverseBindMatrices length ${c.length} does not match ${s.joints.length} joints; using identity inverse binds.`),m=void 0);let d=s.skeleton!==void 0?t[s.skeleton]?.transform:void 0,f=u||l.length===0?null:new sr(s.name??`skin_${a}`,l,m??null);f||q(r,`skin[${a}] has no valid runtime; meshes referencing it will render unskinned.`),o.push({name:s.name,joints:l,inverseBindMatrices:c,skeleton:d,runtime:f})}return o},Wm=n=>n===""?[]:n.startsWith("/")?n.slice(1).split("/").map(e=>e.replace(/~1/g,"/").replace(/~0/g,"~")):null,kn=(n,e)=>{let t=n[e];if(t===void 0||!/^(0|[1-9]\d*)$/.test(t))return null;let r=Number(t);return Number.isSafeInteger(r)?r:null},Hs=n=>{let e=n.target.extensions?.KHR_animation_pointer;return typeof e?.pointer=="string"?e.pointer:null},el=n=>n==="rotation"?1:n==="offset"||n==="scale"?2:null,tl=(n,e,t)=>{let r={offset:[n?.offset?.[0]??0,n?.offset?.[1]??0],rotation:n?.rotation??0,scale:[n?.scale?.[0]??1,n?.scale?.[1]??1],texCoord:n?.texCoord};return e==="offset"?r.offset=[t[0]??0,t[1]??0]:e==="rotation"?r.rotation=t[0]??0:e==="scale"&&(r.scale=[t[0]??1,t[1]??1]),r},jm=(n,e)=>{let t=n.extensions;e(t),n.setExtensions(t)},ve=(n,e,t,r,i=!1)=>!(n instanceof J)||!n.extensions[e]?null:{kind:"pointer",canonical:"",valueSize:t,allowDuplicateTarget:i,setValue:a=>{jm(n,s=>{let l=s[e];l&&r(l,a)})}},Hm=(n,e,t,r)=>{let i=el(r);return i===null?null:ve(n,e,i,(o,a)=>{o[t]=tl(o[t],r,a)},!0)},$s=(n,e,t)=>{let r=el(t);if(r===null)return null;let i=(o,a)=>({kind:"pointer",canonical:"",valueSize:r,allowDuplicateTarget:!0,setValue:s=>a(tl(o(),t,s))});if(e==="baseColorTexture"&&(n instanceof J||n instanceof ke))return i(()=>n.baseColorTextureTransform,o=>{n.baseColorTextureTransform=o});if(!(n instanceof J))return null;switch(e){case"metallicRoughnessTexture":return i(()=>n.metallicRoughnessTextureTransform,o=>{n.metallicRoughnessTextureTransform=o});case"normalTexture":return i(()=>n.normalTextureTransform,o=>{n.normalTextureTransform=o});case"occlusionTexture":return i(()=>n.occlusionTextureTransform,o=>{n.occlusionTextureTransform=o});case"emissiveTexture":return i(()=>n.emissiveTextureTransform,o=>{n.emissiveTextureTransform=o});default:return null}},Ao=n=>!!n?.extensions?.KHR_texture_transform,$m=(n,e,t)=>{let r=kn(e,1),i=r!==null?n.json.materials?.[r]:void 0,o=r!==null?n.materialCache.get(r):void 0;if(r===null||!i||!o)return q(n.opts,`KHR_animation_pointer: material pointer '${t}' does not resolve to an imported runtime material.`),null;let a=f=>(f&&(f.canonical=t),f),s=i.pbrMetallicRoughness;if(e[2]==="pbrMetallicRoughness")return s?e.length===4&&e[3]==="baseColorFactor"&&(o instanceof J||o instanceof ke)?a({kind:"pointer",canonical:t,valueSize:4,setValue:f=>{o.color=[f[0]??1,f[1]??1,f[2]??1],o.opacity=f[3]??1}}):e.length===4&&e[3]==="metallicFactor"&&o instanceof J?a({kind:"pointer",canonical:t,valueSize:1,setValue:f=>{o.metallic=f[0]??0}}):e.length===4&&e[3]==="roughnessFactor"&&o instanceof J?a({kind:"pointer",canonical:t,valueSize:1,setValue:f=>{o.roughness=f[0]??1}}):e.length===7&&e[4]==="extensions"&&e[5]==="KHR_texture_transform"&&Ao(s[e[3]])?a($s(o,e[3],e[6])):null:null;if(e.length===3&&e[2]==="alphaCutoff"&&(o instanceof J||o instanceof ke))return a({kind:"pointer",canonical:t,valueSize:1,setValue:f=>{o.alphaCutoff=f[0]??0}});if(e.length===3&&e[2]==="emissiveFactor"&&o instanceof J)return a({kind:"pointer",canonical:t,valueSize:3,setValue:f=>{o.emissive=[f[0]??0,f[1]??0,f[2]??0]}});if(e.length===4&&e[2]==="normalTexture"&&e[3]==="scale"&&i.normalTexture&&o instanceof J)return a({kind:"pointer",canonical:t,valueSize:1,setValue:f=>{o.normalScale=f[0]??1}});if(e.length===4&&e[2]==="occlusionTexture"&&e[3]==="strength"&&i.occlusionTexture&&o instanceof J)return a({kind:"pointer",canonical:t,valueSize:1,setValue:f=>{o.occlusionStrength=f[0]??1}});if(e.length===6&&e[3]==="extensions"&&e[4]==="KHR_texture_transform"&&Ao(i[e[2]]))return a($s(o,e[2],e[5]));if(e[2]!=="extensions"||e.length<5)return null;let l=i.extensions,u=e[3],c=l?.[u];if(!c||!(o instanceof J))return null;let m=e[4],d=o.extensions;if(e.length===5)switch(u){case"KHR_materials_anisotropy":if(m==="anisotropyStrength")return a(ve(o,"anisotropy",1,(f,p)=>{f.strength=p[0]??0}));if(m==="anisotropyRotation")return a(ve(o,"anisotropy",1,(f,p)=>{f.rotation=p[0]??0}));break;case"KHR_materials_clearcoat":if(m==="clearcoatFactor")return a(ve(o,"clearcoat",1,(f,p)=>{f.factor=p[0]??0}));if(m==="clearcoatRoughnessFactor")return a(ve(o,"clearcoat",1,(f,p)=>{f.roughness=p[0]??0}));break;case"KHR_materials_dispersion":if(m==="dispersion")return a(ve(o,"dispersion",1,(f,p)=>{f.dispersion=p[0]??0}));break;case"KHR_materials_emissive_strength":if(m==="emissiveStrength")return a(ve(o,"emissiveStrength",1,(f,p)=>{f.strength=p[0]??1}));break;case"KHR_materials_ior":if(m==="ior")return a(ve(o,"ior",1,(f,p)=>{f.ior=p[0]??1.5}));break;case"KHR_materials_iridescence":if(m==="iridescenceFactor")return a(ve(o,"iridescence",1,(f,p)=>{f.factor=p[0]??0}));if(m==="iridescenceIor")return a(ve(o,"iridescence",1,(f,p)=>{f.ior=p[0]??1.3}));if(m==="iridescenceThicknessMinimum")return a(ve(o,"iridescence",1,(f,p)=>{f.thicknessMinimum=p[0]??100}));if(m==="iridescenceThicknessMaximum")return a(ve(o,"iridescence",1,(f,p)=>{f.thicknessMaximum=p[0]??400}));break;case"KHR_materials_sheen":if(m==="sheenColorFactor")return a(ve(o,"sheen",3,(f,p)=>{f.color=[p[0]??0,p[1]??0,p[2]??0]}));if(m==="sheenRoughnessFactor")return a(ve(o,"sheen",1,(f,p)=>{f.roughness=p[0]??0}));break;case"KHR_materials_specular":if(m==="specularFactor")return a(ve(o,"specular",1,(f,p)=>{f.factor=p[0]??1}));if(m==="specularColorFactor")return a(ve(o,"specular",3,(f,p)=>{f.color=[p[0]??1,p[1]??1,p[2]??1]}));break;case"KHR_materials_transmission":if(m==="transmissionFactor")return a(ve(o,"transmission",1,(f,p)=>{f.factor=p[0]??0}));break;case"KHR_materials_volume":if(m==="thicknessFactor")return a(ve(o,"volume",1,(f,p)=>{f.thicknessFactor=p[0]??0}));if(m==="attenuationDistance")return a(ve(o,"volume",1,(f,p)=>{f.attenuationDistance=p[0]??1/0}));if(m==="attenuationColor")return a(ve(o,"volume",3,(f,p)=>{f.attenuationColor=[p[0]??1,p[1]??1,p[2]??1]}));break;case"KHR_materials_diffuse_transmission":if(m==="diffuseTransmissionFactor")return a(ve(o,"diffuseTransmission",1,(f,p)=>{f.factor=p[0]??0}));if(m==="diffuseTransmissionColorFactor")return a(ve(o,"diffuseTransmission",3,(f,p)=>{f.color=[p[0]??1,p[1]??1,p[2]??1]}));break}if(e.length===6&&e[5]==="scale"&&u==="KHR_materials_clearcoat"&&m==="clearcoatNormalTexture"&&c.clearcoatNormalTexture&&d.clearcoat)return a(ve(o,"clearcoat",1,(f,p)=>{f.normalScale=p[0]??1}));if(e.length===8&&e[5]==="extensions"&&e[6]==="KHR_texture_transform"&&Ao(c[m])){let f={KHR_materials_anisotropy:{anisotropyTexture:"textureTransform"},KHR_materials_clearcoat:{clearcoatTexture:"textureTransform",clearcoatRoughnessTexture:"roughnessTextureTransform",clearcoatNormalTexture:"normalTextureTransform"},KHR_materials_iridescence:{iridescenceTexture:"textureTransform",iridescenceThicknessTexture:"thicknessTextureTransform"},KHR_materials_sheen:{sheenColorTexture:"colorTextureTransform",sheenRoughnessTexture:"roughnessTextureTransform"},KHR_materials_specular:{specularTexture:"textureTransform",specularColorTexture:"colorTextureTransform"},KHR_materials_transmission:{transmissionTexture:"textureTransform"},KHR_materials_volume:{thicknessTexture:"thicknessTextureTransform"},KHR_materials_diffuse_transmission:{diffuseTransmissionTexture:"textureTransform",diffuseTransmissionColorTexture:"colorTextureTransform"}},p={KHR_materials_anisotropy:"anisotropy",KHR_materials_clearcoat:"clearcoat",KHR_materials_iridescence:"iridescence",KHR_materials_sheen:"sheen",KHR_materials_specular:"specular",KHR_materials_transmission:"transmission",KHR_materials_volume:"volume",KHR_materials_diffuse_transmission:"diffuseTransmission"},h=f[u]?.[m],g=p[u];if(h&&g)return a(Hm(o,g,h,e[7]))}return null},qm=(n,e,t)=>{let r=kn(e,1),i=r!==null?n.nodes[r]:void 0,o=r!==null?n.json.nodes?.[r]:void 0;if(r===null||!i||!o)return q(n.opts,`KHR_animation_pointer: node pointer '${t}' does not resolve to an imported node.`),null;if(e.length===3){let a=e[2];if(a==="translation")return{kind:"trs",canonical:t,targetIndex:i.transform.index>>>0,pathCode:0};if(a==="rotation")return o.matrix?null:{kind:"trs",canonical:t,targetIndex:i.transform.index>>>0,pathCode:1};if(a==="scale")return o.matrix?null:{kind:"trs",canonical:t,targetIndex:i.transform.index>>>0,pathCode:2};if(a==="weights"){let s=i.meshes.filter(l=>l.geometry.morphTargets.length>0);return s.length>0?{kind:"weights",canonical:t,meshes:s}:null}}if(e.length===4&&e[2]==="weights"){let a=kn(e,3);if(a===null)return null;let s=i.meshes.filter(l=>l.geometry.morphTargets.length>a);return s.length===0?null:{kind:"pointer",canonical:t,valueSize:1,setValue:l=>{let u=l[0]??0;for(let c of s)sa(c,a,u)}}}return e.length===5&&e[2]==="extensions"&&e[3]==="KHR_node_visibility"&&e[4]==="visible"&&o.extensions?.KHR_node_visibility?{kind:"pointer",canonical:t,valueSize:1,requiresStep:!0,setValue:a=>{i.visible=(a[0]??0)!==0}}:null},Km=(n,e,t)=>{let r=kn(e,1),i=r!==null?n.json.cameras?.[r]:void 0,o=r!==null?n.cameraRuntimeMap.get(r)??[]:[];if(r===null||!i||o.length===0||e.length!==4)return null;let a=e[2],s=e[3];if(a==="perspective"&&i.type==="perspective"){let l=o.filter(m=>m instanceof Dt);if(l.length===0||s==="aspectRatio"&&i.perspective?.aspectRatio===void 0||s==="zfar"&&i.perspective?.zfar===void 0)return null;let c={aspectRatio:(m,d)=>{m.aspect=d},yfov:(m,d)=>{m.fov=d*180/Math.PI},znear:(m,d)=>{m.near=d},zfar:(m,d)=>{m.far=d}}[s];return c?{kind:"pointer",canonical:t,valueSize:1,setValue:m=>{for(let d of l)c(d,m[0]??0)}}:null}if(a==="orthographic"&&i.type==="orthographic"){let l=o.filter(m=>m instanceof Nt);if(l.length===0)return null;let c={xmag:(m,d)=>{m.left=-d,m.right=d},ymag:(m,d)=>{m.top=d,m.bottom=-d},znear:(m,d)=>{m.near=d},zfar:(m,d)=>{m.far=d}}[s];return c?{kind:"pointer",canonical:t,valueSize:1,setValue:m=>{for(let d of l)c(d,m[0]??0)}}:null}return null},Xm=(n,e,t)=>{if(e.length<5||e[0]!=="extensions"||e[1]!=="KHR_lights_punctual"||e[2]!=="lights")return null;let r=kn(e,3),i=Ys(n.json),o=r!==null?i?.lights?.[r]:void 0,a=r!==null?n.lightRuntimeMap.get(r)??[]:[];if(r===null||!o||a.length===0)return null;if(e.length===5){let s=e[4];if(s==="color")return{kind:"pointer",canonical:t,valueSize:3,setValue:l=>{for(let u of a)u.color=[l[0]??1,l[1]??1,l[2]??1]}};if(s==="intensity")return{kind:"pointer",canonical:t,valueSize:1,setValue:l=>{for(let u of a)u.intensity=l[0]??1}};if(s==="range"){let l=a.filter(u=>u instanceof Tt||u instanceof ct);return l.length===0?null:{kind:"pointer",canonical:t,valueSize:1,setValue:u=>{for(let c of l)c.range=u[0]??0}}}}if(e.length===6&&e[4]==="spot"&&o.type==="spot"){let s=a.filter(l=>l instanceof ct);if(e[5]==="innerConeAngle")return{kind:"pointer",canonical:t,valueSize:1,setValue:l=>{for(let u of s)u.innerCone=l[0]??0}};if(e[5]==="outerConeAngle")return{kind:"pointer",canonical:t,valueSize:1,setValue:l=>{for(let u of s)u.outerCone=l[0]??Math.PI/4}}}return null},Ym=n=>`/${n.map(e=>e.replace(/~/g,"~0").replace(/\//g,"~1")).join("/")}`,Zm=(n,e)=>{let t=Wm(e);if(!t)return q(n.opts,`KHR_animation_pointer: invalid JSON pointer '${e}'.`),null;let r=Ym(t);return t[0]==="nodes"?qm(n,t,r):t[0]==="materials"?$m(n,t,r):t[0]==="cameras"?Km(n,t,r):t[0]==="extensions"?Xm(n,t,r):null},Fo=(n,e,t,r,i)=>{let o=e.match(/^\/nodes\/(\d+)\/weights\/(\d+)$/),a=o?`/nodes/${o[1]}/weights`:e.match(/^\/nodes\/(\d+)\/weights$/)?.[0]??null;for(let s of n){if(s===e){if(!i)throw new Error(`glTF animation '${t}' targets '${e}' more than once.`);q(r,`KHR_animation_pointer: animation '${t}' targets '${e}' more than once; applying duplicate pointer channels in file order.`);continue}if(a&&(e===a?s.startsWith(`${a}/`):s===a))throw new Error(`glTF animation '${t}' targets overlapping morph weight paths '${s}' and '${e}'.`)}n.add(e)},Qm=(n,e,t,r,i,o,a)=>{let s=e.animations??[],l=[],u=m=>{switch(m){case"STEP":return 0;case"CUBICSPLINE":return 2;default:return 1}},c=m=>{switch(m){case"translation":return 0;case"rotation":return 1;case"scale":return 2;default:return-1}};for(let m=0;m<s.length;m++){let d=s[m],f=[],p=[],h=[],g=[],b=new Set,P=d.name??`anim_${m}`,v=d.samplers.length|0,x=v>0?_.allocU32(v*5):0,T=[],w=[];v>0&&w.push({ptr:x,len:v*5});let M=Number.POSITIVE_INFINITY,B=Number.NEGATIVE_INFINITY;for(let k=0;k<d.samplers.length;k++){let A=d.samplers[k],I=Ae(n,A.input),O=It(n,A.output),N=Ae(n,A.output);f.push({interpolation:A.interpolation??"LINEAR",input:I,output:N});let z=A.interpolation??"LINEAR",E=z==="CUBICSPLINE"?Math.max(1,(I.length|0)*3):Math.max(1,I.length|0),H=Math.max(0,Math.floor(N.length/E));if(p.push({interpolation:z,input:I,output:N,valueSize:H}),I.length>0&&(M=Math.min(M,I[0]),B=Math.max(B,I[I.length-1])),v>0){let j=_.allocF32(I.length);_.f32view(j,I.length).set(I),T.push({ptr:j,len:I.length});let Z=_.allocF32(N.length);_.f32view(Z,N.length).set(N),T.push({ptr:Z,len:N.length});let xe=_.u32view(x,v*5),te=k*5;xe[te+0]=j>>>0,xe[te+1]=(I.length|0)>>>0,xe[te+2]=Z>>>0,xe[te+3]=(O.numComponents|0)>>>0,xe[te+4]=u(A.interpolation??"LINEAR")>>>0}}let S=[],R=[],G={json:e,nodes:t,materialCache:r,cameraRuntimeMap:i,lightRuntimeMap:o,opts:a};for(let k=0;k<d.channels.length;k++){let A=d.channels[k],I=A.target.node,N=(I!==void 0?t[I]??null:null)?.transform??null,z={sampler:A.sampler|0,targetNode:N,path:A.target.path};if(A.target.path==="pointer"&&(z.targetPointer=Hs(A)??void 0),g.push(z),A.target.path==="pointer"){if(I!==void 0){q(a,`KHR_animation_pointer: animation '${P}' channel ${k} sets target.node; skipping pointer channel.`);continue}let H=Hs(A);if(!H){q(a,`KHR_animation_pointer: animation '${P}' channel ${k} is missing extensions.KHR_animation_pointer.pointer.`);continue}let j=Zm(G,H);if(!j){q(a,`KHR_animation_pointer: animation '${P}' channel ${k} pointer '${H}' is not supported by this importer.`);continue}if(Fo(b,j.canonical,P,a,j.kind==="pointer"&&j.allowDuplicateTarget===!0),j.kind==="trs"){S.push({sampler:z.sampler|0,targetIndex:j.targetIndex,pathCode:j.pathCode});continue}if(j.kind==="weights"){R.push({sampler:z.sampler|0,meshes:j.meshes});continue}let Z=p[z.sampler];if(!Z){q(a,`KHR_animation_pointer: animation '${P}' channel ${k} references missing sampler ${z.sampler}.`);continue}if(j.requiresStep&&Z.interpolation!=="STEP"){q(a,`KHR_animation_pointer: boolean pointer '${j.canonical}' requires STEP interpolation; skipping channel.`);continue}if((Z.valueSize|0)!==(j.valueSize|0)){q(a,`KHR_animation_pointer: pointer '${j.canonical}' expects ${j.valueSize} output component(s), got ${Z.valueSize}; skipping channel.`);continue}h.push({sampler:z.sampler|0,scratch:new Float32Array(j.valueSize),setValue:j.setValue});continue}let E=c(z.path);if(N&&E>=0)I!==void 0&&Fo(b,`/nodes/${I}/${z.path}`,P,a,!1),S.push({sampler:z.sampler|0,targetIndex:N.index>>>0,pathCode:E});else if(z.path==="weights"&&I!==void 0){Fo(b,`/nodes/${I}/weights`,P,a,!1);let H=(t[I]?.meshes??[]).filter(j=>j.geometry.morphTargets.length>0);H.length>0&&R.push({sampler:z.sampler|0,meshes:H})}}let L=null,U=S.length|0,F=R.length|0,D=h.length|0;if(v>0&&(U>0||F>0||D>0)){let k=0;if(U>0){k=_.allocU32(U*3);let A=_.u32view(k,U*3);w.push({ptr:k,len:U*3});for(let I=0;I<U;I++){let O=S[I],N=I*3;A[N+0]=O.sampler>>>0,A[N+1]=O.targetIndex>>>0,A[N+2]=O.pathCode>>>0}}Number.isFinite(M)||(M=0),Number.isFinite(B)||(B=0),L=new ar({name:d.name??`anim_${m}`,samplerCount:v,channelCount:U,samplersPtr:x,channelsPtr:k,startTime:M,endTime:B,ownedF32Allocs:T,ownedU32Allocs:w,weightSamplers:p,weightChannels:R.map(A=>({sampler:A.sampler,meshes:A.meshes,scratch:new Float32Array(p[A.sampler]?.valueSize??0)})),pointerSamplers:p,pointerChannels:h})}else{for(let k of T)_.freeF32(k.ptr,k.len);for(let k of w)_.freeU32(k.ptr,k.len)}l.push({name:d.name,samplers:f,channels:g,clip:L})}return l},ki=(n,e={})=>{let t=n.json,r=e.targetScene??new $e,i=e.addToScene!==!1,o=xm(t,e),a=t.nodes??[],s=new Array(a.length);for(let L=0;L<a.length;L++){let U=a[L],F=new we;if(U.matrix&&U.matrix.length>=16)Sm(F,U.matrix);else{let D=U.translation??[0,0,0],k=U.rotation??[0,0,0,1],A=U.scale??[1,1,1];F.setPosition(D[0],D[1],D[2]),F.setRotation(k[0],k[1],k[2],k[3]),F.setScale(A[0],A[1],A[2])}s[L]=new Io(L,F,U)}for(let L=0;L<a.length;L++){let U=a[L],F=s[L];for(let D of U.children??[]){let k=s[D];k?(k.transform.setParent(F.transform),k.parentIndex=L,k.setParentNode(F)):q(e,`Node ${L} child ${D} missing transform`)}}let l=Bm(t),u=km(t),c=Mm(Lm(t,u.packets)),m=Em(n,t,s,e),d=new Map,f=new Map,p=new Map,h=[],g=[],b=[],P=new Map,v=new Map,x=Ys(t),T=(L,U)=>{let F=a[L];if(!F)return;let D=s[L],k=D?.transform;if(!D||!k)return;let A=zm(n,t,L,F,k,d,f,p,c,e);D.meshes=A,D.applyVisibility();let I=F.skin!==void 0?F.skin|0:U;if(I!==void 0){let O=m[I];if(!O||!O.runtime)q(e,`nodes[${L}].skin=${I} missing or invalid; skipping skin binding`);else for(let N of A){if(N.geometry.joints===null||N.geometry.weights===null){q(e,`Mesh '${N.name}' is skinned (node.skin) but is missing JOINTS_0/WEIGHTS_0; it will render unskinned.`);continue}N.skin=O.runtime.createInstance(N.transform)}}for(let O of A)h.push(O),i&&r.add(O);if(e.importCameras){let O=Om(t,F,k,e);if(O&&(g.push(O),D.camera=O,F.camera!==void 0)){let N=F.camera|0,z=P.get(N)??[];z.push(O),P.set(N,z)}}if(e.importLights&&x){let O=Pm(F);if(O){let N=x.lights[O.light];if(!N)q(e,`KHR_lights_punctual node references missing light ${O.light}`);else{let z=Vm(N,k);if(z){Da(z,k),b.push(z),D.light=z;let E=O.light|0,H=v.get(E)??[];H.push(z),v.set(E,H),D.applyVisibility(),i&&r.addLight(z)}else q(e,`Light '${F.name??`index ${L}`}' has unsupported type '${N.type}' and was skipped.`)}}}for(let O of F.children??[])T(O,I)},M=t.scenes?.[o]?.nodes??[];for(let L of M)T(L,void 0);let B=Qm(n,t,s,d,P,v,e),S=B.map(L=>L.clip).filter(L=>L!==null),R=Rm(t,o,l,u,c.public),G=!1;return{scene:r,meshes:h,nodes:s,lights:b,cameras:g,skins:m,animations:B,clips:S,metadata:R,destroy(){if(!G){if(G=!0,i){for(let L of h)r.remove(L);for(let L of b)r.removeLight(L)}for(let L of b)Na(L);for(let L of h)L.destroy();for(let L of g)L.destroy();for(let L of B)L.clip?.dispose();for(let L of m)L.runtime?.dispose();c.destroy();for(let L of f.values())L.destroy();for(let L of s)L.transform.dispose()}}}};var mt=(n,e,t,r)=>{let i=Math.max(1,e),o=Math.max(1,t),a=n.viewProjectionMatrix,s=r[0]??0,l=r[1]??0,u=r[2]??0,c=a[0]*s+a[4]*l+a[8]*u+a[12],m=a[1]*s+a[5]*l+a[9]*u+a[13],d=a[2]*s+a[6]*l+a[10]*u+a[14],f=a[3]*s+a[7]*l+a[11]*u+a[15];if(!Number.isFinite(f)||Math.abs(f)<=1e-8)return null;let p=1/f,h=c*p,g=m*p,b=d*p,P=(h*.5+.5)*i,v=(1-(g*.5+.5))*o,x=f>0,T=h>=-1&&h<=1&&g>=-1&&g<=1&&b>=0&&b<=1;return{x:P,y:v,ndcX:h,ndcY:g,ndcZ:b,clipW:f,inFront:x,insideClip:T,visible:x&&T}},rl=(n,e)=>{if(e.length<17)throw new Error("writeCameraSignature: expected Float64Array length >= 17.");e[0]=n.type==="perspective"?1:2;let t=n.viewProjectionMatrix;for(let r=0;r<16;r++)e[r+1]=t[r]??0},nl=(n,e,t=1e-6)=>{if(n.length!==e.length)return!1;for(let r=0;r<n.length;r++)if(Math.abs(n[r]-e[r])>t)return!1;return!0},Gr=(n,e,t)=>{let r=Math.max(1,e),i=Math.max(1,t),o=n??{kind:"screen",corner:"bottom-left",offsetPx:[16,-16]},a=o.offsetPx?.[0]??0,s=o.offsetPx?.[1]??0;if(typeof o.x=="number"||typeof o.y=="number"){let u=(o.x??0)+a,c=(o.y??0)+s;return[u,c]}let l=o.corner??"bottom-left";return l==="top-left"?[0+a,0+s]:l==="top-right"?[r+a,0+s]:l==="bottom-right"?[r+a,i+s]:[0+a,i+s]};var Jm=(n,e)=>{if(e){if(Array.isArray(e)){for(let t=0;t<e.length;t++)n.add(e[t]);return}n.add(e)}},Ar=class{canvas;parent;root;interactionThrottleMs;autoUpdate;layers=new Map;dirtyReasons=new Set(["layout"]);resizeObserver=null;winResizeListener=null;winScrollListener=null;rafId=null;currentCamera=null;currentScene=null;dpr=1;width=1;height=1;lastLeft=Number.NaN;lastTop=Number.NaN;lastUpdateMs=Number.NaN;interactionActive=!1;pendingInteractionFlush=!1;controlsUnsubChange=null;controlsUnsubInteraction=null;cameraSigA=new Float64Array(17);cameraSigB=new Float64Array(17);hasCameraSig=!1;constructor(e){if(typeof document>"u")throw new Error("OverlaySystem requires a DOM environment.");this.canvas=e.canvas,this.parent=e.parent??this.canvas.parentElement??document.body,this.interactionThrottleMs=Math.max(0,Math.round(e.interactionThrottleMs??24)),this.autoUpdate=e.autoUpdate??!0,this.parent!==document.body&&this.parent!==document.documentElement&&getComputedStyle(this.parent).position==="static"&&(this.parent.style.position="relative");let t=document.createElement("div");t.className=e.className??"wasmgpu-overlay-root",t.style.position=this.parent===document.body||this.parent===document.documentElement?"fixed":"absolute",t.style.pointerEvents="none",t.style.overflow="hidden",t.style.contain="layout style paint",t.style.left="0",t.style.top="0",t.style.width="1px",t.style.height="1px",t.style.zIndex=String(e.zIndex??20),this.parent.appendChild(t),this.root=t,this.currentCamera=e.camera??null,this.currentScene=e.scene??null,this.bindControls(e.controls??null),this.setupResizeEvents(),this.syncRootBounds(),this.invalidate("layout")}get layerCount(){return this.layers.size}get isInteractionActive(){return this.interactionActive}setView(e,t=null){return this.currentCamera=e,this.currentScene=t??null,this.invalidate("camera"),this}bindControls(e){if(this.controlsUnsubChange?.(),this.controlsUnsubInteraction?.(),this.controlsUnsubChange=null,this.controlsUnsubInteraction=null,!e)return this;let t=e;return typeof t.onChange=="function"&&(this.controlsUnsubChange=t.onChange(()=>this.invalidate("camera"))),typeof t.onInteractionState=="function"&&(this.controlsUnsubInteraction=t.onInteractionState(r=>this.setInteractionActive(r))),this}addLayer(e){if(this.layers.has(e.id))throw new Error(`OverlaySystem: duplicate layer id '${e.id}'.`);return this.layers.set(e.id,e),e.setSystem?.(this),e.attach(this.root),this.invalidate("manual"),this}removeLayer(e){let t=this.layers.get(e);return t?(t.setSystem?.(null),t.detach(),this.layers.delete(e),this.invalidate("manual"),this):this}clearLayers(){for(let e of this.layers.values())e.setSystem?.(null),e.detach();return this.layers.clear(),this.invalidate("manual"),this}invalidate(e="manual"){this.dirtyReasons.add(e),this.requestFrame()}setInteractionActive(e){return this.interactionActive===e?this:(this.interactionActive=e,e||(this.pendingInteractionFlush=!0),this.invalidate("interaction"),this)}update(e={}){e.camera!==void 0&&(this.currentCamera=e.camera),e.scene!==void 0&&(this.currentScene=e.scene),Jm(this.dirtyReasons,e.reasons),this.syncRootBounds();let t=this.currentCamera;if(!t)return!1;let r=e.nowMs??hr();rl(t,this.cameraSigB),(!this.hasCameraSig||!nl(this.cameraSigA,this.cameraSigB,1e-6))&&(this.cameraSigA.set(this.cameraSigB),this.hasCameraSig=!0,this.dirtyReasons.add("camera"));let i=!!e.force;if(this.dirtyReasons.size===0&&!this.pendingInteractionFlush&&!i||this.interactionActive&&this.interactionThrottleMs>0&&!i&&Number.isFinite(this.lastUpdateMs)&&r-this.lastUpdateMs<this.interactionThrottleMs)return!1;let o=new Set(this.dirtyReasons);this.pendingInteractionFlush&&o.add("interaction");for(let a of this.layers.values())a.update({camera:t,scene:this.currentScene??null,width:this.width,height:this.height,dpr:this.dpr,nowMs:r,reasons:o,root:this.root});return this.lastUpdateMs=r,this.pendingInteractionFlush=!1,this.dirtyReasons.clear(),!0}destroy(){if(this.cancelFrame(),this.controlsUnsubChange?.(),this.controlsUnsubInteraction?.(),this.controlsUnsubChange=null,this.controlsUnsubInteraction=null,this.resizeObserver){try{this.resizeObserver.disconnect()}catch{}this.resizeObserver=null}this.winResizeListener&&window.removeEventListener("resize",this.winResizeListener),this.winScrollListener&&window.removeEventListener("scroll",this.winScrollListener,!0),this.winResizeListener=null,this.winScrollListener=null,this.clearLayers(),this.root.remove()}requestFrame(){!this.autoUpdate||this.rafId!==null||typeof requestAnimationFrame=="function"&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null,this.update()}))}cancelFrame(){this.rafId!==null&&(typeof cancelAnimationFrame=="function"&&cancelAnimationFrame(this.rafId),this.rafId=null)}setupResizeEvents(){let e=()=>{this.syncRootBounds(),this.invalidate("viewport")};this.winResizeListener=e,this.winScrollListener=e,window.addEventListener("resize",e),window.addEventListener("scroll",e,!0),typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(e),this.resizeObserver.observe(this.canvas))}syncRootBounds(){let e=this.canvas.getBoundingClientRect(),t=this.parent===document.body||this.parent===document.documentElement?{left:0,top:0}:this.parent.getBoundingClientRect(),r=e.left-t.left+(this.parent.scrollLeft??0),i=e.top-t.top+(this.parent.scrollTop??0),o=Math.max(1,Math.round(e.width||this.canvas.clientWidth||1)),a=Math.max(1,Math.round(e.height||this.canvas.clientHeight||1)),s=Math.max(1,window.devicePixelRatio||1),l=!Number.isFinite(this.lastLeft)||!Number.isFinite(this.lastTop)||Math.abs(r-this.lastLeft)>.5||Math.abs(i-this.lastTop)>.5,u=o!==this.width||a!==this.height||Math.abs(s-this.dpr)>1e-6;!l&&!u||(this.lastLeft=r,this.lastTop=i,this.width=o,this.height=a,this.dpr=s,this.root.style.left=`${r}px`,this.root.style.top=`${i}px`,this.root.style.width=`${o}px`,this.root.style.height=`${a}px`,this.dirtyReasons.add(l?"layout":"viewport"))}};var il=[[1,0,0],[0,1,0],[0,0,1]],ed=(n,e)=>{let t=Math.hypot(n,e);return t<=1e-8?[0,0]:[n/t,e/t]},Fr=class{id;anchor;lengthWorld;sizePx;lineWidthPx;labels;colors;labelOffsetPx;font;root=null;container=null;lines=[];labelEls=[];_system=null;constructor(e={}){this.id=e.id??"overlay-axis-triad",this.anchor=e.anchor??{kind:"screen",corner:"bottom-left",offsetPx:[26,-26]},this.lengthWorld=Math.max(1e-6,e.lengthWorld??1),this.sizePx=Math.max(8,e.sizePx??56),this.lineWidthPx=Math.max(1,e.lineWidthPx??2),this.labels=e.labels??["X","Y","Z"],this.colors=e.colors??["#ff5f56","#3fd77a","#4ca7ff"],this.labelOffsetPx=Math.max(0,e.labelOffsetPx??8),this.font=e.font??"11px monospace"}setSystem(e){this._system=e}attach(e){this.root=e;let t=document.createElement("div");t.style.position="absolute",t.style.inset="0",t.style.pointerEvents="none",e.appendChild(t),this.container=t,this.lines=[],this.labelEls=[];for(let r=0;r<3;r++){let i=document.createElement("div");i.style.position="absolute",i.style.transformOrigin="0 50%",i.style.background=this.colors[r],t.appendChild(i),this.lines.push(i);let o=document.createElement("div");o.style.position="absolute",o.style.font=this.font,o.style.color=this.colors[r],o.style.whiteSpace="nowrap",o.textContent=this.labels[r],t.appendChild(o),this.labelEls.push(o)}}detach(){this.container?.remove(),this.root=null,this.container=null,this.lines=[],this.labelEls=[]}update(e){if(!(!this.container||!this.root)){if(this.anchor?.kind==="world"){this.updateWorld(e,this.anchor);return}this.updateScreen(e)}}updateWorld(e,t){let r=mt(e.camera,e.width,e.height,t.position);if(!r||!r.inFront){this.hideAll();return}for(let i=0;i<3;i++){let o=il[i],a=mt(e.camera,e.width,e.height,[t.position[0]+o[0]*this.lengthWorld,t.position[1]+o[1]*this.lengthWorld,t.position[2]+o[2]*this.lengthWorld]);if(!a||!a.inFront){this.lines[i].style.display="none",this.labelEls[i].style.display="none";continue}this.drawLine(this.lines[i],r.x,r.y,a.x,a.y,this.colors[i],this.lineWidthPx),this.drawLabel(this.labelEls[i],a.x,a.y,this.colors[i])}}updateScreen(e){let[t,r]=Gr(this.anchor?.kind==="screen"?this.anchor:{kind:"screen",corner:"bottom-left",offsetPx:[26,-26]},e.width,e.height),i=e.camera.viewMatrix;for(let o=0;o<3;o++){let a=il[o],s=i[0]*a[0]+i[4]*a[1]+i[8]*a[2],l=i[1]*a[0]+i[5]*a[1]+i[9]*a[2],[u,c]=ed(s,-l),m=t+u*this.sizePx,d=r+c*this.sizePx;this.drawLine(this.lines[o],t,r,m,d,this.colors[o],this.lineWidthPx),this.drawLabel(this.labelEls[o],m,d,this.colors[o])}}drawLine(e,t,r,i,o,a,s){let l=i-t,u=o-r,c=Math.hypot(l,u);if(!Number.isFinite(c)||c<=1e-5){e.style.display="none";return}let m=Math.atan2(u,l);e.style.display="",e.style.background=a,e.style.left=`${t}px`,e.style.top=`${r}px`,e.style.width=`${c}px`,e.style.height=`${Math.max(1,s)}px`,e.style.transform=`translateY(${-.5*Math.max(1,s)}px) rotate(${m}rad)`}drawLabel(e,t,r,i){e.style.display="",e.style.left=`${t+this.labelOffsetPx}px`,e.style.top=`${r-this.labelOffsetPx}px`,e.style.color=i}hideAll(){for(let e=0;e<this.lines.length;e++)this.lines[e].style.display="none";for(let e=0;e<this.labelEls.length;e++)this.labelEls[e].style.display="none"}};var Ct=class{constructor(e,t,r){this.parent=e;this.create=t;this.maxNodes=r}nodes=[];used=0;beginFrame(){this.used=0}acquire(){if(this.used<this.nodes.length){let t=this.nodes[this.used++];return t.style.display="",t}if(this.nodes.length>=this.maxNodes)throw new Error(`DOMNodePool: exceeded max node budget (${this.maxNodes}).`);let e=this.create();return this.parent.appendChild(e),this.nodes.push(e),this.used++,e}endFrame(){for(let e=this.used;e<this.nodes.length;e++)this.nodes[e].style.display="none"}get size(){return this.nodes.length}clear(e=!1){this.used=0;for(let t=0;t<this.nodes.length;t++)e?this.nodes[t].remove():this.nodes[t].style.display="none";e&&(this.nodes.length=0)}};var ol=n=>{if(!Number.isFinite(n))return"nan";let e=Math.abs(n);return e>=1e4||e>0&&e<.001?n.toExponential(2):`${Math.round(n*1e3)/1e3}`},al=n=>{let e=Math.max(1e-9,Math.abs(n)),t=Math.floor(Math.log10(e)),r=Math.pow(10,t),i=e/r;return(i<=1?1:i<=2?2:i<=5?5:10)*r},td=n=>n==="xy"?{u:[1,0,0],v:[0,1,0]}:n==="xz"?{u:[1,0,0],v:[0,0,1]}:{u:[0,1,0],v:[0,0,1]},rd=(n,e)=>n==="xy"?{uMin:e.boxMin[0],uMax:e.boxMax[0],vMin:e.boxMin[1],vMax:e.boxMax[1]}:n==="xz"?{uMin:e.boxMin[0],uMax:e.boxMax[0],vMin:e.boxMin[2],vMax:e.boxMax[2]}:{uMin:e.boxMin[1],uMax:e.boxMax[1],vMin:e.boxMin[2],vMax:e.boxMax[2]},Mi=(n,e,t,r)=>n==="xy"?[e[0]+t,e[1]+r,e[2]]:n==="xz"?[e[0]+t,e[1],e[2]+r]:[e[0],e[1]+t,e[2]+r],sl=(n,e,t,r,i,o,a)=>{let s=r-e,l=i-t,u=Math.hypot(s,l);if(!Number.isFinite(u)||u<=1e-5){n.style.display="none";return}n.style.display="",n.style.left=`${e}px`,n.style.top=`${t}px`,n.style.width=`${u}px`,n.style.height=`${Math.max(1,a)}px`,n.style.background=o,n.style.transform=`translateY(${-.5*Math.max(1,a)}px) rotate(${Math.atan2(l,s)}rad)`},nd=(n,e)=>Math.abs(n)<=e?0:n,Li=(n,e,t)=>Math.abs(n-e)<=t,Gi=(n,e)=>Math.max(1e-9,Math.abs(n)*1e-9,Math.abs(e)*1e-6),Ri=(n,e,t)=>{if(!Number.isFinite(e)||e<=t)return!1;let r=n/e;return Math.abs(r-Math.round(r))<=1e-4},Ui=(n,e,t)=>{let r=Math.max(0,e-n),i=Gi(r,t);if(t<=i)return 0;let o=0,a=Math.ceil((n+i)/t)*t,s=e-i;for(let l=0;l<1e6&&a<=s;l++,a+=t)a>n+i&&a<e-i&&o++;return o},ll=(n,e,t)=>{let r=Math.max(0,e-n),i=Gi(r,t);if(r<=i)return[n];let o=[n];if(t>i){let a=Math.ceil((n+i)/t)*t,s=e-i;for(let l=0;l<1e6&&a<=s;l++,a+=t)a<=n+i||a>=e-i||o.push(nd(a,i))}return o.push(e),o},Ir=class{id;plane;origin;extentMode;fixedUMin;fixedUMax;fixedVMin;fixedVMax;targetMinorSpacingPx;majorStepFactor;minLabelSpacingPx;maxLines;maxLabels;minorColor;majorColor;axisColor;labelColor;lineWidthMinorPx;lineWidthMajorPx;font;container=null;linePool=null;labelPool=null;constructor(e={}){this.id=e.id??"overlay-grid",this.plane=e.plane??"xy",this.origin=e.origin??[0,0,0],this.extentMode=e.extentMode??"scene-fit",this.fixedUMin=e.fixedUMin??-10,this.fixedUMax=e.fixedUMax??10,this.fixedVMin=e.fixedVMin??-10,this.fixedVMax=e.fixedVMax??10,this.targetMinorSpacingPx=Math.max(6,e.targetMinorSpacingPx??30),this.majorStepFactor=Math.max(2,Math.round(e.majorStepFactor??5)),this.minLabelSpacingPx=Math.max(8,e.minLabelSpacingPx??58),this.maxLines=Math.max(4,Math.round(e.maxLines??160)),this.maxLabels=Math.max(2,Math.round(e.maxLabels??60)),this.minorColor=e.minorColor??"rgba(180, 210, 255, 0.17)",this.majorColor=e.majorColor??"rgba(180, 210, 255, 0.36)",this.axisColor=e.axisColor??"rgba(220, 235, 255, 0.8)",this.labelColor=e.labelColor??"rgba(220, 235, 255, 0.9)",this.lineWidthMinorPx=Math.max(1,e.lineWidthMinorPx??1),this.lineWidthMajorPx=Math.max(1,e.lineWidthMajorPx??2),this.font=e.font??"11px monospace"}attach(e){let t=document.createElement("div");t.style.position="absolute",t.style.inset="0",t.style.pointerEvents="none",e.appendChild(t),this.container=t,this.linePool=new Ct(t,()=>{let r=document.createElement("div");return r.style.position="absolute",r.style.transformOrigin="0 50%",r},this.maxLines),this.labelPool=new Ct(t,()=>{let r=document.createElement("div");return r.style.position="absolute",r.style.color=this.labelColor,r.style.font=this.font,r.style.whiteSpace="nowrap",r},this.maxLabels)}detach(){this.linePool?.clear(!0),this.labelPool?.clear(!0),this.linePool=null,this.labelPool=null,this.container?.remove(),this.container=null}update(e){if(!this.container||!this.linePool||!this.labelPool)return;let{uMin:t,uMax:r,vMin:i,vMax:o}=this.resolveExtent(e),a=Math.max(1e-6,r-t),s=Math.max(1e-6,o-i),l=this.estimatePixelsPerUnitAxes(e),u=Math.max(l.u,l.v),c=al(this.targetMinorSpacingPx/Math.max(1e-6,u)),m=(a>1e-9?2:1)+(s>1e-9?2:1),d=Math.max(0,this.maxLines-m),f=Ui(t,r,c),p=Ui(i,o,c);for(let k=0;k<32&&f+p>d;k++)c=al(c*1.5),f=Ui(t,r,c),p=Ui(i,o,c);let h=c*this.majorStepFactor,g=h*l.u,b=h*l.v,P=Math.max(1,Math.ceil(this.minLabelSpacingPx/Math.max(1e-6,g))),v=Math.max(1,Math.ceil(this.minLabelSpacingPx/Math.max(1e-6,b))),x=ll(t,r,c),T=ll(i,o,c),w=Gi(a,c),M=Gi(s,c),B=Math.max(w,Math.abs(h)*1e-6),S=Math.max(M,Math.abs(h)*1e-6),R=Math.max(w,Math.abs(c)*.001),G=Math.max(M,Math.abs(c)*.001),L=x.reduce((k,A)=>k+(Ri(A,h,B)?1:0),0),U=T.reduce((k,A)=>k+(Ri(A,h,S)?1:0),0);for(let k=0;k<32;k++){let A=L>0?Math.ceil(L/P):0,I=U>0?Math.ceil(U/v):0;if(A+I<=this.maxLabels)break;A>=I?P++:v++}this.linePool.beginFrame(),this.labelPool.beginFrame();let F=0;for(let k=0;k<x.length;k++){let A=x[k],I=this.projectFrontClippedSegment(e,Mi(this.plane,this.origin,A,i),Mi(this.plane,this.origin,A,o));if(!I)continue;let O=I.p0,N=I.p1,z=Ri(A,h,B),E=Math.abs(A)<=R,H=Li(A,t,w)||Li(A,r,w),j=this.linePool.acquire();if(sl(j,O.x,O.y,N.x,N.y,E?this.axisColor:z||H?this.majorColor:this.minorColor,z||E||H?this.lineWidthMajorPx:this.lineWidthMinorPx),z&&F%P===0){let Z=this.labelPool.acquire();Z.textContent=ol(A),Z.style.left=`${O.x+4}px`,Z.style.top=`${O.y+2}px`}z&&F++}let D=0;for(let k=0;k<T.length;k++){let A=T[k],I=this.projectFrontClippedSegment(e,Mi(this.plane,this.origin,t,A),Mi(this.plane,this.origin,r,A));if(!I)continue;let O=I.p0,N=I.p1,z=Ri(A,h,S),E=Math.abs(A)<=G,H=Li(A,i,M)||Li(A,o,M),j=this.linePool.acquire();if(sl(j,O.x,O.y,N.x,N.y,E?this.axisColor:z||H?this.majorColor:this.minorColor,z||E||H?this.lineWidthMajorPx:this.lineWidthMinorPx),z&&D%v===0){let Z=this.labelPool.acquire();Z.textContent=ol(A),Z.style.left=`${O.x+4}px`,Z.style.top=`${O.y+2}px`}z&&D++}this.linePool.endFrame(),this.labelPool.endFrame()}projectFrontClippedSegment(e,t,r){let i=this.getCameraNear(e.camera),o=-(i>0?i+Math.max(i*1e-4,1e-6):0),a=e.camera.viewMatrix,s=[t[0],t[1],t[2]],l=[r[0],r[1],r[2]],u=this.transformPoint(a,s),c=this.transformPoint(a,l);if(u[2]>o||c[2]>o){if(u[2]>o&&c[2]>o)return null;if(u[2]>o){let f=c[2]-u[2];if(!Number.isFinite(f)||Math.abs(f)<=1e-8)return null;let p=se((o-u[2])/f,0,1);s=[s[0]+(l[0]-s[0])*p,s[1]+(l[1]-s[1])*p,s[2]+(l[2]-s[2])*p],u=[u[0]+(c[0]-u[0])*p,u[1]+(c[1]-u[1])*p,o]}if(c[2]>o){let f=u[2]-c[2];if(!Number.isFinite(f)||Math.abs(f)<=1e-8)return null;let p=se((o-c[2])/f,0,1);l=[l[0]+(s[0]-l[0])*p,l[1]+(s[1]-l[1])*p,l[2]+(s[2]-l[2])*p],c=[c[0]+(u[0]-c[0])*p,c[1]+(u[1]-c[1])*p,o]}}let m=mt(e.camera,e.width,e.height,s),d=mt(e.camera,e.width,e.height,l);return!m||!d||!m.inFront||!d.inFront||!Number.isFinite(m.x)||!Number.isFinite(m.y)||!Number.isFinite(d.x)||!Number.isFinite(d.y)?null:{p0:m,p1:d}}getCameraNear(e){let t=e.near;return typeof t!="number"||!Number.isFinite(t)?0:Math.max(0,t)}transformPoint(e,t){let r=t[0]??0,i=t[1]??0,o=t[2]??0;return[e[0]*r+e[4]*i+e[8]*o+e[12],e[1]*r+e[5]*i+e[9]*o+e[13],e[2]*r+e[6]*i+e[10]*o+e[14]]}resolveExtent(e){if(this.extentMode==="fixed")return{uMin:Math.min(this.fixedUMin,this.fixedUMax),uMax:Math.max(this.fixedUMin,this.fixedUMax),vMin:Math.min(this.fixedVMin,this.fixedVMax),vMax:Math.max(this.fixedVMin,this.fixedVMax)};let t=e.scene;if(!t)return{uMin:-10,uMax:10,vMin:-10,vMax:10};let r=t.getBounds();if(r.empty)return{uMin:-10,uMax:10,vMin:-10,vMax:10};let i=rd(this.plane,r),o=Math.max(.001,(i.uMax-i.uMin)*.1),a=Math.max(.001,(i.vMax-i.vMin)*.1);return{uMin:i.uMin-o,uMax:i.uMax+o,vMin:i.vMin-a,vMax:i.vMax+a}}estimatePixelsPerUnitAxes(e){let t=td(this.plane),r=mt(e.camera,e.width,e.height,this.origin);if(!r||!r.inFront||r.ndcZ<0||r.ndcZ>1)return{u:1,v:1};let i=mt(e.camera,e.width,e.height,[this.origin[0]+t.u[0],this.origin[1]+t.u[1],this.origin[2]+t.u[2]]),o=mt(e.camera,e.width,e.height,[this.origin[0]+t.v[0],this.origin[1]+t.v[1],this.origin[2]+t.v[2]]),a=i&&i.inFront&&i.ndcZ>=0&&i.ndcZ<=1&&Number.isFinite(i.x)&&Number.isFinite(i.y)?Math.hypot(i.x-r.x,i.y-r.y):1,s=o&&o.inFront&&o.ndcZ>=0&&o.ndcZ<=1&&Number.isFinite(o.x)&&Number.isFinite(o.y)?Math.hypot(o.x-r.x,o.y-r.y):1;return{u:se(a,1e-6,1e9),v:se(s,1e-6,1e9)}}};var id=n=>{if(!Number.isFinite(n))return"nan";let e=Math.abs(n);return e>=1e4||e>0&&e<.001?n.toExponential(3):`${Math.round(n*1e6)/1e6}`},Ai=(n,e)=>Xo(n,e),Lt=n=>[n.mode,n.clampMode,n.valueMode,n.componentCount,n.componentIndex,n.stride,n.offset,n.domainMin,n.domainMax,n.clampMin,n.clampMax,n.percentileLow,n.percentileHigh,n.logBase,n.symlogLinThresh,n.gamma,n.invert?1:0].join("|"),od=n=>{if(n instanceof Oe)return n;let e=n;return e.nodelink instanceof Oe?e.nodelink:n},ad=(n,e)=>{let t=od(n);return typeof t.onVisualChange!="function"?null:t.onVisualChange(()=>e())??null},sd=(n,e)=>{if(n instanceof rt){let o=fe(n.scaleTransform);if(n.colormap==="custom"){let s=n.colormapStops.slice();return{transform:o,signature:`pointcloud|custom|${Lt(o)}|${JSON.stringify(s)}`,sample:l=>Ai(l,s)}}let a=n.getColormapForBinding();if(e&&!a.canSampleCPU)throw new Error("LegendLayer: bound point cloud colormap is GPU-only and cannot be sampled on CPU in strict parity mode.");return{transform:o,signature:`pointcloud|cm:${a.id}|f:${a.filter}|w:${a.width}|${Lt(o)}`,sample:s=>a.sampleCPU(s)}}if(n instanceof ze){let o=fe(n.scaleTransform);if(n.colorMode==="scalar"&&n.colormap==="custom"){let s=n.colormapStops.slice();return{transform:o,signature:`glyphfield|custom|${Lt(o)}|${JSON.stringify(s)}`,sample:l=>Ai(l,s)}}let a=n.getColormapForBinding();if(e&&!a.canSampleCPU)throw new Error("LegendLayer: bound glyph colormap is GPU-only and cannot be sampled on CPU in strict parity mode.");return{transform:o,signature:`glyphfield|cm:${a.id}|f:${a.filter}|w:${a.width}|${Lt(o)}`,sample:s=>a.sampleCPU(s)}}if(n instanceof Oe||n.nodelink instanceof Oe){let o=n instanceof Oe?n:n.nodelink,a=n instanceof Oe?"node":n.component??"node",s=fe(a==="edge"?o.edgeScaleTransform:o.nodeScaleTransform),l=a==="edge"?o.edgeColormap:o.nodeColormap,u=a==="edge"?o.edgeColormapStops:o.nodeColormapStops;if(typeof l=="string"&&l==="custom")return{transform:s,signature:`nodelink|${a}|custom|${Lt(s)}|${JSON.stringify(u)}`,sample:m=>Ai(m,u)};let c=a==="edge"?o.getEdgeColormapForBinding():o.getNodeColormapForBinding();if(e&&!c.canSampleCPU)throw new Error("LegendLayer: bound nodelink colormap is GPU-only and cannot be sampled on CPU in strict parity mode.");return{transform:s,signature:`nodelink|${a}|cm:${c.id}|f:${c.filter}|w:${c.width}|${Lt(s)}`,sample:m=>c.sampleCPU(m)}}if(n instanceof He){let o=fe(n.scaleTransform),a=n.getColormapForBinding();if(e&&!a.canSampleCPU)throw new Error("LegendLayer: bound data-material colormap is GPU-only and cannot be sampled on CPU in strict parity mode.");return{transform:o,signature:`datamaterial|cm:${a.id}|f:${a.filter}|w:${a.width}|${Lt(o)}`,sample:s=>a.sampleCPU(s)}}let t=n,r=fe(t.scaleTransform);if(t.colormapStops&&t.colormapStops.length>=2){let o=t.colormapStops.slice();return{transform:r,signature:`explicit|stops|${Lt(r)}|${JSON.stringify(o)}`,sample:a=>Ai(a,o)}}let i=typeof t.colormap=="string"?$.builtin(t.colormap):t.colormap;if(e&&!i.canSampleCPU)throw new Error("LegendLayer: explicit colormap is GPU-only and cannot be sampled on CPU in strict parity mode.");return{transform:r,signature:`explicit|cm:${i.id}|f:${i.filter}|w:${i.width}|${Lt(r)}`,sample:o=>i.sampleCPU(o)}},Dr=class{id;source;strictParity;widthPx;heightPx;tickCount;font;formatValue;title;anchor;_system=null;unsubscribeSource=null;sourceDirty=!0;lastSignature=null;container=null;titleEl=null;gradientCanvas=null;gradientCtx=null;messageEl=null;tickMarkPool=null;tickLabelPool=null;constructor(e){this.id=e.id??"overlay-legend",this.source=e.source,this.strictParity=e.strictParity??!0,this.widthPx=Math.max(8,Math.round(e.widthPx??26)),this.heightPx=Math.max(32,Math.round(e.heightPx??240)),this.tickCount=Math.max(2,Math.round(e.tickCount??7)),this.font=e.font??"11px monospace",this.formatValue=e.formatValue??id,this.title=e.title??"Legend",this.anchor=e.anchor??{kind:"screen",corner:"top-right",offsetPx:[-16,16]},this.bindSource(this.source)}setSystem(e){this._system=e}setSource(e){this.source=e,this.bindSource(e),this.sourceDirty=!0,this._system?.invalidate("scale")}attach(e){let t=document.createElement("div");t.style.position="absolute",t.style.pointerEvents="none",t.style.padding="8px",t.style.border="1px solid rgba(190, 215, 255, 0.35)",t.style.background="rgba(7, 13, 24, 0.78)",t.style.borderRadius="6px",t.style.color="#e3eeff",t.style.font=this.font,e.appendChild(t),this.container=t;let r=document.createElement("div");r.textContent=this.title,r.style.marginBottom="6px",r.style.font=this.font,t.appendChild(r),this.titleEl=r;let i=document.createElement("div");i.style.position="relative",i.style.width=`${this.widthPx+64}px`,i.style.height=`${this.heightPx}px`,t.appendChild(i);let o=document.createElement("canvas");o.width=this.widthPx,o.height=this.heightPx,o.style.position="absolute",o.style.left="0",o.style.top="0",o.style.width=`${this.widthPx}px`,o.style.height=`${this.heightPx}px`,o.style.border="1px solid rgba(180, 210, 255, 0.35)",o.style.borderRadius="2px",i.appendChild(o),this.gradientCanvas=o,this.gradientCtx=o.getContext("2d");let a=document.createElement("div");a.style.position="absolute",a.style.left="0",a.style.top=`${this.heightPx+6}px`,a.style.color="rgba(255, 191, 191, 0.95)",a.style.maxWidth=`${this.widthPx+64}px`,i.appendChild(a),this.messageEl=a,this.tickMarkPool=new Ct(i,()=>{let s=document.createElement("div");return s.style.position="absolute",s},this.tickCount),this.tickLabelPool=new Ct(i,()=>{let s=document.createElement("div");return s.style.position="absolute",s.style.font=this.font,s.style.color="#e3eeff",s},this.tickCount)}detach(){this.unsubscribeSource?.(),this.unsubscribeSource=null,this.tickMarkPool?.clear(!0),this.tickLabelPool?.clear(!0),this.tickMarkPool=null,this.tickLabelPool=null,this.container?.remove(),this.container=null,this.titleEl=null,this.gradientCanvas=null,this.gradientCtx=null,this.messageEl=null}update(e){!this.container||(this.positionContainer(e),!(e.reasons.has("scale")||e.reasons.has("colormap")||e.reasons.has("manual")||e.reasons.has("viewport")||e.reasons.has("layout"))&&!this.sourceDirty)||(this.sourceDirty=!1,this.renderLegend())}positionContainer(e){if(!this.container)return;let[t,r]=Gr(this.anchor,e.width,e.height),i=this.anchor?.corner??"top-right",o=this.heightPx+32,a=this.widthPx+80,s=t,l=r;this.anchor?.x===void 0&&i.includes("right")&&(s-=a),this.anchor?.y===void 0&&i.includes("bottom")&&(l-=o),this.container.style.left=`${s}px`,this.container.style.top=`${l}px`}bindSource(e){this.unsubscribeSource?.(),this.unsubscribeSource=ad(e,()=>{this.sourceDirty=!0,this._system?.invalidate("scale")})}renderLegend(){if(!(!this.gradientCanvas||!this.gradientCtx||!this.tickMarkPool||!this.tickLabelPool))try{let e=sd(this.source,this.strictParity);e.signature!==this.lastSignature&&(this.lastSignature=e.signature,this.renderGradient(e),this.renderTicks(e)),this.messageEl&&(this.messageEl.textContent="")}catch(e){this.messageEl&&(this.messageEl.textContent=`${e instanceof Error?e.message:String(e)}`)}}renderGradient(e){if(!this.gradientCtx||!this.gradientCanvas)return;let t=this.gradientCanvas.width,r=this.gradientCanvas.height,i=this.gradientCtx.createImageData(t,r);for(let o=0;o<r;o++){let a=1-o/Math.max(1,r-1),s=e.sample(a),l=Math.max(0,Math.min(255,Math.round(s[0]*255))),u=Math.max(0,Math.min(255,Math.round(s[1]*255))),c=Math.max(0,Math.min(255,Math.round(s[2]*255))),m=Math.max(0,Math.min(255,Math.round(s[3]*255)));for(let d=0;d<t;d++){let f=(o*t+d)*4;i.data[f+0]=l,i.data[f+1]=u,i.data[f+2]=c,i.data[f+3]=m}}this.gradientCtx.putImageData(i,0,0)}renderTicks(e){if(!this.tickMarkPool||!this.tickLabelPool||!this.gradientCanvas)return;this.tickMarkPool.beginFrame(),this.tickLabelPool.beginFrame();let t=this.gradientCanvas.height;for(let r=0;r<this.tickCount;r++){let i=r/Math.max(1,this.tickCount-1),o=i*t,a=1-i,s=ei(le(a),e.transform),l=this.tickMarkPool.acquire();l.style.left=`${this.widthPx+4}px`,l.style.top=`${o}px`,l.style.width="8px",l.style.height="1px",l.style.background="#dce9ff";let u=this.tickLabelPool.acquire();u.style.left=`${this.widthPx+16}px`,u.style.top=`${o-6}px`,u.textContent=this.formatValue(s)}this.tickMarkPool.endFrame(),this.tickLabelPool.endFrame()}};var Rt={Idle:"idle",Marker:"marker",Distance:"distance",Angle:"angle"},ul={Marker:"marker",Distance:"distance",Angle:"angle"},Mn={Degrees:"deg",Radians:"rad"},zt=n=>[n[0],n[1],n[2],n[3]],Ln=n=>[n[0]??0,n[1]??0,n[2]??0],No=n=>n?{scalar:n.scalar??null,vector:n.vector?[n.vector[0],n.vector[1],n.vector[2],n.vector[3]]:null,packedPoint:n.packedPoint?[n.packedPoint[0],n.packedPoint[1],n.packedPoint[2],n.packedPoint[3]]:null,component:n.component??null,componentIndex:n.componentIndex??null,color:n.color?[n.color[0],n.color[1],n.color[2],n.color[3]]:null,edgeEndpoints:n.edgeEndpoints?[n.edgeEndpoints[0],n.edgeEndpoints[1]]:null,edgePositions:n.edgePositions?[n.edgePositions[0],n.edgePositions[1],n.edgePositions[2],n.edgePositions[3],n.edgePositions[4],n.edgePositions[5]]:null}:null,cl=n=>n?{kind:n.kind,objectId:n.objectId,elementIndex:n.elementIndex,ndIndex:n.ndIndex?n.ndIndex.slice():null,attributes:No(n.attributes)}:null,ye=n=>({position:Ln(n.position),pick:cl(n.pick)}),Nr=n=>({position:Ln(n.worldPosition),pick:{kind:n.kind,objectId:n.objectId,elementIndex:n.elementIndex,ndIndex:n.ndIndex?n.ndIndex.slice():null,attributes:No(n.attributes)}}),zr=n=>{let e=Math.max(0,Math.min(255,Math.round(n[0]*255))),t=Math.max(0,Math.min(255,Math.round(n[1]*255))),r=Math.max(0,Math.min(255,Math.round(n[2]*255))),i=Math.max(0,Math.min(1,n[3]));return`rgba(${e}, ${t}, ${r}, ${i})`};var Ot=[{exponent:-12,symbol:"p",factor:1e-12},{exponent:-9,symbol:"n",factor:1e-9},{exponent:-6,symbol:"u",factor:1e-6},{exponent:-3,symbol:"m",factor:.001},{exponent:0,symbol:"",factor:1},{exponent:3,symbol:"k",factor:1e3},{exponent:6,symbol:"M",factor:1e6},{exponent:9,symbol:"G",factor:1e9},{exponent:12,symbol:"T",factor:1e12}],ld=n=>n.includes(".")?n.replace(/(\.\d*?[1-9])0+$/g,"$1").replace(/\.0+$/g,""):n,ue=(n,e)=>{if(!Number.isFinite(n))return"nan";let t=Math.abs(n),r=Kr(e,0,12);return t>=1e7||t>0&&t<1e-5?n.toExponential(Math.max(1,Math.min(6,r))):ld(n.toFixed(r))},Or=(n={})=>{let e=Number.isFinite(n.worldUnitsPerUnit)&&n.worldUnitsPerUnit>0?n.worldUnitsPerUnit:1,t=typeof n.symbol=="string"?n.symbol:"wu",r=Kr(n.decimals??3,0,12),i=!!n.autoMetric,o=n.angleUnit??Mn.Degrees,a=Kr(n.angleDecimals??2,0,12);return{worldUnitsPerUnit:e,symbol:t,decimals:r,autoMetric:i,angleUnit:o,angleDecimals:a}},ud=n=>{let e=Math.abs(n);if(!Number.isFinite(e)||e<=0)return Ot[4];let t=Kr(Math.floor(Math.log10(e)/3)*3,Ot[0].exponent,Ot[Ot.length-1].exponent);for(let r=0;r<Ot.length;r++)if(Ot[r].exponent===t)return Ot[r];return Ot[4]},Fi=(n,e={})=>{let t=Or(e);if(!Number.isFinite(n))return{worldDistance:n,value:Number.NaN,unitSymbol:t.symbol,text:`nan ${t.symbol}`};let r=n/t.worldUnitsPerUnit;if(!t.autoMetric){let l=`${ue(r,t.decimals)} ${t.symbol}`.trim();return{worldDistance:n,value:r,unitSymbol:t.symbol,text:l}}let i=ud(r),o=r/i.factor,a=`${i.symbol}${t.symbol}`,s=`${ue(o,t.decimals)} ${a}`.trim();return{worldDistance:n,value:o,unitSymbol:a,text:s}},Ii=(n,e={})=>{let t=Or(e);if(!Number.isFinite(n))return{radians:n,value:Number.NaN,unitSymbol:t.angleUnit,text:`nan ${t.angleUnit}`};if(t.angleUnit===Mn.Radians){let o=`${ue(n,t.angleDecimals)} rad`;return{radians:n,value:n,unitSymbol:"rad",text:o}}let r=n*(180/Math.PI),i=`${ue(r,t.angleDecimals)} deg`;return{radians:n,value:r,unitSymbol:"deg",text:i}},Di=(n,e=5)=>n?`[${ue(n[0]??Number.NaN,e)}, ${ue(n[1]??Number.NaN,e)}, ${ue(n[2]??Number.NaN,e)}]`:"null";var cd=n=>!n||n.length===0?"null":`[${n.join(", ")}]`,md=n=>{if(!n)return["attributes: null"];let e=[];return n.scalar!==void 0&&n.scalar!==null&&e.push(`scalar: ${ue(n.scalar,6)}`),n.vector&&e.push(`vector: [${ue(n.vector[0],4)}, ${ue(n.vector[1],4)}, ${ue(n.vector[2],4)}, ${ue(n.vector[3],4)}]`),n.packedPoint&&e.push(`packedPoint: [${ue(n.packedPoint[0],4)}, ${ue(n.packedPoint[1],4)}, ${ue(n.packedPoint[2],4)}, ${ue(n.packedPoint[3],4)}]`),n.component&&e.push(`component: ${n.component}`),n.componentIndex!==void 0&&n.componentIndex!==null&&e.push(`componentIndex: ${n.componentIndex}`),n.color&&e.push(`color: [${ue(n.color[0],4)}, ${ue(n.color[1],4)}, ${ue(n.color[2],4)}, ${ue(n.color[3],4)}]`),n.edgeEndpoints&&e.push(`edgeEndpoints: [${n.edgeEndpoints[0]}, ${n.edgeEndpoints[1]}]`),n.edgePositions&&e.push(`edgePositions: [${ue(n.edgePositions[0],4)}, ${ue(n.edgePositions[1],4)}, ${ue(n.edgePositions[2],4)}, ${ue(n.edgePositions[3],4)}, ${ue(n.edgePositions[4],4)}, ${ue(n.edgePositions[5],4)}]`),e.length===0&&e.push("attributes: {}"),e},ml=n=>n?{...n,vector:n.vector?[...n.vector]:null,packedPoint:n.packedPoint?[...n.packedPoint]:null,color:n.color?[...n.color]:null,edgeEndpoints:n.edgeEndpoints?[...n.edgeEndpoints]:null,edgePositions:n.edgePositions?[...n.edgePositions]:null}:null,dl=(n,e)=>!e||!e.hit?`${n}: miss`:[`${n}: hit`,`kind: ${e.kind}`,`objectId: ${e.objectId}`,`elementIndex: ${e.elementIndex}`,`world: ${Di(e.worldPosition,5)}`,`ndIndex: ${cd(e.ndIndex)}`,...md(e.attributes)].join(`
|
|
23
|
+
`),dd=(n,e)=>{if(!e||!e.hit)return`${n}: miss`;let t=dl(n,e).split(`
|
|
14
24
|
`);return e.annotationId&&t.push(`annotationId: ${e.annotationId}`),e.annotationKind&&t.push(`annotationKind: ${e.annotationKind}`),e.anchorRole&&t.push(`anchorRole: ${e.anchorRole}`),t.join(`
|
|
15
|
-
`)},ir=class{id;maxLabels;font;labelOffsetPx;readoutAnchor;readoutWidthPx;container=null;labelPool=null;hoverReadoutEl=null;selectionReadoutEl=null;_system=null;entries=[];entriesRevision=-1;entriesDirty=!0;hoverReadout=null;selectionReadout=null;readoutDirty=!0;hoverTextCache="";selectionTextCache="";constructor(e={}){this.id=e.id??"annotation-label-layer",this.maxLabels=Math.max(1,Math.round(e.maxLabels??256)),this.font=e.font??"11px monospace",this.labelOffsetPx=e.labelOffsetPx??[8,-8],this.readoutAnchor=e.readoutAnchor??{kind:"screen",corner:"top-left",offsetPx:[12,12]},this.readoutWidthPx=Math.max(180,Math.round(e.readoutWidthPx??330))}get pooledNodeCount(){return this.labelPool?.size??0}setSystem(e){this._system=e}attach(e){let t=document.createElement("div");t.style.position="absolute",t.style.inset="0",t.style.pointerEvents="none",e.appendChild(t),this.container=t,this.labelPool=new $e(t,()=>{let r=document.createElement("div");return r.style.position="absolute",r.style.whiteSpace="nowrap",r.style.font=this.font,r.style.textShadow="0 1px 1px rgba(0, 0, 0, 0.8)",r.style.willChange="transform,left,top",r},this.maxLabels),this.hoverReadoutEl=document.createElement("div"),this.selectionReadoutEl=document.createElement("div");for(let r of[this.hoverReadoutEl,this.selectionReadoutEl])r.style.position="absolute",r.style.pointerEvents="none",r.style.whiteSpace="pre-line",r.style.font=this.font,r.style.color="#dce9ff",r.style.padding="6px 7px",r.style.border="1px solid rgba(180, 210, 255, 0.28)",r.style.background="rgba(5, 11, 20, 0.72)",r.style.borderRadius="4px",r.style.minWidth=`${Math.floor(this.readoutWidthPx*.5)}px`,r.style.maxWidth=`${this.readoutWidthPx}px`,t.appendChild(r);this.entriesDirty=!0,this.readoutDirty=!0}detach(){this.labelPool?.clear(!0),this.labelPool=null,this.hoverReadoutEl=null,this.selectionReadoutEl=null,this.container?.remove(),this.container=null,this.hoverTextCache="",this.selectionTextCache=""}setEntries(e,t){this.entries=new Array(Math.min(this.maxLabels,e.length));for(let r=0;r<this.entries.length;r++){let i=e[r];this.entries[r]={key:i.key,text:i.text,color:i.color,position:[i.position[0],i.position[1],i.position[2]]}}t!==this.entriesRevision&&(this.entriesRevision=t,this.entriesDirty=!0),this._system?.invalidate("manual")}setHoverReadout(e){this.hoverReadout=e?{...e,worldPosition:e.worldPosition?[e.worldPosition[0],e.worldPosition[1],e.worldPosition[2]]:null,ndIndex:e.ndIndex?e.ndIndex.slice():null,attributes:e.attributes?{...e.attributes,vector:e.attributes.vector?[...e.attributes.vector]:null,packedPoint:e.attributes.packedPoint?[...e.attributes.packedPoint]:null}:null}:null,this.readoutDirty=!0,this._system?.invalidate("manual")}setSelectionReadout(e){this.selectionReadout=e?{...e,worldPosition:e.worldPosition?[e.worldPosition[0],e.worldPosition[1],e.worldPosition[2]]:null,ndIndex:e.ndIndex?e.ndIndex.slice():null,attributes:e.attributes?{...e.attributes,vector:e.attributes.vector?[...e.attributes.vector]:null,packedPoint:e.attributes.packedPoint?[...e.attributes.packedPoint]:null}:null}:null,this.readoutDirty=!0,this._system?.invalidate("manual")}update(e){if(!this.container||!this.labelPool)return;(e.reasons.has("camera")||e.reasons.has("viewport")||e.reasons.has("layout")||e.reasons.has("manual")||e.reasons.has("interaction")||this.entriesDirty)&&this.renderLabels(e),(this.readoutDirty||e.reasons.has("viewport")||e.reasons.has("layout")||e.reasons.has("manual"))&&this.renderReadouts(e)}renderLabels(e){if(this.labelPool){this.labelPool.beginFrame();for(let t=0;t<this.entries.length;t++){let r=this.entries[t],i=Fe(e.camera,e.width,e.height,r.position);if(!i||!i.visible)continue;let o=this.labelPool.acquire();(this.entriesDirty||o.dataset.annotationKey!==r.key)&&(o.dataset.annotationKey=r.key,o.style.color=r.color,o.textContent=r.text),o.style.left=`${i.x+this.labelOffsetPx[0]}px`,o.style.top=`${i.y+this.labelOffsetPx[1]}px`}this.labelPool.endFrame(),this.entriesDirty=!1}}renderReadouts(e){if(!this.hoverReadoutEl||!this.selectionReadoutEl)return;let[t,r]=Yt(this.readoutAnchor,e.width,e.height);this.hoverReadoutEl.style.left=`${t}px`,this.hoverReadoutEl.style.top=`${r}px`,this.selectionReadoutEl.style.left=`${t}px`,this.selectionReadoutEl.style.top=`${r+122}px`;let i=oa("Hover",this.hoverReadout),o=au("Selection",this.selectionReadout);i!==this.hoverTextCache&&(this.hoverTextCache=i,this.hoverReadoutEl.textContent=i),o!==this.selectionTextCache&&(this.selectionTextCache=o,this.selectionReadoutEl.textContent=o),this.readoutDirty=!1}};var su=n=>{if(Array.isArray(n))return[Math.max(1e-6,n[0]??1),Math.max(1e-6,n[1]??1),Math.max(1e-6,n[2]??1)];let e=Math.max(1e-6,n??.16);return[e,e,e]},or=(n,e,t,r,i,o)=>{n.push({key:`${e}:${r}`,annotationId:e,annotationKind:t,role:r,anchor:re(i),color:ot(o)})},aa=n=>{let e=[];for(let t=0;t<n.length;t++){let r=n[t];if(r.visible){if(r.kind==="marker"){or(e,r.id,r.kind,"marker",r.anchor,r.color);continue}if(r.kind==="distance"){or(e,r.id,r.kind,"start",r.start,r.color),or(e,r.id,r.kind,"end",r.end,r.color);continue}or(e,r.id,r.kind,"a",r.a,r.color),or(e,r.id,r.kind,"b",r.b,r.color),or(e,r.id,r.kind,"c",r.c,r.color)}}return e},ar=class{glyphField;maxInstances;markerScale;keepCPUData;ownsGlyphField;attachedScene=null;appliedRevision=-1;updateCount=0;instances=[];constructor(e={}){this.markerScale=su(e.markerScale),this.maxInstances=Math.max(1,Math.round(e.maxInstances??4096)),this.keepCPUData=e.keepCPUData??!0,this.ownsGlyphField=!e.glyphField,this.glyphField=e.glyphField??new Re({shape:e.shape??"ellipsoid",instanceCount:0,colorMode:"rgba",lit:!1,depthWrite:!0,depthTest:!0,keepCPUData:this.keepCPUData,name:e.name??"annotation-markers",scaleTransform:{componentCount:4,componentIndex:0,valueMode:"component",stride:4,offset:0,mode:"linear",clampMode:"none"}})}get revision(){return this.appliedRevision}get syncCount(){return this.updateCount}get instanceCount(){return this.instances.length}attach(e){return this.attachedScene===e?this:(this.detach(),e.add(this.glyphField),this.attachedScene=e,this)}detach(){return this.attachedScene&&this.attachedScene.remove(this.glyphField),this.attachedScene=null,this}destroy(){this.detach(),this.ownsGlyphField&&this.glyphField.destroy(),this.instances=[],this.appliedRevision=-1}getInstance(e){if(!Number.isInteger(e)||e<0||e>=this.instances.length)return null;let t=this.instances[e];return{key:t.key,annotationId:t.annotationId,annotationKind:t.annotationKind,role:t.role,anchor:re(t.anchor),color:ot(t.color)}}sync(e,t){if(P(Number.isFinite(t),"AnnotationMarkerRenderer.sync: revision must be finite."),t===this.appliedRevision)return!1;let r=aa(e),i=r.length>this.maxInstances?r.slice(0,this.maxInstances):r;this.instances=i;let o=i.length;if(o<=0)return this.glyphField.setCPUData(null,null,null,null,{instanceCount:0,keepCPUData:this.keepCPUData}),this.glyphField.visible=!1,this.appliedRevision=t,this.updateCount++,!0;let a=new Float32Array(o*4),s=new Float32Array(o*4),l=new Float32Array(o*4),u=new Float32Array(o*4);for(let m=0;m<o;m++){let c=m*4,d=i[m];a[c+0]=d.anchor.position[0],a[c+1]=d.anchor.position[1],a[c+2]=d.anchor.position[2],a[c+3]=0,s[c+0]=0,s[c+1]=0,s[c+2]=0,s[c+3]=1,l[c+0]=this.markerScale[0],l[c+1]=this.markerScale[1],l[c+2]=this.markerScale[2],l[c+3]=0,u[c+0]=d.color[0],u[c+1]=d.color[1],u[c+2]=d.color[2],u[c+3]=d.color[3]}return this.glyphField.visible=!0,this.glyphField.setCPUData(a,s,l,u,{keepCPUData:this.keepCPUData}),this.appliedRevision=t,this.updateCount++,!0}};var lu={marker:[.9,.8,.2,1],distance:[.2,.8,1,1],angle:[1,.5,.2,1]},uu=()=>typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now(),Nr=(n,e,t)=>n<e?e:n>t?t:n,sa=(n,e)=>[(n[0]??0)-(e[0]??0),(n[1]??0)-(e[1]??0),(n[2]??0)-(e[2]??0)],cu=(n,e)=>(n[0]??0)*(e[0]??0)+(n[1]??0)*(e[1]??0)+(n[2]??0)*(e[2]??0),la=n=>Math.hypot(n[0]??0,n[1]??0,n[2]??0),st=n=>n.kind==="marker"?{...n,color:ot(n.color),anchor:re(n.anchor)}:n.kind==="distance"?{...n,color:ot(n.color),start:re(n.start),end:re(n.end)}:{...n,color:ot(n.color),a:re(n.a),b:re(n.b),c:re(n.c)},An=(n,e)=>{let t=n??lu[e];return[Nr(t[0],0,1),Nr(t[1],0,1),Nr(t[2],0,1),Nr(t[3],0,1)]},Un=n=>{if(n==null)return null;let e=`${n}`.trim();return e.length>0?e:null},wi=n=>n===void 0?!0:!!n,kn=(n,e)=>{let t=(n[0]??0)-(e[0]??0),r=(n[1]??0)-(e[1]??0),i=(n[2]??0)-(e[2]??0);return Math.hypot(t,r,i)},Gn=(n,e,t)=>{let r=sa(n,e),i=sa(t,e),o=la(r),a=la(i);if(o<=1e-12||a<=1e-12)return 0;let s=Nr(cu(r,i)/(o*a),-1,1);return Math.acos(s)},ua=(n,e=null)=>({position:Wr(n),pick:e?{...e,ndIndex:e.ndIndex?e.ndIndex.slice():null,attributes:e.attributes?{...e.attributes,vector:e.attributes.vector?[...e.attributes.vector]:null,packedPoint:e.attributes.packedPoint?[...e.attributes.packedPoint]:null}:null}:null}),sr=class{records=new Map;order=[];listeners=new Set;nowMs;idPrefix;idCounter=1;_revision=0;constructor(e={}){this.nowMs=e.nowMs??uu,this.idPrefix=`${e.idPrefix??"ann"}`.trim()}get size(){return this.order.length}get revision(){return this._revision}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}has(e){return this.records.has(e)}ids(){return this.order.slice()}get(e){let t=this.records.get(e);return t?st(t):null}values(){let e=new Array(this.order.length);for(let t=0;t<this.order.length;t++)e[t]=st(this.records.get(this.order[t]));return e}clear(){return this.records.size===0?this:(this.records.clear(),this.order.length=0,this.bumpRevision(),this)}createMarker(e,t={}){let r=this.nowMs(),i={id:this.nextId("marker"),kind:"marker",label:Un(t.label),visible:wi(t.visible),color:An(t.color,"marker"),createdAtMs:r,updatedAtMs:r,anchor:re(e)};return this.push(i),st(i)}createDistance(e,t,r={}){let i=this.nowMs(),o=re(e),a=re(t),s={id:this.nextId("distance"),kind:"distance",label:Un(r.label),visible:wi(r.visible),color:An(r.color,"distance"),createdAtMs:i,updatedAtMs:i,start:o,end:a,distanceWorld:kn(o.position,a.position)};return this.push(s),st(s)}createAngle(e,t,r,i={}){let o=this.nowMs(),a=re(e),s=re(t),l=re(r),u={id:this.nextId("angle"),kind:"angle",label:Un(i.label),visible:wi(i.visible),color:An(i.color,"angle"),createdAtMs:o,updatedAtMs:o,a,b:s,c:l,angleRadians:Gn(a.position,s.position,l.position)};return this.push(u),st(u)}updateMarker(e,t){let r=this.records.get(e);return!r||r.kind!=="marker"?null:(this.applyCommonPatch(r,t),t.anchor&&(r.anchor=re(t.anchor)),r.updatedAtMs=this.nowMs(),this.bumpRevision(),st(r))}updateDistance(e,t){let r=this.records.get(e);return!r||r.kind!=="distance"?null:(this.applyCommonPatch(r,t),t.start&&(r.start=re(t.start)),t.end&&(r.end=re(t.end)),r.distanceWorld=kn(r.start.position,r.end.position),r.updatedAtMs=this.nowMs(),this.bumpRevision(),st(r))}updateAngle(e,t){let r=this.records.get(e);return!r||r.kind!=="angle"?null:(this.applyCommonPatch(r,t),t.a&&(r.a=re(t.a)),t.b&&(r.b=re(t.b)),t.c&&(r.c=re(t.c)),r.angleRadians=Gn(r.a.position,r.b.position,r.c.position),r.updatedAtMs=this.nowMs(),this.bumpRevision(),st(r))}remove(e){if(!this.records.delete(e))return!1;let r=this.order.indexOf(e);return r!==-1&&this.order.splice(r,1),this.bumpRevision(),!0}push(e){P(!this.records.has(e.id),`AnnotationStore: duplicate id '${e.id}'.`),this.records.set(e.id,e),this.order.push(e.id),this.bumpRevision()}applyCommonPatch(e,t){t.label!==void 0&&(e.label=Un(t.label)),t.color!==void 0&&(e.color=An(t.color,e.kind)),t.visible!==void 0&&(e.visible=!!t.visible)}nextId(e){let t=String(this.idCounter++).padStart(6,"0");return`${this.idPrefix.length>0?`${this.idPrefix}-`:""}${e}-${t}`}bumpRevision(){this._revision++;for(let e of this.listeners)try{e(this._revision)}catch{}}};var mu=1,du=(n,e)=>[(n[0]+e[0])*.5,(n[1]+e[1])*.5,(n[2]+e[2])*.5],Vr=n=>n?{hit:!0,kind:n.kind,objectId:n.objectId,elementIndex:n.elementIndex,worldPosition:[n.worldPosition[0],n.worldPosition[1],n.worldPosition[2]],ndIndex:n.ndIndex?n.ndIndex.slice():null,attributes:n.attributes?{...n.attributes,vector:n.attributes.vector?[...n.attributes.vector]:null,packedPoint:n.attributes.packedPoint?[...n.attributes.packedPoint]:null}:null}:{hit:!1,kind:null,objectId:null,elementIndex:null,worldPosition:null,ndIndex:null,attributes:null},Si=(n,e)=>({...Vr(n),annotationId:e.annotationId,annotationKind:e.annotationKind,anchorRole:e.anchorRole}),pu=n=>{let e=new Array(n.length);for(let t=0;t<n.length;t++){let r=n[t];e[t]={position:[r.position[0],r.position[1],r.position[2]],pick:r.pick?{kind:r.pick.kind,objectId:r.pick.objectId,elementIndex:r.pick.elementIndex,ndIndex:r.pick.ndIndex?r.pick.ndIndex.slice():null,attributes:r.pick.attributes?{...r.pick.attributes,vector:r.pick.attributes.vector?[...r.pick.attributes.vector]:null,packedPoint:r.pick.attributes.packedPoint?[...r.pick.attributes.packedPoint]:null}:null}:null}}return e},fu=(n,e)=>{let t=[];for(let r=0;r<n.length;r++){let i=n[r];if(!i.visible)continue;if(i.kind==="marker"){t.push({key:i.id,text:i.label??i.id,color:rr(i.color),position:[i.anchor.position[0],i.anchor.position[1],i.anchor.position[2]]});continue}if(i.kind==="distance"){let s=_n(i.distanceWorld,e),l=i.label?`${i.label}: ${s.text}`:s.text;t.push({key:i.id,text:l,color:rr(i.color),position:du(i.start.position,i.end.position)});continue}let o=Bn(i.angleRadians,e),a=i.label?`${i.label}: ${o.text}`:o.text;t.push({key:i.id,text:a,color:rr(i.color),position:[i.b.position[0],i.b.position[1],i.b.position[2]]})}return t},lr=class{store;markerRenderer;labelLayer;runtime;annotationsListeners=new Set;modeListeners=new Set;hoverListeners=new Set;selectionListeners=new Set;stagingListeners=new Set;autoCreateOverlay;overlaySystemOptions;modeValue=Ze.Idle;unitsValue;scene=null;camera=null;controls=null;overlaySystem=null;ownsOverlaySystem=!1;canvas=null;pointerTarget=null;hoverReadout=Vr(null);selectionReadout=Si(null,{annotationId:null,annotationKind:null,anchorRole:null});pendingAnchors=[];boundPointerEvents=!1;autoBindPointerEvents;hoverPickToken=0;clickPickToken=0;constructor(e,t={}){this.runtime=e;let r=mu++;this.store=new sr({idPrefix:t.storeIdPrefix??`ann${r}`}),this.markerRenderer=new ar({...t.markerRenderer,name:t.markerRenderer?.name??`annotation-markers-${r}`}),this.labelLayer=new ir({...t.labelLayer,id:t.labelLayer?.id??`annotation-label-layer-${r}`}),this.autoBindPointerEvents=t.autoBindPointerEvents??!0,this.autoCreateOverlay=t.autoCreateOverlay??!0,this.overlaySystemOptions=t.overlaySystemOptions??{},this.unitsValue=t.units??{},this.controls=t.controls??null,this.canvas=t.canvas??null,this.pointerTarget=t.pointerTarget??this.canvas,t.overlaySystem&&(this.overlaySystem=t.overlaySystem,this.ownsOverlaySystem=!1),this.store.onChange(()=>this.handleStoreChanged()),this.labelLayer.setHoverReadout(this.hoverReadout),this.labelLayer.setSelectionReadout(this.selectionReadout),t.scene&&t.camera&&this.attach({scene:t.scene,camera:t.camera,controls:this.controls,overlaySystem:this.overlaySystem,pointerTarget:this.pointerTarget})}get mode(){return this.modeValue}get units(){return nr(this.unitsValue)}get revision(){return this.store.revision}get pendingCount(){return this.pendingAnchors.length}get hoverProbe(){return{...this.hoverReadout,worldPosition:this.hoverReadout.worldPosition?[this.hoverReadout.worldPosition[0],this.hoverReadout.worldPosition[1],this.hoverReadout.worldPosition[2]]:null,ndIndex:this.hoverReadout.ndIndex?this.hoverReadout.ndIndex.slice():null,attributes:this.hoverReadout.attributes?{...this.hoverReadout.attributes,vector:this.hoverReadout.attributes.vector?[...this.hoverReadout.attributes.vector]:null,packedPoint:this.hoverReadout.attributes.packedPoint?[...this.hoverReadout.attributes.packedPoint]:null}:null}}get selectionProbe(){return{...this.selectionReadout,worldPosition:this.selectionReadout.worldPosition?[this.selectionReadout.worldPosition[0],this.selectionReadout.worldPosition[1],this.selectionReadout.worldPosition[2]]:null,ndIndex:this.selectionReadout.ndIndex?this.selectionReadout.ndIndex.slice():null,attributes:this.selectionReadout.attributes?{...this.selectionReadout.attributes,vector:this.selectionReadout.attributes.vector?[...this.selectionReadout.attributes.vector]:null,packedPoint:this.selectionReadout.attributes.packedPoint?[...this.selectionReadout.attributes.packedPoint]:null}:null}}onAnnotationsChange(e){return this.annotationsListeners.add(e),()=>this.annotationsListeners.delete(e)}onModeChange(e){return this.modeListeners.add(e),()=>this.modeListeners.delete(e)}onHoverReadout(e){return this.hoverListeners.add(e),()=>this.hoverListeners.delete(e)}onSelectionReadout(e){return this.selectionListeners.add(e),()=>this.selectionListeners.delete(e)}onStagingChange(e){return this.stagingListeners.add(e),()=>this.stagingListeners.delete(e)}setUnits(e){return this.unitsValue=e,this.handleStoreChanged(),this}setMode(e){if(e===this.modeValue)return this;this.modeValue=e,this.clearPending();for(let t of this.modeListeners)try{t(this.modeValue)}catch{}return this}cancel(){this.modeValue=Ze.Idle,this.clearPending();for(let e of this.modeListeners)try{e(this.modeValue)}catch{}return this}attach(e){return this.scene=e.scene,this.camera=e.camera,e.controls!==void 0&&(this.controls=e.controls??null),e.pointerTarget!==void 0&&(this.pointerTarget=e.pointerTarget??this.pointerTarget),e.overlaySystem!==void 0&&(this.detachOverlayLayer(),this.overlaySystem=e.overlaySystem??null,this.ownsOverlaySystem=!1),this.markerRenderer.attach(this.scene),this.ensureOverlaySystem(),this.ensureOverlayLayer(),this.overlaySystem?.setView(this.camera,this.scene),this.handleStoreChanged(),this.autoBindPointerEvents&&this.bindPointerEvents(),this}setView(e,t=this.scene){return this.camera=e,t&&(this.scene=t),this.scene&&this.markerRenderer.attach(this.scene),this.overlaySystem?.setView(this.camera,this.scene),this.overlaySystem?.invalidate("camera"),this}detach(){return this.unbindPointerEvents(),this.detachOverlayLayer(),this.ownsOverlaySystem&&this.overlaySystem?.destroy(),this.overlaySystem=null,this.ownsOverlaySystem=!1,this.markerRenderer.detach(),this.scene=null,this.camera=null,this.clearPending(),this.hoverPickToken++,this.clickPickToken++,this.setHoverReadout(Vr(null)),this.setSelectionReadout(Si(null,{annotationId:null,annotationKind:null,anchorRole:null})),this}destroy(){this.detach(),this.markerRenderer.destroy()}bindPointerTarget(e){return this.unbindPointerEvents(),this.pointerTarget=e,this.autoBindPointerEvents&&this.bindPointerEvents(),this}setAutoBindPointerEvents(e){return this.autoBindPointerEvents=!!e,this.autoBindPointerEvents?this.bindPointerEvents():this.unbindPointerEvents(),this}getAnnotations(){return this.store.values()}createMarker(e,t={}){return this.store.createMarker(e,t)}createDistance(e,t,r={}){return this.store.createDistance(e,t,r)}createAngle(e,t,r,i={}){return this.store.createAngle(e,t,r,i)}updateAnnotation(e,t){let r=this.store.get(e);return r?r.kind==="marker"?this.store.updateMarker(e,t):r.kind==="distance"?this.store.updateDistance(e,t):this.store.updateAngle(e,t):null}removeAnnotation(e){return this.store.remove(e)}removeSelectionAnnotation(){let e=this.selectionReadout.annotationId;return e?this.store.remove(e):!1}clearAnnotations(){return this.store.clear(),this}ingestHoverHit(e){let t=Vr(e);return this.setHoverReadout(t),t}ingestSelectionHit(e){let t=this.resolveSelectionMeta(e);if(this.setSelectionReadout(Si(e,t)),!e)return this.modeValue===Ze.Idle&&this.clearPending(),null;if(this.modeValue===Ze.Marker)return this.store.createMarker(tr(e));if(this.modeValue===Ze.Distance){if(this.pendingAnchors.push(tr(e)),this.emitStaging(),this.pendingAnchors.length<2)return null;let r=this.store.createDistance(this.pendingAnchors[0],this.pendingAnchors[1]);return this.clearPending(),r}if(this.modeValue===Ze.Angle){if(this.pendingAnchors.push(tr(e)),this.emitStaging(),this.pendingAnchors.length<3)return null;let r=this.store.createAngle(this.pendingAnchors[0],this.pendingAnchors[1],this.pendingAnchors[2]);return this.clearPending(),r}return this.clearPending(),null}async pickHoverAt(e,t){let r=this.scene,i=this.camera;if(!r||!i)return this.ingestHoverHit(null);let o=++this.hoverPickToken;try{let a=await this.runtime.pick(r,i,e,t,{includeAttributes:!0});return o!==this.hoverPickToken?this.hoverProbe:this.ingestHoverHit(a)}catch{return o!==this.hoverPickToken?this.hoverProbe:this.ingestHoverHit(null)}}async pickAtAndCommit(e,t){let r=this.scene,i=this.camera;if(!r||!i)return this.ingestSelectionHit(null);let o=++this.clickPickToken;try{let a=await this.runtime.pick(r,i,e,t,{includeAttributes:!0});return o!==this.clickPickToken?null:this.ingestSelectionHit(a)}catch{return o!==this.clickPickToken?null:this.ingestSelectionHit(null)}}handleStoreChanged(){let e=this.store.values();this.markerRenderer.sync(e,this.store.revision),this.labelLayer.setEntries(fu(e,this.unitsValue),this.store.revision),this.overlaySystem?.invalidate("manual");for(let t of this.annotationsListeners)try{t(e,this.store.revision)}catch{}}ensureOverlaySystem(){this.overlaySystem||this.autoCreateOverlay&&(!this.runtime.createOverlay||!this.camera||(this.overlaySystem=this.runtime.createOverlay.system({controls:this.controls??void 0,camera:this.camera,scene:this.scene,autoUpdate:!0,...this.overlaySystemOptions}),this.ownsOverlaySystem=!0))}ensureOverlayLayer(){this.overlaySystem&&(this.overlaySystem.removeLayer(this.labelLayer.id),this.overlaySystem.addLayer(this.labelLayer))}detachOverlayLayer(){this.overlaySystem&&this.overlaySystem.removeLayer(this.labelLayer.id)}setHoverReadout(e){this.hoverReadout=e,this.labelLayer.setHoverReadout(e);for(let t of this.hoverListeners)try{t(this.hoverProbe)}catch{}}setSelectionReadout(e){this.selectionReadout=e,this.labelLayer.setSelectionReadout(e);for(let t of this.selectionListeners)try{t(this.selectionProbe)}catch{}}resolveSelectionMeta(e){if(!e)return{annotationId:null,annotationKind:null,anchorRole:null};if(e.kind!=="glyphfield"||e.object!==this.markerRenderer.glyphField)return{annotationId:null,annotationKind:null,anchorRole:null};let t=this.markerRenderer.getInstance(e.elementIndex);return t?{annotationId:t.annotationId,annotationKind:t.annotationKind,anchorRole:t.role}:{annotationId:null,annotationKind:null,anchorRole:null}}clearPending(){this.pendingAnchors.length!==0&&(this.pendingAnchors.length=0,this.emitStaging())}emitStaging(){let e=pu(this.pendingAnchors);for(let t of this.stagingListeners)try{t(this.modeValue,e)}catch{}}bindPointerEvents(){this.boundPointerEvents||!this.pointerTarget||(this.pointerTarget.addEventListener("pointermove",this.onPointerMove),this.pointerTarget.addEventListener("pointerleave",this.onPointerLeave),this.pointerTarget.addEventListener("click",this.onClick),this.boundPointerEvents=!0)}unbindPointerEvents(){!this.boundPointerEvents||!this.pointerTarget||(this.pointerTarget.removeEventListener("pointermove",this.onPointerMove),this.pointerTarget.removeEventListener("pointerleave",this.onPointerLeave),this.pointerTarget.removeEventListener("click",this.onClick),this.boundPointerEvents=!1)}clientToLocal(e,t){let r=this.pointerTarget?.getBoundingClientRect();return r?{x:e-r.left,y:t-r.top}:{x:e,y:t}}onPointerMove=e=>{if(!this.scene||!this.camera)return;let{x:t,y:r}=this.clientToLocal(e.clientX,e.clientY);this.pickHoverAt(t,r)};onPointerLeave=()=>{this.hoverPickToken++,this.ingestHoverHit(null)};onClick=e=>{if(e.button!==0||!this.scene||!this.camera)return;let{x:t,y:r}=this.clientToLocal(e.clientX,e.clientY);this.pickAtAndCommit(t,r)}},ca=Vr;var hu=n=>typeof n=="object"&&n!==null&&typeof n.getBuffer=="function",bu=n=>typeof n=="object"&&n!==null&&typeof n.data=="object"&&Array.isArray(n.shape),ur=n=>{let e=new Array(n.length);for(let t=0;t<n.length;t++){let r=n[t];P(Number.isFinite(r),`shape[${t}] must be finite`),P(Number.isInteger(r),`shape[${t}] must be an integer`),P(r>=0,`shape[${t}] must be >= 0`),e[t]=r>>>0}return e},Rn=n=>{if(n.length===0)return 1;let e=1;for(let t of n){let r=t>>>0,i=e*r;P(Number.isSafeInteger(i),"shape is too large (numel overflow)"),e=i}return e>>>0},ma=n=>n instanceof Float32Array?"f32":n instanceof Float64Array?"f64":n instanceof Int8Array?"i8":n instanceof Uint8Array||n instanceof Uint8ClampedArray?"u8":n instanceof Int16Array?"i16":n instanceof Uint16Array?"u16":n instanceof Int32Array?"i32":n instanceof Uint32Array?"u32":null,da=(n,e,t=0,r)=>{let i=ye(n),o=i.ctor,a=i.bytesPerElement>>>0,s=t>>>0,l=r===void 0?(e.byteLength>>>0)/a>>>0:r>>>0,u=(e.byteOffset>>>0)+s*a>>>0;return new o(e.buffer,u>>>0,l>>>0)},gu=(n,e,t)=>{let r=n>>>0,i=e>>>0,o=i===0?16:i;if((o&o-1)!==0)throw new Error(`allocBytes(${n}, ${e}): align must be a power of two`);if(t==="frame")return{kind:"frame",ptr:W.alloc(r,o)>>>0};if(t&&typeof t=="object"){let l=t,u=l.epoch()>>>0;return{kind:"arena",ptr:l.alloc(r,o)>>>0,epoch:u}}let a=_.allocBytes(r)>>>0;if(!a&&r!==0)throw new Error(`wasm.allocBytes(${r}) failed`);let s=Math.min(o,8)>>>0;if(s!==0&&(a&s-1)!==0)throw new Error(`wasm.allocBytes(${r}) returned ptr 0x${a.toString(16)} which is not ${s}-byte aligned`);return{kind:"heap",ptr:a}},Tn=(n,e,t)=>{let i=ye(n).ctor,o=oe.buffer();return new i(o,e>>>0,t>>>0)},yu=(n,e)=>{let t=oe.bytes(),r=n>>>0,i=r+(e>>>0)>>>0;return t.subarray(r,i)},vu=n=>{if(typeof n.c_contiguous=="boolean"){P(n.c_contiguous,'Python buffer must be C-contiguous (use numpy.ascontiguousarray(..., order="C"))');return}let e=ur(n.shape??[]),t=Array.from(n.strides??[]);if(P(t.length===e.length,"Python buffer strides/shape rank mismatch"),Rn(e)===0)return;let r=1;for(let i=e.length-1;i>=0;i--)P(t[i]===r,'Python buffer must be C-contiguous (use numpy.ascontiguousarray(..., order="C"))'),r*=e[i]},Ci=(n,e)=>{if(hu(n)){let s=n.getBuffer(),l=Ci(s,e),u=typeof s.release=="function"?()=>s.release?.():void 0;return{...l,release:u}}if(bu(n)){vu(n),P(ArrayBuffer.isView(n.data),"Python buffer .data must be an ArrayBufferView"),P(typeof n.data.subarray=="function","Python buffer .data must be a TypedArray (DataView is not supported)");let s=ma(n.data);P(s!==null,"Unsupported Python buffer dtype (expected a numeric TypedArray)");let l=e.dtype??s;P(l===s,`dtype mismatch: expected ${l}, got ${s}`);let u=ur(n.shape),m=ur(e.shape??u),c=Rn(m),d=(n.offset??0)>>>0,f=da(l,n.data,d,c);return P(f.length>>>0===c>>>0,"Python buffer view length mismatch"),e.shape&&P(ur(e.shape).length===u.length&&ur(e.shape).every((p,b)=>p===u[b]),"shape mismatch"),{dtype:l,shape:m,data:f,release:typeof n.release=="function"?()=>n.release?.():void 0}}P(ArrayBuffer.isView(n),"Expected a TypedArray / ArrayBufferView or a PyProxy supporting getBuffer()");let t=ma(n);P(t!==null,"Unsupported TypedArray dtype");let r=e.dtype??t;P(r===t,`dtype mismatch: expected ${r}, got ${t}`),P(e.shape,"shape is required when sending a plain TypedArray (no Python buffer metadata available)");let i=ur(e.shape),o=Rn(i);P(n.byteLength>>>0>=o*ye(r).bytesPerElement,"source TypedArray is too small for the provided shape");let a=da(r,n,0,o);return P(a.length>>>0===o>>>0,"source TypedArray length mismatch"),{dtype:r,shape:i,data:a}},Ln={sendNdarray:(n,e={})=>{let t=Ci(n,e),{dtype:r,shape:i,data:o}=t,a=ye(r),s=Rn(i),l=s*a.bytesPerElement>>>0,u=gu(l,16,e.allocator);Tn(r,u.ptr,s).set(o);try{t.release?.()}catch{}let c={kind:u.kind,dtype:r,shape:i,ptr:u.ptr>>>0,length:s>>>0,byteLength:l>>>0};return u.epoch!==void 0&&(c.epoch=u.epoch>>>0),c},view:n=>Tn(n.dtype,n.ptr,n.length),bytes:n=>yu(n.ptr,n.byteLength),copyInto:(n,e,t={})=>{let r=Ci(e,{...t,dtype:n.dtype,shape:n.shape}),{data:i}=r;P(i.length>>>0===n.length>>>0,"copyInto: source length mismatch"),Tn(n.dtype,n.ptr,n.length).set(i);try{r.release?.()}catch{}},receiveNdarray:(n,e={})=>{let t=Tn(n.dtype,n.ptr,n.length);if(!e.copy)return{dtype:n.dtype,shape:Array.from(n.shape),data:t};let i=ye(n.dtype).ctor,o=new i(n.length>>>0);return o.set(t),{dtype:n.dtype,shape:Array.from(n.shape),data:o}},free:n=>{if(n.kind!=="heap")throw new Error(`pythonInterop.free(): cannot free a ${n.kind} allocation. Use reset() for arena-like allocators (frameArena.reset() / WasmHeapArena.reset()).`);_.freeBytes(n.ptr>>>0,n.byteLength>>>0)}};var xu={Y_UP_RH:{right:[1,0,0],up:[0,1,0],forward:[0,0,1]},Z_UP_RH:{right:[1,0,0],up:[0,0,1],forward:[0,-1,0]},X_UP_RH:{right:[0,0,1],up:[1,0,0],forward:[0,1,0]}},K=1e-6,pa=.001,fa=.35,_e=(n,e,t)=>Math.max(e,Math.min(t,n)),Fn=n=>_e(n,0,1),De=(n,e,t)=>n+(e-n)*t,Pu=n=>n<.5?4*n*n*n:1-Math.pow(-2*n+2,3)*.5,te=n=>[n[0]??0,n[1]??0,n[2]??0],Pe=(n,e)=>[n[0]+e[0],n[1]+e[1],n[2]+e[2]],_t=(n,e)=>[n[0]-e[0],n[1]-e[1],n[2]-e[2]],V=(n,e)=>[n[0]*e,n[1]*e,n[2]*e],Ce=(n,e)=>n[0]*e[0]+n[1]*e[1]+n[2]*e[2],Mt=(n,e)=>[n[1]*e[2]-n[2]*e[1],n[2]*e[0]-n[0]*e[2],n[0]*e[1]-n[1]*e[0]],Bt=n=>Math.hypot(n[0],n[1],n[2]),Q=(n,e=[0,0,1])=>{let t=Bt(n);if(t<=K)return te(e);let r=1/t;return[n[0]*r,n[1]*r,n[2]*r]},_i=(n,e,t)=>[De(n[0],e[0],t),De(n[1],e[1],t),De(n[2],e[2],t)],ha=(n,e,t,r,i,o,a,s)=>[r*i+n*s+e*a-t*o,r*o-n*a+e*s+t*i,r*a+n*o-e*i+t*s,r*s-n*i-e*o-t*a],wu=(n,e,t,r)=>[-n,-e,-t,r],Bi=(n,e,t,r)=>{let i=Math.hypot(n,e,t,r);if(i<=K)return[0,0,0,1];let o=1/i;return[n*o,e*o,t*o,r*o]},ba=(n,e,t,r,i,o,a)=>{let s=2*(i*t-o*e),l=2*(o*n-r*t),u=2*(r*e-i*n);return[n+a*s+(i*u-o*l),e+a*l+(o*s-r*u),t+a*u+(r*l-i*s)]},Su=(n,e,t,r)=>Math.abs(n)<K&&Math.abs(e)<K&&Math.abs(t)<K&&Math.abs(1-r)<K,Cu=(n,e,t,r,i)=>{let o=Fn(i),a=_e(r,-1,1),s=n,l=e,u=t,m=r;if(a<0&&(a=-a,s=-s,l=-l,u=-u,m=-m),a>=.9995)return Bi(s*o,l*o,u*o,1-o+m*o);let c=Math.acos(a),d=Math.sqrt(1-a*a);if(d<=K)return[0,0,0,1];let f=Math.sin((1-o)*c)/d,p=Math.sin(o*c)/d;return[s*p,l*p,u*p,f+m*p]},ga=n=>{if(!n||n==="y-up-rh")return{right:[1,0,0],up:[0,1,0],forward:[0,0,1]};if(n==="z-up-rh")return{right:[1,0,0],up:[0,0,1],forward:[0,-1,0]};if(n==="x-up-rh")return{right:[0,0,1],up:[1,0,0],forward:[0,1,0]};let e=n.right??Mt(n.up,n.forward),t=Q(e,[1,0,0]),r=Q(n.up,[0,1,0]),i=Q(Mt(t,r),n.forward),o=Q(Mt(r,i),t),a=Q(Mt(i,o),r);return{right:o,up:a,forward:i}},At=class{camera;domElement;target;enabled=!0;enableRotate=!0;enablePan=!0;enableZoom=!0;rotateSpeed=1;panSpeed=1;zoomSpeed=1;zoomOnCursor=!1;enableDamping=!1;dampingFactor=.1;minDistance=0;maxDistance=1/0;minZoom=.01;maxZoom=1/0;minPolarAngle=0;maxPolarAngle=Math.PI;minAzimuthAngle=-1/0;maxAzimuthAngle=1/0;mouseButtons={rotate:0,zoom:1,pan:2};_mode;_axisConvention=ga(void 0);_state="none";_pointerId=null;_pointerX=0;_pointerY=0;_zoomCursorClientX=0;_zoomCursorClientY=0;_zoomCursorValid=!1;_transition=null;_theta=0;_phi=Math.PI*.5;_thetaDelta=0;_phiDelta=0;_trackballRotateStart=[0,0,1];_trackballRotationDelta=[0,0,0,1];_trackballEye=[0,0,1];_trackballUp=[0,1,0];_radius=1;_zoom=1;_dollyDelta=0;_panOffset=[0,0,0];_orthoBaseLeft=-1;_orthoBaseRight=1;_orthoBaseTop=1;_orthoBaseBottom=-1;_savedTarget=[0,0,0];_savedPosition=[0,0,1];_savedUp=[0,1,0];_savedProjection={type:"perspective",near:.1,far:1e3};_wheelListenerOptions={passive:!1};_changeListeners=new Set;_interactionListeners=new Set;_interactionActive=!1;_wheelInteractionTimer=null;constructor(e,t,r={}){this.camera=e,this.domElement=t,this.target=r.target?te(r.target):[0,0,0],this._mode=r.mode??"orbit",this.axisConvention=r.axisConvention??"y-up-rh",r.enabled!==void 0&&(this.enabled=r.enabled),r.enableRotate!==void 0&&(this.enableRotate=r.enableRotate),r.enablePan!==void 0&&(this.enablePan=r.enablePan),r.enableZoom!==void 0&&(this.enableZoom=r.enableZoom),r.rotateSpeed!==void 0&&(this.rotateSpeed=r.rotateSpeed),r.panSpeed!==void 0&&(this.panSpeed=r.panSpeed),r.zoomSpeed!==void 0&&(this.zoomSpeed=r.zoomSpeed),r.zoomOnCursor!==void 0&&(this.zoomOnCursor=r.zoomOnCursor),r.enableDamping!==void 0&&(this.enableDamping=r.enableDamping),r.dampingFactor!==void 0&&(this.dampingFactor=r.dampingFactor),r.minDistance!==void 0&&(this.minDistance=r.minDistance),r.maxDistance!==void 0&&(this.maxDistance=r.maxDistance),r.minZoom!==void 0&&(this.minZoom=r.minZoom),r.maxZoom!==void 0&&(this.maxZoom=r.maxZoom),r.minPolarAngle!==void 0&&(this.minPolarAngle=r.minPolarAngle),r.maxPolarAngle!==void 0&&(this.maxPolarAngle=r.maxPolarAngle),r.minAzimuthAngle!==void 0&&(this.minAzimuthAngle=r.minAzimuthAngle),r.maxAzimuthAngle!==void 0&&(this.maxAzimuthAngle=r.maxAzimuthAngle),r.mouseButtons&&(r.mouseButtons.rotate!==void 0&&(this.mouseButtons.rotate=r.mouseButtons.rotate),r.mouseButtons.zoom!==void 0&&(this.mouseButtons.zoom=r.mouseButtons.zoom),r.mouseButtons.pan!==void 0&&(this.mouseButtons.pan=r.mouseButtons.pan)),this.domElement.style.touchAction="none",this.syncFromCamera(),this.saveState(),this.domElement.addEventListener("pointerdown",this.onPointerDown),this.domElement.addEventListener("pointermove",this.onPointerMove),this.domElement.addEventListener("pointerup",this.onPointerUp),this.domElement.addEventListener("pointercancel",this.onPointerUp),this.domElement.addEventListener("wheel",this.onWheel,this._wheelListenerOptions),this.domElement.addEventListener("contextmenu",this.onContextMenu)}dispose(){this.cancelTransition(),this.clearWheelInteractionTimer(),this.setInteractionState(!1),this.domElement.removeEventListener("pointerdown",this.onPointerDown),this.domElement.removeEventListener("pointermove",this.onPointerMove),this.domElement.removeEventListener("pointerup",this.onPointerUp),this.domElement.removeEventListener("pointercancel",this.onPointerUp),this.domElement.removeEventListener("wheel",this.onWheel,this._wheelListenerOptions),this.domElement.removeEventListener("contextmenu",this.onContextMenu),this._changeListeners.clear(),this._interactionListeners.clear()}onChange(e){return this._changeListeners.add(e),()=>{this._changeListeners.delete(e)}}onInteractionState(e){return this._interactionListeners.add(e),()=>{this._interactionListeners.delete(e)}}get mode(){return this._mode}set mode(e){this.setMode(e)}get axisConvention(){return{right:te(this._axisConvention.right),up:te(this._axisConvention.up),forward:te(this._axisConvention.forward)}}set axisConvention(e){this._axisConvention=ga(e),this.syncFromCamera()}get azimuthAngle(){return this._theta}set azimuthAngle(e){this._theta=e}get polarAngle(){return this._phi}set polarAngle(e){this._phi=e}get distance(){return this._radius}set distance(e){let t=Math.max(K,e);if(this._radius=t,this._mode==="trackball"){let r=Q(this._trackballEye,this._axisConvention.forward);this._trackballEye=V(r,t)}}get zoom(){return this._zoom}set zoom(e){this._zoom=_e(e,this.minZoom,this.maxZoom)}get hasActiveTransition(){return this._transition!==null}setCamera(e){return this.camera=e,this.cancelTransition(),this.syncFromCamera(),this.emitChange(),this}setMode(e){return e===this._mode?this:(this.syncFromCamera(),this._mode=e,this.syncFromCamera(),this)}syncFromCamera(){let e=te(this.camera.position),t=_t(e,this.target);if(this._radius=Math.max(K,Bt(t)),this.camera.type==="orthographic"){let i=this.camera;this._orthoBaseLeft=i.left,this._orthoBaseRight=i.right,this._orthoBaseTop=i.top,this._orthoBaseBottom=i.bottom,this._zoom=1}let r=this.offsetToSpherical(t);this._theta=r.theta,this._phi=r.phi,this._thetaDelta=0,this._phiDelta=0,this._dollyDelta=0,this._panOffset=[0,0,0],this._trackballEye=t,this._trackballUp=Q(this.camera.up,this._axisConvention.up),this._trackballRotateStart=[0,0,1],this._trackballRotationDelta=[0,0,0,1]}saveState(){this._savedTarget=te(this.target),this._savedPosition=te(this.camera.position),this._savedUp=Q(this.camera.up,this._axisConvention.up),this._savedProjection=this.captureProjectionState()}reset(){this.cancelTransition(),this.applyPose(this._savedPosition,this._savedTarget,this._savedUp),this.applyProjectionState(this._savedProjection),this.syncFromCamera(),this.emitChange()}setTarget(e,t,r){return typeof e=="number"?this.target=[e,t??0,r??0]:this.target=te(e),this}cancelTransition(){return this._transition=null,this}update(e=0){if(!this.enabled)return;let t=e>0?e:1/60;if(this._transition){this.updateTransition(t),this.emitChange();return}this._mode==="orbit"?this.updateOrbit(t):this.updateTrackball(t),this.emitChange()}setView(e,t={}){let r=this.getInspectionViewDirection(e),i=t.up?Q(t.up,this._axisConvention.up):this.getInspectionViewUp(e),o=t.target?te(t.target):te(this.target),a=Math.max(K,t.distance??this._radius),s=Pe(o,V(r,a));return this.applyPoseOrTransition(s,o,i,this.captureProjectionState(),t.animate,t.duration),this}fitScene(e,t={}){return this.fitToBounds(e.getBounds(),t)}viewBounds(e,t,r={}){return this.fitToBounds(t,{...r,view:e})}fitToBounds(e,t={}){let r=this.resolveBounds(e);if(r.empty)return r;let i=this.solveFit(r,t);return this.applyPoseOrTransition(i.position,i.target,i.up,i.projection,t.animate,t.duration),r}updateTransition(e){let t=this._transition;if(!t)return;t.elapsed+=e;let r=Fn(t.elapsed/Math.max(K,t.duration)),i=Pu(r),o=_i(t.fromPosition,t.toPosition,i),a=_i(t.fromTarget,t.toTarget,i),s=Q(_i(t.fromUp,t.toUp,i),t.toUp);this.applyPose(o,a,s),this.applyProjectionState(this.lerpProjectionState(t.fromProjection,t.toProjection,i)),r>=1&&(this._transition=null,this.syncFromCamera())}onPointerDown=e=>{!this.enabled||this._pointerId!==null||(this.cancelTransition(),this._pointerId=e.pointerId,this.domElement.setPointerCapture(this._pointerId),this._pointerX=e.clientX,this._pointerY=e.clientY,this._zoomCursorClientX=e.clientX,this._zoomCursorClientY=e.clientY,this._zoomCursorValid=!0,e.button===this.mouseButtons.rotate?this._state="rotate":e.button===this.mouseButtons.pan?this._state="pan":e.button===this.mouseButtons.zoom?this._state="zoom":this._state="none",this._state!=="none"&&this.setInteractionState(!0),this._state==="rotate"&&this._mode==="trackball"&&(this._trackballRotateStart=this.getTrackballVector(e.clientX,e.clientY)),e.preventDefault())};onPointerMove=e=>{if(!this.enabled||this._pointerId===null||e.pointerId!==this._pointerId)return;let t=e.clientX-this._pointerX,r=e.clientY-this._pointerY;if(this._pointerX=e.clientX,this._pointerY=e.clientY,this._zoomCursorClientX=e.clientX,this._zoomCursorClientY=e.clientY,this._zoomCursorValid=!0,!(t===0&&r===0)){if(this._state==="rotate"&&this.enableRotate)if(this._mode==="orbit"){let i=Math.max(1,this.getViewportHeight()),o=2*Math.PI/i;this._thetaDelta+=-t*o*this.rotateSpeed,this._phiDelta+=-r*o*this.rotateSpeed}else{let i=this.getTrackballVector(e.clientX,e.clientY),o=this.rotationFromTrackballDrag(this._trackballRotateStart,i);o&&(this._trackballRotationDelta=Bi(...ha(o[0],o[1],o[2],o[3],this._trackballRotationDelta[0],this._trackballRotationDelta[1],this._trackballRotationDelta[2],this._trackballRotationDelta[3]))),this._trackballRotateStart=i}else this._state==="pan"&&this.enablePan?this._mode==="orbit"?this.panOrbit(t,r):this.panTrackball(t,r):this._state==="zoom"&&this.enableZoom&&(this._dollyDelta+=r*this.zoomSpeed*.002);e.preventDefault()}};onPointerUp=e=>{this._pointerId===null||e.pointerId!==this._pointerId||(this.domElement.releasePointerCapture(this._pointerId),this._pointerId=null,this._state="none",this.setInteractionState(!1),e.preventDefault())};onWheel=e=>{!this.enabled||!this.enableZoom||(this.cancelTransition(),this._dollyDelta+=e.deltaY*this.zoomSpeed*.001,this._zoomCursorClientX=e.clientX,this._zoomCursorClientY=e.clientY,this._zoomCursorValid=!0,this.setInteractionState(!0),this.scheduleWheelInteractionEnd(),e.preventDefault(),e.stopPropagation())};onContextMenu=e=>{e.preventDefault()};getViewportRect(){let e=this.domElement.getBoundingClientRect(),t=Math.max(1,e.width||this.domElement.clientWidth||1),r=Math.max(1,e.height||this.domElement.clientHeight||1);return{left:e.left,top:e.top,width:t,height:r}}getViewportWidth(){return this.getViewportRect().width}getViewportHeight(){return this.getViewportRect().height}getAspect(e){return e&&e>0?e:this.getViewportWidth()/Math.max(1,this.getViewportHeight())}captureProjectionState(){if(this.camera.type==="orthographic"){let t=this.camera;return{type:"orthographic",left:t.left,right:t.right,top:t.top,bottom:t.bottom,near:t.near,far:t.far}}let e=this.camera;return{type:"perspective",near:e.near,far:e.far}}applyProjectionState(e){if(e.type==="orthographic"&&this.camera.type==="orthographic"){let t=this.camera;t.left=e.left,t.right=e.right,t.top=e.top,t.bottom=e.bottom,t.near=e.near,t.far=e.far}else if(e.type==="perspective"&&this.camera.type==="perspective"){let t=this.camera;t.near=e.near,t.far=e.far}}lerpProjectionState(e,t,r){return e.type==="orthographic"&&t.type==="orthographic"?{type:"orthographic",left:De(e.left,t.left,r),right:De(e.right,t.right,r),top:De(e.top,t.top,r),bottom:De(e.bottom,t.bottom,r),near:De(e.near,t.near,r),far:De(e.far,t.far,r)}:{type:"perspective",near:De(e.near,t.near,r),far:De(e.far,t.far,r)}}applyPose(e,t,r){this.target=te(t),this.camera.transform.setPosition(e[0],e[1],e[2]),this.camera.lookAtWithUp(t,r)}applyPoseOrTransition(e,t,r,i,o,a){if(!(o??!0)||(a??fa)<=0){this.cancelTransition(),this.applyPose(e,t,r),this.applyProjectionState(i),this.syncFromCamera(),this.emitChange();return}this._transition={elapsed:0,duration:a??fa,fromPosition:te(this.camera.position),toPosition:te(e),fromTarget:te(this.target),toTarget:te(t),fromUp:Q(this.camera.up,this._axisConvention.up),toUp:Q(r,this._axisConvention.up),fromProjection:this.captureProjectionState(),toProjection:i}}updateOrbit(e){let t=this.enableDamping?1-Math.pow(1-Fn(this.dampingFactor),e*60):1;this.enableRotate?(this._theta+=this._thetaDelta*t,this._phi+=this._phiDelta*t,this._thetaDelta*=1-t,this._phiDelta*=1-t):(this._thetaDelta=0,this._phiDelta=0);let r=Math.max(this.minPolarAngle,pa),i=Math.min(this.maxPolarAngle,Math.PI-pa);r<=i?this._phi=_e(this._phi,r,i):this._phi=_e(this._phi,this.minPolarAngle,this.maxPolarAngle),this._theta=_e(this._theta,this.minAzimuthAngle,this.maxAzimuthAngle),this.applyDolly(t,this.computeOrbitBasis()),this.applyPan(t),this._radius=_e(this._radius,this.minDistance,this.maxDistance);let o=this.sphericalToOffset(this._theta,this._phi,Math.max(K,this._radius)),a=Pe(this.target,o),s=Q(_t(this.target,a),V(this._axisConvention.forward,-1)),l=this.getOrbitUp(s);this.camera.transform.setPosition(a[0],a[1],a[2]),this.camera.lookAtWithUp(this.target,l),this.camera.type==="orthographic"?this.applyOrthographicZoom():this.relaxPerspectiveClipForZoom()}updateTrackball(e){let t=this.enableDamping?1-Math.pow(1-Fn(this.dampingFactor),e*60):1;if(this.enableRotate){let o=this._trackballRotationDelta;if(!Su(o[0],o[1],o[2],o[3])){let a=Cu(o[0],o[1],o[2],o[3],t);this._trackballEye=ba(this._trackballEye[0],this._trackballEye[1],this._trackballEye[2],a[0],a[1],a[2],a[3]),this._trackballUp=Q(ba(this._trackballUp[0],this._trackballUp[1],this._trackballUp[2],a[0],a[1],a[2],a[3]),this._axisConvention.up);let s=ha(o[0],o[1],o[2],o[3],...wu(a[0],a[1],a[2],a[3]));this._trackballRotationDelta=Bi(s[0],s[1],s[2],s[3])}}else this._trackballRotationDelta=[0,0,0,1];this.applyDolly(t,this.computeTrackballBasis()),this.applyPan(t);let r=Bt(this._trackballEye);this._radius=_e(Math.max(K,r),this.minDistance,this.maxDistance),r>K?this._trackballEye=V(this._trackballEye,this._radius/r):this._trackballEye=V(this._axisConvention.forward,this._radius);let i=Pe(this.target,this._trackballEye);this.camera.transform.setPosition(i[0],i[1],i[2]),this.camera.lookAtWithUp(this.target,this._trackballUp),this.camera.type==="orthographic"?this.applyOrthographicZoom():this.relaxPerspectiveClipForZoom()}emitChange(){for(let e of this._changeListeners)try{e()}catch{}}setInteractionState(e){if(this._interactionActive!==e){this._interactionActive=e;for(let t of this._interactionListeners)try{t(e)}catch{}}}clearWheelInteractionTimer(){this._wheelInteractionTimer!==null&&(clearTimeout(this._wheelInteractionTimer),this._wheelInteractionTimer=null)}scheduleWheelInteractionEnd(){this.clearWheelInteractionTimer(),this._wheelInteractionTimer=setTimeout(()=>{this._wheelInteractionTimer=null,this._pointerId===null&&this._state==="none"&&this.setInteractionState(!1)},120)}applyDolly(e,t){if(!this.enableZoom){this._dollyDelta=0;return}let r=this._dollyDelta*e;if(Math.abs(r)<=K){this._dollyDelta*=1-e;return}let i=this._radius,o=this._zoom;if(this.camera.type==="orthographic")this._zoom=_e(this._zoom*Math.exp(-r),this.minZoom,this.maxZoom);else{let a=_e(this._radius*Math.exp(r),this.minDistance,this.maxDistance);if(this._mode==="trackball"){let s=Math.max(K,Bt(this._trackballEye));this._trackballEye=V(this._trackballEye,a/s)}this._radius=a}this.zoomOnCursor&&this._zoomCursorValid&&this.applyZoomOnCursor(i,o,t),this._dollyDelta*=1-e}applyPan(e){if(!this.enablePan){this._panOffset=[0,0,0];return}this.target[0]+=this._panOffset[0]*e,this.target[1]+=this._panOffset[1]*e,this.target[2]+=this._panOffset[2]*e,this._panOffset=V(this._panOffset,1-e)}panOrbit(e,t){let r=this.computeOrbitBasis();this.queuePan(e,t,r)}panTrackball(e,t){let r=this.computeTrackballBasis();this.queuePan(e,t,r)}queuePan(e,t,r){let i=Math.max(1,this.getViewportWidth()),o=Math.max(1,this.getViewportHeight()),a=0,s=0;if(this.camera.type==="orthographic"){let l=(this._orthoBaseRight-this._orthoBaseLeft)/Math.max(K,this._zoom),u=(this._orthoBaseTop-this._orthoBaseBottom)/Math.max(K,this._zoom);a=e*l/i*this.panSpeed,s=t*u/o*this.panSpeed}else{let l=this.camera,u=this._radius*Math.tan(l.fov*Math.PI/180*.5);a=2*e*u/o*this.panSpeed,s=2*t*u/o*this.panSpeed}this._panOffset=Pe(this._panOffset,Pe(V(r.right,-a),V(r.up,s)))}applyZoomOnCursor(e,t,r){let i=this.getViewportRect(),o=(this._zoomCursorClientX-i.left)/i.width,a=(this._zoomCursorClientY-i.top)/i.height,s=o*2-1,l=1-a*2;if(this.camera.type==="orthographic"){let g=this._orthoBaseRight-this._orthoBaseLeft,x=this._orthoBaseTop-this._orthoBaseBottom,M=g/Math.max(K,t)*.5,h=g/Math.max(K,this._zoom)*.5,w=x/Math.max(K,t)*.5,S=x/Math.max(K,this._zoom)*.5;this.target=Pe(this.target,Pe(V(r.right,s*(M-h)),V(r.up,l*(w-S))));return}let u=this.camera,m=Math.tan(u.fov*Math.PI/180*.5),c=i.width/i.height,d=e*m,f=this._radius*m,p=d*c,b=f*c;this.target=Pe(this.target,Pe(V(r.right,s*(p-b)),V(r.up,l*(d-f))))}applyOrthographicZoom(){if(this.camera.type!=="orthographic")return;let e=this.camera,t=(this._orthoBaseLeft+this._orthoBaseRight)*.5,r=(this._orthoBaseBottom+this._orthoBaseTop)*.5,i=(this._orthoBaseRight-this._orthoBaseLeft)/Math.max(K,this._zoom),o=(this._orthoBaseTop-this._orthoBaseBottom)/Math.max(K,this._zoom);e.left=t-i*.5,e.right=t+i*.5,e.bottom=r-o*.5,e.top=r+o*.5}relaxPerspectiveClipForZoom(){if(this.camera.type!=="perspective")return;let e=this.camera,t=1e-4,r=Math.max(t,this._radius*.02);if(r<e.near){let o=Math.max(t,e.far-.01),a=_e(r,t,o);a<e.near&&(e.near=a)}let i=Math.max(this._radius*4,e.near+.01);i>e.far&&(e.far=i)}offsetToSpherical(e){let t=Ce(e,this._axisConvention.right),r=Ce(e,this._axisConvention.up),i=Ce(e,this._axisConvention.forward),o=Math.max(K,Math.hypot(t,r,i));return{theta:Math.atan2(t,i),phi:Math.acos(_e(r/o,-1,1))}}sphericalToOffset(e,t,r){let i=Math.sin(t),o=r*i*Math.sin(e),a=r*Math.cos(t),s=r*i*Math.cos(e);return Pe(Pe(V(this._axisConvention.right,o),V(this._axisConvention.up,a)),V(this._axisConvention.forward,s))}computeLookBasis(e,t){let r=Q(e,V(this._axisConvention.forward,-1)),i=Q(t,this._axisConvention.up);Math.abs(Ce(r,i))>.999&&(i=Math.abs(r[1])<.9?[0,1,0]:[1,0,0]);let o=Q(Mt(r,i),this._axisConvention.right),a=Q(Mt(o,r),i);return{right:o,up:a,forward:r}}computeOrbitBasis(){let e=this.sphericalToOffset(this._theta,this._phi,Math.max(K,this._radius)),t=Q(V(e,-1),V(this._axisConvention.forward,-1));return this.computeLookBasis(t,this.getOrbitUp(t))}computeTrackballBasis(){let e=Q(V(this._trackballEye,-1),V(this._axisConvention.forward,-1)),t=this.computeLookBasis(e,this._trackballUp);return this._trackballUp=t.up,t}getOrbitUp(e){let t=this._axisConvention.up,r=_t(t,V(e,Ce(t,e))),i=Bt(r);if(i>K)return V(r,1/i);let o=this._axisConvention.forward;return r=_t(o,V(e,Ce(o,e))),i=Bt(r),i>K?V(r,1/i):te(this._axisConvention.right)}getTrackballVector(e,t){let r=this.getViewportRect(),i=(e-r.left)/r.width*2-1,o=1-(t-r.top)/r.height*2,a=i*i+o*o;if(a<=1)return[i,o,Math.sqrt(1-a)];let s=1/Math.sqrt(a);return[i*s,o*s,0]}rotationFromTrackballDrag(e,t){let r=_e(Ce(e,t),-1,1),i=Math.acos(r);if(i<=K)return null;i*=this.rotateSpeed;let o=Mt(e,t),a=Bt(o);if(a<=K)return null;o=V(o,1/a);let s=this.computeTrackballBasis(),l=Q(Pe(Pe(V(s.right,o[0]),V(s.up,o[1])),V(V(s.forward,-1),o[2])),s.right),u=i*.5,m=Math.sin(u);return[l[0]*m,l[1]*m,l[2]*m,Math.cos(u)]}resolveBounds(e){return $n(e)}getInspectionViewDirection(e){switch(e){case"front":return te(this._axisConvention.forward);case"back":return V(this._axisConvention.forward,-1);case"right":return te(this._axisConvention.right);case"left":return V(this._axisConvention.right,-1);case"top":return te(this._axisConvention.up);case"bottom":return V(this._axisConvention.up,-1)}}getInspectionViewUp(e){return e==="top"?V(this._axisConvention.forward,-1):te(e==="bottom"?this._axisConvention.forward:this._axisConvention.up)}getCurrentViewOrientation(){let e=te(this.camera.position),t=Q(_t(e,this.target),this._axisConvention.forward);return{direction:t,up:Q(this.camera.up,this.getOrbitUp(V(t,-1)))}}solveFit(e,t){let r=Math.max(1,t.padding??1.1),i=this.getAspect(t.aspect),o=t.view?{direction:this.getInspectionViewDirection(t.view),up:t.up?Q(t.up,this._axisConvention.up):this.getInspectionViewUp(t.view)}:{direction:t.eyeDirection?Q(t.eyeDirection,this._axisConvention.forward):this.getCurrentViewOrientation().direction,up:t.up?Q(t.up,this._axisConvention.up):this.getCurrentViewOrientation().up},a=t.boundsMode==="sphere"?ct(e.sphereCenter,e.sphereRadius*r,e.partial):qn(e,r),s=this.computeLookBasis(V(o.direction,-1),o.up),l=t.boundsMode==="sphere"?te(e.sphereCenter):Xr(a);return this.camera.type==="orthographic"?this.solveFitOrthographic(a,e,s,l,i,t.minNear):this.solveFitPerspective(a,e,s,l,i,t.minNear)}solveFitPerspective(e,t,r,i,o,a){let s=Yr(e),l=this.camera,u=Math.tan(l.fov*Math.PI/180*.5),m=u*Math.max(o,K),c=t.sphereRadius,d=[];for(let v of s){let A=_t(v,i),C=Ce(A,r.right),k=Ce(A,r.up),G=Ce(A,r.forward);d.push(G),c=Math.max(c,Math.abs(C)/Math.max(m,K)-G,Math.abs(k)/Math.max(u,K)-G)}c=Math.max(c,t.sphereRadius,a??.01);let f=Math.min(...d.map(v=>c+v)),p=Math.max(...d.map(v=>c+v)),b=a??.01,g=Math.max(t.sphereRadius*.05,.01),x=Math.max(e.sphereRadius,t.sphereRadius,.01),M=Math.max(x*.1,g),h=c-x-M,w=c+x+M,S=Math.max(b,Math.min(f-g,h)),B=Math.max(S+.01,Math.max(p+g,w));return{position:Pe(i,V(V(r.forward,-1),c)),target:i,up:r.up,projection:{type:"perspective",near:S,far:B}}}solveFitOrthographic(e,t,r,i,o,a){let s=Yr(e),l=0,u=0,m=1/0,c=-1/0;for(let w of s){let S=_t(w,i),B=Ce(S,r.right),v=Ce(S,r.up),A=Ce(S,r.forward);l=Math.max(l,Math.abs(B)),u=Math.max(u,Math.abs(v)),A<m&&(m=A),A>c&&(c=A)}o>=1?l=Math.max(l,u*o):u=Math.max(u,l/Math.max(o,K));let d=Math.max(Math.abs(m),Math.abs(c),t.sphereRadius),f=Math.max(d*2+Math.max(l,u),t.sphereRadius*2,.1),p=a??.01,b=Math.max(t.sphereRadius*.05,.01),g=Math.max(e.sphereRadius,t.sphereRadius,.01),x=Math.max(g*.1,b),M=Math.max(p,Math.min(f+m-b,f-g-x)),h=Math.max(M+.01,Math.max(f+c+b,f+g+x));return{position:Pe(i,V(V(r.forward,-1),f)),target:i,up:r.up,projection:{type:"orthographic",left:-Math.max(l,.01),right:Math.max(l,.01),bottom:-Math.max(u,.01),top:Math.max(u,.01),near:M,far:h}}}},jr=class extends At{constructor(e,t,r={}){super(e,t,{...r,mode:"orbit"})}},$r=class extends At{constructor(e,t,r={}){super(e,t,{...r,mode:"trackball"})}};var Hr=(n,e)=>`${n}:${e}`,Mi=n=>n?Array.isArray(n)?n:[n]:[],ya=n=>({...n,key:Hr(n.objectId,n.elementIndex)}),cr=class{entries=new Map;get size(){return this.entries.size}has(e,t){return this.entries.has(Hr(e,t))}values(){return Array.from(this.entries.values())}clear(){return this.entries.clear(),this}replace(e){return this.entries.clear(),this.add(e),this}add(e){for(let t of Mi(e))this.entries.set(Hr(t.objectId,t.elementIndex),ya(t));return this}remove(e){for(let t of Mi(e))this.entries.delete(Hr(t.objectId,t.elementIndex));return this}toggle(e){for(let t of Mi(e)){let r=Hr(t.objectId,t.elementIndex);this.entries.has(r)?this.entries.delete(r):this.entries.set(r,ya(t))}return this}apply(e,t){switch(e){case"replace":return this.replace(t);case"add":return this.add(t);case"toggle":return this.toggle(t);case"remove":return this.remove(t)}}};var Dn=class n{renderer;compute;scale;_performanceStats=null;_isRunning=!1;_lastTime=0;_frameCallback=null;_animationFrameId=null;constructor(e,t){this.renderer=e;let r=e.gpu;this.compute=new Rr(r.device,r.queue,t),this.scale=new It(this.compute)}static async create(e,t={}){await Vn();let r=await Sr.create(e,t);return new n(r,t)}run(e){if(this._isRunning)return;this._isRunning=!0,this._frameCallback=e,this._lastTime=performance.now();let t=r=>{if(!this._isRunning)return;W.reset();let i=(r-this._lastTime)/1e3;this._lastTime=r;let o=performance.now();this._frameCallback?.(i,r/1e3,this);let a=performance.now()-o;this._performanceStats?.update(i,a),this._animationFrameId=requestAnimationFrame(t)};this._animationFrameId=requestAnimationFrame(t)}stop(){this._isRunning=!1,this._animationFrameId!==null&&(cancelAnimationFrame(this._animationFrameId),this._animationFrameId=null)}get gpu(){return this.renderer.gpu}get isRunning(){return this._isRunning}get cullingStats(){return this.renderer.cullingStats}static get interop(){return oe}get interop(){return oe}static get python(){return Ln}get python(){return Ln}static get math(){return{mat4:ze,quat:Kr,vec3:Ge}}get math(){return{mat4:ze,quat:Kr,vec3:Ge}}static createHeapArena(e,t=16){return oe.createHeapArena(e,t)}createHeapArena(e,t=16){return oe.createHeapArena(e,t)}static get frameArena(){return W}get frameArena(){return W}static createSelectionStore(){return new cr}createSelectionStore(){return new cr}createPerformanceStats(e={}){this._performanceStats?.destroy(),this.renderer.enableGpuTiming(e.showGpuTime??!0);let t=new Cr({getGpuTimeNs:()=>this.renderer.gpuTimeNs,getCullingStats:()=>this.renderer.cullingStats},{canvas:this.renderer.canvas,...e});return this._performanceStats=t,t}get performanceStats(){return this._performanceStats}destroyPerformanceStats(){this._performanceStats?.destroy(),this._performanceStats=null,this.renderer.enableGpuTiming(!1)}render(e,t){this._isRunning||W.reset(),this.renderer.render(e,t)}buildPickNdIndex(e){return e.kind==="pointcloud"||e.kind==="glyphfield"?e.object.mapLinearIndexToNd(e.elementIndex):null}buildPickAttributes(e,t){if(!t)return null;if(e.kind==="pointcloud"){let r=e.object.getPointRecord(e.elementIndex);return r?{scalar:r.scalar,packedPoint:r.packed}:null}if(e.kind==="glyphfield"){let r=e.object.getAttributeRecord(e.elementIndex);return r?{vector:r}:null}return null}buildPickHit(e,t){return{kind:e.kind,object:e.object,objectId:e.objectId,elementIndex:e.elementIndex,worldPosition:[e.worldPosition[0],e.worldPosition[1],e.worldPosition[2]],ndIndex:this.buildPickNdIndex(e),attributes:this.buildPickAttributes(e,t)}}async pick(e,t,r,i,o={}){let a=await this.renderer.pick(e,t,r,i,o);if(!a)return null;let s=o.includeAttributes??!0;return this.buildPickHit(a,s)}async pickRect(e,t,r,i,o,a,s={}){let l=s.includeAttributes??!0,u=await this.renderer.pickRect(e,t,r,i,o,a,s);return{mode:u.mode,hits:u.hits.map(m=>this.buildPickHit(m,l)),truncated:u.truncated,bounds:{x:u.bounds.x,y:u.bounds.y,width:u.bounds.width,height:u.bounds.height},sampledPixels:u.sampledPixels}}async pickLasso(e,t,r,i={}){let o=i.includeAttributes??!0,a=await this.renderer.pickLasso(e,t,r,i);return{mode:a.mode,hits:a.hits.map(s=>this.buildPickHit(s,o)),truncated:a.truncated,bounds:{x:a.bounds.x,y:a.bounds.y,width:a.bounds.width,height:a.bounds.height},sampledPixels:a.sampledPixels}}createScene(e){return new Xe({background:e})}createCamera={perspective:e=>new wt(e),orthographic:e=>new St(e)};createControls={navigation:(e,t,r)=>new At(e,t,r),orbit:(e,t,r)=>new jr(e,t,r),trackball:(e,t,r)=>new $r(e,t,r)};createOverlay={system:(e={})=>new Qt({canvas:this.renderer.canvas,...e}),axisTriad:(e={})=>new Zt(e),grid:(e={})=>new Jt(e),legend:e=>new er(e)};createAnnotation={toolkit:(e={})=>new lr({pick:this.pick.bind(this),createOverlay:this.createOverlay},{canvas:this.renderer.canvas,...e})};geometry={custom:e=>new X(e),point:(e,t,r)=>X.point(e,t,r),line:(e,t,r,i)=>X.line(e,t,r,i),plane:(e,t,r,i)=>X.plane(e,t,r,i),triangle:(e,t,r,i)=>X.triangle(e,t,r,i),rectangle:(e,t,r,i)=>X.rectangle(e,t,r,i),circle:(e,t,r,i)=>X.circle(e,t,r,i),ellipse:(e,t,r,i,o)=>X.ellipse(e,t,r,i,o),box:(e,t,r)=>X.box(e,t,r),sphere:(e,t,r)=>X.sphere(e,t,r),cylinder:(e,t,r,i,o,a)=>X.cylinder(e,t,r,i,o,a),pyramid:(e,t,r)=>X.pyramid(e,t,r),torus:(e,t,r,i)=>X.torus(e,t,r,i),prism:(e,t,r)=>X.prism(e,t,r),cartesianCurve:e=>X.cartesianCurve(e),cartesianSurface:e=>X.cartesianSurface(e),parametricCurve:e=>X.parametricCurve(e),parametricSurface:e=>X.parametricSurface(e)};material={unlit:e=>new Se(e),standard:e=>new xe(e),data:e=>new Ae(e),custom:e=>new xr(e)};texture={create2D:e=>vt.createFrom(e)};createTransform(){return new pe}createMesh(e,t){return new Me(e,t)}createPointCloud(e){return new Ue(e)}createGlyphField(e){return new Re(e)}colormap={builtin:e=>H.builtin(e),grayscale:()=>H.builtin("grayscale"),turbo:()=>H.builtin("turbo"),viridis:()=>H.builtin("viridis"),magma:()=>H.builtin("magma"),plasma:()=>H.builtin("plasma"),inferno:()=>H.builtin("inferno"),fromStops:(e,t={})=>H.fromStops(e,t),fromPalette:(e,t={})=>H.fromPalette(e,t)};createLight={ambient:e=>new wr(e),directional:e=>new Ye(e),point:e=>new Ve(e)};gltf={load:async(e,t)=>dn(e,t),import:async(e,t)=>bn(e,t),loadAndImport:async(e,t={})=>{let r=await dn(e,t.load);return bn(r,t.import)},parseGLB:e=>qt(e),readAccessor:(e,t)=>it(e,t),readAccessorAsFloat32:(e,t)=>ke(e,t),readAccessorAsUint16:(e,t)=>Xt(e,t),readIndicesAsUint32:(e,t)=>Ir(e,t)};animation={createClip:e=>new xt(e),createPlayer:(e,t)=>new Er(e,t),createSkin:(e,t,r)=>new Pt(e,t,r)};destroy(){this.stop(),this.destroyPerformanceStats(),this.scale.clearCache(),this.compute.destroy(),this.renderer.destroy()}};export{wr as AmbientLight,xt as AnimationClip,Er as AnimationPlayer,zr as AnnotationAngleUnit,na as AnnotationKind,ir as AnnotationLabelLayer,ar as AnnotationMarkerRenderer,Ze as AnnotationMode,sr as AnnotationStore,lr as AnnotationToolkit,xu as AxisConventions,Zt as AxisTriadLayer,Et as BlendMode,gt as CPUndarray,Or as Camera,H as Colormap,Rr as Compute,Ht as ComputeKernels,ee as ComputePipeline,Pr as CullMode,xr as CustomMaterial,Ae as DataMaterial,Ye as DirectionalLight,yt as GPUndarray,X as Geometry,Re as GlyphField,Jt as GridLayer,er as LegendLayer,Ot as Light,ht as Material,Me as Mesh,At as NavigationControls,nt as Ndarray,jr as OrbitControls,St as OrthographicCamera,Qt as OverlaySystem,Cr as PerformanceStats,wt as PerspectiveCamera,Ue as PointCloud,Ve as PointLight,bt as ReadbackRing,Sr as Renderer,Te as SCALE_UNIFORM_FLOAT_COUNT,It as ScaleService,Xe as Scene,cr as SelectionStore,Pt as Skin,pn as SkinInstance,xe as StandardMaterial,q as StorageBuffer,vt as Texture2D,$r as TrackballControls,pe as Transform,N as TransformStore,Nt as UniformBuffer,Se as UnlitMaterial,Dn as WasmGPU,mr as WasmHeapArena,ge as WasmSlice,tr as annotationAnchorFromHit,Xi as applyScaleTransformCPU,qe as boundsFromBox,mt as boundsFromBoxAndSphere,ct as boundsFromSphere,hr as cloneBounds,We as cloneScaleTransform,rr as colorToCssRgba,Gn as computeAngleRadians,kn as computeDistanceWorld,ua as createAnnotationAnchor,et as cullf,Dn as default,Qn as defaultScaleTransform,ye as dtypeInfo,ut as emptyBounds,qn as expandBounds,Bn as formatAngleRadians,_n as formatDistanceWorld,me as formatFiniteNumber,Mn as formatWorldVector,W as frameArena,pr as frustumf,Xr as getBoundsCenter,Yr as getBoundsCorners,ka as getBoundsSize,bn as importGltf,Vn as initWebAssembly,Zr as invertScaleTransformCPU,dn as loadGltf,Vt as makeWorkgroupCounts,ho as makeWorkgroupSize,ca as mapAnnotationProbeReadout,ze as mat4,jn as ndarrayf,$n as normalizeBounds,ie as normalizeScaleTransform,Ur as normalizeWorkgroups,Ne as packScaleTransform,qt as parseGLB,Ln as pythonInterop,Kr as quat,it as readAccessor,ke as readAccessorAsFloat32,Xt as readAccessorAsUint16,Ir as readIndicesAsUint32,nr as resolveAnnotationUnits,Ki as resolveScaleTransformDomainCPU,yr as scaleClampModeToId,gr as scaleModeToId,vr as scaleValueModeToId,dt as transformBounds,Hn as unionBounds,Ge as vec3,_ as wasm,oe as wasmInterop,fe as workgroups1D,Mr as workgroups2D,Ar as workgroups3D};
|
|
25
|
+
`)},Vr=class{id;maxLabels;font;labelOffsetPx;readoutAnchor;readoutWidthPx;container=null;labelPool=null;hoverReadoutEl=null;selectionReadoutEl=null;_system=null;entries=[];entriesRevision=-1;entriesDirty=!0;hoverReadout=null;selectionReadout=null;readoutDirty=!0;hoverTextCache="";selectionTextCache="";constructor(e={}){this.id=e.id??"annotation-label-layer",this.maxLabels=Math.max(1,Math.round(e.maxLabels??256)),this.font=e.font??"11px monospace",this.labelOffsetPx=e.labelOffsetPx??[8,-8],this.readoutAnchor=e.readoutAnchor??{kind:"screen",corner:"top-left",offsetPx:[12,12]},this.readoutWidthPx=Math.max(180,Math.round(e.readoutWidthPx??330))}get pooledNodeCount(){return this.labelPool?.size??0}setSystem(e){this._system=e}attach(e){let t=document.createElement("div");t.style.position="absolute",t.style.inset="0",t.style.pointerEvents="none",e.appendChild(t),this.container=t,this.labelPool=new Ct(t,()=>{let r=document.createElement("div");return r.style.position="absolute",r.style.whiteSpace="nowrap",r.style.font=this.font,r.style.textShadow="0 1px 1px rgba(0, 0, 0, 0.8)",r.style.willChange="transform,left,top",r},this.maxLabels),this.hoverReadoutEl=document.createElement("div"),this.selectionReadoutEl=document.createElement("div");for(let r of[this.hoverReadoutEl,this.selectionReadoutEl])r.style.position="absolute",r.style.pointerEvents="none",r.style.whiteSpace="pre-line",r.style.font=this.font,r.style.color="#dce9ff",r.style.padding="6px 7px",r.style.border="1px solid rgba(180, 210, 255, 0.28)",r.style.background="rgba(5, 11, 20, 0.72)",r.style.borderRadius="4px",r.style.minWidth=`${Math.floor(this.readoutWidthPx*.5)}px`,r.style.maxWidth=`${this.readoutWidthPx}px`,t.appendChild(r);this.entriesDirty=!0,this.readoutDirty=!0}detach(){this.labelPool?.clear(!0),this.labelPool=null,this.hoverReadoutEl=null,this.selectionReadoutEl=null,this.container?.remove(),this.container=null,this.hoverTextCache="",this.selectionTextCache=""}setEntries(e,t){this.entries=new Array(Math.min(this.maxLabels,e.length));for(let r=0;r<this.entries.length;r++){let i=e[r];this.entries[r]={key:i.key,text:i.text,color:i.color,position:[i.position[0],i.position[1],i.position[2]]}}t!==this.entriesRevision&&(this.entriesRevision=t,this.entriesDirty=!0),this._system?.invalidate("manual")}setHoverReadout(e){this.hoverReadout=e?{...e,worldPosition:e.worldPosition?[e.worldPosition[0],e.worldPosition[1],e.worldPosition[2]]:null,ndIndex:e.ndIndex?e.ndIndex.slice():null,attributes:ml(e.attributes)}:null,this.readoutDirty=!0,this._system?.invalidate("manual")}setSelectionReadout(e){this.selectionReadout=e?{...e,worldPosition:e.worldPosition?[e.worldPosition[0],e.worldPosition[1],e.worldPosition[2]]:null,ndIndex:e.ndIndex?e.ndIndex.slice():null,attributes:ml(e.attributes)}:null,this.readoutDirty=!0,this._system?.invalidate("manual")}update(e){if(!this.container||!this.labelPool)return;(e.reasons.has("camera")||e.reasons.has("viewport")||e.reasons.has("layout")||e.reasons.has("manual")||e.reasons.has("interaction")||this.entriesDirty)&&this.renderLabels(e),(this.readoutDirty||e.reasons.has("viewport")||e.reasons.has("layout")||e.reasons.has("manual"))&&this.renderReadouts(e)}renderLabels(e){if(this.labelPool){this.labelPool.beginFrame();for(let t=0;t<this.entries.length;t++){let r=this.entries[t],i=mt(e.camera,e.width,e.height,r.position);if(!i||!i.visible)continue;let o=this.labelPool.acquire();(this.entriesDirty||o.dataset.annotationKey!==r.key)&&(o.dataset.annotationKey=r.key,o.style.color=r.color,o.textContent=r.text),o.style.left=`${i.x+this.labelOffsetPx[0]}px`,o.style.top=`${i.y+this.labelOffsetPx[1]}px`}this.labelPool.endFrame(),this.entriesDirty=!1}}renderReadouts(e){if(!this.hoverReadoutEl||!this.selectionReadoutEl)return;let[t,r]=Gr(this.readoutAnchor,e.width,e.height);this.hoverReadoutEl.style.left=`${t}px`,this.hoverReadoutEl.style.top=`${r}px`,this.selectionReadoutEl.style.left=`${t}px`,this.selectionReadoutEl.style.top=`${r+122}px`;let i=dl("Hover",this.hoverReadout),o=dd("Selection",this.selectionReadout);i!==this.hoverTextCache&&(this.hoverTextCache=i,this.hoverReadoutEl.textContent=i),o!==this.selectionTextCache&&(this.selectionTextCache=o,this.selectionReadoutEl.textContent=o),this.readoutDirty=!1}};var fd=n=>{if(Array.isArray(n))return[Math.max(1e-6,n[0]??1),Math.max(1e-6,n[1]??1),Math.max(1e-6,n[2]??1)];let e=Math.max(1e-6,n??.16);return[e,e,e]},Er=(n,e,t,r,i,o)=>{n.push({key:`${e}:${r}`,annotationId:e,annotationKind:t,role:r,anchor:ye(i),color:zt(o)})},fl=n=>{let e=[];for(let t=0;t<n.length;t++){let r=n[t];if(r.visible){if(r.kind==="marker"){Er(e,r.id,r.kind,"marker",r.anchor,r.color);continue}if(r.kind==="distance"){Er(e,r.id,r.kind,"start",r.start,r.color),Er(e,r.id,r.kind,"end",r.end,r.color);continue}Er(e,r.id,r.kind,"a",r.a,r.color),Er(e,r.id,r.kind,"b",r.b,r.color),Er(e,r.id,r.kind,"c",r.c,r.color)}}return e},Wr=class{glyphField;maxInstances;markerScale;keepCPUData;ownsGlyphField;attachedScene=null;appliedRevision=-1;updateCount=0;instances=[];constructor(e={}){this.markerScale=fd(e.markerScale),this.maxInstances=Math.max(1,Math.round(e.maxInstances??4096)),this.keepCPUData=e.keepCPUData??!0,this.ownsGlyphField=!e.glyphField,this.glyphField=e.glyphField??new ze({shape:e.shape??"ellipsoid",instanceCount:0,colorMode:"rgba",lit:!1,depthWrite:!0,depthTest:!0,keepCPUData:this.keepCPUData,name:e.name??"annotation-markers",scaleTransform:{componentCount:4,componentIndex:0,valueMode:"component",stride:4,offset:0,mode:"linear",clampMode:"none"}})}get revision(){return this.appliedRevision}get syncCount(){return this.updateCount}get instanceCount(){return this.instances.length}attach(e){return this.attachedScene===e?this:(this.detach(),e.add(this.glyphField),this.attachedScene=e,this)}detach(){return this.attachedScene&&this.attachedScene.remove(this.glyphField),this.attachedScene=null,this}destroy(){this.detach(),this.ownsGlyphField&&this.glyphField.destroy(),this.instances=[],this.appliedRevision=-1}getInstance(e){if(!Number.isInteger(e)||e<0||e>=this.instances.length)return null;let t=this.instances[e];return{key:t.key,annotationId:t.annotationId,annotationKind:t.annotationKind,role:t.role,anchor:ye(t.anchor),color:zt(t.color)}}sync(e,t){if(y(Number.isFinite(t),"AnnotationMarkerRenderer.sync: revision must be finite."),t===this.appliedRevision)return!1;let r=fl(e),i=r.length>this.maxInstances?r.slice(0,this.maxInstances):r;this.instances=i;let o=i.length;if(o<=0)return this.glyphField.setCPUData(null,null,null,null,{instanceCount:0,keepCPUData:this.keepCPUData}),this.glyphField.visible=!1,this.appliedRevision=t,this.updateCount++,!0;let a=new Float32Array(o*4),s=new Float32Array(o*4),l=new Float32Array(o*4),u=new Float32Array(o*4);for(let c=0;c<o;c++){let m=c*4,d=i[c];a[m+0]=d.anchor.position[0],a[m+1]=d.anchor.position[1],a[m+2]=d.anchor.position[2],a[m+3]=0,s[m+0]=0,s[m+1]=0,s[m+2]=0,s[m+3]=1,l[m+0]=this.markerScale[0],l[m+1]=this.markerScale[1],l[m+2]=this.markerScale[2],l[m+3]=0,u[m+0]=d.color[0],u[m+1]=d.color[1],u[m+2]=d.color[2],u[m+3]=d.color[3]}return this.glyphField.visible=!0,this.glyphField.setCPUData(a,s,l,u,{keepCPUData:this.keepCPUData}),this.appliedRevision=t,this.updateCount++,!0}};var pd={marker:[.9,.8,.2,1],distance:[.2,.8,1,1],angle:[1,.5,.2,1]},pl=(n,e)=>[(n[0]??0)-(e[0]??0),(n[1]??0)-(e[1]??0),(n[2]??0)-(e[2]??0)],hd=(n,e)=>(n[0]??0)*(e[0]??0)+(n[1]??0)*(e[1]??0)+(n[2]??0)*(e[2]??0),hl=n=>Math.hypot(n[0]??0,n[1]??0,n[2]??0),Vt=n=>n.kind==="marker"?{...n,color:zt(n.color),anchor:ye(n.anchor)}:n.kind==="distance"?{...n,color:zt(n.color),start:ye(n.start),end:ye(n.end)}:{...n,color:zt(n.color),a:ye(n.a),b:ye(n.b),c:ye(n.c)},Ni=(n,e)=>{let t=n??pd[e];return[se(t[0],0,1),se(t[1],0,1),se(t[2],0,1),se(t[3],0,1)]},zi=n=>{if(n==null)return null;let e=`${n}`.trim();return e.length>0?e:null},zo=n=>n===void 0?!0:!!n,Oi=(n,e)=>{let t=(n[0]??0)-(e[0]??0),r=(n[1]??0)-(e[1]??0),i=(n[2]??0)-(e[2]??0);return Math.hypot(t,r,i)},Vi=(n,e,t)=>{let r=pl(n,e),i=pl(t,e),o=hl(r),a=hl(i);if(o<=1e-12||a<=1e-12)return 0;let s=se(hd(r,i)/(o*a),-1,1);return Math.acos(s)},gl=(n,e=null)=>({position:Ln(n),pick:e?{...e,ndIndex:e.ndIndex?e.ndIndex.slice():null,attributes:e.attributes?{...e.attributes,vector:e.attributes.vector?[...e.attributes.vector]:null,packedPoint:e.attributes.packedPoint?[...e.attributes.packedPoint]:null}:null}:null}),jr=class{records=new Map;order=[];listeners=new Set;nowMs;idPrefix;idCounter=1;_revision=0;constructor(e={}){this.nowMs=e.nowMs??hr,this.idPrefix=`${e.idPrefix??"ann"}`.trim()}get size(){return this.order.length}get revision(){return this._revision}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}has(e){return this.records.has(e)}ids(){return this.order.slice()}get(e){let t=this.records.get(e);return t?Vt(t):null}values(){let e=new Array(this.order.length);for(let t=0;t<this.order.length;t++)e[t]=Vt(this.records.get(this.order[t]));return e}clear(){return this.records.size===0?this:(this.records.clear(),this.order.length=0,this.bumpRevision(),this)}createMarker(e,t={}){let r=this.nowMs(),i={id:this.nextId("marker"),kind:"marker",label:zi(t.label),visible:zo(t.visible),color:Ni(t.color,"marker"),createdAtMs:r,updatedAtMs:r,anchor:ye(e)};return this.push(i),Vt(i)}createDistance(e,t,r={}){let i=this.nowMs(),o=ye(e),a=ye(t),s={id:this.nextId("distance"),kind:"distance",label:zi(r.label),visible:zo(r.visible),color:Ni(r.color,"distance"),createdAtMs:i,updatedAtMs:i,start:o,end:a,distanceWorld:Oi(o.position,a.position)};return this.push(s),Vt(s)}createAngle(e,t,r,i={}){let o=this.nowMs(),a=ye(e),s=ye(t),l=ye(r),u={id:this.nextId("angle"),kind:"angle",label:zi(i.label),visible:zo(i.visible),color:Ni(i.color,"angle"),createdAtMs:o,updatedAtMs:o,a,b:s,c:l,angleRadians:Vi(a.position,s.position,l.position)};return this.push(u),Vt(u)}updateMarker(e,t){let r=this.records.get(e);return!r||r.kind!=="marker"?null:(this.applyCommonPatch(r,t),t.anchor&&(r.anchor=ye(t.anchor)),r.updatedAtMs=this.nowMs(),this.bumpRevision(),Vt(r))}updateDistance(e,t){let r=this.records.get(e);return!r||r.kind!=="distance"?null:(this.applyCommonPatch(r,t),t.start&&(r.start=ye(t.start)),t.end&&(r.end=ye(t.end)),r.distanceWorld=Oi(r.start.position,r.end.position),r.updatedAtMs=this.nowMs(),this.bumpRevision(),Vt(r))}updateAngle(e,t){let r=this.records.get(e);return!r||r.kind!=="angle"?null:(this.applyCommonPatch(r,t),t.a&&(r.a=ye(t.a)),t.b&&(r.b=ye(t.b)),t.c&&(r.c=ye(t.c)),r.angleRadians=Vi(r.a.position,r.b.position,r.c.position),r.updatedAtMs=this.nowMs(),this.bumpRevision(),Vt(r))}remove(e){if(!this.records.delete(e))return!1;let r=this.order.indexOf(e);return r!==-1&&this.order.splice(r,1),this.bumpRevision(),!0}push(e){y(!this.records.has(e.id),`AnnotationStore: duplicate id '${e.id}'.`),this.records.set(e.id,e),this.order.push(e.id),this.bumpRevision()}applyCommonPatch(e,t){t.label!==void 0&&(e.label=zi(t.label)),t.color!==void 0&&(e.color=Ni(t.color,e.kind)),t.visible!==void 0&&(e.visible=!!t.visible)}nextId(e){let t=String(this.idCounter++).padStart(6,"0");return`${this.idPrefix.length>0?`${this.idPrefix}-`:""}${e}-${t}`}bumpRevision(){this._revision++;for(let e of this.listeners)try{e(this._revision)}catch{}}};var gd=1,bd=(n,e)=>[(n[0]+e[0])*.5,(n[1]+e[1])*.5,(n[2]+e[2])*.5],Ei=n=>n?{...n,vector:n.vector?[...n.vector]:null,packedPoint:n.packedPoint?[...n.packedPoint]:null,color:n.color?[...n.color]:null,edgeEndpoints:n.edgeEndpoints?[...n.edgeEndpoints]:null,edgePositions:n.edgePositions?[...n.edgePositions]:null}:null,Rn=n=>n?{hit:!0,kind:n.kind,objectId:n.objectId,elementIndex:n.elementIndex,worldPosition:[n.worldPosition[0],n.worldPosition[1],n.worldPosition[2]],ndIndex:n.ndIndex?n.ndIndex.slice():null,attributes:Ei(n.attributes)}:{hit:!1,kind:null,objectId:null,elementIndex:null,worldPosition:null,ndIndex:null,attributes:null},Oo=(n,e)=>({...Rn(n),annotationId:e.annotationId,annotationKind:e.annotationKind,anchorRole:e.anchorRole}),vd=n=>{let e=new Array(n.length);for(let t=0;t<n.length;t++){let r=n[t];e[t]={position:[r.position[0],r.position[1],r.position[2]],pick:r.pick?{kind:r.pick.kind,objectId:r.pick.objectId,elementIndex:r.pick.elementIndex,ndIndex:r.pick.ndIndex?r.pick.ndIndex.slice():null,attributes:Ei(r.pick.attributes)}:null}}return e},yd=(n,e)=>{let t=[];for(let r=0;r<n.length;r++){let i=n[r];if(!i.visible)continue;if(i.kind==="marker"){t.push({key:i.id,text:i.label??i.id,color:zr(i.color),position:[i.anchor.position[0],i.anchor.position[1],i.anchor.position[2]]});continue}if(i.kind==="distance"){let s=Fi(i.distanceWorld,e),l=i.label?`${i.label}: ${s.text}`:s.text;t.push({key:i.id,text:l,color:zr(i.color),position:bd(i.start.position,i.end.position)});continue}let o=Ii(i.angleRadians,e),a=i.label?`${i.label}: ${o.text}`:o.text;t.push({key:i.id,text:a,color:zr(i.color),position:[i.b.position[0],i.b.position[1],i.b.position[2]]})}return t},Hr=class{store;markerRenderer;labelLayer;runtime;annotationsListeners=new Set;modeListeners=new Set;hoverListeners=new Set;selectionListeners=new Set;stagingListeners=new Set;autoCreateOverlay;overlaySystemOptions;modeValue=Rt.Idle;unitsValue;scene=null;camera=null;controls=null;overlaySystem=null;ownsOverlaySystem=!1;canvas=null;pointerTarget=null;hoverReadout=Rn(null);selectionReadout=Oo(null,{annotationId:null,annotationKind:null,anchorRole:null});pendingAnchors=[];boundPointerEvents=!1;autoBindPointerEvents;hoverPickToken=0;clickPickToken=0;constructor(e,t={}){this.runtime=e;let r=gd++;this.store=new jr({idPrefix:t.storeIdPrefix??`ann${r}`}),this.markerRenderer=new Wr({...t.markerRenderer,name:t.markerRenderer?.name??`annotation-markers-${r}`}),this.labelLayer=new Vr({...t.labelLayer,id:t.labelLayer?.id??`annotation-label-layer-${r}`}),this.autoBindPointerEvents=t.autoBindPointerEvents??!0,this.autoCreateOverlay=t.autoCreateOverlay??!0,this.overlaySystemOptions=t.overlaySystemOptions??{},this.unitsValue=t.units??{},this.controls=t.controls??null,this.canvas=t.canvas??null,this.pointerTarget=t.pointerTarget??this.canvas,t.overlaySystem&&(this.overlaySystem=t.overlaySystem,this.ownsOverlaySystem=!1),this.store.onChange(()=>this.handleStoreChanged()),this.labelLayer.setHoverReadout(this.hoverReadout),this.labelLayer.setSelectionReadout(this.selectionReadout),t.scene&&t.camera&&this.attach({scene:t.scene,camera:t.camera,controls:this.controls,overlaySystem:this.overlaySystem,pointerTarget:this.pointerTarget})}get mode(){return this.modeValue}get units(){return Or(this.unitsValue)}get revision(){return this.store.revision}get pendingCount(){return this.pendingAnchors.length}get hoverProbe(){return{...this.hoverReadout,worldPosition:this.hoverReadout.worldPosition?[this.hoverReadout.worldPosition[0],this.hoverReadout.worldPosition[1],this.hoverReadout.worldPosition[2]]:null,ndIndex:this.hoverReadout.ndIndex?this.hoverReadout.ndIndex.slice():null,attributes:Ei(this.hoverReadout.attributes)}}get selectionProbe(){return{...this.selectionReadout,worldPosition:this.selectionReadout.worldPosition?[this.selectionReadout.worldPosition[0],this.selectionReadout.worldPosition[1],this.selectionReadout.worldPosition[2]]:null,ndIndex:this.selectionReadout.ndIndex?this.selectionReadout.ndIndex.slice():null,attributes:Ei(this.selectionReadout.attributes)}}onAnnotationsChange(e){return this.annotationsListeners.add(e),()=>this.annotationsListeners.delete(e)}onModeChange(e){return this.modeListeners.add(e),()=>this.modeListeners.delete(e)}onHoverReadout(e){return this.hoverListeners.add(e),()=>this.hoverListeners.delete(e)}onSelectionReadout(e){return this.selectionListeners.add(e),()=>this.selectionListeners.delete(e)}onStagingChange(e){return this.stagingListeners.add(e),()=>this.stagingListeners.delete(e)}setUnits(e){return this.unitsValue=e,this.handleStoreChanged(),this}setMode(e){if(e===this.modeValue)return this;this.modeValue=e,this.clearPending();for(let t of this.modeListeners)try{t(this.modeValue)}catch{}return this}cancel(){this.modeValue=Rt.Idle,this.clearPending();for(let e of this.modeListeners)try{e(this.modeValue)}catch{}return this}attach(e){return this.scene=e.scene,this.camera=e.camera,e.controls!==void 0&&(this.controls=e.controls??null),e.pointerTarget!==void 0&&(this.pointerTarget=e.pointerTarget??this.pointerTarget),e.overlaySystem!==void 0&&(this.detachOverlayLayer(),this.overlaySystem=e.overlaySystem??null,this.ownsOverlaySystem=!1),this.markerRenderer.attach(this.scene),this.ensureOverlaySystem(),this.ensureOverlayLayer(),this.overlaySystem?.setView(this.camera,this.scene),this.handleStoreChanged(),this.autoBindPointerEvents&&this.bindPointerEvents(),this}setView(e,t=this.scene){return this.camera=e,t&&(this.scene=t),this.scene&&this.markerRenderer.attach(this.scene),this.overlaySystem?.setView(this.camera,this.scene),this.overlaySystem?.invalidate("camera"),this}detach(){return this.unbindPointerEvents(),this.detachOverlayLayer(),this.ownsOverlaySystem&&this.overlaySystem?.destroy(),this.overlaySystem=null,this.ownsOverlaySystem=!1,this.markerRenderer.detach(),this.scene=null,this.camera=null,this.clearPending(),this.hoverPickToken++,this.clickPickToken++,this.setHoverReadout(Rn(null)),this.setSelectionReadout(Oo(null,{annotationId:null,annotationKind:null,anchorRole:null})),this}destroy(){this.detach(),this.markerRenderer.destroy()}bindPointerTarget(e){return this.unbindPointerEvents(),this.pointerTarget=e,this.autoBindPointerEvents&&this.bindPointerEvents(),this}setAutoBindPointerEvents(e){return this.autoBindPointerEvents=!!e,this.autoBindPointerEvents?this.bindPointerEvents():this.unbindPointerEvents(),this}getAnnotations(){return this.store.values()}createMarker(e,t={}){return this.store.createMarker(e,t)}createDistance(e,t,r={}){return this.store.createDistance(e,t,r)}createAngle(e,t,r,i={}){return this.store.createAngle(e,t,r,i)}updateAnnotation(e,t){let r=this.store.get(e);return r?r.kind==="marker"?this.store.updateMarker(e,t):r.kind==="distance"?this.store.updateDistance(e,t):this.store.updateAngle(e,t):null}removeAnnotation(e){return this.store.remove(e)}removeSelectionAnnotation(){let e=this.selectionReadout.annotationId;return e?this.store.remove(e):!1}clearAnnotations(){return this.store.clear(),this}ingestHoverHit(e){let t=Rn(e);return this.setHoverReadout(t),t}ingestSelectionHit(e){let t=this.resolveSelectionMeta(e);if(this.setSelectionReadout(Oo(e,t)),!e)return this.modeValue===Rt.Idle&&this.clearPending(),null;if(this.modeValue===Rt.Marker)return this.store.createMarker(Nr(e));if(this.modeValue===Rt.Distance){if(this.pendingAnchors.push(Nr(e)),this.emitStaging(),this.pendingAnchors.length<2)return null;let r=this.store.createDistance(this.pendingAnchors[0],this.pendingAnchors[1]);return this.clearPending(),r}if(this.modeValue===Rt.Angle){if(this.pendingAnchors.push(Nr(e)),this.emitStaging(),this.pendingAnchors.length<3)return null;let r=this.store.createAngle(this.pendingAnchors[0],this.pendingAnchors[1],this.pendingAnchors[2]);return this.clearPending(),r}return this.clearPending(),null}async pickHoverAt(e,t){let r=this.scene,i=this.camera;if(!r||!i)return this.ingestHoverHit(null);let o=++this.hoverPickToken;try{let a=await this.runtime.pick(r,i,e,t,{includeAttributes:!0});return o!==this.hoverPickToken?this.hoverProbe:this.ingestHoverHit(a)}catch{return o!==this.hoverPickToken?this.hoverProbe:this.ingestHoverHit(null)}}async pickAtAndCommit(e,t){let r=this.scene,i=this.camera;if(!r||!i)return this.ingestSelectionHit(null);let o=++this.clickPickToken;try{let a=await this.runtime.pick(r,i,e,t,{includeAttributes:!0});return o!==this.clickPickToken?null:this.ingestSelectionHit(a)}catch{return o!==this.clickPickToken?null:this.ingestSelectionHit(null)}}handleStoreChanged(){let e=this.store.values();this.markerRenderer.sync(e,this.store.revision),this.labelLayer.setEntries(yd(e,this.unitsValue),this.store.revision),this.overlaySystem?.invalidate("manual");for(let t of this.annotationsListeners)try{t(e,this.store.revision)}catch{}}ensureOverlaySystem(){this.overlaySystem||this.autoCreateOverlay&&(!this.runtime.createOverlay||!this.camera||(this.overlaySystem=this.runtime.createOverlay.system({controls:this.controls??void 0,camera:this.camera,scene:this.scene,autoUpdate:!0,...this.overlaySystemOptions}),this.ownsOverlaySystem=!0))}ensureOverlayLayer(){this.overlaySystem&&(this.overlaySystem.removeLayer(this.labelLayer.id),this.overlaySystem.addLayer(this.labelLayer))}detachOverlayLayer(){this.overlaySystem&&this.overlaySystem.removeLayer(this.labelLayer.id)}setHoverReadout(e){this.hoverReadout=e,this.labelLayer.setHoverReadout(e);for(let t of this.hoverListeners)try{t(this.hoverProbe)}catch{}}setSelectionReadout(e){this.selectionReadout=e,this.labelLayer.setSelectionReadout(e);for(let t of this.selectionListeners)try{t(this.selectionProbe)}catch{}}resolveSelectionMeta(e){if(!e)return{annotationId:null,annotationKind:null,anchorRole:null};if(e.kind!=="glyphfield"||e.object!==this.markerRenderer.glyphField)return{annotationId:null,annotationKind:null,anchorRole:null};let t=this.markerRenderer.getInstance(e.elementIndex);return t?{annotationId:t.annotationId,annotationKind:t.annotationKind,anchorRole:t.role}:{annotationId:null,annotationKind:null,anchorRole:null}}clearPending(){this.pendingAnchors.length!==0&&(this.pendingAnchors.length=0,this.emitStaging())}emitStaging(){let e=vd(this.pendingAnchors);for(let t of this.stagingListeners)try{t(this.modeValue,e)}catch{}}bindPointerEvents(){this.boundPointerEvents||!this.pointerTarget||(this.pointerTarget.addEventListener("pointermove",this.onPointerMove),this.pointerTarget.addEventListener("pointerleave",this.onPointerLeave),this.pointerTarget.addEventListener("click",this.onClick),this.boundPointerEvents=!0)}unbindPointerEvents(){!this.boundPointerEvents||!this.pointerTarget||(this.pointerTarget.removeEventListener("pointermove",this.onPointerMove),this.pointerTarget.removeEventListener("pointerleave",this.onPointerLeave),this.pointerTarget.removeEventListener("click",this.onClick),this.boundPointerEvents=!1)}clientToLocal(e,t){let r=this.pointerTarget?.getBoundingClientRect();return r?{x:e-r.left,y:t-r.top}:{x:e,y:t}}onPointerMove=e=>{if(!this.scene||!this.camera)return;let{x:t,y:r}=this.clientToLocal(e.clientX,e.clientY);this.pickHoverAt(t,r)};onPointerLeave=()=>{this.hoverPickToken++,this.ingestHoverHit(null)};onClick=e=>{if(e.button!==0||!this.scene||!this.camera)return;let{x:t,y:r}=this.clientToLocal(e.clientX,e.clientY);this.pickAtAndCommit(t,r)}},bl=Rn;var xd=n=>typeof n=="object"&&n!==null&&typeof n.getBuffer=="function",Pd=n=>typeof n=="object"&&n!==null&&typeof n.data=="object"&&Array.isArray(n.shape),$r=n=>{let e=new Array(n.length);for(let t=0;t<n.length;t++){let r=n[t];y(Number.isFinite(r),`shape[${t}] must be finite`),y(Number.isInteger(r),`shape[${t}] must be an integer`),y(r>=0,`shape[${t}] must be >= 0`),e[t]=r>>>0}return e},ji=n=>{if(n.length===0)return 1;let e=1;for(let t of n){let r=t>>>0,i=e*r;y(Number.isSafeInteger(i),"shape is too large (numel overflow)"),e=i}return e>>>0},vl=n=>n instanceof Float32Array?"f32":n instanceof Float64Array?"f64":n instanceof Int8Array?"i8":n instanceof Uint8Array||n instanceof Uint8ClampedArray?"u8":n instanceof Int16Array?"i16":n instanceof Uint16Array?"u16":n instanceof Int32Array?"i32":n instanceof Uint32Array?"u32":null,yl=(n,e,t=0,r)=>{let i=Ce(n),o=i.ctor,a=i.bytesPerElement>>>0,s=t>>>0,l=r===void 0?(e.byteLength>>>0)/a>>>0:r>>>0,u=(e.byteOffset>>>0)+s*a>>>0;return new o(e.buffer,u>>>0,l>>>0)},Td=(n,e,t)=>{let r=n>>>0,i=e>>>0,o=i===0?16:i;if((o&o-1)!==0)throw new Error(`allocBytes(${n}, ${e}): align must be a power of two`);if(t==="frame")return{kind:"frame",ptr:W.alloc(r,o)>>>0};if(t&&typeof t=="object"){let l=t,u=l.epoch()>>>0;return{kind:"arena",ptr:l.alloc(r,o)>>>0,epoch:u}}let a=_.allocBytes(r)>>>0;if(!a&&r!==0)throw new Error(`wasm.allocBytes(${r}) failed`);let s=Math.min(o,8)>>>0;if(s!==0&&(a&s-1)!==0)throw new Error(`wasm.allocBytes(${r}) returned ptr 0x${a.toString(16)} which is not ${s}-byte aligned`);return{kind:"heap",ptr:a}},Wi=(n,e,t)=>{let i=Ce(n).ctor,o=de.buffer();return new i(o,e>>>0,t>>>0)},Sd=(n,e)=>{let t=de.bytes(),r=n>>>0,i=r+(e>>>0)>>>0;return t.subarray(r,i)},Cd=n=>{if(typeof n.c_contiguous=="boolean"){y(n.c_contiguous,'Python buffer must be C-contiguous (use numpy.ascontiguousarray(..., order="C"))');return}let e=$r(n.shape??[]),t=Array.from(n.strides??[]);if(y(t.length===e.length,"Python buffer strides/shape rank mismatch"),ji(e)===0)return;let r=1;for(let i=e.length-1;i>=0;i--)y(t[i]===r,'Python buffer must be C-contiguous (use numpy.ascontiguousarray(..., order="C"))'),r*=e[i]},Vo=(n,e)=>{if(xd(n)){let s=n.getBuffer(),l=Vo(s,e),u=typeof s.release=="function"?()=>s.release?.():void 0;return{...l,release:u}}if(Pd(n)){Cd(n),y(ArrayBuffer.isView(n.data),"Python buffer .data must be an ArrayBufferView"),y(typeof n.data.subarray=="function","Python buffer .data must be a TypedArray (DataView is not supported)");let s=vl(n.data);y(s!==null,"Unsupported Python buffer dtype (expected a numeric TypedArray)");let l=e.dtype??s;y(l===s,`dtype mismatch: expected ${l}, got ${s}`);let u=$r(n.shape),c=$r(e.shape??u),m=ji(c),d=(n.offset??0)>>>0,f=yl(l,n.data,d,m);return y(f.length>>>0===m>>>0,"Python buffer view length mismatch"),e.shape&&y($r(e.shape).length===u.length&&$r(e.shape).every((p,h)=>p===u[h]),"shape mismatch"),{dtype:l,shape:c,data:f,release:typeof n.release=="function"?()=>n.release?.():void 0}}y(ArrayBuffer.isView(n),"Expected a TypedArray / ArrayBufferView or a PyProxy supporting getBuffer()");let t=vl(n);y(t!==null,"Unsupported TypedArray dtype");let r=e.dtype??t;y(r===t,`dtype mismatch: expected ${r}, got ${t}`),y(e.shape,"shape is required when sending a plain TypedArray (no Python buffer metadata available)");let i=$r(e.shape),o=ji(i);y(n.byteLength>>>0>=o*Ce(r).bytesPerElement,"source TypedArray is too small for the provided shape");let a=yl(r,n,0,o);return y(a.length>>>0===o>>>0,"source TypedArray length mismatch"),{dtype:r,shape:i,data:a}},Hi={sendNdarray:(n,e={})=>{let t=Vo(n,e),{dtype:r,shape:i,data:o}=t,a=Ce(r),s=ji(i),l=s*a.bytesPerElement>>>0,u=Td(l,16,e.allocator);Wi(r,u.ptr,s).set(o);try{t.release?.()}catch{}let m={kind:u.kind,dtype:r,shape:i,ptr:u.ptr>>>0,length:s>>>0,byteLength:l>>>0};return u.epoch!==void 0&&(m.epoch=u.epoch>>>0),m},view:n=>Wi(n.dtype,n.ptr,n.length),bytes:n=>Sd(n.ptr,n.byteLength),copyInto:(n,e,t={})=>{let r=Vo(e,{...t,dtype:n.dtype,shape:n.shape}),{data:i}=r;y(i.length>>>0===n.length>>>0,"copyInto: source length mismatch"),Wi(n.dtype,n.ptr,n.length).set(i);try{r.release?.()}catch{}},receiveNdarray:(n,e={})=>{let t=Wi(n.dtype,n.ptr,n.length);if(!e.copy)return{dtype:n.dtype,shape:Array.from(n.shape),data:t};let i=Ce(n.dtype).ctor,o=new i(n.length>>>0);return o.set(t),{dtype:n.dtype,shape:Array.from(n.shape),data:o}},free:n=>{if(n.kind!=="heap")throw new Error(`pythonInterop.free(): cannot free a ${n.kind} allocation. Use reset() for arena-like allocators (frameArena.reset() / WasmHeapArena.reset()).`);_.freeBytes(n.ptr>>>0,n.byteLength>>>0)}};var wd={Y_UP_RH:{right:[1,0,0],up:[0,1,0],forward:[0,0,1]},Z_UP_RH:{right:[1,0,0],up:[0,0,1],forward:[0,-1,0]},X_UP_RH:{right:[0,0,1],up:[1,0,0],forward:[0,1,0]}},ee=1e-6,xl=.001,Pl=.35,Ke=(n,e,t)=>Math.max(e,Math.min(t,n)),$i=n=>Ke(n,0,1),dt=(n,e,t)=>n+(e-n)*t,_d=n=>n<.5?4*n*n*n:1-Math.pow(-2*n+2,3)*.5,ge=n=>[n[0]??0,n[1]??0,n[2]??0],De=(n,e)=>[n[0]+e[0],n[1]+e[1],n[2]+e[2]],lr=(n,e)=>[n[0]-e[0],n[1]-e[1],n[2]-e[2]],X=(n,e)=>[n[0]*e,n[1]*e,n[2]*e],qe=(n,e)=>n[0]*e[0]+n[1]*e[1]+n[2]*e[2],cr=(n,e)=>[n[1]*e[2]-n[2]*e[1],n[2]*e[0]-n[0]*e[2],n[0]*e[1]-n[1]*e[0]],ur=n=>Math.hypot(n[0],n[1],n[2]),pe=(n,e=[0,0,1])=>{let t=ur(n);if(t<=ee)return ge(e);let r=1/t;return[n[0]*r,n[1]*r,n[2]*r]},Eo=(n,e,t)=>[dt(n[0],e[0],t),dt(n[1],e[1],t),dt(n[2],e[2],t)],Tl=(n,e,t,r,i,o,a,s)=>[r*i+n*s+e*a-t*o,r*o-n*a+e*s+t*i,r*a+n*o-e*i+t*s,r*s-n*i-e*o-t*a],Bd=(n,e,t,r)=>[-n,-e,-t,r],Wo=(n,e,t,r)=>{let i=Math.hypot(n,e,t,r);if(i<=ee)return[0,0,0,1];let o=1/i;return[n*o,e*o,t*o,r*o]},Sl=(n,e,t,r,i,o,a)=>{let s=2*(i*t-o*e),l=2*(o*n-r*t),u=2*(r*e-i*n);return[n+a*s+(i*u-o*l),e+a*l+(o*s-r*u),t+a*u+(r*l-i*s)]},kd=(n,e,t,r)=>Math.abs(n)<ee&&Math.abs(e)<ee&&Math.abs(t)<ee&&Math.abs(1-r)<ee,Md=(n,e,t,r,i)=>{let o=$i(i),a=Ke(r,-1,1),s=n,l=e,u=t,c=r;if(a<0&&(a=-a,s=-s,l=-l,u=-u,c=-c),a>=.9995)return Wo(s*o,l*o,u*o,1-o+c*o);let m=Math.acos(a),d=Math.sqrt(1-a*a);if(d<=ee)return[0,0,0,1];let f=Math.sin((1-o)*m)/d,p=Math.sin(o*m)/d;return[s*p,l*p,u*p,f+c*p]},Cl=n=>{if(!n||n==="y-up-rh")return{right:[1,0,0],up:[0,1,0],forward:[0,0,1]};if(n==="z-up-rh")return{right:[1,0,0],up:[0,0,1],forward:[0,-1,0]};if(n==="x-up-rh")return{right:[0,0,1],up:[1,0,0],forward:[0,1,0]};let e=n.right??cr(n.up,n.forward),t=pe(e,[1,0,0]),r=pe(n.up,[0,1,0]),i=pe(cr(t,r),n.forward),o=pe(cr(r,i),t),a=pe(cr(i,o),r);return{right:o,up:a,forward:i}},mr=class{camera;domElement;target;enabled=!0;enableRotate=!0;enablePan=!0;enableZoom=!0;rotateSpeed=1;panSpeed=1;zoomSpeed=1;zoomOnCursor=!1;enableDamping=!1;dampingFactor=.1;minDistance=0;maxDistance=1/0;minZoom=.01;maxZoom=1/0;minPolarAngle=0;maxPolarAngle=Math.PI;minAzimuthAngle=-1/0;maxAzimuthAngle=1/0;mouseButtons={rotate:0,zoom:1,pan:2};_mode;_axisConvention=Cl(void 0);_state="none";_pointerId=null;_pointerX=0;_pointerY=0;_zoomCursorClientX=0;_zoomCursorClientY=0;_zoomCursorValid=!1;_transition=null;_theta=0;_phi=Math.PI*.5;_thetaDelta=0;_phiDelta=0;_trackballRotateStart=[0,0,1];_trackballRotationDelta=[0,0,0,1];_trackballEye=[0,0,1];_trackballUp=[0,1,0];_radius=1;_zoom=1;_dollyDelta=0;_panOffset=[0,0,0];_orthoBaseLeft=-1;_orthoBaseRight=1;_orthoBaseTop=1;_orthoBaseBottom=-1;_savedTarget=[0,0,0];_savedPosition=[0,0,1];_savedUp=[0,1,0];_savedProjection={type:"perspective",near:.1,far:1e3};_wheelListenerOptions={passive:!1};_changeListeners=new Set;_interactionListeners=new Set;_interactionActive=!1;_wheelInteractionTimer=null;constructor(e,t,r={}){this.camera=e,this.domElement=t,this.target=r.target?ge(r.target):[0,0,0],this._mode=r.mode??"orbit",this.axisConvention=r.axisConvention??"y-up-rh",r.enabled!==void 0&&(this.enabled=r.enabled),r.enableRotate!==void 0&&(this.enableRotate=r.enableRotate),r.enablePan!==void 0&&(this.enablePan=r.enablePan),r.enableZoom!==void 0&&(this.enableZoom=r.enableZoom),r.rotateSpeed!==void 0&&(this.rotateSpeed=r.rotateSpeed),r.panSpeed!==void 0&&(this.panSpeed=r.panSpeed),r.zoomSpeed!==void 0&&(this.zoomSpeed=r.zoomSpeed),r.zoomOnCursor!==void 0&&(this.zoomOnCursor=r.zoomOnCursor),r.enableDamping!==void 0&&(this.enableDamping=r.enableDamping),r.dampingFactor!==void 0&&(this.dampingFactor=r.dampingFactor),r.minDistance!==void 0&&(this.minDistance=r.minDistance),r.maxDistance!==void 0&&(this.maxDistance=r.maxDistance),r.minZoom!==void 0&&(this.minZoom=r.minZoom),r.maxZoom!==void 0&&(this.maxZoom=r.maxZoom),r.minPolarAngle!==void 0&&(this.minPolarAngle=r.minPolarAngle),r.maxPolarAngle!==void 0&&(this.maxPolarAngle=r.maxPolarAngle),r.minAzimuthAngle!==void 0&&(this.minAzimuthAngle=r.minAzimuthAngle),r.maxAzimuthAngle!==void 0&&(this.maxAzimuthAngle=r.maxAzimuthAngle),r.mouseButtons&&(r.mouseButtons.rotate!==void 0&&(this.mouseButtons.rotate=r.mouseButtons.rotate),r.mouseButtons.zoom!==void 0&&(this.mouseButtons.zoom=r.mouseButtons.zoom),r.mouseButtons.pan!==void 0&&(this.mouseButtons.pan=r.mouseButtons.pan)),this.domElement.style.touchAction="none",this.syncFromCamera(),this.saveState(),this.domElement.addEventListener("pointerdown",this.onPointerDown),this.domElement.addEventListener("pointermove",this.onPointerMove),this.domElement.addEventListener("pointerup",this.onPointerUp),this.domElement.addEventListener("pointercancel",this.onPointerUp),this.domElement.addEventListener("wheel",this.onWheel,this._wheelListenerOptions),this.domElement.addEventListener("contextmenu",this.onContextMenu)}dispose(){this.cancelTransition(),this.clearWheelInteractionTimer(),this.setInteractionState(!1),this.domElement.removeEventListener("pointerdown",this.onPointerDown),this.domElement.removeEventListener("pointermove",this.onPointerMove),this.domElement.removeEventListener("pointerup",this.onPointerUp),this.domElement.removeEventListener("pointercancel",this.onPointerUp),this.domElement.removeEventListener("wheel",this.onWheel,this._wheelListenerOptions),this.domElement.removeEventListener("contextmenu",this.onContextMenu),this._changeListeners.clear(),this._interactionListeners.clear()}onChange(e){return this._changeListeners.add(e),()=>{this._changeListeners.delete(e)}}onInteractionState(e){return this._interactionListeners.add(e),()=>{this._interactionListeners.delete(e)}}get mode(){return this._mode}set mode(e){this.setMode(e)}get axisConvention(){return{right:ge(this._axisConvention.right),up:ge(this._axisConvention.up),forward:ge(this._axisConvention.forward)}}set axisConvention(e){this._axisConvention=Cl(e),this.syncFromCamera()}get azimuthAngle(){return this._theta}set azimuthAngle(e){this._theta=e}get polarAngle(){return this._phi}set polarAngle(e){this._phi=e}get distance(){return this._radius}set distance(e){let t=Math.max(ee,e);if(this._radius=t,this._mode==="trackball"){let r=pe(this._trackballEye,this._axisConvention.forward);this._trackballEye=X(r,t)}}get zoom(){return this._zoom}set zoom(e){this._zoom=Ke(e,this.minZoom,this.maxZoom)}get hasActiveTransition(){return this._transition!==null}setCamera(e){return this.camera=e,this.cancelTransition(),this.syncFromCamera(),this.emitChange(),this}setMode(e){return e===this._mode?this:(this.syncFromCamera(),this._mode=e,this.syncFromCamera(),this)}syncFromCamera(){let e=ge(this.camera.position),t=lr(e,this.target);if(this._radius=Math.max(ee,ur(t)),this.camera.type==="orthographic"){let i=this.camera;this._orthoBaseLeft=i.left,this._orthoBaseRight=i.right,this._orthoBaseTop=i.top,this._orthoBaseBottom=i.bottom,this._zoom=1}let r=this.offsetToSpherical(t);this._theta=r.theta,this._phi=r.phi,this._thetaDelta=0,this._phiDelta=0,this._dollyDelta=0,this._panOffset=[0,0,0],this._trackballEye=t,this._trackballUp=pe(this.camera.up,this._axisConvention.up),this._trackballRotateStart=[0,0,1],this._trackballRotationDelta=[0,0,0,1]}saveState(){this._savedTarget=ge(this.target),this._savedPosition=ge(this.camera.position),this._savedUp=pe(this.camera.up,this._axisConvention.up),this._savedProjection=this.captureProjectionState()}reset(){this.cancelTransition(),this.applyPose(this._savedPosition,this._savedTarget,this._savedUp),this.applyProjectionState(this._savedProjection),this.syncFromCamera(),this.emitChange()}setTarget(e,t,r){return typeof e=="number"?this.target=[e,t??0,r??0]:this.target=ge(e),this}cancelTransition(){return this._transition=null,this}update(e=0){if(!this.enabled)return;let t=e>0?e:1/60;if(this._transition){this.updateTransition(t),this.emitChange();return}this._mode==="orbit"?this.updateOrbit(t):this.updateTrackball(t),this.emitChange()}setView(e,t={}){let r=this.getInspectionViewDirection(e),i=t.up?pe(t.up,this._axisConvention.up):this.getInspectionViewUp(e),o=t.target?ge(t.target):ge(this.target),a=Math.max(ee,t.distance??this._radius),s=De(o,X(r,a));return this.applyPoseOrTransition(s,o,i,this.captureProjectionState(),t.animate,t.duration),this}fitScene(e,t={}){return this.fitToBounds(e.getBounds(),t)}viewBounds(e,t,r={}){return this.fitToBounds(t,{...r,view:e})}fitToBounds(e,t={}){let r=this.resolveBounds(e);if(r.empty)return r;let i=this.solveFit(r,t);return this.applyPoseOrTransition(i.position,i.target,i.up,i.projection,t.animate,t.duration),r}updateTransition(e){let t=this._transition;if(!t)return;t.elapsed+=e;let r=$i(t.elapsed/Math.max(ee,t.duration)),i=_d(r),o=Eo(t.fromPosition,t.toPosition,i),a=Eo(t.fromTarget,t.toTarget,i),s=pe(Eo(t.fromUp,t.toUp,i),t.toUp);this.applyPose(o,a,s),this.applyProjectionState(this.lerpProjectionState(t.fromProjection,t.toProjection,i)),r>=1&&(this._transition=null,this.syncFromCamera())}onPointerDown=e=>{!this.enabled||this._pointerId!==null||(this.cancelTransition(),this._pointerId=e.pointerId,this.domElement.setPointerCapture(this._pointerId),this._pointerX=e.clientX,this._pointerY=e.clientY,this._zoomCursorClientX=e.clientX,this._zoomCursorClientY=e.clientY,this._zoomCursorValid=!0,e.button===this.mouseButtons.rotate?this._state="rotate":e.button===this.mouseButtons.pan?this._state="pan":e.button===this.mouseButtons.zoom?this._state="zoom":this._state="none",this._state!=="none"&&this.setInteractionState(!0),this._state==="rotate"&&this._mode==="trackball"&&(this._trackballRotateStart=this.getTrackballVector(e.clientX,e.clientY)),e.preventDefault())};onPointerMove=e=>{if(!this.enabled||this._pointerId===null||e.pointerId!==this._pointerId)return;let t=e.clientX-this._pointerX,r=e.clientY-this._pointerY;if(this._pointerX=e.clientX,this._pointerY=e.clientY,this._zoomCursorClientX=e.clientX,this._zoomCursorClientY=e.clientY,this._zoomCursorValid=!0,!(t===0&&r===0)){if(this._state==="rotate"&&this.enableRotate)if(this._mode==="orbit"){let i=Math.max(1,this.getViewportHeight()),o=2*Math.PI/i;this._thetaDelta+=-t*o*this.rotateSpeed,this._phiDelta+=-r*o*this.rotateSpeed}else{let i=this.getTrackballVector(e.clientX,e.clientY),o=this.rotationFromTrackballDrag(this._trackballRotateStart,i);o&&(this._trackballRotationDelta=Wo(...Tl(o[0],o[1],o[2],o[3],this._trackballRotationDelta[0],this._trackballRotationDelta[1],this._trackballRotationDelta[2],this._trackballRotationDelta[3]))),this._trackballRotateStart=i}else this._state==="pan"&&this.enablePan?this._mode==="orbit"?this.panOrbit(t,r):this.panTrackball(t,r):this._state==="zoom"&&this.enableZoom&&(this._dollyDelta+=r*this.zoomSpeed*.002);e.preventDefault()}};onPointerUp=e=>{this._pointerId===null||e.pointerId!==this._pointerId||(this.domElement.releasePointerCapture(this._pointerId),this._pointerId=null,this._state="none",this.setInteractionState(!1),e.preventDefault())};onWheel=e=>{!this.enabled||!this.enableZoom||(this.cancelTransition(),this._dollyDelta+=e.deltaY*this.zoomSpeed*.001,this._zoomCursorClientX=e.clientX,this._zoomCursorClientY=e.clientY,this._zoomCursorValid=!0,this.setInteractionState(!0),this.scheduleWheelInteractionEnd(),e.preventDefault(),e.stopPropagation())};onContextMenu=e=>{e.preventDefault()};getViewportRect(){let e=this.domElement.getBoundingClientRect(),t=Math.max(1,e.width||this.domElement.clientWidth||1),r=Math.max(1,e.height||this.domElement.clientHeight||1);return{left:e.left,top:e.top,width:t,height:r}}getViewportWidth(){return this.getViewportRect().width}getViewportHeight(){return this.getViewportRect().height}getAspect(e){return e&&e>0?e:this.getViewportWidth()/Math.max(1,this.getViewportHeight())}captureProjectionState(){if(this.camera.type==="orthographic"){let t=this.camera;return{type:"orthographic",left:t.left,right:t.right,top:t.top,bottom:t.bottom,near:t.near,far:t.far}}let e=this.camera;return{type:"perspective",near:e.near,far:e.far}}applyProjectionState(e){if(e.type==="orthographic"&&this.camera.type==="orthographic"){let t=this.camera;t.left=e.left,t.right=e.right,t.top=e.top,t.bottom=e.bottom,t.near=e.near,t.far=e.far}else if(e.type==="perspective"&&this.camera.type==="perspective"){let t=this.camera;t.near=e.near,t.far=e.far}}lerpProjectionState(e,t,r){return e.type==="orthographic"&&t.type==="orthographic"?{type:"orthographic",left:dt(e.left,t.left,r),right:dt(e.right,t.right,r),top:dt(e.top,t.top,r),bottom:dt(e.bottom,t.bottom,r),near:dt(e.near,t.near,r),far:dt(e.far,t.far,r)}:{type:"perspective",near:dt(e.near,t.near,r),far:dt(e.far,t.far,r)}}applyPose(e,t,r){this.target=ge(t),this.camera.transform.setPosition(e[0],e[1],e[2]),this.camera.lookAtWithUp(t,r)}applyPoseOrTransition(e,t,r,i,o,a){if(!(o??!0)||(a??Pl)<=0){this.cancelTransition(),this.applyPose(e,t,r),this.applyProjectionState(i),this.syncFromCamera(),this.emitChange();return}this._transition={elapsed:0,duration:a??Pl,fromPosition:ge(this.camera.position),toPosition:ge(e),fromTarget:ge(this.target),toTarget:ge(t),fromUp:pe(this.camera.up,this._axisConvention.up),toUp:pe(r,this._axisConvention.up),fromProjection:this.captureProjectionState(),toProjection:i}}updateOrbit(e){let t=this.enableDamping?1-Math.pow(1-$i(this.dampingFactor),e*60):1;this.enableRotate?(this._theta+=this._thetaDelta*t,this._phi+=this._phiDelta*t,this._thetaDelta*=1-t,this._phiDelta*=1-t):(this._thetaDelta=0,this._phiDelta=0);let r=Math.max(this.minPolarAngle,xl),i=Math.min(this.maxPolarAngle,Math.PI-xl);r<=i?this._phi=Ke(this._phi,r,i):this._phi=Ke(this._phi,this.minPolarAngle,this.maxPolarAngle),this._theta=Ke(this._theta,this.minAzimuthAngle,this.maxAzimuthAngle),this.applyDolly(t,this.computeOrbitBasis()),this.applyPan(t),this._radius=Ke(this._radius,this.minDistance,this.maxDistance);let o=this.sphericalToOffset(this._theta,this._phi,Math.max(ee,this._radius)),a=De(this.target,o),s=pe(lr(this.target,a),X(this._axisConvention.forward,-1)),l=this.getOrbitUp(s);this.camera.transform.setPosition(a[0],a[1],a[2]),this.camera.lookAtWithUp(this.target,l),this.camera.type==="orthographic"?this.applyOrthographicZoom():this.relaxPerspectiveClipForZoom()}updateTrackball(e){let t=this.enableDamping?1-Math.pow(1-$i(this.dampingFactor),e*60):1;if(this.enableRotate){let o=this._trackballRotationDelta;if(!kd(o[0],o[1],o[2],o[3])){let a=Md(o[0],o[1],o[2],o[3],t);this._trackballEye=Sl(this._trackballEye[0],this._trackballEye[1],this._trackballEye[2],a[0],a[1],a[2],a[3]),this._trackballUp=pe(Sl(this._trackballUp[0],this._trackballUp[1],this._trackballUp[2],a[0],a[1],a[2],a[3]),this._axisConvention.up);let s=Tl(o[0],o[1],o[2],o[3],...Bd(a[0],a[1],a[2],a[3]));this._trackballRotationDelta=Wo(s[0],s[1],s[2],s[3])}}else this._trackballRotationDelta=[0,0,0,1];this.applyDolly(t,this.computeTrackballBasis()),this.applyPan(t);let r=ur(this._trackballEye);this._radius=Ke(Math.max(ee,r),this.minDistance,this.maxDistance),r>ee?this._trackballEye=X(this._trackballEye,this._radius/r):this._trackballEye=X(this._axisConvention.forward,this._radius);let i=De(this.target,this._trackballEye);this.camera.transform.setPosition(i[0],i[1],i[2]),this.camera.lookAtWithUp(this.target,this._trackballUp),this.camera.type==="orthographic"?this.applyOrthographicZoom():this.relaxPerspectiveClipForZoom()}emitChange(){for(let e of this._changeListeners)try{e()}catch{}}setInteractionState(e){if(this._interactionActive!==e){this._interactionActive=e;for(let t of this._interactionListeners)try{t(e)}catch{}}}clearWheelInteractionTimer(){this._wheelInteractionTimer!==null&&(clearTimeout(this._wheelInteractionTimer),this._wheelInteractionTimer=null)}scheduleWheelInteractionEnd(){this.clearWheelInteractionTimer(),this._wheelInteractionTimer=setTimeout(()=>{this._wheelInteractionTimer=null,this._pointerId===null&&this._state==="none"&&this.setInteractionState(!1)},120)}applyDolly(e,t){if(!this.enableZoom){this._dollyDelta=0;return}let r=this._dollyDelta*e;if(Math.abs(r)<=ee){this._dollyDelta*=1-e;return}let i=this._radius,o=this._zoom;if(this.camera.type==="orthographic")this._zoom=Ke(this._zoom*Math.exp(-r),this.minZoom,this.maxZoom);else{let a=Ke(this._radius*Math.exp(r),this.minDistance,this.maxDistance);if(this._mode==="trackball"){let s=Math.max(ee,ur(this._trackballEye));this._trackballEye=X(this._trackballEye,a/s)}this._radius=a}this.zoomOnCursor&&this._zoomCursorValid&&this.applyZoomOnCursor(i,o,t),this._dollyDelta*=1-e}applyPan(e){if(!this.enablePan){this._panOffset=[0,0,0];return}this.target[0]+=this._panOffset[0]*e,this.target[1]+=this._panOffset[1]*e,this.target[2]+=this._panOffset[2]*e,this._panOffset=X(this._panOffset,1-e)}panOrbit(e,t){let r=this.computeOrbitBasis();this.queuePan(e,t,r)}panTrackball(e,t){let r=this.computeTrackballBasis();this.queuePan(e,t,r)}queuePan(e,t,r){let i=Math.max(1,this.getViewportWidth()),o=Math.max(1,this.getViewportHeight()),a=0,s=0;if(this.camera.type==="orthographic"){let l=(this._orthoBaseRight-this._orthoBaseLeft)/Math.max(ee,this._zoom),u=(this._orthoBaseTop-this._orthoBaseBottom)/Math.max(ee,this._zoom);a=e*l/i*this.panSpeed,s=t*u/o*this.panSpeed}else{let l=this.camera,u=this._radius*Math.tan(l.fov*Math.PI/180*.5);a=2*e*u/o*this.panSpeed,s=2*t*u/o*this.panSpeed}this._panOffset=De(this._panOffset,De(X(r.right,-a),X(r.up,s)))}applyZoomOnCursor(e,t,r){let i=this.getViewportRect(),o=(this._zoomCursorClientX-i.left)/i.width,a=(this._zoomCursorClientY-i.top)/i.height,s=o*2-1,l=1-a*2;if(this.camera.type==="orthographic"){let g=this._orthoBaseRight-this._orthoBaseLeft,b=this._orthoBaseTop-this._orthoBaseBottom,P=g/Math.max(ee,t)*.5,v=g/Math.max(ee,this._zoom)*.5,x=b/Math.max(ee,t)*.5,T=b/Math.max(ee,this._zoom)*.5;this.target=De(this.target,De(X(r.right,s*(P-v)),X(r.up,l*(x-T))));return}let u=this.camera,c=Math.tan(u.fov*Math.PI/180*.5),m=i.width/i.height,d=e*c,f=this._radius*c,p=d*m,h=f*m;this.target=De(this.target,De(X(r.right,s*(p-h)),X(r.up,l*(d-f))))}applyOrthographicZoom(){if(this.camera.type!=="orthographic")return;let e=this.camera,t=(this._orthoBaseLeft+this._orthoBaseRight)*.5,r=(this._orthoBaseBottom+this._orthoBaseTop)*.5,i=(this._orthoBaseRight-this._orthoBaseLeft)/Math.max(ee,this._zoom),o=(this._orthoBaseTop-this._orthoBaseBottom)/Math.max(ee,this._zoom);e.left=t-i*.5,e.right=t+i*.5,e.bottom=r-o*.5,e.top=r+o*.5}relaxPerspectiveClipForZoom(){if(this.camera.type!=="perspective")return;let e=this.camera,t=1e-5,r=Math.max(t,this._radius*.001),i=Math.max(t,e.far-.01),o=Ke(r,t,i);Math.abs(o-e.near)>Math.max(t,e.near)*.001&&(e.near=o);let a=Math.max(this._radius*4,e.near+.01);a>e.far&&(e.far=a)}offsetToSpherical(e){let t=qe(e,this._axisConvention.right),r=qe(e,this._axisConvention.up),i=qe(e,this._axisConvention.forward),o=Math.max(ee,Math.hypot(t,r,i));return{theta:Math.atan2(t,i),phi:Math.acos(Ke(r/o,-1,1))}}sphericalToOffset(e,t,r){let i=Math.sin(t),o=r*i*Math.sin(e),a=r*Math.cos(t),s=r*i*Math.cos(e);return De(De(X(this._axisConvention.right,o),X(this._axisConvention.up,a)),X(this._axisConvention.forward,s))}computeLookBasis(e,t){let r=pe(e,X(this._axisConvention.forward,-1)),i=pe(t,this._axisConvention.up);Math.abs(qe(r,i))>.999&&(i=Math.abs(r[1])<.9?[0,1,0]:[1,0,0]);let o=pe(cr(r,i),this._axisConvention.right),a=pe(cr(o,r),i);return{right:o,up:a,forward:r}}computeOrbitBasis(){let e=this.sphericalToOffset(this._theta,this._phi,Math.max(ee,this._radius)),t=pe(X(e,-1),X(this._axisConvention.forward,-1));return this.computeLookBasis(t,this.getOrbitUp(t))}computeTrackballBasis(){let e=pe(X(this._trackballEye,-1),X(this._axisConvention.forward,-1)),t=this.computeLookBasis(e,this._trackballUp);return this._trackballUp=t.up,t}getOrbitUp(e){let t=this._axisConvention.up,r=lr(t,X(e,qe(t,e))),i=ur(r);if(i>ee)return X(r,1/i);let o=this._axisConvention.forward;return r=lr(o,X(e,qe(o,e))),i=ur(r),i>ee?X(r,1/i):ge(this._axisConvention.right)}getTrackballVector(e,t){let r=this.getViewportRect(),i=(e-r.left)/r.width*2-1,o=1-(t-r.top)/r.height*2,a=i*i+o*o;if(a<=1)return[i,o,Math.sqrt(1-a)];let s=1/Math.sqrt(a);return[i*s,o*s,0]}rotationFromTrackballDrag(e,t){let r=Ke(qe(e,t),-1,1),i=Math.acos(r);if(i<=ee)return null;i*=this.rotateSpeed;let o=cr(e,t),a=ur(o);if(a<=ee)return null;o=X(o,1/a);let s=this.computeTrackballBasis(),l=pe(De(De(X(s.right,o[0]),X(s.up,o[1])),X(X(s.forward,-1),o[2])),s.right),u=i*.5,c=Math.sin(u);return[l[0]*c,l[1]*c,l[2]*c,Math.cos(u)]}resolveBounds(e){return ho(e)}getInspectionViewDirection(e){switch(e){case"front":return ge(this._axisConvention.forward);case"back":return X(this._axisConvention.forward,-1);case"right":return ge(this._axisConvention.right);case"left":return X(this._axisConvention.right,-1);case"top":return ge(this._axisConvention.up);case"bottom":return X(this._axisConvention.up,-1)}}getInspectionViewUp(e){return e==="top"?X(this._axisConvention.forward,-1):ge(e==="bottom"?this._axisConvention.forward:this._axisConvention.up)}getCurrentViewOrientation(){let e=ge(this.camera.position),t=pe(lr(e,this.target),this._axisConvention.forward);return{direction:t,up:pe(this.camera.up,this.getOrbitUp(X(t,-1)))}}solveFit(e,t){let r=Math.max(1,t.padding??1.1),i=this.getAspect(t.aspect),o=t.view?{direction:this.getInspectionViewDirection(t.view),up:t.up?pe(t.up,this._axisConvention.up):this.getInspectionViewUp(t.view)}:{direction:t.eyeDirection?pe(t.eyeDirection,this._axisConvention.forward):this.getCurrentViewOrientation().direction,up:t.up?pe(t.up,this._axisConvention.up):this.getCurrentViewOrientation().up},a=t.boundsMode==="sphere"?yt(e.sphereCenter,e.sphereRadius*r,e.partial):bo(e,r),s=this.computeLookBasis(X(o.direction,-1),o.up),l=t.boundsMode==="sphere"?ge(e.sphereCenter):Yn(a);return this.camera.type==="orthographic"?this.solveFitOrthographic(a,e,s,l,i,t.minNear):this.solveFitPerspective(a,e,s,l,i,t.minNear)}solveFitPerspective(e,t,r,i,o,a){let s=Zn(e),l=this.camera,u=Math.tan(l.fov*Math.PI/180*.5),c=u*Math.max(o,ee),m=t.sphereRadius,d=[];for(let M of s){let B=lr(M,i),S=qe(B,r.right),R=qe(B,r.up),G=qe(B,r.forward);d.push(G),m=Math.max(m,Math.abs(S)/Math.max(c,ee)-G,Math.abs(R)/Math.max(u,ee)-G)}m=Math.max(m,t.sphereRadius,a??.01);let f=Math.min(...d.map(M=>m+M)),p=Math.max(...d.map(M=>m+M)),h=a??.01,g=Math.max(t.sphereRadius*.05,.01),b=Math.max(e.sphereRadius,t.sphereRadius,.01),P=Math.max(b*.1,g),v=m-b-P,x=m+b+P,T=Math.max(h,Math.min(f-g,v)),w=Math.max(T+.01,Math.max(p+g,x));return{position:De(i,X(X(r.forward,-1),m)),target:i,up:r.up,projection:{type:"perspective",near:T,far:w}}}solveFitOrthographic(e,t,r,i,o,a){let s=Zn(e),l=0,u=0,c=1/0,m=-1/0;for(let x of s){let T=lr(x,i),w=qe(T,r.right),M=qe(T,r.up),B=qe(T,r.forward);l=Math.max(l,Math.abs(w)),u=Math.max(u,Math.abs(M)),B<c&&(c=B),B>m&&(m=B)}o>=1?l=Math.max(l,u*o):u=Math.max(u,l/Math.max(o,ee));let d=Math.max(Math.abs(c),Math.abs(m),t.sphereRadius),f=Math.max(d*2+Math.max(l,u),t.sphereRadius*2,.1),p=a??.01,h=Math.max(t.sphereRadius*.05,.01),g=Math.max(e.sphereRadius,t.sphereRadius,.01),b=Math.max(g*.1,h),P=Math.max(p,Math.min(f+c-h,f-g-b)),v=Math.max(P+.01,Math.max(f+m+h,f+g+b));return{position:De(i,X(X(r.forward,-1),f)),target:i,up:r.up,projection:{type:"orthographic",left:-Math.max(l,.01),right:Math.max(l,.01),bottom:-Math.max(u,.01),top:Math.max(u,.01),near:P,far:v}}}},Un=class extends mr{constructor(e,t,r={}){super(e,t,{...r,mode:"orbit"})}},Gn=class extends mr{constructor(e,t,r={}){super(e,t,{...r,mode:"trackball"})}};var An=(n,e)=>`${n}:${e}`,jo=n=>n?Array.isArray(n)?n:[n]:[],wl=n=>({...n,key:An(n.objectId,n.elementIndex)}),qr=class{entries=new Map;get size(){return this.entries.size}has(e,t){return this.entries.has(An(e,t))}values(){return Array.from(this.entries.values())}clear(){return this.entries.clear(),this}replace(e){return this.entries.clear(),this.add(e),this}add(e){for(let t of jo(e))this.entries.set(An(t.objectId,t.elementIndex),wl(t));return this}remove(e){for(let t of jo(e))this.entries.delete(An(t.objectId,t.elementIndex));return this}toggle(e){for(let t of jo(e)){let r=An(t.objectId,t.elementIndex);this.entries.has(r)?this.entries.delete(r):this.entries.set(r,wl(t))}return this}apply(e,t){switch(e){case"replace":return this.replace(t);case"add":return this.add(t);case"toggle":return this.toggle(t);case"remove":return this.remove(t)}}};var qi=class n{renderer;compute;scale;_performanceStats=null;_isRunning=!1;_lastTime=0;_frameCallback=null;_animationFrameId=null;constructor(e,t){this.renderer=e;let r=e.gpu;this.compute=new Pn(r.device,r.queue,t),this.scale=new Tr(this.compute)}static async create(e,t={}){await Nn();let r=await pn.create(e,t);return new n(r,t)}run(e){if(this._isRunning)return;this._isRunning=!0,this._frameCallback=e,this._lastTime=performance.now();let t=r=>{if(!this._isRunning)return;W.reset();let i=(r-this._lastTime)/1e3;this._lastTime=r;let o=performance.now();this._frameCallback?.(i,r/1e3,this);let a=performance.now()-o;this._performanceStats?.update(i,a),this._animationFrameId=requestAnimationFrame(t)};this._animationFrameId=requestAnimationFrame(t)}stop(){this._isRunning=!1,this._animationFrameId!==null&&(cancelAnimationFrame(this._animationFrameId),this._animationFrameId=null)}get gpu(){return this.renderer.gpu}get isRunning(){return this._isRunning}get cullingStats(){return this.renderer.cullingStats}static get driver(){return de}get driver(){return de}static get webassembly(){return nn}get webassembly(){return nn}static get python(){return Hi}get python(){return Hi}static get math(){return{mat4:st,quat:Jr,vec3:Je}}get math(){return{mat4:st,quat:Jr,vec3:Je}}static createHeapArena(e,t=16){return de.createHeapArena(e,t)}createHeapArena(e,t=16){return de.createHeapArena(e,t)}static get frameArena(){return W}get frameArena(){return W}static createSelectionStore(){return new qr}createSelectionStore(){return new qr}createPerformanceStats(e={}){this._performanceStats?.destroy(),this.renderer.enableGpuTiming(e.showGpuTime??!0);let t=new hn({getGpuTimeNs:()=>this.renderer.gpuTimeNs,getCullingStats:()=>this.renderer.cullingStats},{canvas:this.renderer.canvas,...e});return this._performanceStats=t,t}get performanceStats(){return this._performanceStats}destroyPerformanceStats(){this._performanceStats?.destroy(),this._performanceStats=null,this.renderer.enableGpuTiming(!1)}render(e,t){this._isRunning||W.reset(),this.renderer.render(e,t)}async warmup(e={}){if(e.compute??!1)throw new Error("WasmGPU.warmup: compute warmup is not implemented yet.");if(!(e.render??!0))return;let{scene:i,camera:o}=e;if(!i||!o)throw new Error("WasmGPU.warmup: scene and camera are required when render warmup is enabled.");this._isRunning||W.reset(),this.renderer.warmup(i,o)}buildPickNdIndex(e){if(e.kind==="pointcloud"||e.kind==="glyphfield")return e.object.mapLinearIndexToNd(e.elementIndex);if(e.kind==="nodelink"){let t=e.object.decodePickElement(e.elementIndex);return!t||t.component!=="node"?null:e.object.mapLinearNodeIndexToNd(t.componentIndex)}return null}buildPickAttributes(e,t){if(!t)return null;if(e.kind==="pointcloud"){let r=e.object.getPointRecord(e.elementIndex);return r?{scalar:r.scalar,packedPoint:r.packed}:null}if(e.kind==="glyphfield"){let r=e.object.getAttributeRecord(e.elementIndex);return r?{vector:r}:null}if(e.kind==="nodelink"){let r=e.object.decodePickElement(e.elementIndex);if(!r)return null;if(r.component==="node"){let o=e.object.getNodeRecord(r.componentIndex);return{component:"node",componentIndex:r.componentIndex,scalar:o?.scalar??null,color:o?.color??null}}let i=e.object.getEdgeRecord(r.componentIndex);return{component:"edge",componentIndex:r.componentIndex,scalar:i?.scalar??null,color:i?.color??null,edgeEndpoints:i?[i.src,i.dst]:null,edgePositions:i&&i.srcPosition&&i.dstPosition?[i.srcPosition[0],i.srcPosition[1],i.srcPosition[2],i.dstPosition[0],i.dstPosition[1],i.dstPosition[2]]:null}}return null}buildPickHit(e,t){return{kind:e.kind,object:e.object,objectId:e.objectId,elementIndex:e.elementIndex,worldPosition:[e.worldPosition[0],e.worldPosition[1],e.worldPosition[2]],ndIndex:this.buildPickNdIndex(e),attributes:this.buildPickAttributes(e,t)}}async pick(e,t,r,i,o={}){let a=await this.renderer.pick(e,t,r,i,o);if(!a)return null;let s=o.includeAttributes??!0;return this.buildPickHit(a,s)}async pickRect(e,t,r,i,o,a,s={}){let l=s.includeAttributes??!0,u=await this.renderer.pickRect(e,t,r,i,o,a,s);return{mode:u.mode,hits:u.hits.map(c=>this.buildPickHit(c,l)),truncated:u.truncated,bounds:{x:u.bounds.x,y:u.bounds.y,width:u.bounds.width,height:u.bounds.height},sampledPixels:u.sampledPixels}}async pickLasso(e,t,r,i={}){let o=i.includeAttributes??!0,a=await this.renderer.pickLasso(e,t,r,i);return{mode:a.mode,hits:a.hits.map(s=>this.buildPickHit(s,o)),truncated:a.truncated,bounds:{x:a.bounds.x,y:a.bounds.y,width:a.bounds.width,height:a.bounds.height},sampledPixels:a.sampledPixels}}createScene(e){return new $e({background:e})}createCamera={perspective:e=>new Dt(e),orthographic:e=>new Nt(e)};createControls={navigation:(e,t,r)=>new mr(e,t,r),orbit:(e,t,r)=>new Un(e,t,r),trackball:(e,t,r)=>new Gn(e,t,r)};createOverlay={system:(e={})=>new Ar({canvas:this.renderer.canvas,...e}),axisTriad:(e={})=>new Fr(e),grid:(e={})=>new Ir(e),legend:e=>new Dr(e)};createAnnotation={toolkit:(e={})=>new Hr({pick:this.pick.bind(this),createOverlay:this.createOverlay},{canvas:this.renderer.canvas,...e})};geometry={custom:e=>new ae(e),point:(e,t,r)=>ae.point(e,t,r),line:(e,t,r,i)=>ae.line(e,t,r,i),plane:(e,t,r,i)=>ae.plane(e,t,r,i),triangle:(e,t,r,i)=>ae.triangle(e,t,r,i),rectangle:(e,t,r,i)=>ae.rectangle(e,t,r,i),circle:(e,t,r,i)=>ae.circle(e,t,r,i),ellipse:(e,t,r,i,o)=>ae.ellipse(e,t,r,i,o),box:(e,t,r)=>ae.box(e,t,r),sphere:(e,t,r)=>ae.sphere(e,t,r),cylinder:(e,t,r,i,o,a)=>ae.cylinder(e,t,r,i,o,a),pyramid:(e,t,r)=>ae.pyramid(e,t,r),torus:(e,t,r,i)=>ae.torus(e,t,r,i),prism:(e,t,r)=>ae.prism(e,t,r),cartesianCurve:e=>ae.cartesianCurve(e),cartesianSurface:e=>ae.cartesianSurface(e),parametricCurve:e=>ae.parametricCurve(e),parametricSurface:e=>ae.parametricSurface(e)};material={unlit:e=>new ke(e),standard:e=>new J(e),data:e=>new He(e),custom:e=>new tr(e)};texture={create2D:e=>or.createFrom(e)};createTransform(){return new we}createMesh(e,t){return new tt(e,t)}createPointCloud(e){return new rt(e)}createGlyphField(e){return new ze(e)}createNodeLink(e){return new Oe(e)}colormap={builtin:e=>$.builtin(e),grayscale:()=>$.builtin("grayscale"),turbo:()=>$.builtin("turbo"),viridis:()=>$.builtin("viridis"),magma:()=>$.builtin("magma"),plasma:()=>$.builtin("plasma"),inferno:()=>$.builtin("inferno"),fromStops:(e,t={})=>$.fromStops(e,t),fromPalette:(e,t={})=>$.fromPalette(e,t)};createLight={ambient:e=>new dn(e),directional:e=>new Pt(e),point:e=>new Tt(e),spot:e=>new ct(e)};gltf={load:async(e,t)=>Ci(e,t),import:async(e,t)=>ki(e,t),loadAndImport:async(e,t={})=>{let r=await Ci(e,t.load);return ki(r,t.import)},parseGLB:e=>Lr(e),readAccessor:(e,t)=>It(e,t),readAccessorAsFloat32:(e,t)=>Ae(e,t),readAccessorAsUint16:(e,t)=>Ur(e,t),readIndicesAsUint32:(e,t)=>wn(e,t)};animation={createClip:e=>new ar(e),createPlayer:(e,t)=>new _n(e,t),createSkin:(e,t,r)=>new sr(e,t,r)};destroy(){this.stop(),this.destroyPerformanceStats(),this.scale.clearCache(),this.compute.destroy(),this.renderer.destroy()}};export{dn as AmbientLight,ar as AnimationClip,_n as AnimationPlayer,Mn as AnnotationAngleUnit,ul as AnnotationKind,Vr as AnnotationLabelLayer,Wr as AnnotationMarkerRenderer,Rt as AnnotationMode,jr as AnnotationStore,Hr as AnnotationToolkit,wd as AxisConventions,Fr as AxisTriadLayer,rr as BlendMode,Kt as CPUndarray,Bn as Camera,$ as Colormap,Pn as Compute,Mr as ComputeKernels,Q as ComputePipeline,Cr as CullMode,tr as CustomMaterial,He as DataMaterial,Pt as DirectionalLight,Xt as GPUndarray,ae as Geometry,ze as GlyphField,Ir as GridLayer,Dr as LegendLayer,nr as Light,er as Material,tt as Mesh,mr as NavigationControls,Ft as Ndarray,Oe as NodeLink,Un as OrbitControls,Nt as OrthographicCamera,Ar as OverlaySystem,hn as PerformanceStats,Dt as PerspectiveCamera,rt as PointCloud,Tt as PointLight,ir as ReadbackRing,pn as Renderer,lt as SCALE_UNIFORM_FLOAT_COUNT,Tr as ScaleService,$e as Scene,qr as SelectionStore,sr as Skin,wi as SkinInstance,ct as SpotLight,J as StandardMaterial,oe as StorageBuffer,or as Texture2D,Gn as TrackballControls,we as Transform,K as TransformStore,xr as UniformBuffer,ke as UnlitMaterial,qi as WasmGPU,Zr as WasmHeapArena,rn as WasmMemoryView,Yt as WasmModule,Ue as WasmSlice,Nr as annotationAnchorFromHit,Ba as applyScaleTransformCPU,et as boundsFromBox,Zt as boundsFromBoxAndSphere,yt as boundsFromSphere,an as cloneBounds,Ie as cloneScaleTransform,zr as colorToCssRgba,Vi as computeAngleRadians,Oi as computeDistanceWorld,gl as createAnnotationAnchor,We as cullf,qi as default,To as defaultScaleTransform,de as driver,Ce as dtypeInfo,kt as emptyBounds,bo as expandBounds,Ii as formatAngleRadians,Fi as formatDistanceWorld,ue as formatFiniteNumber,Di as formatWorldVector,W as frameArena,$t as frustumf,Yn as getBoundsCenter,Zn as getBoundsCorners,Yl as getBoundsSize,ki as importGltf,Nn as initWebAssembly,ei as invertScaleTransformCPU,Ci as loadGltf,Br as makeWorkgroupCounts,ts as makeWorkgroupSize,bl as mapAnnotationProbeReadout,st as mat4,zn as ndarrayf,ho as normalizeBounds,fe as normalizeScaleTransform,vn as normalizeWorkgroups,je as packScaleTransform,Lr as parseGLB,Hi as pythonInterop,Jr as quat,It as readAccessor,Ae as readAccessorAsFloat32,Ur as readAccessorAsUint16,wn as readIndicesAsUint32,Or as resolveAnnotationUnits,_a as resolveScaleTransformDomainCPU,cn as scaleClampModeToId,un as scaleModeToId,mn as scaleValueModeToId,Mt as transformBounds,go as unionBounds,Je as vec3,_ as wasm,nn as webassemblyInterop,Te as workgroups1D,gn as workgroups2D,bn as workgroups3D};
|