@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.iife.min.js
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
|
-
"use strict";var WasmGPU=(()=>{var _n=Object.defineProperty;var va=Object.getOwnPropertyDescriptor;var xa=Object.getOwnPropertyNames;var Pa=Object.prototype.hasOwnProperty;var wa=(n,e)=>{for(var t in e)_n(n,t,{get:e[t],enumerable:!0})},Sa=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of xa(e))!Pa.call(n,i)&&i!==t&&_n(n,i,{get:()=>e[i],enumerable:!(r=va(e,i))||r.enumerable});return n};var _a=n=>Sa(_n({},"__esModule",{value:!0}),n);var _u={};wa(_u,{default:()=>xn});var Bn=null,wi=(n,e)=>{Bn={wasm:n,frameArena:e}},me=()=>{if(!Bn)throw new Error("wasm interop host not set. This is an internal error: WasmGPU/src/wasm/index.ts should call setWasmInteropHost().");return Bn},xi=typeof FinalizationRegistry<"u"?new FinalizationRegistry(n=>{try{let{wasm:e}=me(),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"&&xi?.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(),me().wasm.memory().buffer}view(){this.assertAlive();let e=me().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,xi?.unregister(this);let{wasm:e}=me(),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}},Ca=(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},Sr=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}=me(),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=Ca(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.")}},Pi=null,Cn=null,Ba=()=>{let n=me().wasm.memory().buffer;return(n!==Pi||!Cn)&&(Pi=n,Cn=new Uint8Array(n)),Cn},ae={buffer:()=>me().wasm.memory().buffer,bytes:()=>Ba(),isSharedMemory:()=>{let n=me().wasm.memory().buffer;return typeof SharedArrayBuffer<"u"&&n instanceof SharedArrayBuffer},requireSharedMemory:()=>{let n=me().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(me().wasm.memory().buffer,e>>>0,t>>>0),createHeapArena:(n,e=16)=>new Sr(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}=me(),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}=me(),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}=me(),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}=me(),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}=me(),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}=me(),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}=me(),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}=me(),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 Si=null,pt=null,$t=0,_i=8*1024*1024,Ma=(()=>{if(typeof document>"u")return null;let e=document.currentScript?.src;return e&&e.length>0?e:null})(),Aa=()=>{let n=Ma??location.href;return new URL(".",n).toString()},Ci=async n=>{if(pt)return;let e=n??Aa(),t=new URL("wasm.js",e).toString();Si??=import(t),pt=await Si,pt.wasmgpu_frame_arena_init(_i),$t=pt.wasmgpu_frame_arena_epoch()>>>0},y=()=>{if(!pt)throw new Error("WebAssembly driver not initialized. Call await initWebAssembly() first.");return pt},Mn=()=>($t=y().wasmgpu_frame_arena_epoch()>>>0,$t),Ce=n=>!!n,C={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=_i)=>{let e=y().wasmgpu_frame_arena_init(n>>>0)>>>0;if(!e)throw new Error(`wasmgpu_frame_arena_init(${n}) failed`);return Mn(),e},reset:()=>{y().wasmgpu_frame_arena_reset(),Mn()},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:()=>($t||Mn(),$t),usedBytes:()=>y().wasmgpu_frame_arena_used()>>>0,capBytes:()=>y().wasmgpu_frame_arena_cap()>>>0};wi(C,W);var ft={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)}},ht={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)}},bt={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)}},ot={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},_r={writePlanesFromViewProjection:(n,e)=>{if(typeof e=="number"){y().cull_write_planes_from_view_projection(n>>>0,e>>>0);return}let t=W.allocF32(16);C.writeF32(t,16,e),y().cull_write_planes_from_view_projection(n>>>0,t>>>0)}},ne={alloc:()=>C.allocF32(16),view:n=>C.f32view(n,16),set:(n,e)=>C.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)=>Ce(y().mat4_isEqual(n>>>0,e>>>0)),isIdentity:n=>Ce(y().mat4_isIdentity(n>>>0)),isInverse:(n,e)=>Ce(y().mat4_isInverse(n>>>0,e>>>0)),isZero:n=>Ce(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=C.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
|
+
"use strict";var WasmGPU=(()=>{var Ui=Object.defineProperty;var wl=Object.getOwnPropertyDescriptor;var _l=Object.getOwnPropertyNames;var Bl=Object.prototype.hasOwnProperty;var kl=(n,e)=>{for(var t in e)Ui(n,t,{get:e[t],enumerable:!0})},Ml=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of _l(e))!Bl.call(n,i)&&i!==t&&Ui(n,i,{get:()=>e[i],enumerable:!(r=wl(e,i))||r.enumerable});return n};var Ll=n=>Ml(Ui({},"__esModule",{value:!0}),n);var Md={};kl(Md,{default:()=>Ri});var y=(n,e)=>{if(!n)throw new Error(e)},pe=(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,ze=(n,e,t)=>n+(e-n)*t,Oe=(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)),zt=n=>Number.isInteger(n)&&n>0,Te=n=>Number.isInteger(n)&&n>=0,dt=(n,e)=>typeof n=="number"&&Number.isFinite(n)?n:e,Mr=(n,e)=>typeof n=="number"&&Number.isInteger(n)?n:e,Lr=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},tr=()=>typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now(),rr=n=>typeof n=="object"&&n!==null&&n.mapState!==void 0,re=n=>rr(n)?n:n.buffer,nr=(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},ir=(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},qe=(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},jo=(n,e,t=8)=>{let r=Math.min(Math.max(2,t|0),Math.max(2,e.length)),i=qe(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]:[ze(i[a][0],i[s][0],l),ze(i[a][1],i[s][1],l),ze(i[a][2],i[s][2],l),ze(i[a][3],i[s][3],l)]},ne=(n,e,t,r)=>{let i=n.createBuffer({label:r,size:pe(e.byteLength,4),usage:t,mappedAtCreation:!0});return new Uint8Array(i.getMappedRange()).set(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),i.unmap(),i},mn=(n,e,t,r=1)=>n.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:"depth24plus",sampleCount:r,usage:GPUTextureUsage.RENDER_ATTACHMENT});var Ii=null,Rl=(n,e)=>{Ii={wasm:n,frameArena:e}},Ce=()=>{if(!Ii)throw new Error("WebAssembly driver host not set. This is an internal error: WasmGPU/src/wasm/driver.ts should call setWebAssemblyDriverHost().");return Ii},Ho=typeof FinalizationRegistry<"u"?new FinalizationRegistry(n=>{try{let{wasm:e}=Ce(),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,Ae=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"&&Ho?.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(),Ce().wasm.memory().buffer}view(){this.assertAlive();let e=Ce().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,Ho?.unregister(this);let{wasm:e}=Ce(),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}},Gl=(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},dn=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}=Ce(),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=Gl(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 Ae("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 Ae("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 Ae("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 Ae("arena","u8",i,r,Uint8Array,o,()=>this.epoch())}assertAlive(){if(this.destroyed)throw new Error("WasmHeapArena has been destroyed.")}},$o=null,Ai=null,Ul=()=>{let n=Ce().wasm.memory().buffer;return(n!==$o||!Ai)&&($o=n,Ai=new Uint8Array(n)),Ai},fe={buffer:()=>Ce().wasm.memory().buffer,bytes:()=>Ul(),isSharedMemory:()=>{let n=Ce().wasm.memory().buffer;return typeof SharedArrayBuffer<"u"&&n instanceof SharedArrayBuffer},requireSharedMemory:()=>{let n=Ce().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(Ce().wasm.memory().buffer,e>>>0,t>>>0),createHeapArena:(n,e=16)=>new dn(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}=Ce(),t=e.allocF32(n);if(!t&&n>>>0)throw new Error(`driver.heap.allocF32(${n}) failed`);return new Ae("heap","f32",t,n,Float32Array,0,null)},allocU32:n=>{let{wasm:e}=Ce(),t=e.allocU32(n);if(!t&&n>>>0)throw new Error(`driver.heap.allocU32(${n}) failed`);return new Ae("heap","u32",t,n,Uint32Array,0,null)},allocI32:n=>{let{wasm:e}=Ce(),t=e.allocU32(n);if(!t&&n>>>0)throw new Error(`driver.heap.allocI32(${n}) failed`);return new Ae("heap","i32",t,n,Int32Array,0,null)},allocU8:(n,e=16)=>{let{wasm:t}=Ce(),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 Ae("heap","u8",r,n,Uint8Array,0,null)}},frame:{allocF32:n=>{let{frameArena:e}=Ce(),t=e.allocF32(n);if(!t&&n>>>0)throw new Error(`driver.frame.allocF32(${n}) failed`);return new Ae("frame","f32",t,n,Float32Array,e.epoch(),()=>e.epoch())},allocU32:n=>{let{frameArena:e}=Ce(),t=e.alloc((n>>>0)*4,16);if(!t&&n>>>0)throw new Error(`driver.frame.allocU32(${n}) failed`);return new Ae("frame","u32",t,n,Uint32Array,e.epoch(),()=>e.epoch())},allocI32:n=>{let{frameArena:e}=Ce(),t=e.alloc((n>>>0)*4,16);if(!t&&n>>>0)throw new Error(`driver.frame.allocI32(${n}) failed`);return new Ae("frame","i32",t,n,Int32Array,e.epoch(),()=>e.epoch())},allocU8:(n,e=16)=>{let{frameArena:t}=Ce(),r=t.alloc(n>>>0,e>>>0);if(!r&&n>>>0)throw new Error(`driver.frame.allocU8(${n}) failed`);return new Ae("frame","u8",r,n,Uint8Array,t.epoch(),()=>t.epoch())}}},qo=null,or=null,Rr=0,Ko=8*1024*1024,Al=(()=>{if(typeof document>"u")return null;let e=document.currentScript?.src;return e&&e.length>0?e:null})(),Fl=()=>{let n=Al??location.href;return new URL(".",n).toString()},Di=async n=>{if(or)return;let e=n??Fl(),t=new URL("wasm.js",e).toString();qo??=import(t),or=await qo,or.wasmgpu_frame_arena_init(Ko),Rr=or.wasmgpu_frame_arena_epoch()>>>0},C=()=>{if(!or)throw new Error("WebAssembly driver not initialized. Call await initWebAssembly() first.");return or},Fi=()=>(Rr=C().wasmgpu_frame_arena_epoch()>>>0,Rr),Ke=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=Ko)=>{let e=C().wasmgpu_frame_arena_init(n>>>0)>>>0;if(!e)throw new Error(`wasmgpu_frame_arena_init(${n}) failed`);return Fi(),e},reset:()=>{C().wasmgpu_frame_arena_reset(),Fi()},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:()=>(Rr||Fi(),Rr),usedBytes:()=>C().wasmgpu_frame_arena_used()>>>0,capBytes:()=>C().wasmgpu_frame_arena_cap()>>>0};Rl(_,W);var Ot={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)}},Mt={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)}},Vt={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)}},Xe={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},ar={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)=>Ke(C().mat4_isEqual(n>>>0,e>>>0)),isIdentity:n=>Ke(C().mat4_isIdentity(n>>>0)),isInverse:(n,e)=>Ke(C().mat4_isInverse(n>>>0,e>>>0)),isZero:n=>Ke(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]} ]`)}},Bi={computeVertexNormals:(n,e,t,r,i)=>{y().mesh_compute_vertex_normals(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)}},Mi={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},fe={alloc:()=>C.allocF32(4),view:n=>C.f32view(n,4),set:(n,e)=>C.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)=>Ce(y().quat_isEqual(n>>>0,e>>>0)),isNormalized:n=>Ce(y().quat_isNormalized(n>>>0)),isZero:n=>Ce(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=C.f32view(n,4);console.log(`[ ${e[0]} ${e[1]} ${e[2]} ${e[3]} ]`)}},gt={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)}},yt={alloc:()=>C.allocF32(4),view3:n=>C.f32view(n,3),view4:n=>C.f32view(n,4),set3:(n,e)=>C.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)=>Ce(y().vec3_isEqual(n>>>0,e>>>0)),isNormalized:n=>Ce(y().vec3_isNormalized(n>>>0)),isOrthogonal:(n,e)=>Ce(y().vec3_isOrthogonal(n>>>0,e>>>0)),isParallel:(n,e)=>Ce(y().vec3_isParallel(n>>>0,e>>>0)),isZero:n=>Ce(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=C.f32view(n,3);console.log(`[ ${e[0]} ${e[1]} ${e[2]} ]`)}},Ne={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)},An={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)},Ie={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 Ht=4294967295,j=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=C.allocF32(e*3),this.rotPtr=C.allocF32(e*4),this.sclPtr=C.allocF32(e*3),this.localPtr=C.allocF32(e*16),this.worldPtr=C.allocF32(e*16),this.parentPtr=C.allocU32(e),this.orderPtr=C.allocU32(e),this.tmpAxisPtr=C.allocF32(4),this.tmpQuatPtr=C.allocF32(4),this.ensureViews();let t=this.u32(),r=this.parentPtr>>>2;for(let i=0;i<e;i++)t[r+i]=Ht}ensureViews(){let e=C.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=C.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]=Ht}setParent(e,t){this.ensureViews();let r=this.u32();r[(this.parentPtr>>>2)+e]=t===null?Ht: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]=Ht;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(),gt.composeLocalMany(this.localPtr,this.posPtr,this.rotPtr,this.sclPtr,e),gt.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;gt.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]===Ht)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}},he=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=j.global();this.index=e.alloc(this)}static updateAll(){j.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=j.global().f32();t[0]=i[e+0],t[1]=i[e+1],t[2]=i[e+2]}readQuatFromStore(e,t){let i=j.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=j.global().f32();for(let o=0;o<16;o++)t[o]=i[e+o]}get positionPtr(){return this.assertAlive(),j.global().posPtr+this.index*3*4>>>0}get rotationPtr(){return this.assertAlive(),j.global().rotPtr+this.index*4*4>>>0}get scalePtr(){return this.assertAlive(),j.global().sclPtr+this.index*3*4>>>0}get localMatrixPtr(){return this.assertAlive(),j.global().localPtr+this.index*16*4>>>0}get worldMatrixPtr(){return this.assertAlive(),j.global().worldPtr+this.index*16*4>>>0}get position(){return this._position}setPosition(e,t,r){this.assertAlive();let i=j.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=j.global(),a=this.rotationPtr;fe.init(a,e,t,r,i),fe.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=j.global(),i=r.f32(),o=r.tmpAxisPtr>>>2;i[o+0]=e[0],i[o+1]=e[1],i[o+2]=e[2],yt.normalize(r.tmpAxisPtr,r.tmpAxisPtr);let a=this.rotationPtr;fe.fromAxisAngle(a,r.tmpAxisPtr,t),fe.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=j.global(),i=r.f32(),o=r.tmpAxisPtr>>>2;i[o+0]=e[0],i[o+1]=e[1],i[o+2]=e[2],yt.normalize(r.tmpAxisPtr,r.tmpAxisPtr),fe.fromAxisAngle(r.tmpQuatPtr,r.tmpAxisPtr,t);let a=this.rotationPtr;fe.mul(a,a,r.tmpQuatPtr),fe.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=j.global(),r=t.f32(),i=t.tmpAxisPtr>>>2;r[i+0]=1,r[i+1]=0,r[i+2]=0,yt.normalize(t.tmpAxisPtr,t.tmpAxisPtr),fe.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;fe.mul(o,o,t.tmpQuatPtr),fe.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=j.global(),r=t.f32(),i=t.tmpAxisPtr>>>2;r[i+0]=0,r[i+1]=1,r[i+2]=0,yt.normalize(t.tmpAxisPtr,t.tmpAxisPtr),fe.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;fe.mul(o,o,t.tmpQuatPtr),fe.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=j.global(),r=t.f32(),i=t.tmpAxisPtr>>>2;r[i+0]=0,r[i+1]=0,r[i+2]=1,yt.normalize(t.tmpAxisPtr,t.tmpAxisPtr),fe.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;fe.mul(o,o,t.tmpQuatPtr),fe.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=j.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=j.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=j.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=j.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),j.global().setParent(this.index,e.index)):j.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,j.global().setParent(this.index,null),this}reset(){return this.assertAlive(),this._parent=null,this._children.length=0,j.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(),j.global().free(this.index),this._disposed=!0}};var Ve=n=>[n[0]??0,n[1]??0,n[2]??0],vt=(n=!1)=>({boxMin:[0,0,0],boxMax:[0,0,0],sphereCenter:[0,0,0],sphereRadius:0,empty:!0,partial:n}),Cr=n=>({boxMin:Ve(n.boxMin),boxMax:Ve(n.boxMax),sphereCenter:Ve(n.sphereCenter),sphereRadius:n.sphereRadius,empty:n.empty,partial:n.partial}),Xe=(n,e,t=!1)=>{let r=Ve(n),i=Ve(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}},xt=(n,e,t=!1)=>{let r=Ve(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}},Pt=(n,e,t,r,i=!1)=>({boxMin:Ve(n),boxMax:Ve(e),sphereCenter:Ve(t),sphereRadius:Math.max(0,r),empty:!1,partial:i}),Ai=n=>"getBounds"in n&&typeof n.getBounds=="function"?n.getBounds():n,Ui=(n,e)=>{if(n.empty){let t=Cr(e);return t.partial=n.partial||e.partial,t}if(e.empty){let t=Cr(n);return t.partial=n.partial||e.partial,t}return Xe([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)},Un=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];var ki=(n,e)=>{if(n.empty)return Cr(n);let t=Math.max(1,e),r=Un(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 Xe([r[0]-i,r[1]-o,r[2]-a],[r[0]+i,r[1]+o,r[2]+a],n.partial)},kn=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]]]},wt=(n,e)=>{if(n.empty)return Cr(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],P=e[2]*n.sphereCenter[0]+e[6]*n.sphereCenter[1]+e[10]*n.sphereCenter[2]+e[14];return Pt([l-c,u-d,m-f],[l+c,u+d,m+f],[M,h,P],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 he}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 Pt(this.geometry.boundsMin,this.geometry.boundsMax,this.geometry.boundsCenter,this.geometry.boundsRadius)}getWorldBounds(){return wt(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 w=(n,e)=>{if(!n)throw new Error(e)},se=(n,e)=>Math.ceil(n/e)*e,ye=(n,e,t)=>{let r=n.createBuffer({size:se(e.byteLength,4),usage:t,mappedAtCreation:!0});return new Uint8Array(r.getMappedRange()).set(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),r.unmap(),r},Gn=(n,e,t,r=1)=>n.createTexture({size:{width:e,height:t,depthOrArrayLayers:1},format:"depth24plus",sampleCount:r,usage:GPUTextureUsage.RENDER_ATTACHMENT});var at=256,Gi={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=="},Ye=n=>n<0?0:n>1?1:n,Tn=n=>n<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4),Ua=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).")},St=n=>{let e=Gi,t=e[n];if(t instanceof Uint8Array)return t;let r=Ua(Gi[n]);return e[n]=r,r},ka=n=>{w(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=Ye(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},Qe=(n,e,t)=>n+(e-n)*t,Ga=(n,e)=>{let t=Ye(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[Qe(o.color[0],a.color[0],l),Qe(o.color[1],a.color[1],l),Qe(o.color[2],a.color[2],l),Qe(o.color[3],a.color[3],l)]}}return n[r].color},Ti=(n,e)=>{let t=new Uint8Array(n.length*4);for(let r=0;r<n.length;r++){let i=Ye(n[r][0]),o=Ye(n[r][1]),a=Ye(n[r][2]),s=Ye(n[r][3]);e==="srgb"&&(i=Tn(i),o=Tn(o),a=Tn(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},Ta=(n,e,t)=>{let r=Math.min(e-1,Math.max(0,Math.round(Ye(t)*(e-1))));return[n[r*4+0]/255,n[r*4+1]/255,n[r*4+2]/255,n[r*4+3]/255]},Ra=(n,e,t)=>{let r=Ye(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[Qe(n[s+0]/255,n[l+0]/255,a),Qe(n[s+1]/255,n[l+1]/255,a),Qe(n[s+2]/255,n[l+2]/255,a),Qe(n[s+3]/255,n[l+3]/255,a)]},La=(n,e,t,r,i)=>{w(r>0,"Colormap: width must be > 0."),w(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=se(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},Fa=(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"}),Da=1,H=class n{id=Da++;_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 Ia[e]}static fromStops(e,t={}){let r=Math.max(2,Math.floor(t.resolution??at)),i=t.filter??"linear",o=t.colorSpace??"srgb",a=ka(e),s=new Array(r);for(let u=0;u<r;u++){let m=r===1?0:u/(r-1);s[u]=Ga(a,m)}let l=Ti(s,o);return new n({label:"Colormap.customStops",width:r,filter:i,rgba8Linear:l})}static fromPalette(e,t={}){w(e.length>=1,"Colormap.fromPalette: expected at least 1 color.");let r=t.filter??"nearest",i=t.colorSpace??"srgb",o=Ti(e,i);return new n({label:"Colormap.palette",width:e.length,filter:r,rgba8Linear:o})}static fromGPUTextureView(e,t,r,i,o="linear"){return w(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"?Ta(t,this._width,e):Ra(t,this._width,e)}getGPUResources(e,t){if(this._external)return w(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=La(e,t,i,this._width,this._label),a=o.createView({dimension:"1d"}),s=Fa(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}},Ia={grayscale:new H({label:"Colormap.grayscale",width:at,filter:"linear",rgba8Linear:St("grayscale")}),turbo:new H({label:"Colormap.turbo",width:at,filter:"linear",rgba8Linear:St("turbo")}),viridis:new H({label:"Colormap.viridis",width:at,filter:"linear",rgba8Linear:St("viridis")}),magma:new H({label:"Colormap.magma",width:at,filter:"linear",rgba8Linear:St("magma")}),plasma:new H({label:"Colormap.plasma",width:at,filter:"linear",rgba8Linear:St("plasma")}),inferno:new H({label:"Colormap.inferno",width:at,filter:"linear",rgba8Linear:St("inferno")})};var Ri="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 Li="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 Fi="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 Di="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 Ii="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 Ei="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 Oi="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 zi="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 Wi="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 Ni="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 Ee=20,_t=(n,e,t)=>n<e?e:n>t?t:n,Ka=n=>_t(n,0,1),je=(n,e)=>typeof n=="number"&&Number.isFinite(n)?n:e,Br=(n,e)=>typeof n=="number"&&Number.isInteger(n)?n:e,Xa={linear:0,log:1,symlog:2},Ya={none:0,range:1,percentile:2},Qa={component:0,magnitude:1},Mr=n=>Xa[n],Ar=n=>Ya[n],Ur=n=>Qa[n],$e=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}),$i=()=>({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}),ce=n=>{let e=$i(),t=n.mode??e.mode,r=n.clampMode??e.clampMode,i=n.valueMode??e.valueMode;w(t==="linear"||t==="log"||t==="symlog",`Invalid scale mode: ${String(t)}`),w(r==="none"||r==="range"||r==="percentile",`Invalid scale clamp mode: ${String(r)}`),w(i==="component"||i==="magnitude",`Invalid scale value mode: ${String(i)}`);let o=_t(Br(n.componentCount,e.componentCount),1,4),a=_t(Br(n.componentIndex,e.componentIndex),0,3),s=Math.max(o,Br(n.stride,e.stride)),l=Math.max(0,Br(n.offset,e.offset)),u=je(n.domainMin,e.domainMin),m=je(n.domainMax,e.domainMax),c=je(n.clampMin,e.clampMin),d=je(n.clampMax,e.clampMax),f=_t(je(n.percentileLow,e.percentileLow),0,100),p=_t(je(n.percentileHigh,e.percentileHigh),0,100);w(p>f,`Scale transform requires percentileHigh > percentileLow (got ${f}, ${p})`);let b=Math.max(1.000001,je(n.logBase,e.logBase)),g=Math.max(1e-20,je(n.symlogLinThresh,e.symlogLinThresh)),x=Math.max(1e-6,je(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}},He=(n,e,t=0)=>{let r=ce(n);e[t+0]=r.componentCount,e[t+1]=r.componentIndex,e[t+2]=Ur(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]=Ar(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]=Mr(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},Vi=(n,e)=>{let t=Math.max(1.000001,e);return Math.log(n)/Math.log(t)},ji=(n,e,t,r)=>{if(e==="linear")return n;if(e==="log")return Vi(Math.max(n,1e-20),r);let i=Math.max(t,1e-20),o=n>=0?1:-1,a=Vi(1+Math.abs(n)/i,r);return o*a},Za=(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)},Ja=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}};var Rn=(n,e)=>{let t=ce(e),r=Ja(t),i=Ka(n);t.invert&&(i=1-i),i=Math.pow(i,1/Math.max(t.gamma,1e-6));let o=ji(r.domainMin,t.mode,t.symlogLinThresh,t.logBase),a=ji(r.domainMax,t.mode,t.symlogLinThresh,t.logBase),s=o+(a-o)*i,l=Za(s,t.mode,t.symlogLinThresh,t.logBase);return r.hasClamp&&(l=_t(l,r.clampMin,r.clampMax)),l};var Ct=(n,e,t)=>n<e?e:n>t?t:n,qi=n=>n.mapState!==void 0,Ln=n=>qi(n)?n:n.buffer,es=n=>qi(n)?Number(n.size):typeof n.byteLength=="number"?n.byteLength:null,Hi=(n,e,t,r,i)=>{if(!Number.isFinite(t)||!Number.isFinite(r)||i<=0)return Number.NaN;if(r<=t)return t;let a=Ct(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+Ct(f,0,1)*s}l=c}return r},ts=n=>{w(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=Ct(e,1,4),r=typeof n.componentIndex=="number"&&Number.isInteger(n.componentIndex)?n.componentIndex:0,i=Ct(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";w(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;w(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}},qt=class{compute;sourceIds=new WeakMap;cache=new Map;sourceCacheKeys=new Map;nextSourceId=1;constructor(e){this.compute=e}createTransform(e){return ce(e)}invalidate(e){let t=e.buffer?e.buffer:e,r=Ln(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=Ct(e.percentiles?.low??2,0,100),i=Ct(e.percentiles?.high??98,0,100);w(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(Ln(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=Ln(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=Hi(b,t.low,u,m,a),d=Hi(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 Ki=n=>n<0?0:n>1?1:n;var Bt=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}},Be=class n extends Bt{_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?Li:e.skinned8?Di:e.skinned?Fi:Ri}},Pe=class n extends Bt{_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?Ei:e.skinned8?zi:e.skinned?Oi:Ii}},Ae=class n extends Bt{_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(w(!!e&&!!e.scaleTransform,"DataMaterial: scaleTransform is required."),super({...e,blendMode:e.blendMode??((e.opacity??1)<1?"transparent":"opaque")}),this._scaleTransform=ce(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 $e(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=ce(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={}){w(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=ye(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=ye(e,r,i)}this._elementCount=this.computeElementCountFromFloatLength(r.length),this._keepCPUData||(this._CPUData=null),this._dataDirty=!1,this.bindGroupKey=null}getUniformBufferSize(){return(Ee+4)*4}getUniformData(){let e=this.getUniformDataCache(Ee+4);return e.fill(0),He(this._scaleTransform,e,0),e[Ee+0]=Ki(this._opacity),e[Ee+1]=Ki(this._shading),e[Ee+2]=0,e[Ee+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 Wi}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()}},kr=class extends Bt{_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 Ni}getShaderCode(e={}){let t=`struct CustomUniforms {
|
|
5
|
-
|
|
13
|
+
[ ${e[12]} ${e[13]} ${e[14]} ${e[15]} ]`)}},Ni={computeVertexNormals:(n,e,t,r,i)=>{C().mesh_compute_vertex_normals(n>>>0,e>>>0,t>>>0,r>>>0,i>>>0)}},zi={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},we={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)=>Ke(C().quat_isEqual(n>>>0,e>>>0)),isNormalized:n=>Ke(C().quat_isNormalized(n>>>0)),isZero:n=>Ke(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]} ]`)}},Lt={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)}},Et={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)=>Ke(C().vec3_isEqual(n>>>0,e>>>0)),isNormalized:n=>Ke(C().vec3_isNormalized(n>>>0)),isOrthogonal:(n,e)=>Ke(C().vec3_isOrthogonal(n>>>0,e>>>0)),isParallel:(n,e)=>Ke(C().vec3_isParallel(n>>>0,e>>>0)),isZero:n=>Ke(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]} ]`)}},ft={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)},fn={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)},nt={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),Gr=(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=Gr(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=pe(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)},pn=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 pn{label;constructor(e,t,r){let i=r.data?Gr(r.data).size:r.byteLength??0;y(Number.isInteger(i)&&i>=0,`StorageBuffer.byteLength must be an integer >= 0 (got ${i})`);let o=pe(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=Gr(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=pe(r,4),o=pe(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)}},Ur=class extends pn{label;constructor(e,t,r){let i=r.data?Gr(r.data).size:r.byteLength??0;y(Number.isInteger(i)&&i>=0,`UniformBuffer.byteLength must be an integer >= 0 (got ${i})`);let o=pe(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=Gr(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"}},_e=n=>{let e=Nl[n];if(!e)throw new Error(`Unknown dtype: ${String(n)}`);return e},Oi=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},hn=(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},Vi=(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},Ei=(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},ji=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},Wi=(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(ji(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||ji(n)===0)return!0;let i=hn(n,r);for(let o=0;o<n.length;o++)if(e[o]!==i[o])return!1;return!0},Wt=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=_e(e).bytesPerElement,this.numel=ji(t),this.byteLength=o}get ndim(){return this.shape.length}get wgslScalarType(){return _e(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,sr=class n extends Wt{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=_e(e),i=Oi(t.shape),o=Ei(t.offsetBytes,r.bytesPerElement),a=t.stridesBytes?Vi(t.stridesBytes,i.length,r.bytesPerElement):hn(i,r.bytesPerElement),s=Wi(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=_e(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=_e(this.dtype).ctor;return new t(e,0,0)}return new(_e(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=zi.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 lr(this.dtype,this.shape.slice(),this.stridesBytes.slice(),this.offsetBytes,this.byteLength,i,0,!0)}},lr=class n extends Wt{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=_e(t),a=Oi(r.shape),s=Ei(r.offsetBytes,o.bytesPerElement),l=r.stridesBytes?Vi(r.stridesBytes,a.length,o.bytesPerElement):hn(a,o.bytesPerElement),u=Wi(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=_e(t),a=Oi(r.shape),s=Ei(r.offsetBytes,o.bytesPerElement),l=r.stridesBytes?Vi(r.stridesBytes,a.length,o.bytesPerElement):hn(a,o.bytesPerElement),u=Wi(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:pe(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=sr.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 Ar=n=>typeof WebAssembly<"u"&&typeof WebAssembly.Memory<"u"&&n instanceof WebAssembly.Memory,gn=n=>typeof WebAssembly<"u"&&typeof WebAssembly.Global<"u"&&n instanceof WebAssembly.Global,ht=(n,e)=>e?`${n} '${e}'`:n,bn=n=>n||null,pt=(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),vn=(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),Xo=(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},Hi=n=>_e(n).ctor,ur=class n{exportsObject;defaultMemorySource;name;constructor(e={},t={}){this.exportsObject=e,this.defaultMemorySource=t.memory,this.name=bn(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(Ar(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),`${ht("WasmModule export",this.name)} does not contain export '${e}'.`),this.exportsObject[e]}getFunction(e){let t=this.getExport(e);return y(typeof t=="function",`${ht("WasmModule export",this.name)} '${e}' is not a function.`),t}getGlobal(e){let t=this.getExport(e);return y(gn(t),`${ht("WasmModule export",this.name)} '${e}' is not a WebAssembly.Global.`),t}memory(e){let t=e!==void 0?e:this.defaultMemorySource;if(Ar(t))return t;if(typeof t=="string"){let i=this.getExport(t);return y(Ar(i),`${ht("WasmModule export",this.name)} '${t}' is not a WebAssembly.Memory.`),i}if(t!=null)throw new Error(`${ht("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(`${ht("WasmModule",this.name)} could not resolve a WebAssembly.Memory. Pass memory explicitly or export one memory.`):new Error(`${ht("WasmModule",this.name)} has multiple memory exports (${r.join(", ")}). Pass memory explicitly.`)}view(e){return new yn(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=bn(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=bn(e.name),r=ht("WasmMemoryView",t),i=e.dtype,o=_e(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=bn(e.name),r=ht("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))Ar(r)&&e.push(t);return e}resolveByteRange(e,t,r,i,o){let a=this.memory(e);y(Ar(a),`${o} requires a valid WebAssembly.Memory.`);let s=this.resolveValue(t,`${o} ptr`),l=El(r,o),u=Xo(s,l,`${o} ptr + byteOffset`),c=Xo(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 pt(e,t);if(typeof e=="string"){let o=this.getExport(e);if(typeof o=="function")return pt(o(),`${t} export '${e}' result`);if(gn(o))return pt(o.value,`${t} export '${e}' value`);throw new Error(`${t} export '${e}' must be a function or WebAssembly.Global.`)}if(typeof e=="function")return pt(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=vn(o.args,t);return pt(o.function(...a),`${t} function result`)}if(Object.prototype.hasOwnProperty.call(e,"global")){let o=e;return y(gn(o.global),`${t} global descriptor must contain a WebAssembly.Global.`),pt(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 pt(this.getGlobal(r.export).value,`${t} export '${r.export}' value`);if(r.kind==="function")return pt(this.getFunction(r.export)(...vn(r.args,t)),`${t} export '${r.export}' result`);let i=this.getExport(r.export);if(typeof i=="function")return pt(i(...vn(r.args,t)),`${t} export '${r.export}' result`);if(gn(i))return y(vn(r.args,t).length===0,`${t} export '${r.export}' is a global and does not accept args.`),pt(i.value,`${t} export '${r.export}' value`);throw new Error(`${t} export '${r.export}' must be a function or WebAssembly.Global.`)}},yn=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=Hi(this.dtype),r=new t(new ArrayBuffer(this.byteLength>>>0),0,this.length>>>0);return r.set(e),r}copyInto(e){let t=ht("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=Hi(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=Hi(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)}},xn={fromInstance:(n,e={})=>ur.fromInstance(n,e),fromExports:(n,e={})=>ur.fromExports(n,e),fromMemory:(n,e={})=>ur.fromMemory(n,e)};var Fr=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]=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 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(),Lt.composeLocalMany(this.localPtr,this.posPtr,this.rotPtr,this.sclPtr,e),Lt.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;Lt.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 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}},Be=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;we.init(a,e,t,r,i),we.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],Et.normalize(r.tmpAxisPtr,r.tmpAxisPtr);let a=this.rotationPtr;we.fromAxisAngle(a,r.tmpAxisPtr,t),we.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],Et.normalize(r.tmpAxisPtr,r.tmpAxisPtr),we.fromAxisAngle(r.tmpQuatPtr,r.tmpAxisPtr,t);let a=this.rotationPtr;we.mul(a,a,r.tmpQuatPtr),we.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,Et.normalize(t.tmpAxisPtr,t.tmpAxisPtr),we.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;we.mul(o,o,t.tmpQuatPtr),we.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,Et.normalize(t.tmpAxisPtr,t.tmpAxisPtr),we.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;we.mul(o,o,t.tmpQuatPtr),we.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,Et.normalize(t.tmpAxisPtr,t.tmpAxisPtr),we.fromAxisAngle(t.tmpQuatPtr,t.tmpAxisPtr,e);let o=this.rotationPtr;we.mul(o,o,t.tmpQuatPtr),we.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 Yi=0,$i=0,Pn=0,Tn=0,Sn=0,Cn=0,Zi=0,qi=0,Qi=0,Ki=0,Ji=0,Xi=0,jl=n=>{$i<n&&($i=Lr(n),Yi=_.allocF32($i)),Pn===0&&(Pn=_.allocF32(3)),Tn===0&&(Tn=_.allocF32(3)),Sn===0&&(Sn=_.allocF32(3)),Cn===0&&(Cn=_.allocF32(1))},Hl=(n,e)=>{qi<n&&(qi=Lr(n),Zi=_.allocF32(qi)),Xi<n&&(Xi=Lr(n),Ji=_.allocF32(Xi)),e>0&&Ki<e&&(Ki=Lr(e),Qi=_.allocU32(Ki))},eo=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(Yi,n.length).set(n),Vt.geometryPositions(Pn,Tn,Sn,Cn,Yi,e);let t=_.f32view(Pn,3),r=_.f32view(Tn,3),i=_.f32view(Sn,3),o=_.f32view(Cn,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]}},wn=(n,e)=>{let t=n.length/3|0,r=e?e.length|0:0;Hl(n.length,r),_.f32view(Zi,n.length).set(n);let i=e&&r>0?Qi:0;e&&r>0&&_.u32view(Qi,r).set(e),Ni.computeVertexNormals(Ji,Zi,t,i,r);let o=new Float32Array(n.length);return o.set(_.f32view(Ji,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])},Yo=(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],U=t[P+1]-t[b+1],L=t[v+0]-t[b+0],G=t[v+1]-t[b+1],F=R*G-L*U;if(Math.abs(F)<=1e-12)continue;let D=1/F,k=(G*x-U*M)*D,A=(G*T-U*B)*D,I=(G*w-U*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],U=s[d+2],L=w*S+M*R+B*U<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=eo(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],U=w[1]-x[1],L=w[2]-x[2],G=B*L-S*U,F=S*R-M*L,D=M*U-B*R,k=Math.sqrt(G*G+F*F+D*D);return[G/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],U=T[2]-v[2],L=M*U-B*R,G=B*S-w*U,F=w*R-M*S,D=Math.sqrt(L*L+G*G+F*F);return[L/D,G/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,U=(v+1)/r;a.push(R,0,R,1,U,1,U,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 U,L,G;switch(u){case"xy":U=S,L=R,G=0;break;case"xz":U=S,L=0,G=R;break;case"yz":U=0,L=S,G=R;break}v.push(U,L,G)}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 U=0;U<p;U++){let L=d>0?U/d:0,G=r+x*L,F=U+p*B,D=t(G,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=G,N=R,z=I;break;case"xz":O=G,N=I,z=R;break;case"yz":O=I,N=G,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,U=S+p*(B+1),L=S+1+p*(B+1),G=S+1+p*B;u&&(!v[R]||!v[U]||!v[L]||!v[G])||w.push(R,U,G,U,L,G)}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),U,L,G;if(R.length===2){if(U=R[0],L=R[1],G=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(U=R[0],L=R[1],G=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(U)||!Number.isFinite(L)||!Number.isFinite(G)){P=!0,u&&T(!1);continue}let F,D,k;switch(c){case"xy":F=U,D=L,k=G;break;case"xz":F=U,D=G,k=L;break;case"yz":F=G,D=U,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 U=0;U<p;U++){let L=d>0?U/d:0,G=r+x*L,F=U+p*B,D=t(G,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,U=S+p*(B+1),L=S+1+p*(B+1),G=S+1+p*B;u&&(!v[R]||!v[U]||!v[L]||!v[G])||w.push(R,U,G,U,L,G)}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,U=P*w-v*T,L=Math.sqrt(S*S+R*R+U*U);L>1e-12&&(S/=L,R/=L,U/=L),p[0]=S,p[1]=R,p[2]=U;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],ge=f[(k-1)*3+2];if(xe>1e-6){H/=xe,j/=xe,Z/=xe;let Ue=Math.max(-1,Math.min(1,A*N+I*z+O*E)),un=Math.acos(Ue),Dt=Math.cos(un),kt=Math.sin(un),Y=1-Dt,Pt=j*ge-Z*ce,tt=Z*te-H*ge,Nt=H*ce-j*te,rt=H*te+j*ce+Z*ge,$e=te*Dt+Pt*kt+H*rt*Y,Jt=ce*Dt+tt*kt+j*rt*Y,Gi=ge*Dt+Nt*kt+Z*rt*Y;te=$e,ce=Jt,ge=Gi}let He=te*N+ce*z+ge*E;te-=N*He,ce-=z*He,ge-=E*He;let Le=Math.sqrt(te*te+ce*ce+ge*ge);Le>1e-12?(te/=Le,ce/=Le,ge/=Le):(te=f[0],ce=f[1],ge=f[2]),f[k*3+0]=te,f[k*3+1]=ce,f[k*3+2]=ge;let Re=z*ge-E*ce,ct=E*te-N*ge,mt=N*ce-z*te,Qt=Math.sqrt(Re*Re+ct*ct+mt*mt);Qt>1e-12&&(Re/=Qt,ct/=Qt,mt/=Qt),p[k*3+0]=Re,p[k*3+1]=ct,p[k*3+2]=mt}let G=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,ge=ce*Math.PI*2,He=Math.cos(ge),Le=Math.sin(ge),Re=He*z+Le*j,ct=He*E+Le*Z,mt=He*H+Le*xe;a.push(I+t*Re,O+t*ct,N+t*mt),s.push(Re,ct,mt),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+G*k+I,N=c+G*A+I,z=c+G*A+I+1,E=c+G*k+I+1;u.push(O,E,N,N,E,z)}}return c+G*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],U=t[h]?e[h*3+2]:e[m+2],L=v-g,G=x-b,F=T-P,D=S-w,k=R-M,A=U-B,I=k*F-A*G,O=A*L-D*F,N=D*G-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 St=n=>[n[0]??0,n[1]??0,n[2]??0],Rt=(n=!1)=>({boxMin:[0,0,0],boxMax:[0,0,0],sphereCenter:[0,0,0],sphereRadius:0,empty:!0,partial:n}),_n=n=>({boxMin:St(n.boxMin),boxMax:St(n.boxMax),sphereCenter:St(n.sphereCenter),sphereRadius:n.sphereRadius,empty:n.empty,partial:n.partial}),it=(n,e,t=!1)=>{let r=St(n),i=St(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}},Ct=(n,e,t=!1)=>{let r=St(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}},cr=(n,e,t,r,i=!1)=>({boxMin:St(n),boxMax:St(e),sphereCenter:St(t),sphereRadius:Math.max(0,r),empty:!1,partial:i}),Zo=n=>"getBounds"in n&&typeof n.getBounds=="function"?n.getBounds():n,Qo=(n,e)=>{if(n.empty){let t=_n(e);return t.partial=n.partial||e.partial,t}if(e.empty){let t=_n(n);return t.partial=n.partial||e.partial,t}return it([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)},to=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];var Jo=(n,e)=>{if(n.empty)return _n(n);let t=Math.max(1,e),r=to(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 it([r[0]-i,r[1]-o,r[2]-a],[r[0]+i,r[1]+o,r[2]+a],n.partial)},ro=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]]]},Gt=(n,e)=>{if(n.empty)return _n(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 cr([l-m,u-d,c-f],[l+m,u+d,c+f],[P,v,x],n.sphereRadius*b,n.partial)};var gt=new WeakMap,ta=(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},ra=(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(wn(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=eo(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},na=n=>{n.positionBuffer?.destroy(),n.normalBuffer?.destroy(),n.positionBuffer=null,n.normalBuffer=null,n.device=null},no=(n,e)=>{let t=n.geometry.morphTargets.length|0;if(t<=0)return;let r={targetCount:t,weights:ta(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};gt.set(n,r)},ea=(n,e)=>{let t=gt.get(n);t&&no(e,t.weights)},Yl=n=>{let e=gt.get(n);e&&(na(e),gt.delete(n))},Bn=n=>gt.has(n),ia=(n,e)=>{let t=gt.get(n);if(!t)return;let r=ta(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)},oa=(n,e,t)=>{let r=gt.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 kn=n=>{let e=gt.get(n);return e?(ra(e,n.geometry),e):n.geometry},io=n=>gt.has(n)?n:n.geometry,jt=(n,e,t)=>{let r=gt.get(n);if(!r)return n.geometry.upload(e),{positionBuffer:n.geometry.positionBuffer,normalBuffer:n.geometry.normalBuffer};let i=ra(r,n.geometry);return r.device!==e||!r.positionBuffer||!r.normalBuffer?(na(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}},ot=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 Be}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 cr(e.boundsMin,e.boundsMax,e.boundsCenter,e.boundsRadius)}getWorldBounds(){return Gt(this.getLocalBounds(),this.transform.worldMatrix)}getBounds(){return this.getWorldBounds()}destroy(){this._destroyed||(this._destroyed=!0,Zl(this),Yl(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,ea(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,ea(this,t),t}getLocalBoundsSource(){return kn(this)}},Ir=new WeakMap,aa=(n,e)=>{let t=Ir.get(n);t||(t=new Set,Ir.set(n,t)),t.add(e)},oo=(n,e)=>{let t=Ir.get(n);t&&(t.delete(e),t.size===0&&Ir.delete(n))},Zl=n=>{let e=Ir.get(n);if(e)for(let t of[...e])t.remove(n)};var Ht=256,sa={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=="},ao=n=>n<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4),Ql=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).")},mr=n=>{let e=sa,t=e[n];if(t instanceof Uint8Array)return t;let r=Ql(sa[n]);return e[n]=r,r},Jl=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},eu=(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[ze(o.color[0],a.color[0],l),ze(o.color[1],a.color[1],l),ze(o.color[2],a.color[2],l),ze(o.color[3],a.color[3],l)]}}return n[r].color},la=(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=ao(i),o=ao(o),a=ao(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},tu=(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]},ru=(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[ze(n[s+0]/255,n[l+0]/255,a),ze(n[s+1]/255,n[l+1]/255,a),ze(n[s+2]/255,n[l+2]/255,a),ze(n[s+3]/255,n[l+3]/255,a)]},nu=(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=pe(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},iu=(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"}),ou=1,q=class n{id=ou++;_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 au[e]}static fromStops(e,t={}){let r=Math.max(2,Math.floor(t.resolution??Ht)),i=t.filter??"linear",o=t.colorSpace??"srgb",a=Jl(e),s=new Array(r);for(let u=0;u<r;u++){let c=r===1?0:u/(r-1);s[u]=eu(a,c)}let l=la(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=la(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"?tu(t,this._width,e):ru(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=nu(e,t,i,this._width,this._label),a=o.createView({dimension:"1d"}),s=iu(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}},au={grayscale:new q({label:"Colormap.grayscale",width:Ht,filter:"linear",rgba8Linear:mr("grayscale")}),turbo:new q({label:"Colormap.turbo",width:Ht,filter:"linear",rgba8Linear:mr("turbo")}),viridis:new q({label:"Colormap.viridis",width:Ht,filter:"linear",rgba8Linear:mr("viridis")}),magma:new q({label:"Colormap.magma",width:Ht,filter:"linear",rgba8Linear:mr("magma")}),plasma:new q({label:"Colormap.plasma",width:Ht,filter:"linear",rgba8Linear:mr("plasma")}),inferno:new q({label:"Colormap.inferno",width:Ht,filter:"linear",rgba8Linear:mr("inferno")})};var ua="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 ca="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 ma="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 da="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 fa="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 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 }; @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 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, @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 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) 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 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, 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 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, 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 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, @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 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) 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 Pa="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 Ta="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 bt=20,Pu={linear:0,log:1,symlog:2},Tu={none:0,range:1,percentile:2},Su={component:0,magnitude:1},Mn=n=>Pu[n],Ln=n=>Tu[n],Rn=n=>Su[n],De=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}),wa=()=>({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}),be=n=>{let e=wa(),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(Mr(n.componentCount,e.componentCount),1,4),a=se(Mr(n.componentIndex,e.componentIndex),0,3),s=Math.max(o,Mr(n.stride,e.stride)),l=Math.max(0,Mr(n.offset,e.offset)),u=dt(n.domainMin,e.domainMin),c=dt(n.domainMax,e.domainMax),m=dt(n.clampMin,e.clampMin),d=dt(n.clampMax,e.clampMax),f=se(dt(n.percentileLow,e.percentileLow),0,100),p=se(dt(n.percentileHigh,e.percentileHigh),0,100);y(p>f,`Scale transform requires percentileHigh > percentileLow (got ${f}, ${p})`);let h=Math.max(1.000001,dt(n.logBase,e.logBase)),g=Math.max(1e-20,dt(n.symlogLinThresh,e.symlogLinThresh)),b=Math.max(1e-6,dt(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}},Ye=(n,e,t=0)=>{let r=be(n);e[t+0]=r.componentCount,e[t+1]=r.componentIndex,e[t+2]=Rn(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]=Ln(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]=Mn(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},Sa=(n,e)=>{let t=Math.max(1.000001,e);return Math.log(n)/Math.log(t)},Ca=(n,e,t,r)=>{if(e==="linear")return n;if(e==="log")return Sa(Math.max(n,1e-20),r);let i=Math.max(t,1e-20),o=n>=0?1:-1,a=Sa(1+Math.abs(n)/i,r);return o*a},Cu=(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)},wu=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}};var so=(n,e)=>{let t=be(e),r=wu(t),i=le(n);t.invert&&(i=1-i),i=Math.pow(i,1/Math.max(t.gamma,1e-6));let o=Ca(r.domainMin,t.mode,t.symlogLinThresh,t.logBase),a=Ca(r.domainMax,t.mode,t.symlogLinThresh,t.logBase),s=o+(a-o)*i,l=Cu(s,t.mode,t.symlogLinThresh,t.logBase);return r.hasClamp&&(l=se(l,r.clampMin,r.clampMax)),l};var lo=n=>rr(n)?n:n.buffer,_u=n=>rr(n)?Number(n.size):typeof n.byteLength=="number"?n.byteLength:null,_a=(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}},Dr=class{compute;sourceIds=new WeakMap;cache=new Map;sourceCacheKeys=new Map;nextSourceId=1;constructor(e){this.compute=e}createTransform(e){return be(e)}invalidate(e){let t=e.buffer?e.buffer:e,r=lo(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(lo(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=lo(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=_a(h,t.low,u,c,a),d=_a(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}},dr=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};var fr=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 fr{_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 dr(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?ca:e.skinned8?da:e.skinned?ma:ua}};var Gn=(n,e)=>[n?.[0]??e[0],n?.[1]??e[1],n?.[2]??e[2]],uo=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:Gn(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:Gn(n.specular.color,[1,1,1]),colorTexture:n.specular.colorTexture??null,colorTextureTransform:me(n.specular.colorTextureTransform)}:null,sheen:n?.sheen?{color:Gn(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:Gn(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=>uo(n),J=class n extends fr{_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=uo(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 dr(this._baseColorTextureTransform)}set baseColorTextureTransform(e){this._baseColorTextureTransform=me(e),this._dirty=!0}get metallicRoughnessTextureTransform(){return dr(this._metallicRoughnessTextureTransform)}set metallicRoughnessTextureTransform(e){this._metallicRoughnessTextureTransform=me(e),this._dirty=!0}get normalTextureTransform(){return dr(this._normalTextureTransform)}set normalTextureTransform(e){this._normalTextureTransform=me(e),this._dirty=!0}get occlusionTextureTransform(){return dr(this._occlusionTextureTransform)}set occlusionTextureTransform(e){this._occlusionTextureTransform=me(e),this._dirty=!0}get emissiveTextureTransform(){return dr(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=uo(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?va:e.skinned8?xa:e.skinned?ya:ba:e.instanced?pa:e.skinned8?ga:e.skinned?ha:fa}},Ze=class n extends fr{_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=be(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 De(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=be(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 q?`cm:${e.id}`:`cm:${e}`}getColormapForBinding(){let e=this._colormap;return e instanceof q?e:q.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(bt+4)*4}getUniformData(){let e=this.getUniformDataCache(bt+4);return e.fill(0),Ye(this._scaleTransform,e,0),e[bt+0]=le(this._opacity),e[bt+1]=le(this._shading),e[bt+2]=0,e[bt+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 Pa}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()}},pr=class extends fr{_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 Ta}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 Qi=4+Ee+4+32,rs=Qi*4,Xi=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];w(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},Yi=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},Fn=n=>ce({componentCount:4,componentIndex:3,stride:4,...n}),Ue=class{transform=new he;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(w(!!e&&!!e.scaleTransform,"PointCloud: scaleTransform is required."),this._scaleTransform=Fn(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=Yi(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;w(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=Xe(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(xt(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 $e(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=Fn(e),this._uniformDirty=!0,this.emitVisualChange("scale")}applyScaleStats(e){let t=$e(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=Fn(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=Yi(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={}){w(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){w(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=C.allocF32(e.length),i=C.allocF32(3),o=C.allocF32(3),a=C.allocF32(3),s=C.allocF32(1);try{C.f32view(r,e.length).set(e),bt.pointcloudXYZS(i,o,a,s,r,t,4);let l=C.f32view(i,3),u=C.f32view(o,3),m=C.f32view(a,3),c=C.f32view(s,1)[0];this.setBounds(Pt([l[0],l[1],l[2]],[u[0],u[1],u[2]],[m[0],m[1],m[2]],c),"computed")}finally{C.freeF32(s,1),C.freeF32(a,3),C.freeF32(o,3),C.freeF32(i,3),C.freeF32(r,e.length)}}getLocalBounds(){return this._boundsSource==="none"&&this._CPUData&&this.computeBoundsFromCPUData(),this._boundsSource==="none"?vt(this._pointCount>0):Pt(this.boundsMin,this.boundsMax,this.boundsCenter,this.boundsRadius)}getWorldBounds(){return wt(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=ye(e,r,i);else try{t.writeBuffer(this.pointsBuffer,0,r.buffer,r.byteOffset,r.byteLength)}catch{this.pointsBuffer.destroy(),this.pointsBuffer=ye(e,r,i)}this._keepCPUData||(this._CPUData=null),this._pointsDirty=!1,this.bindGroupKey=null}getUniformBufferSize(){return rs}getUniformData(){let e=new Float32Array(Qi),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,He(this._scaleTransform,e,4),e[24]=Xi(this._opacity),e[25]=Xi(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 Ze=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=vt(!1),i=l=>{if(l.empty){l.partial&&(r.partial=!0);return}r=Ui(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 Kt=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}},Gr=class extends Kt{constructor(e={}){super("ambient"),this._color=e.color??[1,1,1],this._intensity=e.intensity??.1}},Je=class extends Kt{_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])}},qe=class extends Kt{_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=C.allocF32(this.positions.length),l=C.allocF32(3),u=C.allocF32(3),m=C.allocF32(3),c=C.allocF32(1);try{C.f32view(s,this.positions.length).set(this.positions),bt.geometryPositions(l,u,m,c,s,this.vertexCount);let d=C.f32view(l,3),f=C.f32view(u,3),p=C.f32view(m,3),b=C.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{C.freeF32(c,1),C.freeF32(m,3),C.freeF32(u,3),C.freeF32(l,3),C.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=ye(e,this.positions,GPUBufferUsage.VERTEX),this._normalBuffer=ye(e,this.normals,GPUBufferUsage.VERTEX),this._uvBuffer=ye(e,this.uvs,GPUBufferUsage.VERTEX),this.joints&&(this._jointsBuffer=ye(e,this.joints,GPUBufferUsage.VERTEX)),this.weights&&(this._weightsBuffer=ye(e,this.weights,GPUBufferUsage.VERTEX)),this.joints1&&(this._joints1Buffer=ye(e,this.joints1,GPUBufferUsage.VERTEX)),this.weights1&&(this._weights1Buffer=ye(e,this.weights1,GPUBufferUsage.VERTEX)),this.indices&&(this._indexBuffer=ye(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 P=h*c-o;f.push(P,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,P=M+u*(x+1),S=M+1+u*(x+1),B=M+1+u*x;g.push(h,P,B,P,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,P)=>{switch(r){case"xy":s.push(h,P,0);break;case"xz":s.push(h,0,P);break;case"yz":s.push(0,h,P);break}l.push(d,f,p),u.push(b(h),g(P))};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,P)=>{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,P)};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,P=e!==0?.5-M*p:.5;l.push(h,P)};b(0,0);for(let x=0;x<o;x++){let M=x/o*Math.PI*2,h=Math.cos(M)*e,P=Math.sin(M)*e;b(h,P)}for(let x=0;x<o;x++){let h=1+x,P=1+(x+1)%o;m?u.push(0,P,h):u.push(0,h,P)}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,P)=>{switch(i){case"xy":s.push(h,P,0);break;case"xz":s.push(h,0,P);break;case"yz":s.push(0,h,P);break}l.push(d,f,p);let S=e!==0?.5+h*b:.5,B=t!==0?.5-P*g:.5;u.push(S,B)};x(0,0);for(let h=0;h<a;h++){let P=h/a*Math.PI*2,S=Math.cos(P)*e,B=Math.sin(P)*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 P=0;P<=i;P++){let S=P/i,B=S*Math.PI*2,v=Math.sin(B),A=Math.cos(B);s.push(h*v,M,h*A);let _=Math.sqrt(1+f*f);l.push(v/_,f/_,A/_),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),P=x+1+(i+1)*(g+1),S=x+1+(i+1)*g;m.push(M,S,h,h,S,P)}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,P=e*Math.sin(h),S=e*Math.cos(h);s.push(P,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,P=t*Math.sin(h),S=t*Math.cos(h);s.push(P,-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=(P,S,B)=>{let v=S[0]-P[0],A=S[1]-P[1],_=S[2]-P[2],k=B[0]-P[0],G=B[1]-P[1],R=B[2]-P[2],T=A*R-_*G,F=_*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=(P,S,B)=>{let v=d(P,S,B);f.push(...P,...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,P=b-x,S=Math.sqrt(M*M+h*h+P*P);a.push(M/S,h/S,P/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 P=h/r*Math.PI*2,S=e*Math.cos(P),B=e*Math.sin(P);m.push([S,l,B]),c.push([S,-l,B])}let d=(h,P,S)=>{let B=P[0]-h[0],v=P[1]-h[1],A=P[2]-h[2],_=S[0]-h[0],k=S[1]-h[1],G=S[2]-h[2],R=v*G-A*k,T=A*_-B*G,F=B*k-v*_,D=Math.sqrt(R*R+T*T+F*F);return[R/D,T/D,F/D]};for(let h=0;h<r;h++){let P=(h+1)%r,S=m[h],B=m[P],v=c[h],A=c[P],_=d(S,B,v);i.push(...S,...v,...A,...B),o.push(..._,..._,..._,..._);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 P=m[h];i.push(...P),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 P=(h+1)%r;s.push(b,b+1+P,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 P=c[h];i.push(...P),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 P=(h+1)%r;s.push(M,M+1+h,M+1+P)}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=[],P=!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,_=r+B*A,k=t(_);if(!Number.isFinite(k)){P=!0,d&&S(!1);continue}let G,R,T;switch(u){case"xy":G=_,R=k,T=0;break;case"xz":G=_,R=0,T=k;break;case"yz":G=0,R=_,T=k;break}h.push(G,R,T)}return S(l&&!P),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),P=i-r,S=a-o;for(let A=0;A<b;A++){let _=f>0?A/f:0,k=o+S*_;for(let G=0;G<p;G++){let R=d>0?G/d:0,T=r+P*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 V=F*2;M[V+0]=R,M[V+1]=1-_}}n._computeGridNormals(g,h,d,f,x);let B=[];for(let A=0;A<f;A++)for(let _=0;_<d;_++){let k=_+p*A,G=_+p*(A+1),R=_+1+p*(A+1),T=_+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,P=null;if(h)switch(m){case"xy":P=h;break;case"xz":P=[h[0],h[2],h[1]];break;case"yz":P=[h[2],h[0],h[1]];break}let S=v=>{if(x.length/3>=2){let _=P??[0,1,0];b=n._appendTubeSegment(new Float32Array(x),a,s,v,_,c,d,f,p,b)}x=[]},B=i-r;for(let v=0;v<g;v++){let A=o>0?v/o:0,_=r+B*A,k=t(_),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":P=h;break;case"xz":P=[h[0],h[2],h[1]];break;case"yz":P=[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":P=h;break;case"xz":P=[h[0],h[2],h[1]];break;case"yz":P=[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),P=i-r,S=a-o;for(let A=0;A<b;A++){let _=f>0?A/f:0,k=o+S*_;for(let G=0;G<p;G++){let R=d>0?G/d:0,T=r+P*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 V,Z,ie;switch(c){case"xy":V=U,Z=L,ie=E;break;case"xz":V=U,Z=E,ie=L;break;case"yz":V=E,Z=U,ie=L;break}g[O+0]=V,g[O+1]=Z,g[O+2]=ie}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-_}}n._computeGridNormals(g,h,d,f,x);let B=[];for(let A=0;A<f;A++)for(let _=0;_<d;_++){let k=_+p*A,G=_+p*(A+1),R=_+1+p*(A+1),T=_+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],V=Math.sqrt(z*z+O*O+I*I);V>1e-12?(z/=V,O/=V,I/=V):(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],P=d[2],S=h*x-P*g,B=P*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-P*g,B=P*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 _=h*v-P*B,k=P*S-M*v,G=M*B-h*S,R=Math.sqrt(_*_+k*k+G*G);R>1e-12&&(_/=R,k/=R,G/=R),p[0]=_,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],V=d[U*3+2],Z=E*V-z*I,ie=z*O-L*V,le=L*I-E*O,Ke=Math.sqrt(Z*Z+ie*ie+le*le),oe=f[(U-1)*3+0],ue=f[(U-1)*3+1],J=f[(U-1)*3+2];if(Ke>1e-6){Z/=Ke,ie/=Ke,le/=Ke;let da=Math.max(-1,Math.min(1,L*O+E*I+z*V)),vi=Math.acos(da),wr=Math.cos(vi),Pn=Math.sin(vi),wn=1-wr,pa=ie*J-le*ue,fa=le*oe-Z*J,ha=Z*ue-ie*oe,Sn=Z*oe+ie*ue+le*J,ba=oe*wr+pa*Pn+Z*Sn*wn,ga=ue*wr+fa*Pn+ie*Sn*wn,ya=J*wr+ha*Pn+le*Sn*wn;oe=ba,ue=ga,J=ya}let Le=oe*O+ue*I+J*V;oe-=O*Le,ue-=I*Le,J-=V*Le;let we=Math.sqrt(oe*oe+ue*ue+J*J);we>1e-12?(oe/=we,ue/=we,J/=we):(oe=f[0],ue=f[1],J=f[2]),f[U*3+0]=oe,f[U*3+1]=ue,f[U*3+2]=J;let Fe=I*J-V*ue,pe=V*oe-O*J,De=O*ue-I*oe,it=Math.sqrt(Fe*Fe+pe*pe+De*De);it>1e-12&&(Fe/=it,pe/=it,De/=it),p[U*3+0]=Fe,p[U*3+1]=pe,p[U*3+2]=De}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],V=f[U*3+1],Z=f[U*3+2],ie=p[U*3+0],le=p[U*3+1],Ke=p[U*3+2];for(let oe=0;oe<=r;oe++){let ue=r>0?oe/r:0,J=ue*Math.PI*2,Le=Math.cos(J),we=Math.sin(J),Fe=Le*I+we*ie,pe=Le*V+we*le,De=Le*Z+we*Ke;a.push(E+t*Fe,z+t*pe,O+t*De),s.push(Fe,pe,De),l.push(L,ue)}}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,V=m+T*U+E+1;u.push(z,V,O,O,V,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],P=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],_=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=P-x,F=S-M,D=_-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 ro=60,os=ro*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];w(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},Zi=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},Tr=n=>ce({componentCount:4,componentIndex:0,stride:4,...n}),us=n=>{switch(n){case"rgba":return 0;case"scalar":return 1;case"solid":return 2}},Rr=n=>n?n.buffer?n.buffer:n:null,Ji=(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,P=f,S=x*d;i.push(h,P,S),o.push(h,P,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=(_,k,G,R,T,F,D,U)=>{let L=t.length/3|0;return t.push(_,k,G),r.push(R,T,F),i.push(D,U),L},f=(_,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,V=E,Z=G;R&&(I=0,V=0,Z=G),T.push(d(z,O,_,I,V,Z,D,_-a))}return T},p=f(a,m,0,!1),b=f(s,m,0,!1);for(let _=0;_<e;_++){let k=p[_],G=p[_+1],R=b[_],T=b[_+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 _=0;_<=e;_++){let G=_/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[_]*3+0]=F*L,r[g[_]*3+1]=D*L,r[g[_]*3+2]=U*L,r[x[_]*3+0]=F*L,r[x[_]*3+1]=D*L,r[x[_]*3+2]=U*L}for(let _=0;_<e;_++){let k=g[_],G=g[_+1],R=x[_],T=x[_+1];o.push(k,G,R),o.push(G,T,R)}let h=f(l,c,0,!1),P=[],S=u-l,B=c/S;for(let _=0;_<=e;_++){let k=_/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);P.push(d(0,0,u,F*L,D*L,U*L,k,u-a))}for(let _=0;_<=e;_++){let G=_/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[_]*3+0]=F*L,r[h[_]*3+1]=D*L,r[h[_]*3+2]=U*L}for(let _=0;_<e;_++){let k=h[_],G=h[_+1],R=P[_];o.push(k,G,R)}let v=d(0,0,a,0,0,-1,.5,0),A=f(a,m,-1,!0);for(let _=0;_<e;_++){let k=A[_],G=A[_+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)})},Lr=null,eo=null,ms=n=>{switch(n){case"ellipsoid":return Lr??=Ji(),Lr;case"arrow":return eo??=cs(),eo;default:return Lr??=Ji(),Lr}},Oe=class{transform=new he;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=Tr({});_scaleRevision=0;_visualChangeListeners=new Set;_opacity=1;_lit=!1;_solidColor=[1,1,1,1];constructor(e){w(!!e&&!!e.scaleTransform,"GlyphField: scaleTransform is required."),this._scaleTransform=Tr(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=Zi(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=Rr(e.positionsBuffer),r=Rr(e.rotationsBuffer),i=Rr(e.scalesBuffer),o=Rr(e.attributesBuffer);if(t||r||i||o){w(!!t&&!!r&&!!i,"GlyphField: positionsBuffer, rotationsBuffer, and scalesBuffer are required when using external buffers.");let a=e.instanceCount??0;w(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){w(!!e.positionsPtr&&!!e.rotationsPtr&&!!e.scalesPtr,"GlyphField: positionsPtr, rotationsPtr, and scalesPtr are required when using wasm pointers.");let a=e.instanceCount??0;w(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=Xe(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(xt(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 $e(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=Tr(e),this._uniformDirty=!0,this.emitVisualChange("scale")}applyScaleStats(e){let t=$e(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=Tr(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&&(w(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=Zi(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&&w(e.length%4===0,"GlyphField: positions length must be a multiple of 4 (x,y,z,_ per instance)."),t&&w(t.length%4===0,"GlyphField: rotations length must be a multiple of 4 (qx,qy,qz,qw per instance)."),r&&w(r.length%4===0,"GlyphField: scales length must be a multiple of 4 (sx,sy,sz,_ per instance)."),i&&w(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;w(a>=0,"GlyphField: instanceCount must be >= 0."),a>0&&w(!!e&&!!t&&!!r,"GlyphField: positions, rotations, and scales are required for CPU-backed glyph fields."),e&&w(e.length/4===a,"GlyphField: positions length does not match instanceCount."),t&&w(t.length/4===a,"GlyphField: rotations length does not match instanceCount."),r&&w(r.length/4===a,"GlyphField: scales length does not match instanceCount."),i&&w(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;w(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;w(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=C.allocF32(e.length),a=C.allocF32(t.length),s=0,l=C.allocF32(3),u=C.allocF32(3),m=C.allocF32(3),c=C.allocF32(3),d=C.allocF32(1);try{C.f32view(o,e.length).set(e),C.f32view(a,t.length).set(t),i&&(s=C.allocF32(i.length),C.f32view(s,i.length).set(i)),C.writeF32(l,3,this.geometry.boundsCenter),bt.glyphInstances(u,m,c,d,o,a,s,r,l,this.geometry.boundsRadius);let f=C.f32view(u,3),p=C.f32view(m,3);this.setBounds(Xe([f[0],f[1],f[2]],[p[0],p[1],p[2]]),"computed")}finally{C.freeF32(d,1),C.freeF32(c,3),C.freeF32(m,3),C.freeF32(u,3),C.freeF32(l,3),s&&i&&C.freeF32(s,i.length),C.freeF32(a,t.length),C.freeF32(o,e.length)}}getLocalBounds(){return this._boundsSource==="none"&&this._positionsCPU&&this._scalesCPU&&this.computeBoundsFromCPUData(),this._boundsSource==="none"?vt(this._instanceCount>0):Xe(this.boundsMin,this.boundsMax)}getWorldBounds(){return wt(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=ae.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(ro);e.fill(0),He(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 no="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 Fr="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 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); } @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 oo="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 ao="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 so="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 Dr="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 Ir="@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 Er=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=Gn(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=C.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=C.f32view(this.cameraUniformStagingPtr,20),this.lightingUniformStagingView=C.f32view(this.lightingUniformStagingPtr,104),this.lightingCountView=C.u32view(this.lightingUniformStagingPtr+16,1),this.modelUniformStagingView=C.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=C.allocF32(t*3),this.cullRadiiPtr=C.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();he.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),P=this.toFramebufferPixel(g,s,this.height);return{mode:"rect",bounds:d,x:Math.min(x,h),y:Math.min(M,P),width:Math.abs(h-x)+1,height:Math.abs(P-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 P=e[h];!Number.isFinite(P.x)||!Number.isFinite(P.y)||(P.x<o&&(o=P.x),P.y<a&&(a=P.y),P.x>s&&(s=P.x),P.y>l&&(l=P.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 P=e[h];if(!Number.isFinite(P.x)||!Number.isFinite(P.y))continue;let S=P.x/Math.max(1,r)*Math.max(1,this.width),B=P.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),he.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 Oe?{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 P=b+M*2,S=c[P]>>>0;if(S===0)continue;let B=c[P+1]>>>0,v=d[g+M];if(!Number.isFinite(v)||v>=1)continue;let A=`${S}:${B}`,_=u.get(A);if(_)v<_.depth&&(_.depth=v,_.px=h,_.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=no;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=Gn(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=Ne.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=j.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<Ze.MAX_LIGHTS;a++){let s=r[a];s instanceof Je?(i[o+0]=s.direction[0],i[o+1]=s.direction[1],i[o+2]=s.direction[2],i[o+3]=0):s instanceof qe&&(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 qe&&(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=j.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,_=A.boundsCenter,k=B*3;x[B]=v.transform.worldMatrixPtr>>>0,M[k+0]=_[0],M[k+1]=_[1],M[k+2]=_[2],h[B]=A.boundsRadius}ot.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,p,b,g,i);let P=W.allocF32(24);_r.writePlanesFromViewProjection(P,this.cameraUniformStagingPtr);let S=W.alloc(i*4,4);a=ot.spheresFrustum(S,this.cullCentersPtr,this.cullRadiiPtr,i,P),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,P=x.skin!==null&&M.joints!==null&&M.weights!==null&&this.materialSupportsSkinning(h),S=P&&M.joints1!==null&&M.weights1!==null,B=this.getOrCreatePipeline(h,!1,P,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=P,v.skinned8=S,v.sortKey=0,h.blendMode==="opaque")this.opaqueDrawList.push(v);else{let A=x.transform.worldMatrixPtr>>>2,_=l[A+12]-c,k=l[A+13]-d,G=l[A+14]-f;v.sortKey=_*_+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,P=this.getOrCreatePipeline(x,!1,M,h),S=this.acquireDrawItem();if(S.mesh=b,S.geometry=g,S.material=x,S.pipeline=P,S.pipelineId=this.getObjectId(P),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,_=l[B+14]-f;S.sortKey=v*v+A*A+_*_,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=j.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[A],k=_.boundsCenter[0],G=_.boundsCenter[1],R=_.boundsCenter[2],T=A*3;x[A]=_.transform.worldMatrixPtr>>>0,M[T+0]=k,M[T+1]=G,M[T+2]=R,h[A]=_.boundsRadius}ot.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,p,b,g,f);let P=W.allocF32(24);_r.writePlanesFromViewProjection(P,this.cameraUniformStagingPtr);let S=W.alloc(c.length*4,4),B=ot.spheresFrustum(S,this.cullCentersPtr,this.cullRadiiPtr,c.length,P),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],P=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=P-s,A=S-l,_=B-u;b.sortKey=v*v+A*A+_*_,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=j.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],_=A.boundsCenter[0],k=A.boundsCenter[1],G=A.boundsCenter[2],R=v*3;b[v]=A.transform.worldMatrixPtr>>>0,g[R+0]=_,g[R+1]=k,g[R+2]=G,x[v]=A.boundsRadius}ot.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,d,f,p,c);let M=W.allocF32(24);_r.writePlanesFromViewProjection(M,this.cameraUniformStagingPtr);let h=W.alloc(u.length*4,4),P=ot.spheresFrustum(h,this.cullCentersPtr,this.cullRadiiPtr,u.length,M),S=r.u32(),B=h>>>2;for(let v=0;v<P;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=ae.bytes(),h=t[p].mesh,P=s.skinned?h.skin:null;if(P){P.ensureGpuResources(this.device,this.skinBindGroupLayout);let A=P.jointCount|0,_=W.allocF32(A*16);ht.computeJointMatricesTo(_,P.skin.jointIndicesPtr,A,P.skin.invBindPtr,j.global().worldPtr,P.bindMatrixPtr),this.queue.writeBuffer(P.boneBuffer,0,M,_,A*64),e.setBindGroup(2,P.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=ae.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=ae.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,P="field"in d;if(h&&P){let S=c,B=d;return S.geometryId-B.geometryId||S.fieldId-B.fieldId}return t(c)-t(d)});let r=ae.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);ht.computeJointMatricesTo(L,D.skin.jointIndicesPtr,U,D.skin.invBindPtr,j.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 _=this.modelBufferIndex++,k=this.modelUniformBuffers[_],G=this.globalBindGroups[_],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++,_=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(_,0,r,G,64),this.queue.writeBuffer(_,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,P=this.modelUniformStagingPtr+64;ne.invert(h,M),ne.transpose(P,h),this.queue.writeBuffer(g,0,r,M,64),this.queue.writeBuffer(g,64,r,P,64),e.setBindGroup(0,x),e.draw(6,p.pointCount)}}executeMeshPickDrawList(e,t){let r=ae.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 P=h.jointCount|0,S=W.allocF32(P*16);ht.computeJointMatricesTo(S,h.skin.jointIndicesPtr,P,h.skin.invBindPtr,j.global().worldPtr,h.bindMatrixPtr),this.queue.writeBuffer(h.boneBuffer,0,r,S,P*64),e.setBindGroup(2,h.bindGroup)}}c.isIndexed?e.drawIndexed(c.indexCount):e.draw(c.vertexCount)}}executePointCloudPickDrawList(e,t){let r=ae.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=ae.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=j.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);gt.packModelNormalMat4FromPtrs(m,s,a);let c=a*this.INSTANCE_STRIDE_BYTES,d=this.instanceBufferOffset,f=d+c;this.ensureInstanceBuffer(f);let p=ae.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?so:t?ao:oo,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(Dr);r||(r=this.device.createShaderModule({code:Dr}),this.shaderCache.set(Dr,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(Ir);o||(o=this.device.createShaderModule({code:Ir}),this.shaderCache.set(Ir,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===Be||e.constructor===Pe||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 Be){let t=e.baseColorTexture;return`unlit:${t?.id??0}:${t?.revision??0}`}if(e instanceof Pe){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 Be){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 Pe){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 Be||e instanceof Pe}materialSupportsSkinning(e){return e instanceof Be||e instanceof Pe}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(Fr);i||(i=this.device.createShaderModule({code:Fr}),this.shaderCache.set(Fr,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=io,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 At=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}},In=(n,e,t)=>Math.max(e,Math.min(t,n)),ze=(n,e)=>{if(!Number.isFinite(n))return"n/a";let t=Math.max(0,e|0);return n.toFixed(t)},Mt=(n,e)=>{if(!Number.isFinite(n))return"n/a";let t=Math.abs(n);return t<1024?`${ze(n,0)} B`:t<1024*1024?`${ze(n/1024,e)} KiB`:`${ze(n/(1024*1024),e)} MiB`},Or=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 At(i),this.frameMsAvg=new At(i),this.cpuMsAvg=new At(i),this.gpuMsAvg=new At(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=In(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: ${ze(r,1)}`),this.show.showFrameTime&&t.push(`Frame: ${ze(i,e)} ms (\u2248${ze(o,0)} Hz)`),this.show.showCpuTime){let s=Math.max(1e-4,this.lastDtSeconds)*1e3,l=In(a/s*100,0,1e3);t.push(`CPU: ${ze(a,e)} ms (${ze(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=In(l/u*100,0,1e3);t.push(`GPU: ${ze(l,e)} ms (${ze(m,0)}%)`)}}if(this.show.showMemory){try{let l=W.usedBytes(),u=W.capBytes();t.push(`Frame arena: ${Mt(l,e)} / ${Mt(u,e)}`)}catch{}try{let l=C.memory().buffer.byteLength;t.push(`WASM memory: ${Mt(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: ${Mt(l,e)} / ${Mt(u,e)}`):t.push(`JS heap: ${Mt(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),Xt=(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)=>{w(Number.isInteger(t)&&t>=0,`dstOffsetBytes must be an integer >= 0 (got ${t})`);let a=Xt(r,i,o);w((t&3)===0,`dstOffsetBytes must be 4-byte aligned (got ${t})`),w((a.offset&3)===0,`srcOffsetBytes must be 4-byte aligned (got ${a.offset})`);let s=se(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)},zr=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)}},K=class extends zr{label;constructor(e,t,r){let i=r.data?Xt(r.data).size:r.byteLength??0;w(Number.isInteger(i)&&i>=0,`StorageBuffer.byteLength must be an integer >= 0 (got ${i})`);let o=se(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=Xt(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){w(this.canReadback,"StorageBuffer.read() requires the buffer to be created with copySrc: true"),w(Number.isInteger(e)&&e>=0,`srcOffsetBytes must be an integer >= 0 (got ${e})`);let r=t??this.byteLength-e;w(Number.isInteger(r)&&r>=0,`sizeBytes must be an integer >= 0 (got ${r})`),w(e+r<=this.byteLength,`read range out of bounds (offset ${e}, size ${r}, byteLength ${this.byteLength})`);let i=se(r,4),o=se(e,4);w(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;w(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)}},Yt=class extends zr{label;constructor(e,t,r){let i=r.data?Xt(r.data).size:r.byteLength??0;w(Number.isInteger(i)&&i>=0,`UniformBuffer.byteLength must be an integer >= 0 (got ${i})`);let o=se(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=Xt(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}}),Qt=n=>({binding:n.binding,visibility:n.visibility??GPUShaderStage.COMPUTE,buffer:{type:"uniform",hasDynamicOffset:n.hasDynamicOffset??!1,minBindingSize:n.minBindingSize}}),co=n=>n.mapState!==void 0,lo=n=>co(n)?n:n.buffer,uo=n=>{if(co(n))return{buffer:n};if(n.buffer!==void 0&&n.device!==void 0)return{buffer:lo(n)};let e=n;return{buffer:lo(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:uo(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:uo(i)})}return e},te=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 w(!!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 Ut=n=>Number.isInteger(n)&&n>0,En=n=>Number.isInteger(n)&&n>=0,ke=(n,e)=>(w(Number.isFinite(n)&&Number.isFinite(e),"ceilDiv expects finite numbers"),w(e!==0,"ceilDiv divisor must be non-zero"),Math.floor((n+e-1)/e));var Zt=(n,e=1,t=1)=>(w(En(n),`workgroups.x must be an integer >= 0 (got ${n})`),w(En(e),`workgroups.y must be an integer >= 0 (got ${e})`),w(En(t),`workgroups.z must be an integer >= 0 (got ${t})`),[n,e,t]),be=(n,e)=>(w(Number.isFinite(n),`invocations must be finite (got ${n})`),w(n>=0,`invocations must be >= 0 (got ${n})`),w(Ut(e),`workgroupSizeX must be a positive integer (got ${e})`),n===0?[0,1,1]:[ke(n,e),1,1]),Wr=(n,e,t,r)=>{if(w(Number.isFinite(n)&&Number.isFinite(e),"width/height must be finite"),w(n>=0&&e>=0,`width/height must be >= 0 (got ${n}x${e})`),w(Ut(t),`workgroupSizeX must be a positive integer (got ${t})`),w(Ut(r),`workgroupSizeY must be a positive integer (got ${r})`),n===0||e===0)return[0,1,1];let i=ke(n,t),o=ke(e,r);return[i,o,1]},Nr=(n,e,t,r,i,o)=>{if(w(Number.isFinite(n)&&Number.isFinite(e)&&Number.isFinite(t),"width/height/depth must be finite"),w(n>=0&&e>=0&&t>=0,`width/height/depth must be >= 0 (got ${n}x${e}x${t})`),w(Ut(r),`workgroupSizeX must be a positive integer (got ${r})`),w(Ut(i),`workgroupSizeY must be a positive integer (got ${i})`),w(Ut(o),`workgroupSizeZ must be a positive integer (got ${o})`),n===0||e===0||t===0)return[0,1,1];let a=ke(n,r),s=ke(e,i),l=ke(t,o);return[a,s,l]};var kt=n=>Number.isInteger(n)&&n>=0,Vr=n=>{if(Array.isArray(n)){let i=n[0]??0,o=n[1]??1,a=n[2]??1;return w(kt(i),`workgroups.x must be an integer >= 0 (got ${i})`),w(kt(o),`workgroups.y must be an integer >= 0 (got ${o})`),w(kt(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 w(kt(e),`workgroups.x must be an integer >= 0 (got ${e})`),w(kt(t),`workgroups.y must be an integer >= 0 (got ${t})`),w(kt(r),`workgroups.z must be an integer >= 0 (got ${r})`),{x:e,y:t,z:r}},Gt=(n,e)=>{let{x:t,y:r,z:i}=Vr(e),o=n.limits.maxComputeWorkgroupsPerDimension;w(t<=o&&r<=o&&i<=o,`dispatchWorkgroups exceeds device.limits.maxComputeWorkgroupsPerDimension (${o})`)},mo=n=>n instanceof te?n.pipeline:n,On=(n,e)=>{let t=n.beginComputePass({label:e.label}),r=mo(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}=Vr(e.workgroups);i>0&&o>0&&a>0&&t.dispatchWorkgroups(i,o,a),t.end()},Jt=(n,e,t)=>{let r=n.beginComputePass({label:t}),i=null;for(let o of e){let a=mo(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}=Vr(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 jr=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){w(Number.isInteger(e)&&e>=0,`ScratchBufferPool.acquire: byteLength must be an integer >= 0 (got ${e})`);let r=Math.max(4,se(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 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 = -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 fo="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 ho="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 bo="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 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 = 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 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 = 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 vo="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 xo="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 Po="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 wo="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 So="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 _o="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 Co="@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 Bo="@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 Mo="@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 Ao="@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 Uo="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 ko="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 Go="@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 To="@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 Ro="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 Lo="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 Fo="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,er=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)=>{w(n%e===0,`${t}: byteLength (${n}) must be divisible by ${e}`)},tr=class{device;queue;scratch;pipelines;constructor(e,t){this.device=e,this.queue=t,this.scratch=new jr(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){w(Number.isInteger(t)&&t>=0,`bindSized: sizeBytes must be an integer >= 0 (got ${t})`);let r=se(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:(w(Number.isInteger(r)&&r>=0,`count must be an integer >= 0 (got ${r})`),w(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)Gt(this.device,i.workgroups);Jt(r,e,t?.label),t?.encoder||(this.queue.submit([r.finish()]),this.scratch.reset())}writeScalarU32(e,t){let r=er(e),i=new Uint32Array([t>>>0]);this.queue.writeBuffer(r,0,i)}writeScalarF32(e,t){let r=er(e),i=new Float32Array([t]);this.queue.writeBuffer(r,0,i)}writeScalarF32Bits(e,t){let r=er(e),i=new Uint32Array([t>>>0]);this.queue.writeBuffer(r,0,i)}writeArgPairBits(e,t,r){let i=er(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 te(this.device,{label:r,code:e==="f32"?t==="sum"?go:t==="max"?po:ho:t==="sum"?yo:t==="max"?fo:bo,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 te(this.device,{label:t,code:e==="argmax"?vo:Po,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"?xo:wo;return new te(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){w(Number.isInteger(o)&&o>0,"encodeReduceScalar expects inputCount > 0");let l=qs(t),u=i,m=o,c=0;for(;;){let d=ke(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:Zt(d,1,1),label:`${s}:reduce:${c}`}),f)break;u=p,m=d,c++}}encodeArgReduceF32Scalar(e,t,r,i,o,a){w(Number.isInteger(i)&&i>0,"encodeArgReduceF32Scalar expects inputCount > 0");let s=r,l=i,u=4,m=0;for(;;){let c=ke(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:Zt(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 te(this.device,{label:e,code:So,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 te(this.device,{label:e,code:_o,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!1}),$({binding:1,readOnly:!0})]}]}))}encodeScanExclusiveU32Into(e,t,r,i,o){if(w(Number.isInteger(r)&&r>=0,`encodeScanExclusiveU32Into: count must be an integer >= 0 (got ${r})`),r===0)return;let a=ke(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:Zt(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:be(r,256),label:`${o}:addOffsets`})}}getHistogramClearPipeline(){let e="kernels:histogram:clearAtomicU32";return this.getPipeline(e,()=>new te(this.device,{label:e,code:Co,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!1})]}]}))}getHistogramPipeline(){let e="kernels:histogram:u32";return this.getPipeline(e,()=>new te(this.device,{label:e,code:Bo,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 te(this.device,{label:t,code:e==="u32"?Ao:Mo,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 te(this.device,{label:r,code:Uo,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 te(this.device,{label:r,code:ko,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 te(this.device,{label:e,code:Go,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 te(this.device,{label:e,code:To,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 te(this.device,{label:e,code:Ro,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1}),$({binding:2,readOnly:!1}),Qt({binding:3})]}]}))}getScaleHistogramF32Pipeline(){let e="kernels:scale:histogramF32";return this.getPipeline(e,()=>new te(this.device,{label:e,code:Lo,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1}),Qt({binding:2})]}]}))}getScaleRemapF32Pipeline(){let e="kernels:scale:remapF32";return this.getPipeline(e,()=>new te(this.device,{label:e,code:Fo,entryPoint:"main",bindGroups:[{label:`${e}:bg0`,entries:[$({binding:0,readOnly:!0}),$({binding:1,readOnly:!1}),Qt({binding:2})]}]}))}encodeCopyF32(e,t,r,i,o){if(w(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:be(r,256),label:`${o}:copy`})}encodeCopyU32(e,t,r,i,o){if(w(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:be(r,256),label:`${o}:copy`})}copyU32(e,t={}){let r=t.count;r===void 0&&(e instanceof K?r=this.resolveCount(e,4,void 0):w(!1,"copyU32: opts.count is required when src is not a StorageBuffer")),w(Number.isInteger(r)&&r>=0,`copyU32: count must be an integer >= 0 (got ${r})`);let i=t.out??new K(this.device,this.queue,{label:"copyU32:out",byteLength:r*4,copySrc:!0});w(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 K(this.device,this.queue,{label:`reduceU32:${t}`,byteLength:4,copySrc:!0});if(w(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 K?r=this.resolveCount(e,4,void 0):w(!1,"copyF32: opts.count is required when src is not a StorageBuffer")),w(Number.isInteger(r)&&r>=0,`copyF32: count must be an integer >= 0 (got ${r})`);let i=t.out??new K(this.device,this.queue,{label:"copyF32:out",byteLength:r*4,copySrc:!0});w(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){w(!t.encoder,"extractScaleValuesF32 does not support opts.encoder");let r=t.count;w(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";w(l==="component"||l==="magnitude",`extractScaleValuesF32: invalid valueMode ${String(l)}`);let u=r>0?s+(r-1)*a+i:0,m=e instanceof K?e.byteLength:er(e).size;w(u*4<=m,`extractScaleValuesF32: source range exceeds source buffer capacity (required ${u} f32, capacity ${Math.floor(m/4)} f32)`);let c=t.values??new K(this.device,this.queue,{label:"scale:extract:values",byteLength:r*4,copySrc:!0}),d=t.flags??new K(this.device,this.queue,{label:"scale:extract:flags",byteLength:r*4,copySrc:!0});if(w(c.byteLength>=r*4,"extractScaleValuesF32: values buffer too small for count"),w(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,Ur(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:be(r,256),label:"scale:extract"}),this.execute(p,t),f.destroy(),{values:c,flags:d}}histogramF32(e,t,r){w(!r.encoder,"histogramF32 does not support opts.encoder"),w(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 K(this.device,this.queue,{label:"histogramF32:bins",byteLength:t*4,copySrc:!0});w(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:be(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:be(i,256),label:"histogramF32:accum"})}return this.execute(a,r),s?.destroy(),o}remapScaleF32(e,t){w(!t.encoder,"remapScaleF32 does not support opts.encoder");let r=this.resolveCount(e,4,t.count),i=t.out??new K(this.device,this.queue,{label:"scale:remap:out",byteLength:r*4,copySrc:!0});if(w(i.byteLength>=r*4,"remapScaleF32: out buffer is too small for requested count"),r===0)return i;let o=ce(t.transform),a=new Float32Array(20);He(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]=Ar(o.clampMode),m[8]=a[8],m[9]=a[9],m[10]=a[10],m[11]=a[11],m[12]=Mr(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:be(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 K(this.device,this.queue,{label:`reduceF32:${t}`,byteLength:4,copySrc:!0});if(w(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 K(this.device,this.queue,{label:`argReduceF32:${t}`,byteLength:8,copySrc:!0});if(w(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 K(this.device,this.queue,{label:"scanExclusiveU32",byteLength:r*4,copySrc:!0});if(w(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={}){w(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 K(this.device,this.queue,{label:"histogramU32:bins",byteLength:t*4,copySrc:!0});w(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:be(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:be(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);w(a===o,"compact: input and flags counts must match");let s=i.out??new K(this.device,this.queue,{label:`compact:${r}:out`,byteLength:o*4,copySrc:!0});w(s.byteLength>=o*4,"compact: out buffer is too small for requested count");let l=new K(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:be(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 K(this.device,this.queue,{label:"radixSortKeysU32:out",byteLength:r*4,copySrc:!0});if(i||w(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:be(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:be(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 Do="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 Io=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 K?n.buffer:n,rr=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=se(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(w(Io(i)&&Io(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",P=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:P}]});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");w(!!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:Do}),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 $r=n=>Number.isInteger(n)&&n>=0,tl=n=>n instanceof K?n.buffer:n,rl=n=>n instanceof K?n.byteLength:Number(n.size),nl=n=>{if(n instanceof K)return n.usage;let e=n.usage;return typeof e=="number"?e:null},Tt=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,se(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(){w(!this.destroyed,"ReadbackRing is destroyed")}assertSourceCanReadback(e){if(e instanceof K){w(e.canReadback,"ReadbackRing requires the source StorageBuffer to be created with copySrc: true");return}let t=nl(e);t!==null&&w((t&GPUBufferUsage.COPY_SRC)!==0,"ReadbackRing requires the source GPUBuffer to have GPUBufferUsage.COPY_SRC")}async read(e,t=0,r,i={}){this.ensureNotDestroyed(),w(this.slots.length>0,"ReadbackRing has no slots"),w($r(t),`srcOffsetBytes must be an integer >= 0 (got ${t})`),w((t&3)===0,`srcOffsetBytes must be 4-byte aligned for readback (got ${t})`),this.assertSourceCanReadback(e);let o=rl(e),a=o-t;w(a>=0,`srcOffsetBytes (${t}) exceeds source byteLength (${o})`);let s=r??a;w($r(s),`sizeBytes must be an integer >= 0 (got ${s})`),w(s<=a,`sizeBytes (${s}) exceeds remaining bytes (${a})`);let l=Math.max(4,se(s,4));w(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{}w(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;w(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={}){w($r(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={}){w($r(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"}},ve=n=>{let e=il[n];if(!e)throw new Error(`Unknown dtype: ${String(n)}`);return e},zn=n=>{w(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];w(Number.isInteger(r)&&r>=0,`shape[${t}] must be an integer >= 0 (got ${r})`),e[t]=r}return e},Hr=(n,e)=>{let t=n.length,r=new Array(t),i=e;for(let o=t-1;o>=0;o--)w(Number.isInteger(i)&&i>=0,"Stride overflow while computing row-major strides"),w(i<=2147483647,`row-major stride exceeds i32 range (got ${i})`),r[o]=i,i=i*n[o],w(Number.isFinite(i)&&i>=0,"Stride overflow while computing row-major strides"),w(i<=Number.MAX_SAFE_INTEGER,"Stride overflow while computing row-major strides");return r},Wn=(n,e,t)=>{w(Array.isArray(n),"stridesBytes must be an array"),w(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];w(Number.isInteger(o),`stridesBytes[${i}] must be an integer (got ${o})`),w(o>=-2147483648&&o<=2147483647,`stridesBytes[${i}] must fit in i32 (got ${o})`),w(o%t===0,`stridesBytes[${i}] (${o}) must be a multiple of bytesPerElement (${t})`),r[i]=o}return r},Nn=(n,e)=>{let t=n??0;return w(Number.isInteger(t)&&t>=0,`offsetBytes must be an integer >= 0 (got ${t})`),w(t%e===0,`offsetBytes (${t}) must be a multiple of bytesPerElement (${e})`),t},jn=n=>{let e=1;for(let t=0;t<n.length;t++){if(e*=n[t],n[t]===0)return 0;w(Number.isFinite(e),"numel overflow")}return e},Vn=(n,e,t,r)=>{if(n.length===0){let s=t+r;return w(s<=4294967295,`required backing bytes exceeds wasm32 address space (got ${s})`),s}if(jn(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}w(i>=0n,`layout underflows: minimum byte offset is ${i} (offsetBytes is too small for negative strides)`);let a=o+BigInt(r);return w(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||jn(n)===0)return!0;let i=Hr(n,r);for(let o=0;o<n.length;o++)if(e[o]!==i[o])return!1;return!0},st=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=ve(e).bytesPerElement,this.numel=jn(t),this.byteLength=o}get ndim(){return this.shape.length}get wgslScalarType(){return ve(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,Rt=class n extends st{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){C.memory();let r=ve(e),i=zn(t.shape),o=Nn(t.offsetBytes,r.bytesPerElement),a=t.stridesBytes?Wn(t.stridesBytes,i.length,r.bytesPerElement):Hr(i,r.bytesPerElement),s=Vn(i,a,o,r.bytesPerElement),l=C.allocU32(i.length>>>0),u=C.allocU32(i.length>>>0),m=C.allocU32(i.length>>>0),c=C.u32view(l,i.length>>>0);for(let p=0;p<i.length;p++)c[p]=i[p]>>>0;let d=C.i32view(u,i.length>>>0);for(let p=0;p<a.length;p++)d[p]=a[p]|0;let f=s>0?C.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});w(i.isContiguousC,"CPUndarray.fromArray currently requires a contiguous row-major layout"),w(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=C.memory().buffer;if(this._buf!==e){this._buf=e;let t=ve(this.dtype).ctor;this._all=new t(e)}return this._all}backingBytes(){return this.byteLength===0?new Uint8Array(C.memory().buffer,0,0):C.u8view(this.basePtrBytes,this.byteLength>>>0)}data(){if(w(this.isContiguousC,"CPUndarray.data() requires a contiguous row-major layout (use backingBytes() for raw backing storage)"),this.numel===0){let e=C.memory().buffer,t=ve(this.dtype).ctor;return new t(e,0,0)}return new(ve(this.dtype)).ctor(C.memory().buffer,this.basePtrBytes+this.offsetBytes>>>0,this.numel>>>0)}offsetBytesAt(e){if(w(e.length===this.ndim,`expected ${this.ndim} indices, got ${e.length}`),this.ndim===0)return this.offsetBytes;let t=C.u32view(this.indicesPtr,this.ndim>>>0);for(let i=0;i<this.ndim;i++){let o=e[i];w(Number.isInteger(o)&&o>=0,`index[${i}] must be an integer >= 0 (got ${o})`),t[i]=o>>>0}let r=Mi.offsetBytes(this.shapePtr,this.stridesPtr,this.indicesPtr,this.ndim>>>0,this.offsetBytes>>>0);return w(r!==al,"index out of bounds (or offset overflow)"),w(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;w(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;w(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 K(e.device,e.queue,{label:t.label,byteLength:this.byteLength,data:r,copyDst:t.copyDst,copySrc:t.copySrc,usage:t.usage});return new Lt(this.dtype,this.shape.slice(),this.stridesBytes.slice(),this.offsetBytes,this.byteLength,i,0,!0)}},Lt=class n extends st{buffer;baseOffsetBytes;owned;constructor(e,t,r,i,o,a,s=0,l=!1){super(e,t,r,i,o),w(Number.isInteger(s)&&s>=0,`baseOffsetBytes must be an integer >= 0 (got ${s})`),w((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=ve(t),a=zn(r.shape),s=Nn(r.offsetBytes,o.bytesPerElement),l=r.stridesBytes?Wn(r.stridesBytes,a.length,o.bytesPerElement):Hr(a,o.bytesPerElement),u=Vn(a,l,s,o.bytesPerElement),m=new K(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=ve(t),a=zn(r.shape),s=Nn(r.offsetBytes,o.bytesPerElement),l=r.stridesBytes?Wn(r.stridesBytes,a.length,o.bytesPerElement):Hr(a,o.bytesPerElement),u=Vn(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:se(this.byteLength,4)}}async readbackToCPU(){w(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=Rt.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 qr=class{device;queue;kernels;readback;ndarray=st;CPUndarray=Rt;GPUndarray=Lt;_rgba8Blitter=null;constructor(e,t,r={}){this.device=e,this.queue=t,this.kernels=new tr(e,t),this.readback=new Tt(e,t,r.readback)}createStorageBuffer(e){return new K(this.device,this.queue,e)}createUniformBuffer(e){return new Yt(this.device,this.queue,e)}createPipeline(e){return new te(this.device,e)}createReadbackRing(e={}){return new Tt(this.device,this.queue,e)}encodeDispatch(e,t,r=!1){r&&Gt(this.device,t.workgroups),On(e,t)}encodeDispatchBatch(e,t,r,i=!1){if(i)for(let o of t)Gt(this.device,o.workgroups);Jt(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=be(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=Wr(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=Nr(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 rr(this.device,this.queue)),this._rgba8Blitter.encode(e,t,r,i,o,a)}workgroups1D(e,t){return be(e,t)}workgroups2D(e,t,r,i){return Wr(e,t,r,i)}workgroups3D(e,t,r,i,o,a){return Nr(e,t,r,i,o,a)}destroy(){this._rgba8Blitter?.destroy(),this._rgba8Blitter=null,this.readback.destroy(),this.kernels.destroy()}};var nr=n=>n.startsWith("data:"),ir=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}},Eo=n=>{let e=n.lastIndexOf("/");return e<0?"":n.slice(0,e+1)},or=(n,e)=>e.startsWith("http://")||e.startsWith("https://")||e.startsWith("blob:")||e.startsWith("/")||!n?e:n+e;var ar=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 Ft={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},$n=(n,e)=>{let t=n.bufferViews?.[e];if(!t)throw new Error(`Invalid bufferView index: ${e}`);return t},Hn=(n,e,t)=>{let r=C.allocBytes(t),i=new Uint8Array(n,e,t);return C.u8view(r,t).set(i),r},ul=(n,e)=>{let t=new Uint8Array(e);return t.set(C.u8view(n,e)),t},lt=(n,e)=>{let t=n.json,r=ll(t,e),i=r.componentType,o=Ft[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=$n(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 P=o.bytes*l,S=(a-1)*x+P,B=Hn(f,g,S),v=a*P,A=C.allocBytes(v);try{ft.deinterleave(A,B,a,l,o.bytes,x);let _=ul(A,v),k=new ArrayBuffer(v);new Uint8Array(k).set(_),c=new o.ctor(k,0,a*l)}finally{C.freeBytes(A,v),C.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=$n(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=Ft[m];if(!c)throw new Error(`Unsupported sparse indices componentType: ${m}`);let d=c.bytes,f=$n(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=Ft[r];if(!g)throw new Error(`Unsupported sparse values componentType: ${r}`);let x=t.length,M=g.bytes,h=x*M,P=C.allocBytes(h);C.u8view(P,h).set(new Uint8Array(t.buffer,t.byteOffset,h));let S=a*d,B=Hn(l,u,S),v=a*i*M,A=Hn(p,b,v);try{ft.applySparse(P,x,r,i,B,m,A,a);let _=C.u8view(P,h);new Uint8Array(t.buffer,t.byteOffset,h).set(_)}finally{C.freeBytes(A,v),C.freeBytes(B,S),C.freeBytes(P,h)}},Ge=(n,e)=>{let t=lt(n,e),r=Ft[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=C.allocBytes(i);C.u8view(o,i).set(new Uint8Array(t.array.buffer,t.array.byteOffset,i));let a=C.allocF32(t.array.length);try{ft.convertToF32(a,o,t.array.length,t.componentType,t.normalized);let s=new Float32Array(t.array.length);return s.set(C.f32view(a,t.array.length)),s}finally{C.freeF32(a,t.array.length),C.freeBytes(o,i)}},sr=(n,e)=>{let t=lt(n,e),r=t.componentType,i=Ft[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=C.allocBytes(o);C.u8view(a,o).set(new Uint8Array(t.array.buffer,t.array.byteOffset,o));let s=t.array.length*2,l=C.allocBytes(s);try{ft.convertToU16(l,a,t.array.length,r);let u=new Uint16Array(t.array.length);return new Uint8Array(u.buffer).set(C.u8view(l,s)),u}finally{C.freeBytes(l,s),C.freeBytes(a,o)}},Kr=(n,e)=>{let t=lt(n,e),r=t.componentType,i=Ft[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=C.allocBytes(o);C.u8view(a,o).set(new Uint8Array(t.array.buffer,t.array.byteOffset,o));let s=t.array.length*4,l=C.allocBytes(s);try{ft.convertToU32(l,a,t.array.length,r);let u=new Uint32Array(t.array.length);return new Uint8Array(u.buffer).set(C.u8view(l,s)),u}finally{C.freeBytes(l,s),C.freeBytes(a,o)}};var ml=(n,e)=>n?.onWarning?.(e),Oo=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},qn=async(n,e)=>{let r=await Oo(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 Oo(e)(n);if(!r.ok)throw new Error(`Failed to fetch ${n}: ${r.status} ${r.statusText}`);return await r.json()},Xr=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(nr(s.uri)){o[a]=ir(s.uri).data;continue}let l=or(e,s.uri);o[a]=await qn(l,t)}return o},Yr=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(nr(s.uri))o[a]=ir(s.uri).data;else{let l=or(t,s.uri);o[a]=await qn(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},Kn=async(n,e)=>{if(typeof n=="string"){let m=n,c=e?.baseUrl??Eo(m);if(m.toLowerCase().endsWith(".glb")){let b=await qn(m,e),{json:g,binChunk:x}=ar(b),M=await Xr(g,c,e,x),h={json:g,buffers:M,baseUrl:c};return e?.loadImages&&(h.images=await Yr(g,M,c,e)),h}let d=await dl(m,e),f=await Xr(d,c,e,null),p={json:d,buffers:f,baseUrl:c};return e?.loadImages&&(p.images=await Yr(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}=ar(t),d=await Xr(m,o,e,c),f={json:m,buffers:d,baseUrl:o};return e?.loadImages&&(f.images=await Yr(m,d,o,e)),f}let a=new TextDecoder("utf-8").decode(t),s=JSON.parse(a),l=await Xr(s,o,e,null),u={json:s,buffers:l,baseUrl:o};return e?.loadImages&&(u.images=await Yr(s,l,o,e)),u};var zo="@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},Wo=new WeakMap,gl=n=>{let e=Wo.get(n);if(e)return e;let t=n.createShaderModule({code:zo}),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 Wo.set(n,s),s},Dt=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 It=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=j.global(),r={posPtr:t.posPtr,rotPtr:t.rotPtr,sclPtr:t.sclPtr};ht.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&&C.freeF32(e.ptr,e.len|0);if(this._ownedU32Allocs)for(let e of this._ownedU32Allocs)e.ptr&&C.freeU32(e.ptr,e.len|0);this._ownedF32Allocs=null,this._ownedU32Allocs=null}}},Qr=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)}},Et=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=C.allocU32(this.jointCount);let i=C.u32view(this.jointIndicesPtr,this.jointCount);for(let a=0;a<this.jointCount;a++)i[a]=t[a].index>>>0;this.invBindPtr=C.allocF32(this.jointCount*16);let o=C.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 Xn(this,e)}dispose(){this._disposed||(this._disposed=!0,this.jointIndicesPtr&&C.freeU32(this.jointIndicesPtr,this.jointCount),this.invBindPtr&&C.freeF32(this.invBindPtr,this.jointCount*16))}},Xn=class{skin;meshTransform;bindMatrixPtr=0;boneBuffer=null;bindGroup=null;constructor(e,t){this.skin=e,this.meshTransform=t,this.bindMatrixPtr=C.allocF32(16);let r=C.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&&(C.freeF32(this.bindMatrixPtr,16),this.bindMatrixPtr=0)}};var Zr=class n{transform;type;_projectionMatrix=null;_viewMatrix=null;_viewProjectionMatrix=null;_projectionDirty=!0;constructor(e){this.type=e,this.transform=new he}get viewMatrix(){let e=this.transform.worldMatrix;return this._viewMatrix=Ne.invert(e),this._viewMatrix}get viewProjectionMatrix(){let e=this.getProjectionMatrix(),t=this.viewMatrix;return this._viewProjectionMatrix=Ne.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=Ie.normalize(Ie.sub(e,r)),o=[t[0],t[1],t[2]];Math.abs(Ie.dot(i,o))>.999&&(Math.abs(i[1])<.9?o=[0,1,0]:o=[1,0,0]);let a=Ie.normalize(Ie.cross(i,o)),s=Ie.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}},Ot=class extends Zr{_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=Ne.perspective(e,this._aspect,this._near,this._far),this._projectionDirty=!1}return this._projectionMatrix}},zt=class extends Zr{_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},Vo=9728,jo=9729,vl=9984,xl=9985,Pl=9986,wl=9987,Sl=33071,_l=33648,Cl=10497,No=n=>{switch(n){case Sl:return"clamp-to-edge";case _l:return"mirror-repeat";case Cl:default:return"repeat"}},Bl=n=>{switch(n){case Vo:return"nearest";case jo:default:return"linear"}},Ml=n=>{switch(n){case Vo:return{minFilter:"nearest",mipmapFilter:"nearest",useMipmaps:!1};case jo: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,Jr=0,en=0,Rl=()=>{Jr!==0&&en!==0||(Jr=C.allocF32(16),en=C.allocF32(10))},Ll=(n,e)=>{Rl();let t=C.f32view(Jr,16);for(let i=0;i<16;i++)t[i]=e[i]??(i%5===0?1:0);ne.decomposeTRS(en,Jr);let r=C.f32view(en,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])},ti=0,Yn=0,ri=0,Qn=0,ni=0,Zn=0,Jn=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)=>{Yn<n&&(Yn=Jn(n),ti=C.allocF32(Yn)),Zn<n&&(Zn=Jn(n),ni=C.allocF32(Zn)),e>0&&Qn<e&&(Qn=Jn(e),ri=C.allocU32(Qn))},Dl=(n,e)=>{let t=n.length/3|0,r=e?e.length|0:0;Fl(n.length,r),C.f32view(ti,n.length).set(n);let i=e&&r>0?ri:0;e&&r>0&&C.u32view(ri,r).set(e),Bi.computeVertexNormals(ni,ti,t,i,r);let o=new Float32Array(n.length);return o.set(C.f32view(ni,n.length)),o},ei=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 Pe({});let a=r.get(t);if(a)return a;let s=e.materials?.[t];if(!s){let U=new Pe({});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 V=z.sampler!==void 0?e.samplers?.[z.sampler]:void 0,Z=No(V?.wrapS),ie=No(V?.wrapT),le=Bl(V?.magFilter),{minFilter:Ke,mipmapFilter:oe,useMipmaps:ue}=Ml(V?.minFilter),J=null,Le=n.images?.[O],we=I.mimeType??Al(I.uri);if(Le)J={kind:"bytes",bytes:Le,mimeType:we};else if(I.bufferView!==void 0){let pe=e.bufferViews?.[I.bufferView],De=pe?n.buffers[pe.buffer]:void 0;if(pe&&De){let it=(pe.byteOffset??0)|0;J={kind:"bytes",bytes:De.slice(it,it+pe.byteLength),mimeType:we}}else Y(o,`glTF image bufferView ${I.bufferView} missing (texture=${U}, usage=${L}).`)}else if(I.uri)if(nr(I.uri)){let pe=ir(I.uri);J={kind:"bytes",bytes:pe.data,mimeType:we??pe.mimeType??void 0}}else J={kind:"url",url:or(n.baseUrl,I.uri),mimeType:we};if(!J)return Y(o,`Could not resolve image source for texture=${U} (usage=${L}).`),null;let Fe=Dt.createFrom({source:J,mipmaps:ue,sampler:{addressModeU:Z,addressModeV:ie,magFilter:le,minFilter:Ke,mipmapFilter:oe}});return i.set(U,Fe),Fe},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 P=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,_=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 Be({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 Pe({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:P,normalTexture:S,occlusionTexture:B,emissiveTexture:v,normalScale:A,occlusionStrength:_,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=Ge(n,a),l=null,u=o.NORMAL;u!==void 0&&(l=Ge(n,u));let m=null,c=o.TEXCOORD_0;c!==void 0&&(m=Ge(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=sr(n,g),v=Ge(n,x);if(M!==void 0&&h!==void 0){let A=sr(n,M),_=Ge(n,h);if(A.length===B.length&&_.length===v.length){let k=Il(v,_);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=ei(v)}else M!==void 0||h!==void 0?(Y(i,"Primitive has JOINTS_1/WEIGHTS_1 mismatch; ignoring additional influences"),d=B,f=ei(v)):(d=B,f=ei(v))}else(g!==void 0||x!==void 0)&&Y(i,"Primitive has JOINTS_0/WEIGHTS_0 mismatch; ignoring skinning attributes for this primitive");let P=t.mode??4,S=null;if(t.indices!==void 0)S=Kr(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=P===4?null:v}if(P===5){let B=S??new Uint32Array(0);S=El(B)}else if(P===6){let B=S??new Uint32Array(0);S=Ol(B)}else if(P!==4)return Y(i,`Unsupported primitive mode=${P} (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 Ot({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 zt({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 Je({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 qe({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=Ge(n,s.inverseBindMatrices));let m=s.skeleton!==void 0?t[s.skeleton]:void 0,c=new Et(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?C.allocU32(d*5):0,p=d>0?C.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=Ge(n,v.input),_=lt(n,v.output),k=Ge(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=C.allocF32(A.length);C.f32view(G,A.length).set(A),b.push({ptr:G,len:A.length});let R=C.allocF32(k.length);C.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]=(_.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,_=A!==void 0?t[A]??null:null,k={sampler:v.sampler|0,targetNode:_,path:v.target.path};c.push(k);let G=s(k.path);_&&G>=0&&h.push({sampler:k.sampler|0,targetIndex:_.index>>>0,pathCode:G})}let P=null,S=h.length|0;if(d>0&&S>0){let B=C.allocU32(S*3),v=C.u32view(B,S*3);g.push({ptr:B,len:S*3});for(let A=0;A<S;A++){let _=h[A],k=A*3;v[k+0]=_.sampler>>>0,v[k+1]=_.targetIndex>>>0,v[k+2]=_.pathCode>>>0}Number.isFinite(x)||(x=0),Number.isFinite(M)||(M=0),P=new It({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)C.freeF32(B.ptr,B.len);for(let B of g)C.freeU32(B.ptr,B.len)}o.push({name:u.name,samplers:m,channels:c,clip:P})}return o},ii=(n,e={})=>{let t=n.json,r=e.targetScene??new Ze,i=e.addToScene!==!1,o=t.nodes??[],a=new Array(o.length);for(let v=0;v<o.length;v++){let A=o[v],_=new he;if(A.matrix&&A.matrix.length>=16)Ll(_,A.matrix);else{let k=A.translation??[0,0,0],G=A.rotation??[0,0,0,1],R=A.scale??[1,1,1];_.setPosition(k[0],k[1],k[2]),_.setRotation(G[0],G[1],G[2],G[3]),_.setScale(R[0],R[1],R[2])}a[v]=_}for(let v=0;v<o.length;v++){let A=o[v],_=a[v];for(let k of A.children??[]){let G=a[k];G?G.setParent(_):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 _=o[v];if(!_)return;let k=a[v];if(!k)return;let G=Nl(n,t,_,k,l,u,m,e),R=_.skin!==void 0?_.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,_,k,e);T&&d.push(T)}if(e.importLights&&p){let T=Gl(_);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 '${_.name??`index ${v}`}' has unsupported type '${F.type}' and was skipped.`)}}}for(let T of _.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),P=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:P,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 Te=(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,P=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:P,insideClip:S,visible:P&&S}},$o=(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},Ho=(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},Wt=(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)}},lr=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();$o(t,this.cameraSigB),(!this.hasCameraSig||!Ho(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]},ur=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=Te(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=Te(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]=Wt(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 We=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 tn=(n,e,t)=>Math.max(e,Math.min(t,n)),Ko=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}`},Xo=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]},rn=(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],Yo=(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,nn=(n,e,t)=>Math.abs(n-e)<=t,sn=(n,e)=>Math.max(1e-9,Math.abs(n)*1e-9,Math.abs(e)*1e-6),on=(n,e,t)=>{if(!Number.isFinite(e)||e<=t)return!1;let r=n/e;return Math.abs(r-Math.round(r))<=1e-4},an=(n,e,t)=>{let r=Math.max(0,e-n),i=sn(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},Qo=(n,e,t)=>{let r=Math.max(0,e-n),i=sn(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},cr=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 We(t,()=>{let r=document.createElement("div");return r.style.position="absolute",r.style.transformOrigin="0 50%",r},this.maxLines),this.labelPool=new We(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=Xo(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=an(t,r,m),p=an(i,o,m);for(let U=0;U<32&&f+p>d;U++)m=Xo(m*1.5),f=an(t,r,m),p=an(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))),P=Qo(t,r,m),S=Qo(i,o,m),B=sn(a,m),v=sn(s,m),A=Math.max(B,Math.abs(b)*1e-6),_=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=P.reduce((U,L)=>U+(on(L,b,A)?1:0),0),T=S.reduce((U,L)=>U+(on(L,b,_)?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<P.length;U++){let L=P[U],E=this.projectFrontClippedSegment(e,rn(this.plane,this.origin,L,i),rn(this.plane,this.origin,L,o));if(!E)continue;let z=E.p0,O=E.p1,I=on(L,b,A),V=Math.abs(L)<=k,Z=nn(L,t,B)||nn(L,r,B),ie=this.linePool.acquire();if(Yo(ie,z.x,z.y,O.x,O.y,V?this.axisColor:I||Z?this.majorColor:this.minorColor,I||V||Z?this.lineWidthMajorPx:this.lineWidthMinorPx),I&&F%M===0){let le=this.labelPool.acquire();le.textContent=Ko(L),le.style.left=`${z.x+4}px`,le.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,rn(this.plane,this.origin,t,L),rn(this.plane,this.origin,r,L));if(!E)continue;let z=E.p0,O=E.p1,I=on(L,b,_),V=Math.abs(L)<=G,Z=nn(L,i,v)||nn(L,o,v),ie=this.linePool.acquire();if(Yo(ie,z.x,z.y,O.x,O.y,V?this.axisColor:I||Z?this.majorColor:this.minorColor,I||V||Z?this.lineWidthMajorPx:this.lineWidthMinorPx),I&&D%h===0){let le=this.labelPool.acquire();le.textContent=Ko(L),le.style.left=`${z.x+4}px`,le.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=tn((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=tn((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=Te(e.camera,e.width,e.height,s),d=Te(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=Te(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=Te(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=Te(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:tn(a,1e-6,1e9),v:tn(s,1e-6,1e9)}}};var Zo=n=>n<0?0:n>1?1:n,ln=(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}`},oi=(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=Zo(n)*(t-1),o=Math.floor(i),a=Math.min(t-1,o+1),s=i-o;return o>=t-1?r[t-1]:[ln(r[o][0],r[a][0],s),ln(r[o][1],r[a][1],s),ln(r[o][2],r[a][2],s),ln(r[o][3],r[a][3],s)]},ut=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=ce(n.scaleTransform);if(n.colormap==="custom"){let s=n.colormapStops.slice();return{transform:o,signature:`pointcloud|custom|${ut(o)}|${JSON.stringify(s)}`,sample:l=>oi(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}|${ut(o)}`,sample:s=>a.sampleCPU(s)}}if(n instanceof Oe){let o=ce(n.scaleTransform);if(n.colorMode==="scalar"&&n.colormap==="custom"){let s=n.colormapStops.slice();return{transform:o,signature:`glyphfield|custom|${ut(o)}|${JSON.stringify(s)}`,sample:l=>oi(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}|${ut(o)}`,sample:s=>a.sampleCPU(s)}}if(n instanceof Ae){let o=ce(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}|${ut(o)}`,sample:s=>a.sampleCPU(s)}}let t=n,r=ce(t.scaleTransform);if(t.colormapStops&&t.colormapStops.length>=2){let o=t.colormapStops.slice();return{transform:r,signature:`explicit|stops|${ut(r)}|${JSON.stringify(o)}`,sample:a=>oi(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}|${ut(r)}`,sample:o=>i.sampleCPU(o)}},mr=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 We(i,()=>{let s=document.createElement("div");return s.style.position="absolute",s},this.tickCount),this.tickLabelPool=new We(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]=Wt(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=Rn(Zo(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 et={Idle:"idle",Marker:"marker",Distance:"distance",Angle:"angle"};var un={Degrees:"deg",Radians:"rad"},tt=n=>[n[0],n[1],n[2],n[3]],cn=n=>[n[0]??0,n[1]??0,n[2]??0],ai=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,Jo=n=>n?{kind:n.kind,objectId:n.objectId,elementIndex:n.elementIndex,ndIndex:n.ndIndex?n.ndIndex.slice():null,attributes:ai(n.attributes)}:null,re=n=>({position:cn(n.position),pick:Jo(n.pick)}),dr=n=>({position:cn(n.worldPosition),pick:{kind:n.kind,objectId:n.objectId,elementIndex:n.elementIndex,ndIndex:n.ndIndex?n.ndIndex.slice():null,attributes:ai(n.attributes)}}),pr=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 rt=[{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}],mn=(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,de=(n,e)=>{if(!Number.isFinite(n))return"nan";let t=Math.abs(n),r=mn(e,0,12);return t>=1e7||t>0&&t<1e-5?n.toExponential(Math.max(1,Math.min(6,r))):ru(n.toFixed(r))},fr=(n={})=>{let e=Number.isFinite(n.worldUnitsPerUnit)&&n.worldUnitsPerUnit>0?n.worldUnitsPerUnit:1,t=typeof n.symbol=="string"?n.symbol:"wu",r=mn(n.decimals??3,0,12),i=!!n.autoMetric,o=n.angleUnit??un.Degrees,a=mn(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 rt[4];let t=mn(Math.floor(Math.log10(e)/3)*3,rt[0].exponent,rt[rt.length-1].exponent);for(let r=0;r<rt.length;r++)if(rt[r].exponent===t)return rt[r];return rt[4]},si=(n,e={})=>{let t=fr(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=`${de(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=`${de(o,t.decimals)} ${a}`.trim();return{worldDistance:n,value:o,unitSymbol:a,text:s}},li=(n,e={})=>{let t=fr(e);if(!Number.isFinite(n))return{radians:n,value:Number.NaN,unitSymbol:t.angleUnit,text:`nan ${t.angleUnit}`};if(t.angleUnit===un.Radians){let o=`${de(n,t.angleDecimals)} rad`;return{radians:n,value:n,unitSymbol:"rad",text:o}}let r=n*(180/Math.PI),i=`${de(r,t.angleDecimals)} deg`;return{radians:n,value:r,unitSymbol:"deg",text:i}},ui=(n,e=5)=>n?`[${de(n[0]??Number.NaN,e)}, ${de(n[1]??Number.NaN,e)}, ${de(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: ${de(n.scalar,6)}`),n.vector&&e.push(`vector: [${de(n.vector[0],4)}, ${de(n.vector[1],4)}, ${de(n.vector[2],4)}, ${de(n.vector[3],4)}]`),n.packedPoint&&e.push(`packedPoint: [${de(n.packedPoint[0],4)}, ${de(n.packedPoint[1],4)}, ${de(n.packedPoint[2],4)}, ${de(n.packedPoint[3],4)}]`),e.length===0&&e.push("attributes: {}"),e},ea=(n,e)=>!e||!e.hit?`${n}: miss`:[`${n}: hit`,`kind: ${e.kind}`,`objectId: ${e.objectId}`,`elementIndex: ${e.elementIndex}`,`world: ${ui(e.worldPosition,5)}`,`ndIndex: ${iu(e.ndIndex)}`,...ou(e.attributes)].join(`
|
|
13
|
-
`),
|
|
21
|
+
`+t+this._fragmentShader}};var ka=4+bt+4+32,Mu=ka*4,co=n=>be({componentCount:4,componentIndex:3,stride:4,...n}),Ba=n=>n==="rgba"?0:1,Ma=new ArrayBuffer(4),Lu=new Float32Array(Ma),Ru=new Uint32Array(Ma),at=(n,e)=>Math.imul((n^e>>>0)>>>0,16777619)>>>0,Un=(n,e)=>(Lu[0]=Number.isFinite(e)?e:0,at(n,Ru[0]>>>0)),st=class{transform=new Be;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=co(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=qe(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=it(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)}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=at(e,this._pointCount>>>0),e=at(e,this._scaleRevision>>>0),e=at(e,this.blendMode==="opaque"?1:this.blendMode==="transparent"?2:3),e=at(e,this.depthWrite?1:0),e=at(e,this.depthTest?1:0),e=at(e,this._pointsDirty?1:0),e=at(e,this._colorsDirty?1:0),e=at(e,this.pointsBuffer?1:0),e=at(e,this.colorsBuffer?1:0),e=at(e,Ba(this._colorMode)>>>0),e=Un(e,this._basePointSize),e=Un(e,this._minPointSize),e=Un(e,this._maxPointSize),e=Un(e,this._sizeAttenuation),e>>>0}get ndShape(){return this._ndShape?this._ndShape.slice():null}set ndShape(e){this._ndShape=nr(e,"PointCloud: ndShape")}get scaleTransform(){return De(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=co(e),this._uniformDirty=!0,this.emitVisualChange("scale")}applyScaleStats(e){let t=De(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=co(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=qe(e),this._uniformDirty=!0,this.emitVisualChange("colormap")}getColormapKey(){let e=this._colormap;return e instanceof q?`cm:${e.id}`:`cm:${e}`}getColormapForBinding(){let e=this._colormap;return e instanceof q?e:e==="custom"?q.builtin("grayscale"):q.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 ir(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),Vt.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(cr([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"?Rt(this._pointCount>0):cr(this.boundsMin,this.boundsMax,this.boundsCenter,this.boundsRadius)}getWorldBounds(){return Gt(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(ka),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,Ye(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]=Ba(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 Ua=60,Gu=Ua*4,Fn=n=>be({componentCount:4,componentIndex:0,stride:4,...n}),La=n=>{switch(n){case"rgba":return 0;case"scalar":return 1;case"solid":return 2}},Aa=new ArrayBuffer(4),Uu=new Float32Array(Aa),Au=new Uint32Array(Aa),Qe=(n,e)=>Math.imul((n^e>>>0)>>>0,16777619)>>>0,Fu=(n,e)=>(Uu[0]=Number.isFinite(e)?e:0,Qe(n,Au[0]>>>0)),Ra=(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,U,L,G,F,D,k)=>{let A=t.length/3|0;return t.push(S,R,U),r.push(L,G,F),i.push(D,k),A},f=(S,R,U,L)=>{let G=[];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=U;L&&(z=0,E=0,H=U),G.push(d(O,N,S,z,E,H,D,S-a))}return G},p=f(a,c,0,!1),h=f(s,c,0,!1);for(let S=0;S<e;S++){let R=p[S],U=p[S+1],L=h[S],G=h[S+1];o.push(R,U,L),o.push(U,G,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 U=S/e*Math.PI*2,L=Math.cos(U),G=Math.sin(U),F=L,D=G,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],U=g[S+1],L=b[S],G=b[S+1];o.push(R,U,L),o.push(U,G,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,U=R*Math.PI*2,L=Math.cos(U),G=Math.sin(U),F=L,D=G,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 U=S/e*Math.PI*2,L=Math.cos(U),G=Math.sin(U),F=L,D=G,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],U=v[S+1],L=x[S];o.push(R,U,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],U=B[S+1];o.push(M,U,R)}return new ae({positions:new Float32Array(t),normals:new Float32Array(r),uvs:new Float32Array(i),indices:new Uint32Array(o)})},In=null,Ga=null,Du=n=>{switch(n){case"ellipsoid":return In??=Ra(),In;case"arrow":return Ga??=Iu(),Ga;default:return In??=Ra(),In}},Ve=class{transform=new Be;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=Fn({});_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=Fn(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=qe(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=it(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 occluderRevision(){let e=2166136261;return e=Qe(e,this._instanceCount>>>0),e=Qe(e,this._scaleRevision>>>0),e=Qe(e,this.blendMode==="opaque"?1:this.blendMode==="transparent"?2:3),e=Qe(e,this.cullMode==="back"?1:this.cullMode==="front"?2:3),e=Qe(e,this.depthWrite?1:0),e=Qe(e,this.depthTest?1:0),e=Qe(e,La(this._colorMode)>>>0),e=Qe(e,this._dataDirty?1:0),e=Qe(e,this.geometry.vertexCount>>>0),e=Qe(e,this.geometry.indexCount>>>0),e=Qe(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=nr(e,"GlyphField: ndShape")}get scaleTransform(){return De(this._scaleTransform)}setScaleTransform(e){this._scaleTransform=Fn(e),this._uniformDirty=!0,this.emitVisualChange("scale")}applyScaleStats(e){let t=De(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=Fn(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=qe(e),this._uniformDirty=!0,this.emitVisualChange("colormap")}getColormapKey(){let e=this._colormap;return e instanceof q?`cm:${e.id}`:`cm:${e}`}getColormapForBinding(){let e=this._colormap;return e instanceof q?e:e==="custom"?q.builtin("grayscale"):q.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 ir(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),Vt.glyphInstances(u,c,m,d,o,a,s,r,l,this.geometry.boundsRadius);let f=_.f32view(u,3),p=_.f32view(c,3);this.setBounds(it([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"?Rt(this._instanceCount>0):it(this.boundsMin,this.boundsMax)}getWorldBounds(){return Gt(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=fe.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 Gu}getUniformData(){let e=new Float32Array(Ua);e.fill(0),Ye(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]=La(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 Je=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 ot){if(e.destroyed)throw new Error("Scene: cannot add a destroyed mesh.");this._meshes.includes(e)||(this._meshes.push(e),aa(e,this))}else e instanceof st?this._pointClouds.includes(e)||this._pointClouds.push(e):e instanceof Ve?this._glyphFields.includes(e)||this._glyphFields.push(e):this._nodeLinks.includes(e)||this._nodeLinks.push(e);return this}remove(e){if(e instanceof ot){let t=this._meshes.indexOf(e);t!==-1&&this._meshes.splice(t,1),oo(e,this)}else if(e instanceof st){let t=this._pointClouds.indexOf(e);t!==-1&&this._pointClouds.splice(t,1)}else if(e instanceof Ve){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)oo(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=Rt(!1),i=u=>{if(u.empty){u.partial&&(r.partial=!0);return}r=Qo(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 Dn=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]},hr=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}},fo=new WeakMap,Fa=(n,e)=>{fo.set(n,e)},Ia=n=>{fo.delete(n)},Da=n=>{let e=fo.get(n);return!e||e.disposed?null:e},Na=(n,e)=>{let t=Da(n);if(!t)return e;let r=t.worldPosition;return[r[0]??0,r[1]??0,r[2]??0]},za=(n,e)=>{let t=Da(n);if(!t)return e;let r=t.worldMatrix;return Dn([-(r[8]??0),-(r[9]??0),-(r[10]??-1)])},po=n=>n.position,zn=n=>n.direction,Nn=class extends hr{constructor(e={}){super("ambient"),this._color=e.color??[1,1,1],this._intensity=e.intensity??.1}},wt=class extends hr{_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 za(this,this._direction)}set direction(e){this._direction=Dn(e)}},_t=class extends hr{_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 Na(this,this._position)}set position(e){this._position=e}get range(){return this._range}set range(e){this._range=e}},vt=class extends hr{_position;_direction;_range;_innerCone;_outerCone;constructor(e={}){super("spot"),this._position=e.position??[0,0,0],this._direction=Dn(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 Na(this,this._position)}set position(e){this._position=e}get direction(){return za(this,this._direction)}set direction(e){this._direction=Dn(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 ja=128,Nu=ja*4,On=n=>be({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??{}}),Vn=n=>be({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??{}}),En=n=>n==="rgba"?0:n==="scalar"?1:2,Oa=n=>n==="points"?0:n==="spheres"?1:n==="ellipsoids"?2:3,Va=n=>n==="lines"?0:1,Ea=n=>n==="points"||n==="spheres"||n==="ellipsoids"||n==="cubes",Wa=n=>n==="lines"||n==="cylinders",Wn=n=>n==="rgba"||n==="scalar"||n==="solid",zu=n=>new Uint8Array(new Uint8Array(n.buffer,n.byteOffset,n.byteLength)),Ha=new ArrayBuffer(4),Ou=new Float32Array(Ha),Vu=new Uint32Array(Ha),Ge=(n,e)=>Math.imul((n^e>>>0)>>>0,16777619)>>>0,Nr=(n,e)=>(Ou[0]=Number.isFinite(e)?e:0,Ge(n,Vu[0]>>>0)),Ee=class{transform=new Be;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=On(void 0);_edgeScaleTransform=Vn(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=On(e.nodeScaleTransform),this._edgeScaleTransform=Vn(e.edgeScaleTransform),e.nodeGeometryMode!==void 0&&y(Ea(e.nodeGeometryMode),`NodeLink: invalid nodeGeometryMode '${String(e.nodeGeometryMode)}'.`),e.edgeGeometryMode!==void 0&&y(Wa(e.edgeGeometryMode),`NodeLink: invalid edgeGeometryMode '${String(e.edgeGeometryMode)}'.`),e.nodeColorMode!==void 0&&y(Wn(e.nodeColorMode),`NodeLink: invalid nodeColorMode '${String(e.nodeColorMode)}'.`),e.edgeColorMode!==void 0&&y(Wn(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=qe(e.nodeColormapStops)),e.edgeColormapStops!==void 0&&(this._edgeColormapStops=qe(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(it(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(Ct(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,Oa(this._nodeGeometryMode)>>>0),e=Ge(e,Va(this._edgeGeometryMode)>>>0),e=Ge(e,En(this._nodeColorMode)>>>0),e=Ge(e,En(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=Nr(e,this._nodeSize),e=Nr(e,this._edgeSize),e=Nr(e,this._minPointSize),e=Nr(e,this._maxPointSize),e=Nr(e,this._pointSizeAttenuation),e>>>0}get ndShape(){return this._ndShape?this._ndShape.slice():null}set ndShape(e){this._ndShape=nr(e,"NodeLink: ndShape")}get nodeGeometryMode(){return this._nodeGeometryMode}set nodeGeometryMode(e){y(Ea(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(Wa(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(Wn(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(Wn(e),`NodeLink: invalid edgeColorMode '${String(e)}'.`),e!==this._edgeColorMode&&(this._edgeColorMode=e,this._uniformDirty=!0,this.emitVisualChange("visual"))}get nodeScaleTransform(){return De(this._nodeScaleTransform)}setNodeScaleTransform(e){this._nodeScaleTransform=On(e),this._uniformDirty=!0,this._nodeScaleRevision++,this.emitVisualChange("scale")}get edgeScaleTransform(){return De(this._edgeScaleTransform)}setEdgeScaleTransform(e){this._edgeScaleTransform=Vn(e),this._uniformDirty=!0,this._edgeScaleRevision++,this.emitVisualChange("scale")}applyNodeScaleStats(e){let t=De(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=On(t),this._uniformDirty=!0,this._nodeScaleRevision++,this.emitVisualChange("scale")}applyEdgeScaleStats(e){let t=De(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=Vn(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=qe(e),this._uniformDirty=!0,this.emitVisualChange("colormap")}get edgeColormapStops(){return this._edgeColormapStops}set edgeColormapStops(e){this._edgeColormapStops=qe(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 ir(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(it([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"?Rt(this._nodeCount>0):Ct(this.boundsCenter,this.boundsRadius)}getWorldBounds(){return Gt(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(ja);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,Ye(this._nodeScaleTransform,e,4),e[24]=En(this._nodeColorMode),e[25]=typeof this._nodeColormap=="string"&&this._nodeColormap==="custom"?Math.min(8,Math.max(2,this._nodeColormapStops.length)):0,e[26]=Oa(this._nodeGeometryMode),e[27]=this.nodeRadiiBuffer?1:0,Ye(this._edgeScaleTransform,e,28),e[48]=En(this._edgeColorMode),e[49]=typeof this._edgeColormap=="string"&&this._edgeColormap==="custom"?Math.min(8,Math.max(2,this._edgeColormapStops.length)):0,e[50]=Va(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 q?`cm:${e.id}`:`cm:${e}`}getEdgeColormapKey(){let e=this._edgeColormap;return e instanceof q?`cm:${e.id}`:`cm:${e}`}getNodeColormapForBinding(){let e=this._nodeColormap;return e instanceof q?e:e==="custom"?q.builtin("grayscale"):q.builtin(e)}getEdgeColormapForBinding(){let e=this._edgeColormap;return e instanceof q?e:e==="custom"?q.builtin("grayscale"):q.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 $a="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 jn="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 qa="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 Hn="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 Ka="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 Xa="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 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 }; 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 $n="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 qn="@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 Kn="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 Xn="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 Yn="@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 Zn="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 Qn="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 Jn="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 Za=new ArrayBuffer(4),nc=new Float32Array(Za),ic=new Uint32Array(Za),ei=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=mn(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+Je.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+Je.MAX_LIGHTS*16),this.modelUniformStagingPtr=W.allocF32(32),"aspect"in t&&(t.aspect=this.aspectRatio),Be.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 ot?{kind:"mesh",object:r,objectId:t.objectId,elementIndex:t.elementIndex,worldPosition:i}:r instanceof st?{kind:"pointcloud",object:r,objectId:t.objectId,elementIndex:t.elementIndex,worldPosition:i}:r instanceof Ve?{kind:"glyphfield",object:r,objectId:t.objectId,elementIndex:t.elementIndex,worldPosition:i}:r instanceof Ee?{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+Je.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+Je.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=$a;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=mn(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=fe.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=ft.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<Je.MAX_LIGHTS;a++){let s=r[a];if(s instanceof wt){let l=zn(s);i[o+0]=l[0],i[o+1]=l[1],i[o+2]=l[2],i[o+3]=0}else if(s instanceof _t){let l=po(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 vt){let l=po(s),u=zn(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 wt){let l=zn(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]=pe(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=mn(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,pe(t,256)),usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),e.capacityBytes=Math.max(256,pe(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=kn(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}Xe.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=Xe.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 pr||e instanceof Ze?!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(io(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,Bn(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=kn(B),R=S.boundsCenter,U=M*3;P[M]=B.transform.worldMatrixPtr>>>0,v[U+0]=R[0],v[U+1]=R[1],v[U+2]=R[2],x[M]=S.boundsRadius}Xe.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,h,g,b,i);let T=W.allocF32(24);ar.writePlanesFromViewProjection(T,this.cameraUniformStagingPtr);let w=W.alloc(i*4,4);a=Xe.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(io(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,U=l[x+13]-d,L=l[x+14]-f;S.sortKey=R*R+U*U+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],U=S.boundsCenter[1],L=S.boundsCenter[2],G=B*3;b[B]=S.transform.worldMatrixPtr>>>0,P[G+0]=R,P[G+1]=U,P[G+2]=L,v[B]=S.boundsRadius}Xe.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,p,h,g,f);let x=W.allocF32(24);ar.writePlanesFromViewProjection(x,this.cameraUniformStagingPtr);let T=W.alloc(m.length*4,4),w=Xe.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],U=B.boundsCenter[2],L=M*3;h[M]=B.transform.worldMatrixPtr>>>0,g[L+0]=S,g[L+1]=R,g[L+2]=U,b[M]=B.boundsRadius}Xe.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,d,f,p,m);let P=W.allocF32(24);ar.writePlanesFromViewProjection(P,this.cameraUniformStagingPtr);let v=W.alloc(u.length*4,4),x=Xe.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}Xe.prepareWorldSpheresFromPtrs(this.cullCentersPtr,this.cullRadiiPtr,f,p,h,d);let v=W.allocF32(24);ar.writePlanesFromViewProjection(v,this.cameraUniformStagingPtr);let x=W.alloc(c.length*4,4),T=Xe.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),jt(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=jt(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),jt(a.mesh,this.device,this.queue),r=l,i=u),s!==t&&(this.ensureMaterialBindGroup(s),t=s),m>1&&!a.skinned&&!Bn(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);Mt.computeJointMatricesTo(r,e.skin.jointIndicesPtr,t,e.skin.invBindPtr,K.global().worldPtr,e.bindMatrixPtr);let i=fe.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);Lt.packModelNormalMat4FromPtrs(s,i,r);let l=r*this.INSTANCE_STRIDE_BYTES,u=this.instanceBufferOffset,c=u+l;this.ensureInstanceBuffer(c);let m=fe.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=jt(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&&!Bn(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=fe.bytes(),T=t[g].mesh,w=l.skinned?T.skin:null;if(w){w.ensureGpuResources(this.device,this.skinBindGroupLayout);let R=w.jointCount|0,U=W.allocF32(R*16);Mt.computeJointMatricesTo(U,w.skin.jointIndicesPtr,R,w.skin.invBindPtr,K.global().worldPtr,w.bindMatrixPtr),this.queue.writeBuffer(w.boneBuffer,0,x,U,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=fe.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=fe.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=fe.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=fe.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=jt(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,U=W.allocF32(R*16);Mt.computeJointMatricesTo(U,S.skin.jointIndicesPtr,R,S.skin.invBindPtr,K.global().worldPtr,S.bindMatrixPtr),this.queue.writeBuffer(S.boneBuffer,0,r,U,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=fe.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=jt(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);Mt.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=fe.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=fe.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=fe.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);Lt.packModelNormalMat4FromPtrs(c,s,a);let m=a*this.INSTANCE_STRIDE_BYTES,d=this.instanceBufferOffset,f=d+m;this.ensureInstanceBuffer(f);let p=fe.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(Yn);return e||(e=this.device.createShaderModule({code:Yn}),this.shaderCache.set(Yn,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(Xn);o||(o=this.device.createShaderModule({code:Xn}),this.shaderCache.set(Xn,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(Zn);r||(r=this.device.createShaderModule({code:Zn}),this.shaderCache.set(Zn,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(Qn);o||(o=this.device.createShaderModule({code:Qn}),this.shaderCache.set(Qn,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(Jn);o||(o=this.device.createShaderModule({code:Jn}),this.shaderCache.set(Jn,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?Ya:t?Xa:Ka,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($n);r||(r=this.device.createShaderModule({code:$n}),this.shaderCache.set($n,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(qn);o||(o=this.device.createShaderModule({code:qn}),this.shaderCache.set(qn,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(Kn);a||(a=this.device.createShaderModule({code:Kn}),this.shaderCache.set(Kn,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===Ze?`${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,U=p?.thicknessTexture??null,L=h?.texture??null,G=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}:${U?.id??0}:${U?.revision??0}:${L?.id??0}:${L?.revision??0}:${G?.id??0}:${G?.revision??0}:${this.transmissionSourceRevision}`}return e instanceof Ze?`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 Ze&&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,U=p?.texture??null,L=h?.texture??null,G=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:G?G.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:24,resource:G?G.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:U?U.getSampler(this.device,this.fallbackSampler):this.fallbackSampler},{binding:30,resource:U?U.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 Ze){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(jn);i||(i=this.device.createShaderModule({code:jn}),this.shaderCache.set(jn,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=qa,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(Hn);o||(o=this.device.createShaderModule({code:Hn}),this.shaderCache.set(Hn,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 br=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}},yt=(n,e)=>{if(!Number.isFinite(n))return"n/a";let t=Math.max(0,e|0);return n.toFixed(t)},gr=(n,e)=>{if(!Number.isFinite(n))return"n/a";let t=Math.abs(n);return t<1024?`${yt(n,0)} B`:t<1024*1024?`${yt(n/1024,e)} KiB`:`${yt(n/(1024*1024),e)} MiB`},ti=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 br(i),this.frameMsAvg=new br(i),this.cpuMsAvg=new br(i),this.gpuMsAvg=new br(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=tr();(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: ${yt(r,1)}`),this.show.showFrameTime&&t.push(`Frame: ${yt(i,e)} ms (\u2248${yt(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: ${yt(a,e)} ms (${yt(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: ${yt(l,e)} ms (${yt(c,0)}%)`)}}if(this.show.showMemory){try{let l=W.usedBytes(),u=W.capBytes();t.push(`Frame arena: ${gr(l,e)} / ${gr(u,e)}`)}catch{}try{let l=_.memory().buffer.byteLength;t.push(`WASM memory: ${gr(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: ${gr(l,e)} / ${gr(u,e)}`):t.push(`JS heap: ${gr(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}}),Qa=n=>{if(rr(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:Qa(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:Qa(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 zr=(n,e=1,t=1)=>(y(Te(n),`workgroups.x must be an integer >= 0 (got ${n})`),y(Te(e),`workgroups.y must be an integer >= 0 (got ${e})`),y(Te(t),`workgroups.z must be an integer >= 0 (got ${t})`),[n,e,t]),Se=(n,e)=>(y(Number.isFinite(n),`invocations must be finite (got ${n})`),y(n>=0,`invocations must be >= 0 (got ${n})`),y(zt(e),`workgroupSizeX must be a positive integer (got ${e})`),n===0?[0,1,1]:[Oe(n,e),1,1]),ri=(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(zt(t),`workgroupSizeX must be a positive integer (got ${t})`),y(zt(r),`workgroupSizeY must be a positive integer (got ${r})`),n===0||e===0)return[0,1,1];let i=Oe(n,t),o=Oe(e,r);return[i,o,1]},ni=(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(zt(r),`workgroupSizeX must be a positive integer (got ${r})`),y(zt(i),`workgroupSizeY must be a positive integer (got ${i})`),y(zt(o),`workgroupSizeZ must be a positive integer (got ${o})`),n===0||e===0||t===0)return[0,1,1];let a=Oe(n,r),s=Oe(e,i),l=Oe(t,o);return[a,s,l]};var ii=n=>{if(Array.isArray(n)){let i=n[0]??0,o=n[1]??1,a=n[2]??1;return y(Te(i),`workgroups.x must be an integer >= 0 (got ${i})`),y(Te(o),`workgroups.y must be an integer >= 0 (got ${o})`),y(Te(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(Te(e),`workgroups.x must be an integer >= 0 (got ${e})`),y(Te(t),`workgroups.y must be an integer >= 0 (got ${t})`),y(Te(r),`workgroups.z must be an integer >= 0 (got ${r})`),{x:e,y:t,z:r}},vr=(n,e)=>{let{x:t,y:r,z:i}=ii(e),o=n.limits.maxComputeWorkgroupsPerDimension;y(t<=o&&r<=o&&i<=o,`dispatchWorkgroups exceeds device.limits.maxComputeWorkgroupsPerDimension (${o})`)},Ja=n=>n instanceof Q?n.pipeline:n,ho=(n,e)=>{let t=n.beginComputePass({label:e.label}),r=Ja(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}=ii(e.workgroups);i>0&&o>0&&a>0&&t.dispatchWorkgroups(i,o,a),t.end()},Or=(n,e,t)=>{let r=n.beginComputePass({label:t}),i=null;for(let o of e){let a=Ja(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}=ii(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 oi=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,pe(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 es="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 ts="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 rs="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 ns="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 is="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 os="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 as="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 ss="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 ls="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 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<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 cs="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 ms="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 ds="@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 fs="@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 ps="@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 hs="@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 gs="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 bs="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 vs="@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 ys="@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 xs="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 Ps="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 Ts="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 Ss="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 Cs="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 ws="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 _s="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 Bs="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 ks="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 Ms="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 Ls="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 Rs="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 Gs="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 Us="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 As="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}`)},Vr=class{device;queue;scratch;pipelines;luBatchedParamsBuffer;luBlockedParamsBuffer;constructor(e,t){this.device=e,this.queue=t,this.scratch=new oi(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=pe(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)vr(this.device,i.workgroups);Or(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"?is:t==="max"?es:rs:t==="sum"?os:t==="max"?ts:ns,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"?as:ls,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"?ss:us;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=Oe(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:zr(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=Oe(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:zr(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:cs,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:ms,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=Oe(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:zr(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:Se(r,256),label:`${o}:addOffsets`})}}getHistogramClearPipeline(){let e="kernels:histogram:clearAtomicU32";return this.getPipeline(e,()=>new Q(this.device,{label:e,code:ds,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:fs,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"?hs:ps,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:gs,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:bs,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:vs,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:ys,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:xs,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:Ps,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:Ts,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:Ss,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:Cs,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:ws,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:_s,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:Rs,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:Gs,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:ks,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:Ms,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:Ls,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:Bs,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:Us,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: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})]}]}))}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:Se(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:Se(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,Rn(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:Se(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:Se(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:Se(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=be(t.transform),a=new Float32Array(20);Ye(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]=Ln(o.clampMode),c[8]=a[8],c[9]=a[9],c[10]=a[10],c[11]=a[11],c[12]=Mn(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:Se(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:Se(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:Se(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:Se(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:Se(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:Se(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:Se(T,256),label:`luFactorF32:upper:kk${b}`});let w=v,M=v,B=16,S=8,R=Math.ceil(w/B),U=Math.ceil(M/S);x.push({pipeline:d,bindGroups:[h],workgroups:{x:U,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:Se(T,256),label:`luFactorComplex64:upper:kk${b}`});let w=v,M=v,B=16,S=8,R=Math.ceil(w/B),U=Math.ceil(M/S);x.push({pipeline:d,bindGroups:[h],workgroups:{x:U,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 Fs="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.")},Er=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=pe(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(Te(i)&&Te(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:Fs}),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},yr=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,pe(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(Te(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(Te(s),`sizeBytes must be an integer >= 0 (got ${s})`),y(s<=a,`sizeBytes (${s}) exceeds remaining bytes (${a})`);let l=Math.max(4,pe(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(Te(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(Te(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 ai=class{device;queue;kernels;readback;ndarray=Wt;CPUndarray=sr;GPUndarray=lr;_rgba8Blitter=null;constructor(e,t,r={}){this.device=e,this.queue=t,this.kernels=new Vr(e,t),this.readback=new yr(e,t,r.readback)}createStorageBuffer(e){return new oe(this.device,this.queue,e)}createUniformBuffer(e){return new Ur(this.device,this.queue,e)}createPipeline(e){return new Q(this.device,e)}createReadbackRing(e={}){return new yr(this.device,this.queue,e)}encodeDispatch(e,t,r=!1){r&&vr(this.device,t.workgroups),ho(e,t)}encodeDispatchBatch(e,t,r,i=!1){if(i)for(let o of t)vr(this.device,o.workgroups);Or(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=Se(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=ri(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=ni(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 Er(this.device,this.queue)),this._rgba8Blitter.encode(e,t,r,i,o,a)}workgroups1D(e,t){return Se(e,t)}workgroups2D(e,t,r,i){return ri(e,t,r,i)}workgroups3D(e,t,r,i,o,a){return ni(e,t,r,i,o,a)}destroy(){this._rgba8Blitter?.destroy(),this._rgba8Blitter=null,this.readback.destroy(),this.kernels.destroy()}};var Wr=n=>n.startsWith("data:"),jr=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}},Is=n=>{let e=n.lastIndexOf("/");return e<0?"":n.slice(0,e+1)},Hr=(n,e)=>e.startsWith("http://")||e.startsWith("https://")||e.startsWith("blob:")||e.startsWith("/")||!n?e:n+e;var $r=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 xr={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},go=(n,e)=>{let t=n.bufferViews?.[e];if(!t)throw new Error(`Invalid bufferView index: ${e}`);return t},bo=(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},$t=(n,e)=>{let t=n.json,r=Zc(t,e),i=r.componentType,o=xr[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=go(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=bo(f,g,T),M=a*x,B=_.allocBytes(M);try{Ot.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=go(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=xr[c];if(!m)throw new Error(`Unsupported sparse indices componentType: ${c}`);let d=m.bytes,f=go(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=xr[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=bo(l,u,T),M=a*i*P,B=bo(p,h,M);try{Ot.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)}},Fe=(n,e)=>{let t=$t(n,e),r=xr[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{Ot.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)}},qr=(n,e)=>{let t=$t(n,e),r=t.componentType,i=xr[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{Ot.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)}},si=(n,e)=>{let t=$t(n,e),r=t.componentType,i=xr[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{Ot.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),Ds=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},vo=async(n,e)=>{let r=await Ds(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 Ds(e)(n);if(!r.ok)throw new Error(`Failed to fetch ${n}: ${r.status} ${r.statusText}`);return await r.json()},li=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(Wr(s.uri)){o[a]=jr(s.uri).data;continue}let l=Hr(e,s.uri);o[a]=await vo(l,t)}return o},ui=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(Wr(s.uri))o[a]=jr(s.uri).data;else{let l=Hr(t,s.uri);o[a]=await vo(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},yo=async(n,e)=>{if(typeof n=="string"){let c=n,m=e?.baseUrl??Is(c);if(c.toLowerCase().endsWith(".glb")){let h=await vo(c,e),{json:g,binChunk:b}=$r(h),P=await li(g,m,e,b),v={json:g,buffers:P,baseUrl:m};return e?.loadImages&&(v.images=await ui(g,P,m,e)),v}let d=await tm(c,e),f=await li(d,m,e,null),p={json:d,buffers:f,baseUrl:m};return e?.loadImages&&(p.images=await ui(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}=$r(t),d=await li(c,o,e,m),f={json:c,buffers:d,baseUrl:o};return e?.loadImages&&(f.images=await ui(c,d,o,e)),f}let a=new TextDecoder("utf-8").decode(t),s=JSON.parse(a),l=await li(s,o,e,null),u={json:s,buffers:l,baseUrl:o};return e?.loadImages&&(u.images=await ui(s,l,o,e)),u};var Ns="@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},zs=new WeakMap,am=n=>{let e=zs.get(n);if(e)return e;let t=n.createShaderModule({code:Ns}),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 zs.set(n,s),s},Pr=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]},Os=(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}}},Tr=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};Mt.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)){Os(r,e,t.scratch);for(let i of t.meshes)ia(i,t.scratch)}}if(this._pointerSamplers&&this._pointerChannels)for(let t of this._pointerChannels){let r=this._pointerSamplers[t.sampler];r&&(Os(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}}},ci=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 xo(this,e)}dispose(){this._disposed||(this._disposed=!0,this.jointIndicesPtr&&_.freeU32(this.jointIndicesPtr,this.jointCount),this.invBindPtr&&_.freeF32(this.invBindPtr,this.jointCount*16))}},xo=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 mi=class n{transform;type;_projectionMatrix=null;_viewMatrix=null;_viewProjectionMatrix=null;_projectionDirty=!0;constructor(e){this.type=e,this.transform=new Be}get destroyed(){return this.transform.disposed}get viewMatrix(){let e=this.transform.worldMatrix;return this._viewMatrix=ft.invert(e),this._viewMatrix}get viewProjectionMatrix(){let e=this.getProjectionMatrix(),t=this.viewMatrix;return this._viewProjectionMatrix=ft.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=nt.normalize(nt.sub(e,r)),o=[t[0],t[1],t[2]];Math.abs(nt.dot(i,o))>.999&&(Math.abs(i[1])<.9?o=[0,1,0]:o=[1,0,0]);let a=nt.normalize(nt.cross(i,o)),s=nt.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()}},qt=class extends mi{_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=ft.perspective(e,this._aspect,this._near,this._far),this._projectionDirty=!1}return this._projectionMatrix}},Kt=class extends mi{_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},Co=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()}},$=(n,e)=>{n?.onWarning?.(e)},wo=n=>{let e=n?.extensions?.KHR_texture_transform;return((e&&typeof e.texCoord=="number"?e.texCoord:n?.texCoord)??0)|0},js=(n,e,t,r)=>{if(!n)return;let i=(p,h)=>{if(!p)return;let g=wo(p);if(g<0||g>1){$(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&&$(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")},Hs=9728,$s=9729,cm=9984,mm=9985,dm=9986,fm=9987,pm=33071,hm=33648,gm=10497,Vs=n=>{switch(n){case pm:return"clamp-to-edge";case hm:return"mirror-repeat";case gm:default:return"repeat"}},bm=n=>{switch(n){case Hs:return"nearest";case $s:default:return"linear"}},vm=n=>{switch(n){case Hs:return{minFilter:"nearest",mipmapFilter:"nearest",useMipmaps:!1};case $s: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,qs=n=>{let e=n.extensions?.KHR_lights_punctual;return e||null},Pm=n=>{let e=n.extensions?.KHR_lights_punctual;return e||null},Ks=n=>!!n.extensions?.KHR_materials_unlit,di=0,fi=0,Tm=()=>{di!==0&&fi!==0||(di=_.allocF32(16),fi=_.allocF32(10))},Sm=(n,e)=>{Tm();let t=_.f32view(di,16);for(let i=0;i<16;i++)t[i]=e[i]??(i%5===0?1:0);ie.decomposeTRS(fi,di);let r=_.f32view(fi,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},Xs=(n,e)=>{let t=Cm(e);return t!==null&&t>=0&&t<n.length?n[t]:null},et=(n,e,t=[])=>({index:n,name:e?.name,extras:e?.extras,extensions:e?.extensions,xmp:Xs(t,e)}),wm=(n,e,t)=>({...et(n,e,t),primitives:e.primitives.map((r,i)=>({...et(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=Xs(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)=>({...et(o,i,e),name:i?.name??`variant_${o}`}))},Rm=(n,e,t,r,i)=>{let o=n.scenes?.[e],a=r.packets;return{asset:et(0,n.asset,a),scene:o?et(e,o,a):null,nodes:(n.nodes??[]).map((s,l)=>et(l,s,a)),meshes:(n.meshes??[]).map((s,l)=>wm(l,s,a)),materials:(n.materials??[]).map((s,l)=>et(l,s,a)),textures:(n.textures??[]).map((s,l)=>et(l,s,a)),images:(n.images??[]).map((s,l)=>et(l,s,a)),cameras:(n.cameras??[]).map((s,l)=>et(l,s,a)),skins:(n.skins??[]).map((s,l)=>et(l,s,a)),animations:(n.animations??[]).map((s,l)=>et(l,s,a)),extensions:t,xmp:r,variants:i}},Gm=(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?$(t,`${r}: morph weights length ${o} is smaller than target count ${e}; padding with zeros.`):o>e&&$(t,`${r}: morph weights length ${o} exceeds target count ${e}; truncating extra values.`),i},Po=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},Um=(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||Ks(n))return[];let e=[],t=a=>{let s=a===1?1:0;e.includes(s)||e.push(s)},r=a=>{a&&t(wo(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},Ys=(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,Pt)=>{if(Y===void 0)return null;let tt=i.get(Y);if(tt)return tt;let Nt=e.textures?.[Y];if(!Nt)return $(o,`glTF texture index ${Y} missing (usage=${Pt}).`),null;let rt=Nt.source,$e=rt!==void 0?e.images?.[rt]:void 0;if(rt===void 0||!$e)return $(o,`glTF texture ${Y} has no valid source image (usage=${Pt}).`),null;let Jt=Nt.sampler!==void 0?e.samplers?.[Nt.sampler]:void 0,Gi=Vs(Jt?.wrapS),xl=Vs(Jt?.wrapT),Pl=bm(Jt?.magFilter),{minFilter:Tl,mipmapFilter:Sl,useMipmaps:Cl}=vm(Jt?.minFilter),er=null,Oo=n.images?.[rt],cn=$e.mimeType??ym($e.uri);if(Oo)er={kind:"bytes",bytes:Oo,mimeType:cn};else if($e.bufferView!==void 0){let Tt=e.bufferViews?.[$e.bufferView],Eo=Tt?n.buffers[Tt.buffer]:void 0;if(Tt&&Eo){let Wo=(Tt.byteOffset??0)|0;er={kind:"bytes",bytes:Eo.slice(Wo,Wo+Tt.byteLength),mimeType:cn}}else $(o,`glTF image bufferView ${$e.bufferView} missing (texture=${Y}, usage=${Pt}).`)}else if($e.uri)if(Wr($e.uri)){let Tt=jr($e.uri);er={kind:"bytes",bytes:Tt.data,mimeType:cn??Tt.mimeType??void 0}}else er={kind:"url",url:Hr(n.baseUrl,$e.uri),mimeType:cn};if(!er)return $(o,`Could not resolve image source for texture=${Y} (usage=${Pt}).`),null;let Vo=Pr.createFrom({source:er,mipmaps:Cl,sampler:{addressModeU:Gi,addressModeV:xl,magFilter:Pl,minFilter:Tl,mipmapFilter:Sl}});return i.set(Y,Vo),Vo},u=(Y,Pt)=>Y?l(Y.index,Pt):null,c=Y=>{if(!Y)return null;let tt=Y.extensions?.KHR_texture_transform,rt=wo(Y)===1?1:0;return tt?{offset:[Number(tt.offset?.[0]??0),Number(tt.offset?.[1]??0)],rotation:Number(tt.rotation??0),scale:[Number(tt.scale?.[0]??1),Number(tt.scale?.[1]??1)],texCoord:rt}:rt===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&&($(o,`Material '${s.name??t}' uses KHR_materials_pbrSpecularGlossiness; approximating using diffuse as baseColor. Specular/glossiness are not fully supported yet.`),g.specularGlossinessTexture&&$(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,U=h?u(M,"metallicRoughness"):null,L=h?c(M):null,G=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,ge=E.KHR_materials_anisotropy,He=E.KHR_materials_transmission,Le=E.KHR_materials_volume,Re=E.KHR_materials_diffuse_transmission,ct=E.KHR_materials_dispersion,mt=E.KHR_materials_ior,Qt=1,Ue={};if(Z&&(Ue.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];Ue.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];Ue.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&&(Ue.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)}),ge&&(Ue.anisotropy={strength:ge.anisotropyStrength??0,rotation:ge.anisotropyRotation??0,texture:u(ge.anisotropyTexture,"anisotropy"),textureTransform:c(ge.anisotropyTexture)}),He&&(Ue.transmission={factor:He.transmissionFactor??0,texture:u(He.transmissionTexture,"transmission"),textureTransform:c(He.transmissionTexture)}),Le){let Y=Array.isArray(Le.attenuationColor)?Le.attenuationColor:[1,1,1];Ue.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];Ue.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)}}ct&&(Ue.dispersion={dispersion:ct.dispersion??0}),mt&&(Ue.ior={ior:mt.ior??1.5}),H&&(Ue.emissiveStrength={strength:j});let un=Ks(s),Dt=f==="opaque",kt;return un?kt=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:Dt}):kt=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:Qt,baseColorTexture:v,metallicRoughnessTexture:U,normalTexture:G,occlusionTexture:D,emissiveTexture:A,baseColorTextureTransform:x,metallicRoughnessTextureTransform:L,normalTextureTransform:F,occlusionTextureTransform:k,emissiveTextureTransform:I,normalScale:O,occlusionStrength:N,alphaCutoff:d,extensions:Object.keys(Ue).length>0?Ue:void 0,blendMode:f,cullMode:p,depthWrite:Dt}),r.set(t,kt),kt},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||(js(e.materials?.[f],t.attributes,o,`${a} variant material ${f}`),p=Ys(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 $(i,"Primitive missing POSITION; skipping"),null;let s=Fe(n,a),l=null,u=o.NORMAL;u!==void 0&&(l=Fe(n,u));let c=null,m=o.TANGENT;m!==void 0&&(c=Fe(n,m));let d=null,f=o.TEXCOORD_0;f!==void 0&&(d=Fe(n,f));let p=null,h=o.TEXCOORD_1;h!==void 0&&(p=Fe(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 G=qr(n,x),F=Fe(n,T);if(w!==void 0&&M!==void 0){let D=qr(n,w),k=Fe(n,M);if(D.length===G.length&&k.length===F.length){let A=Um(F,k);g=G,b=A.weights0,P=D,v=A.weights1}else $(i,"Primitive has JOINTS_1/WEIGHTS_1 but lengths don't match JOINTS_0/WEIGHTS_0; ignoring additional influences"),g=G,b=Po(F)}else w!==void 0||M!==void 0?($(i,"Primitive has JOINTS_1/WEIGHTS_1 mismatch; ignoring additional influences"),g=G,b=Po(F)):(g=G,b=Po(F))}else(x!==void 0||T!==void 0)&&$(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=si(n,t.indices);else{let G=s.length/3|0,F=new Uint32Array(G);for(let D=0;D<G;D++)F[D]=D>>>0;S=B===4?null:F}if(B===5){let G=S??new Uint32Array(0);S=Am(G)}else if(B===6){let G=S??new Uint32Array(0);S=Fm(G)}else if(B!==4)return $(i,`Unsupported primitive mode=${B} (only triangles/strip/fan supported); skipping primitive`),null;let R=[];if(t.targets&&t.targets.length>0)for(let G=0;G<t.targets.length;G++){let F=t.targets[G],D={},k=F.POSITION,A=F.NORMAL;if(k!==void 0){let I=Fe(n,k);I.length===s.length?D.positions=I:$(i,`Primitive morph target ${G} POSITION length ${I.length} does not match base POSITION length ${s.length}; ignoring POSITION deltas.`)}if(A!==void 0){let I=Fe(n,A);I.length===s.length?D.normals=I:$(i,`Primitive morph target ${G} NORMAL length ${I.length} does not match base NORMAL length ${s.length}; ignoring NORMAL deltas.`)}F.TANGENT!==void 0&&$(i,`Primitive morph target ${G} provides TANGENT deltas; WasmGPU ignores tangent morph data.`),!D.positions&&!D.normals&&$(i,`Primitive morph target ${G} has no supported POSITION or NORMAL deltas; preserving target slot with no runtime effect.`),R.push(D)}let U=Im(t.material!==void 0?e.materials?.[t.material]:void 0),L=U.length>0;if(!l&&(r||L)&&(l=wn(s,S)),!c&&L){let G=U[0];if(U.length>1)$(i,"Primitive uses tangent-space textures on multiple texture coordinate sets; shader will fall back to derivative tangent space.");else{let F=G===1?p:d;l&&F?c=Yo(s,l,F,S):$(i,`Primitive uses tangent-space material features but is missing NORMAL or TEXCOORD_${G}; 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 $(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){$(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(js(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=Ys(n,e,p.material,o,a,u),T=new ot(b,x);T.name=r.name??c.name??`gltf_mesh_${r.mesh}_${f}`,T.transform.setParent(i);let w=Gm(r.weights??c.weights,b.morphTargets.length|0,u,`Mesh '${T.name}' primitive ${f}`);b.morphTargets.length>0&&no(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 $(r,`nodes[].camera=${e.camera} missing; skipping camera`),null;let o;if(i.type==="perspective"){let a=i.perspective;if(!a)return $(r,`camera[${e.camera}] missing perspective block; skipping`),null;o=new qt({fov:a.yfov*180/Math.PI,aspect:a.aspectRatio,near:a.znear,far:a.zfar??1e3})}else{let a=i.orthographic;if(!a)return $(r,`camera[${e.camera}] missing orthographic block; skipping`),null;o=new Kt({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 wt({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 _t({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 vt({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){$(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=Fe(n,s.inverseBindMatrices));let m=c;c&&c.length!==s.joints.length*16&&($(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||$(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,Kr=(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},Es=n=>{let e=n.target.extensions?.KHR_animation_pointer;return typeof e?.pointer=="string"?e.pointer:null},Zs=n=>n==="rotation"?1:n==="offset"||n==="scale"?2:null,Qs=(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=Zs(r);return i===null?null:ve(n,e,i,(o,a)=>{o[t]=Qs(o[t],r,a)},!0)},Ws=(n,e,t)=>{let r=Zs(t);if(r===null)return null;let i=(o,a)=>({kind:"pointer",canonical:"",valueSize:r,allowDuplicateTarget:!0,setValue:s=>a(Qs(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}},To=n=>!!n?.extensions?.KHR_texture_transform,$m=(n,e,t)=>{let r=Kr(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 $(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"&&To(s[e[3]])?a(Ws(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"&&To(i[e[2]]))return a(Ws(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"&&To(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=Kr(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 $(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=Kr(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)oa(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=Kr(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 qt);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 Kt);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=Kr(e,3),i=qs(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 _t||u instanceof vt);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 vt);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 $(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},So=(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.`);$(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=Fe(n,A.input),O=$t(n,A.output),N=Fe(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=[],U={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=Es(A)??void 0),g.push(z),A.target.path==="pointer"){if(I!==void 0){$(a,`KHR_animation_pointer: animation '${P}' channel ${k} sets target.node; skipping pointer channel.`);continue}let H=Es(A);if(!H){$(a,`KHR_animation_pointer: animation '${P}' channel ${k} is missing extensions.KHR_animation_pointer.pointer.`);continue}let j=Zm(U,H);if(!j){$(a,`KHR_animation_pointer: animation '${P}' channel ${k} pointer '${H}' is not supported by this importer.`);continue}if(So(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){$(a,`KHR_animation_pointer: animation '${P}' channel ${k} references missing sampler ${z.sampler}.`);continue}if(j.requiresStep&&Z.interpolation!=="STEP"){$(a,`KHR_animation_pointer: boolean pointer '${j.canonical}' requires STEP interpolation; skipping channel.`);continue}if((Z.valueSize|0)!==(j.valueSize|0)){$(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&&So(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){So(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,G=S.length|0,F=R.length|0,D=h.length|0;if(v>0&&(G>0||F>0||D>0)){let k=0;if(G>0){k=_.allocU32(G*3);let A=_.u32view(k,G*3);w.push({ptr:k,len:G*3});for(let I=0;I<G;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 Tr({name:d.name??`anim_${m}`,samplerCount:v,channelCount:G,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},_o=(n,e={})=>{let t=n.json,r=e.targetScene??new Je,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 G=a[L],F=new Be;if(G.matrix&&G.matrix.length>=16)Sm(F,G.matrix);else{let D=G.translation??[0,0,0],k=G.rotation??[0,0,0,1],A=G.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 Co(L,F,G)}for(let L=0;L<a.length;L++){let G=a[L],F=s[L];for(let D of G.children??[]){let k=s[D];k?(k.transform.setParent(F.transform),k.parentIndex=L,k.setParentNode(F)):$(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=qs(t),T=(L,G)=>{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:G;if(I!==void 0){let O=m[I];if(!O||!O.runtime)$(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){$(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)$(e,`KHR_lights_punctual node references missing light ${O.light}`);else{let z=Vm(N,k);if(z){Fa(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 $(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),U=!1;return{scene:r,meshes:h,nodes:s,lights:b,cameras:g,skins:m,animations:B,clips:S,metadata:R,destroy(){if(!U){if(U=!0,i){for(let L of h)r.remove(L);for(let L of b)r.removeLight(L)}for(let L of b)Ia(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 lt=(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}},Js=(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},el=(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},Cr=(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)}},Xr=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??tr();Js(t,this.cameraSigB),(!this.hasCameraSig||!el(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 tl=[[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]},Yr=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=lt(e.camera,e.width,e.height,t.position);if(!r||!r.inFront){this.hideAll();return}for(let i=0;i<3;i++){let o=tl[i],a=lt(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]=Cr(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=tl[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 xt=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 rl=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}`},nl=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]},pi=(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],il=(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,hi=(n,e,t)=>Math.abs(n-e)<=t,vi=(n,e)=>Math.max(1e-9,Math.abs(n)*1e-9,Math.abs(e)*1e-6),gi=(n,e,t)=>{if(!Number.isFinite(e)||e<=t)return!1;let r=n/e;return Math.abs(r-Math.round(r))<=1e-4},bi=(n,e,t)=>{let r=Math.max(0,e-n),i=vi(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},ol=(n,e,t)=>{let r=Math.max(0,e-n),i=vi(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},Zr=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 xt(t,()=>{let r=document.createElement("div");return r.style.position="absolute",r.style.transformOrigin="0 50%",r},this.maxLines),this.labelPool=new xt(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=nl(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=bi(t,r,c),p=bi(i,o,c);for(let k=0;k<32&&f+p>d;k++)c=nl(c*1.5),f=bi(t,r,c),p=bi(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=ol(t,r,c),T=ol(i,o,c),w=vi(a,c),M=vi(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),U=Math.max(M,Math.abs(c)*.001),L=x.reduce((k,A)=>k+(gi(A,h,B)?1:0),0),G=T.reduce((k,A)=>k+(gi(A,h,S)?1:0),0);for(let k=0;k<32;k++){let A=L>0?Math.ceil(L/P):0,I=G>0?Math.ceil(G/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,pi(this.plane,this.origin,A,i),pi(this.plane,this.origin,A,o));if(!I)continue;let O=I.p0,N=I.p1,z=gi(A,h,B),E=Math.abs(A)<=R,H=hi(A,t,w)||hi(A,r,w),j=this.linePool.acquire();if(il(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=rl(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,pi(this.plane,this.origin,t,A),pi(this.plane,this.origin,r,A));if(!I)continue;let O=I.p0,N=I.p1,z=gi(A,h,S),E=Math.abs(A)<=U,H=hi(A,i,M)||hi(A,o,M),j=this.linePool.acquire();if(il(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=rl(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=lt(e.camera,e.width,e.height,s),d=lt(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=lt(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=lt(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=lt(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}`},yi=(n,e)=>jo(n,e),Bt=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 Ee)return n;let e=n;return e.nodelink instanceof Ee?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 st){let o=be(n.scaleTransform);if(n.colormap==="custom"){let s=n.colormapStops.slice();return{transform:o,signature:`pointcloud|custom|${Bt(o)}|${JSON.stringify(s)}`,sample:l=>yi(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}|${Bt(o)}`,sample:s=>a.sampleCPU(s)}}if(n instanceof Ve){let o=be(n.scaleTransform);if(n.colorMode==="scalar"&&n.colormap==="custom"){let s=n.colormapStops.slice();return{transform:o,signature:`glyphfield|custom|${Bt(o)}|${JSON.stringify(s)}`,sample:l=>yi(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}|${Bt(o)}`,sample:s=>a.sampleCPU(s)}}if(n instanceof Ee||n.nodelink instanceof Ee){let o=n instanceof Ee?n:n.nodelink,a=n instanceof Ee?"node":n.component??"node",s=be(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|${Bt(s)}|${JSON.stringify(u)}`,sample:m=>yi(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}|${Bt(s)}`,sample:m=>c.sampleCPU(m)}}if(n instanceof Ze){let o=be(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}|${Bt(o)}`,sample:s=>a.sampleCPU(s)}}let t=n,r=be(t.scaleTransform);if(t.colormapStops&&t.colormapStops.length>=2){let o=t.colormapStops.slice();return{transform:r,signature:`explicit|stops|${Bt(r)}|${JSON.stringify(o)}`,sample:a=>yi(a,o)}}let i=typeof t.colormap=="string"?q.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}|${Bt(r)}`,sample:o=>i.sampleCPU(o)}},Qr=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 xt(i,()=>{let s=document.createElement("div");return s.style.position="absolute",s},this.tickCount),this.tickLabelPool=new xt(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]=Cr(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=so(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 Ut={Idle:"idle",Marker:"marker",Distance:"distance",Angle:"angle"};var xi={Degrees:"deg",Radians:"rad"},At=n=>[n[0],n[1],n[2],n[3]],Pi=n=>[n[0]??0,n[1]??0,n[2]??0],Bo=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,al=n=>n?{kind:n.kind,objectId:n.objectId,elementIndex:n.elementIndex,ndIndex:n.ndIndex?n.ndIndex.slice():null,attributes:Bo(n.attributes)}:null,ye=n=>({position:Pi(n.position),pick:al(n.pick)}),Jr=n=>({position:Pi(n.worldPosition),pick:{kind:n.kind,objectId:n.objectId,elementIndex:n.elementIndex,ndIndex:n.ndIndex?n.ndIndex.slice():null,attributes:Bo(n.attributes)}}),en=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 Ft=[{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))},tn=(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??xi.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 Ft[4];let t=kr(Math.floor(Math.log10(e)/3)*3,Ft[0].exponent,Ft[Ft.length-1].exponent);for(let r=0;r<Ft.length;r++)if(Ft[r].exponent===t)return Ft[r];return Ft[4]},ko=(n,e={})=>{let t=tn(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}},Mo=(n,e={})=>{let t=tn(e);if(!Number.isFinite(n))return{radians:n,value:Number.NaN,unitSymbol:t.angleUnit,text:`nan ${t.angleUnit}`};if(t.angleUnit===xi.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}},Lo=(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},sl=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,ll=(n,e)=>!e||!e.hit?`${n}: miss`:[`${n}: hit`,`kind: ${e.kind}`,`objectId: ${e.objectId}`,`elementIndex: ${e.elementIndex}`,`world: ${Lo(e.worldPosition,5)}`,`ndIndex: ${cd(e.ndIndex)}`,...md(e.attributes)].join(`
|
|
23
|
+
`),dd=(n,e)=>{if(!e||!e.hit)return`${n}: miss`;let t=ll(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
|
-
`)},hr=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 We(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=Te(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]=Wt(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=ea("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]},Nt=(n,e,t,r,i,o)=>{n.push({key:`${e}:${r}`,annotationId:e,annotationKind:t,role:r,anchor:re(i),color:tt(o)})},ta=n=>{let e=[];for(let t=0;t<n.length;t++){let r=n[t];if(r.visible){if(r.kind==="marker"){Nt(e,r.id,r.kind,"marker",r.anchor,r.color);continue}if(r.kind==="distance"){Nt(e,r.id,r.kind,"start",r.start,r.color),Nt(e,r.id,r.kind,"end",r.end,r.color);continue}Nt(e,r.id,r.kind,"a",r.a,r.color),Nt(e,r.id,r.kind,"b",r.b,r.color),Nt(e,r.id,r.kind,"c",r.c,r.color)}}return e},br=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 Oe({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:tt(t.color)}}sync(e,t){if(w(Number.isFinite(t),"AnnotationMarkerRenderer.sync: revision must be finite."),t===this.appliedRevision)return!1;let r=ta(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(),gr=(n,e,t)=>n<e?e:n>t?t:n,ra=(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),na=n=>Math.hypot(n[0]??0,n[1]??0,n[2]??0),nt=n=>n.kind==="marker"?{...n,color:tt(n.color),anchor:re(n.anchor)}:n.kind==="distance"?{...n,color:tt(n.color),start:re(n.start),end:re(n.end)}:{...n,color:tt(n.color),a:re(n.a),b:re(n.b),c:re(n.c)},dn=(n,e)=>{let t=n??lu[e];return[gr(t[0],0,1),gr(t[1],0,1),gr(t[2],0,1),gr(t[3],0,1)]},pn=n=>{if(n==null)return null;let e=`${n}`.trim();return e.length>0?e:null},ci=n=>n===void 0?!0:!!n,mi=(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)},di=(n,e,t)=>{let r=ra(n,e),i=ra(t,e),o=na(r),a=na(i);if(o<=1e-12||a<=1e-12)return 0;let s=gr(cu(r,i)/(o*a),-1,1);return Math.acos(s)};var yr=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?nt(t):null}values(){let e=new Array(this.order.length);for(let t=0;t<this.order.length;t++)e[t]=nt(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:pn(t.label),visible:ci(t.visible),color:dn(t.color,"marker"),createdAtMs:r,updatedAtMs:r,anchor:re(e)};return this.push(i),nt(i)}createDistance(e,t,r={}){let i=this.nowMs(),o=re(e),a=re(t),s={id:this.nextId("distance"),kind:"distance",label:pn(r.label),visible:ci(r.visible),color:dn(r.color,"distance"),createdAtMs:i,updatedAtMs:i,start:o,end:a,distanceWorld:mi(o.position,a.position)};return this.push(s),nt(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:pn(i.label),visible:ci(i.visible),color:dn(i.color,"angle"),createdAtMs:o,updatedAtMs:o,a,b:s,c:l,angleRadians:di(a.position,s.position,l.position)};return this.push(u),nt(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(),nt(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=mi(r.start.position,r.end.position),r.updatedAtMs=this.nowMs(),this.bumpRevision(),nt(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=di(r.a.position,r.b.position,r.c.position),r.updatedAtMs=this.nowMs(),this.bumpRevision(),nt(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){w(!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=pn(t.label)),t.color!==void 0&&(e.color=dn(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],fn=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},pi=(n,e)=>({...fn(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:pr(i.color),position:[i.anchor.position[0],i.anchor.position[1],i.anchor.position[2]]});continue}if(i.kind==="distance"){let s=si(i.distanceWorld,e),l=i.label?`${i.label}: ${s.text}`:s.text;t.push({key:i.id,text:l,color:pr(i.color),position:du(i.start.position,i.end.position)});continue}let o=li(i.angleRadians,e),a=i.label?`${i.label}: ${o.text}`:o.text;t.push({key:i.id,text:a,color:pr(i.color),position:[i.b.position[0],i.b.position[1],i.b.position[2]]})}return t},vr=class{store;markerRenderer;labelLayer;runtime;annotationsListeners=new Set;modeListeners=new Set;hoverListeners=new Set;selectionListeners=new Set;stagingListeners=new Set;autoCreateOverlay;overlaySystemOptions;modeValue=et.Idle;unitsValue;scene=null;camera=null;controls=null;overlaySystem=null;ownsOverlaySystem=!1;canvas=null;pointerTarget=null;hoverReadout=fn(null);selectionReadout=pi(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 yr({idPrefix:t.storeIdPrefix??`ann${r}`}),this.markerRenderer=new br({...t.markerRenderer,name:t.markerRenderer?.name??`annotation-markers-${r}`}),this.labelLayer=new hr({...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 fr(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=et.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(fn(null)),this.setSelectionReadout(pi(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=fn(e);return this.setHoverReadout(t),t}ingestSelectionHit(e){let t=this.resolveSelectionMeta(e);if(this.setSelectionReadout(pi(e,t)),!e)return this.modeValue===et.Idle&&this.clearPending(),null;if(this.modeValue===et.Marker)return this.store.createMarker(dr(e));if(this.modeValue===et.Distance){if(this.pendingAnchors.push(dr(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===et.Angle){if(this.pendingAnchors.push(dr(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)}};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),Vt=n=>{let e=new Array(n.length);for(let t=0;t<n.length;t++){let r=n[t];w(Number.isFinite(r),`shape[${t}] must be finite`),w(Number.isInteger(r),`shape[${t}] must be an integer`),w(r>=0,`shape[${t}] must be >= 0`),e[t]=r>>>0}return e},bn=n=>{if(n.length===0)return 1;let e=1;for(let t of n){let r=t>>>0,i=e*r;w(Number.isSafeInteger(i),"shape is too large (numel overflow)"),e=i}return e>>>0},ia=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,oa=(n,e,t=0,r)=>{let i=ve(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=C.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}},hn=(n,e,t)=>{let i=ve(n).ctor,o=ae.buffer();return new i(o,e>>>0,t>>>0)},yu=(n,e)=>{let t=ae.bytes(),r=n>>>0,i=r+(e>>>0)>>>0;return t.subarray(r,i)},vu=n=>{if(typeof n.c_contiguous=="boolean"){w(n.c_contiguous,'Python buffer must be C-contiguous (use numpy.ascontiguousarray(..., order="C"))');return}let e=Vt(n.shape??[]),t=Array.from(n.strides??[]);if(w(t.length===e.length,"Python buffer strides/shape rank mismatch"),bn(e)===0)return;let r=1;for(let i=e.length-1;i>=0;i--)w(t[i]===r,'Python buffer must be C-contiguous (use numpy.ascontiguousarray(..., order="C"))'),r*=e[i]},fi=(n,e)=>{if(hu(n)){let s=n.getBuffer(),l=fi(s,e),u=typeof s.release=="function"?()=>s.release?.():void 0;return{...l,release:u}}if(bu(n)){vu(n),w(ArrayBuffer.isView(n.data),"Python buffer .data must be an ArrayBufferView"),w(typeof n.data.subarray=="function","Python buffer .data must be a TypedArray (DataView is not supported)");let s=ia(n.data);w(s!==null,"Unsupported Python buffer dtype (expected a numeric TypedArray)");let l=e.dtype??s;w(l===s,`dtype mismatch: expected ${l}, got ${s}`);let u=Vt(n.shape),m=Vt(e.shape??u),c=bn(m),d=(n.offset??0)>>>0,f=oa(l,n.data,d,c);return w(f.length>>>0===c>>>0,"Python buffer view length mismatch"),e.shape&&w(Vt(e.shape).length===u.length&&Vt(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}}w(ArrayBuffer.isView(n),"Expected a TypedArray / ArrayBufferView or a PyProxy supporting getBuffer()");let t=ia(n);w(t!==null,"Unsupported TypedArray dtype");let r=e.dtype??t;w(r===t,`dtype mismatch: expected ${r}, got ${t}`),w(e.shape,"shape is required when sending a plain TypedArray (no Python buffer metadata available)");let i=Vt(e.shape),o=bn(i);w(n.byteLength>>>0>=o*ve(r).bytesPerElement,"source TypedArray is too small for the provided shape");let a=oa(r,n,0,o);return w(a.length>>>0===o>>>0,"source TypedArray length mismatch"),{dtype:r,shape:i,data:a}},hi={sendNdarray:(n,e={})=>{let t=fi(n,e),{dtype:r,shape:i,data:o}=t,a=ve(r),s=bn(i),l=s*a.bytesPerElement>>>0,u=gu(l,16,e.allocator);hn(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=>hn(n.dtype,n.ptr,n.length),bytes:n=>yu(n.ptr,n.byteLength),copyInto:(n,e,t={})=>{let r=fi(e,{...t,dtype:n.dtype,shape:n.shape}),{data:i}=r;w(i.length>>>0===n.length>>>0,"copyInto: source length mismatch"),hn(n.dtype,n.ptr,n.length).set(i);try{r.release?.()}catch{}},receiveNdarray:(n,e={})=>{let t=hn(n.dtype,n.ptr,n.length);if(!e.copy)return{dtype:n.dtype,shape:Array.from(n.shape),data:t};let i=ve(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()).`);C.freeBytes(n.ptr>>>0,n.byteLength>>>0)}};var q=1e-6,aa=.001,sa=.35,_e=(n,e,t)=>Math.max(e,Math.min(t,n)),gn=n=>_e(n,0,1),Re=(n,e,t)=>n+(e-n)*t,xu=n=>n<.5?4*n*n*n:1-Math.pow(-2*n+2,3)*.5,ee=n=>[n[0]??0,n[1]??0,n[2]??0],xe=(n,e)=>[n[0]+e[0],n[1]+e[1],n[2]+e[2]],ct=(n,e)=>[n[0]-e[0],n[1]-e[1],n[2]-e[2]],N=(n,e)=>[n[0]*e,n[1]*e,n[2]*e],Se=(n,e)=>n[0]*e[0]+n[1]*e[1]+n[2]*e[2],dt=(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]],mt=n=>Math.hypot(n[0],n[1],n[2]),Q=(n,e=[0,0,1])=>{let t=mt(n);if(t<=q)return ee(e);let r=1/t;return[n[0]*r,n[1]*r,n[2]*r]},bi=(n,e,t)=>[Re(n[0],e[0],t),Re(n[1],e[1],t),Re(n[2],e[2],t)],la=(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],Pu=(n,e,t,r)=>[-n,-e,-t,r],gi=(n,e,t,r)=>{let i=Math.hypot(n,e,t,r);if(i<=q)return[0,0,0,1];let o=1/i;return[n*o,e*o,t*o,r*o]},ua=(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)]},wu=(n,e,t,r)=>Math.abs(n)<q&&Math.abs(e)<q&&Math.abs(t)<q&&Math.abs(1-r)<q,Su=(n,e,t,r,i)=>{let o=gn(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 gi(s*o,l*o,u*o,1-o+m*o);let c=Math.acos(a),d=Math.sqrt(1-a*a);if(d<=q)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]},ca=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??dt(n.up,n.forward),t=Q(e,[1,0,0]),r=Q(n.up,[0,1,0]),i=Q(dt(t,r),n.forward),o=Q(dt(r,i),t),a=Q(dt(i,o),r);return{right:o,up:a,forward:i}},jt=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=ca(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?ee(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:ee(this._axisConvention.right),up:ee(this._axisConvention.up),forward:ee(this._axisConvention.forward)}}set axisConvention(e){this._axisConvention=ca(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(q,e);if(this._radius=t,this._mode==="trackball"){let r=Q(this._trackballEye,this._axisConvention.forward);this._trackballEye=N(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=ee(this.camera.position),t=ct(e,this.target);if(this._radius=Math.max(q,mt(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=ee(this.target),this._savedPosition=ee(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=ee(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?ee(t.target):ee(this.target),a=Math.max(q,t.distance??this._radius),s=xe(o,N(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=gn(t.elapsed/Math.max(q,t.duration)),i=xu(r),o=bi(t.fromPosition,t.toPosition,i),a=bi(t.fromTarget,t.toTarget,i),s=Q(bi(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=gi(...la(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:Re(e.left,t.left,r),right:Re(e.right,t.right,r),top:Re(e.top,t.top,r),bottom:Re(e.bottom,t.bottom,r),near:Re(e.near,t.near,r),far:Re(e.far,t.far,r)}:{type:"perspective",near:Re(e.near,t.near,r),far:Re(e.far,t.far,r)}}applyPose(e,t,r){this.target=ee(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??sa)<=0){this.cancelTransition(),this.applyPose(e,t,r),this.applyProjectionState(i),this.syncFromCamera(),this.emitChange();return}this._transition={elapsed:0,duration:a??sa,fromPosition:ee(this.camera.position),toPosition:ee(e),fromTarget:ee(this.target),toTarget:ee(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-gn(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,aa),i=Math.min(this.maxPolarAngle,Math.PI-aa);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(q,this._radius)),a=xe(this.target,o),s=Q(ct(this.target,a),N(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-gn(this.dampingFactor),e*60):1;if(this.enableRotate){let o=this._trackballRotationDelta;if(!wu(o[0],o[1],o[2],o[3])){let a=Su(o[0],o[1],o[2],o[3],t);this._trackballEye=ua(this._trackballEye[0],this._trackballEye[1],this._trackballEye[2],a[0],a[1],a[2],a[3]),this._trackballUp=Q(ua(this._trackballUp[0],this._trackballUp[1],this._trackballUp[2],a[0],a[1],a[2],a[3]),this._axisConvention.up);let s=la(o[0],o[1],o[2],o[3],...Pu(a[0],a[1],a[2],a[3]));this._trackballRotationDelta=gi(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=mt(this._trackballEye);this._radius=_e(Math.max(q,r),this.minDistance,this.maxDistance),r>q?this._trackballEye=N(this._trackballEye,this._radius/r):this._trackballEye=N(this._axisConvention.forward,this._radius);let i=xe(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)<=q){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(q,mt(this._trackballEye));this._trackballEye=N(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=N(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(q,this._zoom),u=(this._orthoBaseTop-this._orthoBaseBottom)/Math.max(q,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=xe(this._panOffset,xe(N(r.right,-a),N(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(q,t)*.5,h=g/Math.max(q,this._zoom)*.5,P=x/Math.max(q,t)*.5,S=x/Math.max(q,this._zoom)*.5;this.target=xe(this.target,xe(N(r.right,s*(M-h)),N(r.up,l*(P-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=xe(this.target,xe(N(r.right,s*(p-b)),N(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(q,this._zoom),o=(this._orthoBaseTop-this._orthoBaseBottom)/Math.max(q,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=Se(e,this._axisConvention.right),r=Se(e,this._axisConvention.up),i=Se(e,this._axisConvention.forward),o=Math.max(q,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 xe(xe(N(this._axisConvention.right,o),N(this._axisConvention.up,a)),N(this._axisConvention.forward,s))}computeLookBasis(e,t){let r=Q(e,N(this._axisConvention.forward,-1)),i=Q(t,this._axisConvention.up);Math.abs(Se(r,i))>.999&&(i=Math.abs(r[1])<.9?[0,1,0]:[1,0,0]);let o=Q(dt(r,i),this._axisConvention.right),a=Q(dt(o,r),i);return{right:o,up:a,forward:r}}computeOrbitBasis(){let e=this.sphericalToOffset(this._theta,this._phi,Math.max(q,this._radius)),t=Q(N(e,-1),N(this._axisConvention.forward,-1));return this.computeLookBasis(t,this.getOrbitUp(t))}computeTrackballBasis(){let e=Q(N(this._trackballEye,-1),N(this._axisConvention.forward,-1)),t=this.computeLookBasis(e,this._trackballUp);return this._trackballUp=t.up,t}getOrbitUp(e){let t=this._axisConvention.up,r=ct(t,N(e,Se(t,e))),i=mt(r);if(i>q)return N(r,1/i);let o=this._axisConvention.forward;return r=ct(o,N(e,Se(o,e))),i=mt(r),i>q?N(r,1/i):ee(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(Se(e,t),-1,1),i=Math.acos(r);if(i<=q)return null;i*=this.rotateSpeed;let o=dt(e,t),a=mt(o);if(a<=q)return null;o=N(o,1/a);let s=this.computeTrackballBasis(),l=Q(xe(xe(N(s.right,o[0]),N(s.up,o[1])),N(N(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 Ai(e)}getInspectionViewDirection(e){switch(e){case"front":return ee(this._axisConvention.forward);case"back":return N(this._axisConvention.forward,-1);case"right":return ee(this._axisConvention.right);case"left":return N(this._axisConvention.right,-1);case"top":return ee(this._axisConvention.up);case"bottom":return N(this._axisConvention.up,-1)}}getInspectionViewUp(e){return e==="top"?N(this._axisConvention.forward,-1):ee(e==="bottom"?this._axisConvention.forward:this._axisConvention.up)}getCurrentViewOrientation(){let e=ee(this.camera.position),t=Q(ct(e,this.target),this._axisConvention.forward);return{direction:t,up:Q(this.camera.up,this.getOrbitUp(N(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"?xt(e.sphereCenter,e.sphereRadius*r,e.partial):ki(e,r),s=this.computeLookBasis(N(o.direction,-1),o.up),l=t.boundsMode==="sphere"?ee(e.sphereCenter):Un(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=kn(e),l=this.camera,u=Math.tan(l.fov*Math.PI/180*.5),m=u*Math.max(o,q),c=t.sphereRadius,d=[];for(let v of s){let A=ct(v,i),_=Se(A,r.right),k=Se(A,r.up),G=Se(A,r.forward);d.push(G),c=Math.max(c,Math.abs(_)/Math.max(m,q)-G,Math.abs(k)/Math.max(u,q)-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,P=c+x+M,S=Math.max(b,Math.min(f-g,h)),B=Math.max(S+.01,Math.max(p+g,P));return{position:xe(i,N(N(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=kn(e),l=0,u=0,m=1/0,c=-1/0;for(let P of s){let S=ct(P,i),B=Se(S,r.right),v=Se(S,r.up),A=Se(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,q));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:xe(i,N(N(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}}}},yn=class extends jt{constructor(e,t,r={}){super(e,t,{...r,mode:"orbit"})}},vn=class extends jt{constructor(e,t,r={}){super(e,t,{...r,mode:"trackball"})}};var xr=(n,e)=>`${n}:${e}`,yi=n=>n?Array.isArray(n)?n:[n]:[],ma=n=>({...n,key:xr(n.objectId,n.elementIndex)}),Pr=class{entries=new Map;get size(){return this.entries.size}has(e,t){return this.entries.has(xr(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 yi(e))this.entries.set(xr(t.objectId,t.elementIndex),ma(t));return this}remove(e){for(let t of yi(e))this.entries.delete(xr(t.objectId,t.elementIndex));return this}toggle(e){for(let t of yi(e)){let r=xr(t.objectId,t.elementIndex);this.entries.has(r)?this.entries.delete(r):this.entries.set(r,ma(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 xn=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 qr(r.device,r.queue,t),this.scale=new qt(this.compute)}static async create(e,t={}){await Ci();let r=await Er.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 ae}get interop(){return ae}static get python(){return hi}get python(){return hi}static get math(){return{mat4:Ne,quat:An,vec3:Ie}}get math(){return{mat4:Ne,quat:An,vec3:Ie}}static createHeapArena(e,t=16){return ae.createHeapArena(e,t)}createHeapArena(e,t=16){return ae.createHeapArena(e,t)}static get frameArena(){return W}get frameArena(){return W}static createSelectionStore(){return new Pr}createSelectionStore(){return new Pr}createPerformanceStats(e={}){this._performanceStats?.destroy(),this.renderer.enableGpuTiming(e.showGpuTime??!0);let t=new Or({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 Ze({background:e})}createCamera={perspective:e=>new Ot(e),orthographic:e=>new zt(e)};createControls={navigation:(e,t,r)=>new jt(e,t,r),orbit:(e,t,r)=>new yn(e,t,r),trackball:(e,t,r)=>new vn(e,t,r)};createOverlay={system:(e={})=>new lr({canvas:this.renderer.canvas,...e}),axisTriad:(e={})=>new ur(e),grid:(e={})=>new cr(e),legend:e=>new mr(e)};createAnnotation={toolkit:(e={})=>new vr({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 Be(e),standard:e=>new Pe(e),data:e=>new Ae(e),custom:e=>new kr(e)};texture={create2D:e=>Dt.createFrom(e)};createTransform(){return new he}createMesh(e,t){return new Me(e,t)}createPointCloud(e){return new Ue(e)}createGlyphField(e){return new Oe(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 Gr(e),directional:e=>new Je(e),point:e=>new qe(e)};gltf={load:async(e,t)=>Kn(e,t),import:async(e,t)=>ii(e,t),loadAndImport:async(e,t={})=>{let r=await Kn(e,t.load);return ii(r,t.import)},parseGLB:e=>ar(e),readAccessor:(e,t)=>lt(e,t),readAccessorAsFloat32:(e,t)=>Ge(e,t),readAccessorAsUint16:(e,t)=>sr(e,t),readIndicesAsUint32:(e,t)=>Kr(e,t)};animation={createClip:e=>new It(e),createPlayer:(e,t)=>new Qr(e,t),createSkin:(e,t,r)=>new Et(e,t,r)};destroy(){this.stop(),this.destroyPerformanceStats(),this.scale.clearCache(),this.compute.destroy(),this.renderer.destroy()}};return _a(_u);})();
|
|
25
|
+
`)},rn=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 xt(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:sl(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:sl(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=lt(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]=Cr(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=ll("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]},wr=(n,e,t,r,i,o)=>{n.push({key:`${e}:${r}`,annotationId:e,annotationKind:t,role:r,anchor:ye(i),color:At(o)})},ul=n=>{let e=[];for(let t=0;t<n.length;t++){let r=n[t];if(r.visible){if(r.kind==="marker"){wr(e,r.id,r.kind,"marker",r.anchor,r.color);continue}if(r.kind==="distance"){wr(e,r.id,r.kind,"start",r.start,r.color),wr(e,r.id,r.kind,"end",r.end,r.color);continue}wr(e,r.id,r.kind,"a",r.a,r.color),wr(e,r.id,r.kind,"b",r.b,r.color),wr(e,r.id,r.kind,"c",r.c,r.color)}}return e},nn=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 Ve({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:At(t.color)}}sync(e,t){if(y(Number.isFinite(t),"AnnotationMarkerRenderer.sync: revision must be finite."),t===this.appliedRevision)return!1;let r=ul(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]},cl=(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),ml=n=>Math.hypot(n[0]??0,n[1]??0,n[2]??0),It=n=>n.kind==="marker"?{...n,color:At(n.color),anchor:ye(n.anchor)}:n.kind==="distance"?{...n,color:At(n.color),start:ye(n.start),end:ye(n.end)}:{...n,color:At(n.color),a:ye(n.a),b:ye(n.b),c:ye(n.c)},Ti=(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)]},Si=n=>{if(n==null)return null;let e=`${n}`.trim();return e.length>0?e:null},Ro=n=>n===void 0?!0:!!n,Go=(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)},Uo=(n,e,t)=>{let r=cl(n,e),i=cl(t,e),o=ml(r),a=ml(i);if(o<=1e-12||a<=1e-12)return 0;let s=se(hd(r,i)/(o*a),-1,1);return Math.acos(s)};var on=class{records=new Map;order=[];listeners=new Set;nowMs;idPrefix;idCounter=1;_revision=0;constructor(e={}){this.nowMs=e.nowMs??tr,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?It(t):null}values(){let e=new Array(this.order.length);for(let t=0;t<this.order.length;t++)e[t]=It(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:Si(t.label),visible:Ro(t.visible),color:Ti(t.color,"marker"),createdAtMs:r,updatedAtMs:r,anchor:ye(e)};return this.push(i),It(i)}createDistance(e,t,r={}){let i=this.nowMs(),o=ye(e),a=ye(t),s={id:this.nextId("distance"),kind:"distance",label:Si(r.label),visible:Ro(r.visible),color:Ti(r.color,"distance"),createdAtMs:i,updatedAtMs:i,start:o,end:a,distanceWorld:Go(o.position,a.position)};return this.push(s),It(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:Si(i.label),visible:Ro(i.visible),color:Ti(i.color,"angle"),createdAtMs:o,updatedAtMs:o,a,b:s,c:l,angleRadians:Uo(a.position,s.position,l.position)};return this.push(u),It(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(),It(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=Go(r.start.position,r.end.position),r.updatedAtMs=this.nowMs(),this.bumpRevision(),It(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=Uo(r.a.position,r.b.position,r.c.position),r.updatedAtMs=this.nowMs(),this.bumpRevision(),It(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=Si(t.label)),t.color!==void 0&&(e.color=Ti(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],wi=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,Ci=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:wi(n.attributes)}:{hit:!1,kind:null,objectId:null,elementIndex:null,worldPosition:null,ndIndex:null,attributes:null},Ao=(n,e)=>({...Ci(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:wi(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:en(i.color),position:[i.anchor.position[0],i.anchor.position[1],i.anchor.position[2]]});continue}if(i.kind==="distance"){let s=ko(i.distanceWorld,e),l=i.label?`${i.label}: ${s.text}`:s.text;t.push({key:i.id,text:l,color:en(i.color),position:bd(i.start.position,i.end.position)});continue}let o=Mo(i.angleRadians,e),a=i.label?`${i.label}: ${o.text}`:o.text;t.push({key:i.id,text:a,color:en(i.color),position:[i.b.position[0],i.b.position[1],i.b.position[2]]})}return t},an=class{store;markerRenderer;labelLayer;runtime;annotationsListeners=new Set;modeListeners=new Set;hoverListeners=new Set;selectionListeners=new Set;stagingListeners=new Set;autoCreateOverlay;overlaySystemOptions;modeValue=Ut.Idle;unitsValue;scene=null;camera=null;controls=null;overlaySystem=null;ownsOverlaySystem=!1;canvas=null;pointerTarget=null;hoverReadout=Ci(null);selectionReadout=Ao(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 on({idPrefix:t.storeIdPrefix??`ann${r}`}),this.markerRenderer=new nn({...t.markerRenderer,name:t.markerRenderer?.name??`annotation-markers-${r}`}),this.labelLayer=new rn({...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 tn(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:wi(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:wi(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=Ut.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(Ci(null)),this.setSelectionReadout(Ao(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=Ci(e);return this.setHoverReadout(t),t}ingestSelectionHit(e){let t=this.resolveSelectionMeta(e);if(this.setSelectionReadout(Ao(e,t)),!e)return this.modeValue===Ut.Idle&&this.clearPending(),null;if(this.modeValue===Ut.Marker)return this.store.createMarker(Jr(e));if(this.modeValue===Ut.Distance){if(this.pendingAnchors.push(Jr(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===Ut.Angle){if(this.pendingAnchors.push(Jr(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)}};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},Bi=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},dl=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,fl=(n,e,t=0,r)=>{let i=_e(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}},_i=(n,e,t)=>{let i=_e(n).ctor,o=fe.buffer();return new i(o,e>>>0,t>>>0)},Sd=(n,e)=>{let t=fe.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"),Bi(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]},Fo=(n,e)=>{if(xd(n)){let s=n.getBuffer(),l=Fo(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=dl(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=Bi(c),d=(n.offset??0)>>>0,f=fl(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=dl(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=Bi(i);y(n.byteLength>>>0>=o*_e(r).bytesPerElement,"source TypedArray is too small for the provided shape");let a=fl(r,n,0,o);return y(a.length>>>0===o>>>0,"source TypedArray length mismatch"),{dtype:r,shape:i,data:a}},Io={sendNdarray:(n,e={})=>{let t=Fo(n,e),{dtype:r,shape:i,data:o}=t,a=_e(r),s=Bi(i),l=s*a.bytesPerElement>>>0,u=Td(l,16,e.allocator);_i(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=>_i(n.dtype,n.ptr,n.length),bytes:n=>Sd(n.ptr,n.byteLength),copyInto:(n,e,t={})=>{let r=Fo(e,{...t,dtype:n.dtype,shape:n.shape}),{data:i}=r;y(i.length>>>0===n.length>>>0,"copyInto: source length mismatch"),_i(n.dtype,n.ptr,n.length).set(i);try{r.release?.()}catch{}},receiveNdarray:(n,e={})=>{let t=_i(n.dtype,n.ptr,n.length);if(!e.copy)return{dtype:n.dtype,shape:Array.from(n.shape),data:t};let i=_e(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 ee=1e-6,pl=.001,hl=.35,je=(n,e,t)=>Math.max(e,Math.min(t,n)),ki=n=>je(n,0,1),ut=(n,e,t)=>n+(e-n)*t,wd=n=>n<.5?4*n*n*n:1-Math.pow(-2*n+2,3)*.5,he=n=>[n[0]??0,n[1]??0,n[2]??0],Ie=(n,e)=>[n[0]+e[0],n[1]+e[1],n[2]+e[2]],Xt=(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],We=(n,e)=>n[0]*e[0]+n[1]*e[1]+n[2]*e[2],Zt=(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]],Yt=n=>Math.hypot(n[0],n[1],n[2]),de=(n,e=[0,0,1])=>{let t=Yt(n);if(t<=ee)return he(e);let r=1/t;return[n[0]*r,n[1]*r,n[2]*r]},Do=(n,e,t)=>[ut(n[0],e[0],t),ut(n[1],e[1],t),ut(n[2],e[2],t)],gl=(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],_d=(n,e,t,r)=>[-n,-e,-t,r],No=(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]},bl=(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)]},Bd=(n,e,t,r)=>Math.abs(n)<ee&&Math.abs(e)<ee&&Math.abs(t)<ee&&Math.abs(1-r)<ee,kd=(n,e,t,r,i)=>{let o=ki(i),a=je(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 No(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]},vl=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??Zt(n.up,n.forward),t=de(e,[1,0,0]),r=de(n.up,[0,1,0]),i=de(Zt(t,r),n.forward),o=de(Zt(r,i),t),a=de(Zt(i,o),r);return{right:o,up:a,forward:i}},Br=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=vl(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?he(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:he(this._axisConvention.right),up:he(this._axisConvention.up),forward:he(this._axisConvention.forward)}}set axisConvention(e){this._axisConvention=vl(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=de(this._trackballEye,this._axisConvention.forward);this._trackballEye=X(r,t)}}get zoom(){return this._zoom}set zoom(e){this._zoom=je(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=he(this.camera.position),t=Xt(e,this.target);if(this._radius=Math.max(ee,Yt(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=de(this.camera.up,this._axisConvention.up),this._trackballRotateStart=[0,0,1],this._trackballRotationDelta=[0,0,0,1]}saveState(){this._savedTarget=he(this.target),this._savedPosition=he(this.camera.position),this._savedUp=de(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=he(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?de(t.up,this._axisConvention.up):this.getInspectionViewUp(e),o=t.target?he(t.target):he(this.target),a=Math.max(ee,t.distance??this._radius),s=Ie(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=ki(t.elapsed/Math.max(ee,t.duration)),i=wd(r),o=Do(t.fromPosition,t.toPosition,i),a=Do(t.fromTarget,t.toTarget,i),s=de(Do(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=No(...gl(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:ut(e.left,t.left,r),right:ut(e.right,t.right,r),top:ut(e.top,t.top,r),bottom:ut(e.bottom,t.bottom,r),near:ut(e.near,t.near,r),far:ut(e.far,t.far,r)}:{type:"perspective",near:ut(e.near,t.near,r),far:ut(e.far,t.far,r)}}applyPose(e,t,r){this.target=he(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??hl)<=0){this.cancelTransition(),this.applyPose(e,t,r),this.applyProjectionState(i),this.syncFromCamera(),this.emitChange();return}this._transition={elapsed:0,duration:a??hl,fromPosition:he(this.camera.position),toPosition:he(e),fromTarget:he(this.target),toTarget:he(t),fromUp:de(this.camera.up,this._axisConvention.up),toUp:de(r,this._axisConvention.up),fromProjection:this.captureProjectionState(),toProjection:i}}updateOrbit(e){let t=this.enableDamping?1-Math.pow(1-ki(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,pl),i=Math.min(this.maxPolarAngle,Math.PI-pl);r<=i?this._phi=je(this._phi,r,i):this._phi=je(this._phi,this.minPolarAngle,this.maxPolarAngle),this._theta=je(this._theta,this.minAzimuthAngle,this.maxAzimuthAngle),this.applyDolly(t,this.computeOrbitBasis()),this.applyPan(t),this._radius=je(this._radius,this.minDistance,this.maxDistance);let o=this.sphericalToOffset(this._theta,this._phi,Math.max(ee,this._radius)),a=Ie(this.target,o),s=de(Xt(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-ki(this.dampingFactor),e*60):1;if(this.enableRotate){let o=this._trackballRotationDelta;if(!Bd(o[0],o[1],o[2],o[3])){let a=kd(o[0],o[1],o[2],o[3],t);this._trackballEye=bl(this._trackballEye[0],this._trackballEye[1],this._trackballEye[2],a[0],a[1],a[2],a[3]),this._trackballUp=de(bl(this._trackballUp[0],this._trackballUp[1],this._trackballUp[2],a[0],a[1],a[2],a[3]),this._axisConvention.up);let s=gl(o[0],o[1],o[2],o[3],..._d(a[0],a[1],a[2],a[3]));this._trackballRotationDelta=No(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=Yt(this._trackballEye);this._radius=je(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=Ie(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=je(this._zoom*Math.exp(-r),this.minZoom,this.maxZoom);else{let a=je(this._radius*Math.exp(r),this.minDistance,this.maxDistance);if(this._mode==="trackball"){let s=Math.max(ee,Yt(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=Ie(this._panOffset,Ie(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=Ie(this.target,Ie(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=Ie(this.target,Ie(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=je(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=We(e,this._axisConvention.right),r=We(e,this._axisConvention.up),i=We(e,this._axisConvention.forward),o=Math.max(ee,Math.hypot(t,r,i));return{theta:Math.atan2(t,i),phi:Math.acos(je(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 Ie(Ie(X(this._axisConvention.right,o),X(this._axisConvention.up,a)),X(this._axisConvention.forward,s))}computeLookBasis(e,t){let r=de(e,X(this._axisConvention.forward,-1)),i=de(t,this._axisConvention.up);Math.abs(We(r,i))>.999&&(i=Math.abs(r[1])<.9?[0,1,0]:[1,0,0]);let o=de(Zt(r,i),this._axisConvention.right),a=de(Zt(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=de(X(e,-1),X(this._axisConvention.forward,-1));return this.computeLookBasis(t,this.getOrbitUp(t))}computeTrackballBasis(){let e=de(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=Xt(t,X(e,We(t,e))),i=Yt(r);if(i>ee)return X(r,1/i);let o=this._axisConvention.forward;return r=Xt(o,X(e,We(o,e))),i=Yt(r),i>ee?X(r,1/i):he(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=je(We(e,t),-1,1),i=Math.acos(r);if(i<=ee)return null;i*=this.rotateSpeed;let o=Zt(e,t),a=Yt(o);if(a<=ee)return null;o=X(o,1/a);let s=this.computeTrackballBasis(),l=de(Ie(Ie(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 Zo(e)}getInspectionViewDirection(e){switch(e){case"front":return he(this._axisConvention.forward);case"back":return X(this._axisConvention.forward,-1);case"right":return he(this._axisConvention.right);case"left":return X(this._axisConvention.right,-1);case"top":return he(this._axisConvention.up);case"bottom":return X(this._axisConvention.up,-1)}}getInspectionViewUp(e){return e==="top"?X(this._axisConvention.forward,-1):he(e==="bottom"?this._axisConvention.forward:this._axisConvention.up)}getCurrentViewOrientation(){let e=he(this.camera.position),t=de(Xt(e,this.target),this._axisConvention.forward);return{direction:t,up:de(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?de(t.up,this._axisConvention.up):this.getInspectionViewUp(t.view)}:{direction:t.eyeDirection?de(t.eyeDirection,this._axisConvention.forward):this.getCurrentViewOrientation().direction,up:t.up?de(t.up,this._axisConvention.up):this.getCurrentViewOrientation().up},a=t.boundsMode==="sphere"?Ct(e.sphereCenter,e.sphereRadius*r,e.partial):Jo(e,r),s=this.computeLookBasis(X(o.direction,-1),o.up),l=t.boundsMode==="sphere"?he(e.sphereCenter):to(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=ro(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=Xt(M,i),S=We(B,r.right),R=We(B,r.up),U=We(B,r.forward);d.push(U),m=Math.max(m,Math.abs(S)/Math.max(c,ee)-U,Math.abs(R)/Math.max(u,ee)-U)}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:Ie(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=ro(e),l=0,u=0,c=1/0,m=-1/0;for(let x of s){let T=Xt(x,i),w=We(T,r.right),M=We(T,r.up),B=We(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:Ie(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}}}},Mi=class extends Br{constructor(e,t,r={}){super(e,t,{...r,mode:"orbit"})}},Li=class extends Br{constructor(e,t,r={}){super(e,t,{...r,mode:"trackball"})}};var sn=(n,e)=>`${n}:${e}`,zo=n=>n?Array.isArray(n)?n:[n]:[],yl=n=>({...n,key:sn(n.objectId,n.elementIndex)}),ln=class{entries=new Map;get size(){return this.entries.size}has(e,t){return this.entries.has(sn(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 zo(e))this.entries.set(sn(t.objectId,t.elementIndex),yl(t));return this}remove(e){for(let t of zo(e))this.entries.delete(sn(t.objectId,t.elementIndex));return this}toggle(e){for(let t of zo(e)){let r=sn(t.objectId,t.elementIndex);this.entries.has(r)?this.entries.delete(r):this.entries.set(r,yl(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 Ri=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 ai(r.device,r.queue,t),this.scale=new Dr(this.compute)}static async create(e,t={}){await Di();let r=await ei.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 fe}get driver(){return fe}static get webassembly(){return xn}get webassembly(){return xn}static get python(){return Io}get python(){return Io}static get math(){return{mat4:ft,quat:fn,vec3:nt}}get math(){return{mat4:ft,quat:fn,vec3:nt}}static createHeapArena(e,t=16){return fe.createHeapArena(e,t)}createHeapArena(e,t=16){return fe.createHeapArena(e,t)}static get frameArena(){return W}get frameArena(){return W}static createSelectionStore(){return new ln}createSelectionStore(){return new ln}createPerformanceStats(e={}){this._performanceStats?.destroy(),this.renderer.enableGpuTiming(e.showGpuTime??!0);let t=new ti({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 Je({background:e})}createCamera={perspective:e=>new qt(e),orthographic:e=>new Kt(e)};createControls={navigation:(e,t,r)=>new Br(e,t,r),orbit:(e,t,r)=>new Mi(e,t,r),trackball:(e,t,r)=>new Li(e,t,r)};createOverlay={system:(e={})=>new Xr({canvas:this.renderer.canvas,...e}),axisTriad:(e={})=>new Yr(e),grid:(e={})=>new Zr(e),legend:e=>new Qr(e)};createAnnotation={toolkit:(e={})=>new an({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 Ze(e),custom:e=>new pr(e)};texture={create2D:e=>Pr.createFrom(e)};createTransform(){return new Be}createMesh(e,t){return new ot(e,t)}createPointCloud(e){return new st(e)}createGlyphField(e){return new Ve(e)}createNodeLink(e){return new Ee(e)}colormap={builtin:e=>q.builtin(e),grayscale:()=>q.builtin("grayscale"),turbo:()=>q.builtin("turbo"),viridis:()=>q.builtin("viridis"),magma:()=>q.builtin("magma"),plasma:()=>q.builtin("plasma"),inferno:()=>q.builtin("inferno"),fromStops:(e,t={})=>q.fromStops(e,t),fromPalette:(e,t={})=>q.fromPalette(e,t)};createLight={ambient:e=>new Nn(e),directional:e=>new wt(e),point:e=>new _t(e),spot:e=>new vt(e)};gltf={load:async(e,t)=>yo(e,t),import:async(e,t)=>_o(e,t),loadAndImport:async(e,t={})=>{let r=await yo(e,t.load);return _o(r,t.import)},parseGLB:e=>$r(e),readAccessor:(e,t)=>$t(e,t),readAccessorAsFloat32:(e,t)=>Fe(e,t),readAccessorAsUint16:(e,t)=>qr(e,t),readIndicesAsUint32:(e,t)=>si(e,t)};animation={createClip:e=>new Tr(e),createPlayer:(e,t)=>new ci(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()}};return Ll(Md);})();
|
|
16
26
|
|
|
17
27
|
(() => {
|
|
18
28
|
const g = globalThis;
|