three-environment-shadows 1.0.1 → 2.1.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/README.md CHANGED
@@ -1,14 +1,20 @@
1
+ <a href="https://github.com/mjurczyk/three-environment-shadows" target="_blank">
2
+ <img width="100%" src="https://github.com/user-attachments/assets/0e4dec8a-fcde-4fbb-9d53-1f7ffd9d6d5c" title="Three Environment Shadows" />
3
+ </a>
4
+
1
5
  # three-environment-shadows
2
6
 
3
7
  Use environment as a source of light and _shadows_ in your Three.js scene.
4
8
  Extracts light sources from environment map automatically - no need for any more of the manually set PointLights and SunLights 🤲
5
9
 
10
+ ## Example
11
+
6
12
  ```js
13
+ // NOTE WebGLRenderer
14
+
7
15
  import * as Three from 'three';
8
16
  import { UltraHDRLoader } from 'three/addons/loaders/UltraHDRLoader.js';
9
- import { EnvironmentShadowLights } from 'three-environment-shadows';
10
-
11
- renderer.shadowMap.enabled = true;
17
+ import { EnvironmentShadows } from 'three-environment-shadows';
12
18
 
13
19
  const hdri = await new UltraHDRLoader().loadAsync('./environment.jpg');
14
20
  hdri.mapping = Three.EquirectangularReflectionMapping;
@@ -16,9 +22,69 @@ hdri.mapping = Three.EquirectangularReflectionMapping;
16
22
  scene.background = hdri;
17
23
  scene.environment = hdri;
18
24
 
19
- const shadows = new EnvironmentShadowLights(scene);
20
- shadows.bounds.set(new Three.Vector3(0, 1, 0), 6);
25
+ mesh.castShadow = true;
26
+ mesh.receiveShadow = true;
27
+
28
+ const shadows = new EnvironmentShadows(renderer, scene, {
29
+ bounds: new Three.Sphere(new Three.Vector3(0, 1, 0), 6),
30
+ });
31
+ await shadows.ready;
32
+
33
+ renderer.setAnimationLoop(() => {
34
+ shadows.update(camera);
35
+ renderer.render(scene, camera);
36
+ });
37
+ ```
38
+
39
+
40
+ ```js
41
+ // NOTE WebGPURenderer
42
+
43
+ import * as Three from 'three/webgpu';
44
+ import { UltraHDRLoader } from 'three/addons/loaders/UltraHDRLoader.js';
45
+ import { EnvironmentShadows } from 'three-environment-shadows/webgpu';
21
46
 
47
+ await renderer.init();
48
+
49
+ const hdri = await new UltraHDRLoader().loadAsync('./environment.jpg');
50
+ hdri.mapping = Three.EquirectangularReflectionMapping;
51
+
52
+ scene.background = hdri;
53
+ scene.environment = hdri;
54
+
55
+ mesh.material = new Three.MeshStandardNodeMaterial();
22
56
  mesh.castShadow = true;
23
57
  mesh.receiveShadow = true;
58
+
59
+ const shadows = new EnvironmentShadows(renderer, scene, {
60
+ bounds: new Three.Sphere(new Three.Vector3(0, 1, 0), 6),
61
+ });
62
+ await shadows.ready;
63
+
64
+ renderer.setAnimationLoop(() => {
65
+ shadows.update(camera);
66
+ renderer.render(scene, camera);
67
+ });
24
68
  ```
69
+
70
+ ### Support
71
+
72
+ * `Three.WebGLRenderer` (GLSL) r162+
73
+ * `Three.WebGPURenderer` (TSL) r172+
74
+
75
+ ### Props
76
+
77
+ | Option | Default | |
78
+ |---|---|---|
79
+ | `samplesPerFrame` | `24` | Shadow maps rendered per frame while a bake runs |
80
+ | `samplesPerBake` | `512` | Samples per bake, more is smoother and slower to update |
81
+ | `fadeTime` | `0.3` | Crossfade time (seconds) from the old to the new lightmap |
82
+ | `mapSize` | `512` | Shadow map size of each sample |
83
+ | `atlasSize` | `1024` | Lightmap atlas size (texels) |
84
+ | `shadowNoise` | `8` | Random offset of the shadow lookups (shadow map texels), softens stair-stepped edges |
85
+ | `directionJitter` | `2` | Random tilt of the sample directions (degrees), blends the shadows of neighboring samples |
86
+ | `specularOcclusion` | `true` | The baked visibility also darkens environment reflections |
87
+ | `frustumAtlas` | `true` | Only meshes in the camera frustum get a place in the atlas |
88
+ | `frustumMargin` | `20` | Growth of the bounding spheres for the frustum test (percent) |
89
+ | `bounds` | mesh bounds | `Sphere`, the area that receives shadows |
90
+ | `meshes` | scene meshes | Meshes to use, default: all meshes that cast or receive shadows |
package/index.d.ts CHANGED
@@ -1,140 +1,69 @@
1
- import {
2
- Color,
3
- DataTexture,
4
- DirectionalLight,
5
- Group,
6
- Object3D,
7
- Object3DEventMap,
8
- Scene,
9
- Sphere,
10
- Texture,
11
- Vector3,
12
- } from 'three';
1
+ import type { Camera, Mesh, Scene, Sphere, WebGLRenderer } from 'three';
13
2
 
14
3
  /**
15
- * One part of an extracted light.
4
+ * Options of {@link EnvironmentShadows}, see the properties of the same name.
16
5
  */
17
- export interface LightPart {
18
- /** Unit vector from the scene towards the part, in the space of the environment map. */
19
- direction: Vector3;
20
- /** The color, normalized so its largest component is `1`. */
21
- color: Color;
22
- /** The irradiance, usable as `DirectionalLight.intensity`. */
23
- intensity: number;
24
- /** Half-angle (in radians) of the cone the part emits from. */
25
- coneAngle: number;
26
- }
27
-
28
- /**
29
- * A light source that was found in an environment map.
30
- */
31
- export interface ExtractedLight extends LightPart {
32
- /** Fraction of the total environment energy emitted by this light. */
33
- energyFraction: number;
34
- /**
35
- * `partitions[ n - 1 ]` divides the light into `n` parts (median cut). The energies of the
36
- * parts add up to the energy of the light. `partitions[ 0 ]` holds the light as one part.
37
- */
38
- partitions: LightPart[][];
39
- }
40
-
41
- export interface ExtractionResult {
42
- /** The extracted lights, strongest first. */
43
- lights: ExtractedLight[];
44
- /** `0` if the environment emits equally in all directions, `1` if all light comes from one direction. */
45
- directionality: number;
46
- /** Fraction of the total environment energy emitted by the extracted lights. */
47
- dominance: number;
48
- /** The radiance (luminance) above which texels are part of a light. */
49
- threshold: number;
50
- /** A copy of the environment map without the extracted lights, or `null`. */
51
- texture: DataTexture | null;
52
- }
53
-
54
- export interface ExtractOptions {
55
- /** The maximum number of lights. Default `2`. */
56
- maxLights?: number;
57
- /** Texels brighter than this factor times the mean radiance are part of a light. Default `8`. */
58
- threshold?: number;
59
- /** The minimum fraction of the total energy a light must emit. Default `0.05`. */
60
- minEnergy?: number;
61
- /** The minimum elevation (in radians) of a light, in the space of the environment map. Default `-Math.PI / 2`. */
62
- minElevation?: number;
63
- /** The maximum number of parts per light, see `ExtractedLight.partitions`. Default `4`. */
64
- samples?: number;
65
- /** The width of the grid used to group bright texels into regions. Default `512`. */
66
- resolution?: number;
67
- /** Whether to create a copy of the environment map without the lights. Default `true`. */
68
- removeLights?: boolean;
69
- }
70
-
71
- /**
72
- * Finds the dominant light sources of an equirectangular environment map.
73
- */
74
- export class EnvironmentLightExtractor {
75
- static extract(texture: Texture, options?: ExtractOptions): Promise<ExtractionResult>;
76
- }
77
-
78
- export interface EnvironmentShadowLightsOptions {
79
- /** The maximum number of lights. Default `2`. */
80
- maxLights?: number;
81
- /** Texels brighter than this factor times the mean radiance are part of a light. Default `8`. */
82
- threshold?: number;
83
- /** The minimum fraction of the total energy a light must emit. Default `0.05`. */
84
- minEnergy?: number;
85
- /** The minimum elevation (in radians) of a light, in the space of the environment map. Default `-Math.PI / 2`. */
86
- minElevation?: number;
87
- /** The width of the grid used to group bright texels into regions. Default `512`. */
88
- resolution?: number;
89
- /** The maximum number of shadow casting lights per light source. Default `4`. */
90
- samples?: number;
91
- /** The maximum number of shadow maps of all light sources. Default `4`. */
92
- maxShadowMaps?: number;
93
- /** The shadow map size of each light. Default `1024`. */
6
+ export interface EnvironmentShadowsOptions {
7
+ /** Shadow maps rendered per frame while a bake runs. Default 24. */
8
+ samplesPerFrame?: number;
9
+ /** Samples (shadow maps) per bake. More is smoother and slower to update. Default 512. */
10
+ samplesPerBake?: number;
11
+ /** Crossfade time in seconds from the old to the new lightmap. Default 0.3. */
12
+ fadeTime?: number;
13
+ /** Width and height of the lightmap atlas in texels. Default 1024. */
14
+ atlasSize?: number;
15
+ /** Width and height of the shadow map of each sample. Default 512. */
94
16
  mapSize?: number;
95
- /** The typical distance between shadow casters and receivers, relative to the bounds radius. Default `0.1`. */
96
- relativeOccluderDistance?: number;
97
- }
98
-
99
- export interface EnvironmentShadowLightsEventMap extends Object3DEventMap {
100
- /** The light sources changed, see `EnvironmentShadowLights.result`. */
101
- change: {};
17
+ /** Random offset of each shadow lookup, in shadow map texels. Softens stair-stepped edges. Default 8. */
18
+ shadowNoise?: number;
19
+ /** Random tilt of each sample direction, in degrees. Blends the shadows of neighboring samples. Default 2. */
20
+ directionJitter?: number;
21
+ /** Whether the baked visibility also darkens environment reflections. Default true. */
22
+ specularOcclusion?: boolean;
23
+ /** Whether only the meshes in the camera frustum get a place in the atlas. Default true. */
24
+ frustumAtlas?: boolean;
25
+ /** Growth of the bounding spheres for the frustum test, in percent. Default 20. */
26
+ frustumMargin?: number;
27
+ /** The area that receives shadows. Default: the bounds of the meshes. */
28
+ bounds?: Sphere;
29
+ /** The meshes. Default: all meshes of the scene that cast or receive shadows. */
30
+ meshes?: Mesh[];
31
+ /** URL of xatlas-web.wasm. Default: next to the bundle. */
32
+ xatlasWasmUrl?: string;
102
33
  }
103
34
 
104
35
  /**
105
- * Casts shadows from the light sources of `scene.environment`.
36
+ * Soft, colored shadows from the whole environment map (`scene.environment`), for WebGLRenderer.
37
+ * For WebGPURenderer, import it from `three-environment-shadows/webgpu`.
106
38
  */
107
- export class EnvironmentShadowLights extends Group<EnvironmentShadowLightsEventMap> {
108
- /** Constructs the group and adds it to the scene. */
109
- constructor(scene?: Scene | null, options?: EnvironmentShadowLightsOptions);
39
+ export class EnvironmentShadows {
40
+ constructor(renderer: WebGLRenderer, scene: Scene, options?: EnvironmentShadowsOptions);
110
41
 
111
- readonly isEnvironmentShadowLights: true;
42
+ readonly isEnvironmentShadows: true;
43
+ readonly renderer: WebGLRenderer;
44
+ readonly scene: Scene;
112
45
 
113
- maxLights: number;
114
- threshold: number;
115
- minEnergy: number;
116
- minElevation: number;
117
- resolution: number;
118
- samples: number;
119
- maxShadowMaps: number;
46
+ samplesPerFrame: number;
47
+ samplesPerBake: number;
48
+ fadeTime: number;
49
+ atlasSize: number;
120
50
  mapSize: number;
121
- relativeOccluderDistance: number;
122
-
123
- /** Set to `true` to find the light sources again, e.g. after a change of the options. */
51
+ shadowNoise: number;
52
+ directionJitter: number;
53
+ specularOcclusion: boolean;
54
+ frustumAtlas: boolean;
55
+ frustumMargin: number;
56
+ /** The area that receives shadows, set when {@link ready} resolves if not given. */
57
+ bounds: Sphere | null;
58
+ /** Set to `true` to start a new bake, e.g. after a change of the options. */
124
59
  needsUpdate: boolean;
125
60
 
126
- /** The area that receives shadows, in world space. */
127
- bounds: Sphere;
128
-
129
- /** The light sources of the environment map, or `null` before they are found. */
130
- readonly result: Omit<ExtractionResult, 'texture'> | null;
131
-
132
- /** The target of all lights, at the center of the bounds. */
133
- readonly target: Object3D;
61
+ /** Resolves when the meshes are unwrapped and the shadows are ready to bake. */
62
+ readonly ready: Promise<this>;
134
63
 
135
- /** The lights. The shadow casting lights come first. */
136
- readonly lights: DirectionalLight[];
64
+ /** Bakes a few samples and swaps in finished lightmaps. Call it once per frame before rendering. */
65
+ update(camera: Camera): void;
137
66
 
138
- /** Puts the original environment map back, frees the GPU-related resources and removes the group. */
67
+ /** Removes the patches from the materials and frees the GPU resources. */
139
68
  dispose(): void;
140
69
  }
package/index.js CHANGED
@@ -1,7 +1,8 @@
1
- import { Color, RGBAFormat, RGBFormat, FloatType, HalfFloatType, UnsignedByteType, SRGBColorSpace, LinearSRGBColorSpace, NoColorSpace, DataUtils, DataTexture, Vector3, Group, Sphere, Object3D, DirectionalLight } from 'three';
1
+ import { E as EnvironmentShadowsBase } from './shared.js';
2
+ import { BufferGeometry, Float32BufferAttribute, Mesh, OrthographicCamera, FloatType, HalfFloatType, MeshLambertMaterial, DoubleSide, BackSide, CustomBlending, AddEquation, OneFactor, ShaderChunk, Vector3, ShaderMaterial } from 'three';
2
3
 
3
- const _color=new Color,_rgb={r:0,g:0,b:0};class EnvironmentLightExtractor{static async extract(t,e={}){const{maxLights:n=2,threshold:o=8,minEnergy:r=.05,minElevation:a=-Math.PI/2,samples:i=4,resolution:l=512,removeLights:c=!0}=e,s=readSource(t),h=await runAnalysis({data:s.data,width:s.width,height:s.height,channels:s.channels,encoding:s.encoding,decode:s.decode,flipY:t.flipY,maxLights:n,thresholdFactor:o,minEnergy:r,minElevation:a,maxParts:i,resolution:l});h.clipped&&console.warn("THREE.EnvironmentLightExtractor: Light texels are clipped in the 8-bit texture. Light intensities are too low.");const f=t=>({direction:(new Vector3).fromArray(t.direction),color:(new Color).fromArray(t.color),intensity:t.intensity,coneAngle:t.coneAngle}),p=h.lights.map(t=>{const e=t.partitions.map(t=>t.map(f));return {...f(t),energyFraction:t.energyFraction,partitions:e}});let g=null;return c&&(g=s.createTexture(h.data),removeSelectedLights(s,g.image.data,h)),{lights:p,directionality:h.directionality,dominance:h.dominance,threshold:h.threshold,texture:g}}}function runAnalysis(t){if("undefined"==typeof Worker)return Promise.resolve(analyze(t));const e=`const analyze = ${analyze.toString()};\n\n self.onmessage = (event) => {\n const output = analyze(event.data);\n self.postMessage(output, [output.data.buffer, output.cellSelected.buffer]);\n };`,n=URL.createObjectURL(new Blob([e],{type:"application/javascript"}));return new Promise((e,o)=>{const r=new Worker(n),a=()=>{r.terminate(),URL.revokeObjectURL(n);};r.onmessage=t=>{a(),e(t.data);},r.onerror=t=>{a(),o(new Error("THREE.EnvironmentLightExtractor: "+t.message));},r.postMessage(t,[t.data.buffer]);})}function analyze(t){const{data:e,width:n,height:o,channels:r,flipY:a,maxLights:i,thresholdFactor:l,minEnergy:c,minElevation:s,maxParts:h,resolution:f}=t;let p=t.decode;if("half"===t.encoding){p=new Float32Array(65536);for(let t=0;t<65536;t++){const e=t>>10&31,n=1023&t;let o;o=0===e?n*Math.pow(2,-24):31===e?0===n?1/0:NaN:(1+n/1024)*Math.pow(2,e-15),p[t]=32768&t?-o:o;}}const g="byte"===t.encoding,d=[0,0,0];function u(t,o){const a=(o*n+t)*r;return null===p?(d[0]=e[a],d[1]=e[a+1],d[2]=e[a+2]):(d[0]=p[e[a]],d[1]=p[e[a+1]],d[2]=p[e[a+2]]),.2126*d[0]+.7152*d[1]+.0722*d[2]}const m=new Float64Array(n),y=new Float64Array(n);for(let t=0;t<n;t++){const e=2*((t+.5)/n-.5)*Math.PI;m[t]=Math.sin(e),y[t]=Math.cos(e);}const M=new Float64Array(o),w=new Float64Array(o),x=new Float64Array(o);for(let t=0;t<o;t++){const e=a?1-t/o:t/o,r=a?1-(t+1)/o:(t+1)/o,i=((e+r)/2-.5)*Math.PI;M[t]=Math.sin(i),w[t]=Math.cos(i),x[t]=2*Math.PI/n*Math.abs(Math.sin((r-.5)*Math.PI)-Math.sin((e-.5)*Math.PI));}const E=Math.max(1,Math.min(n,f)),F=Math.max(1,Math.round(E*o/n)),b=E*F,T=new Int32Array(n),S=new Int32Array(o);for(let t=0;t<n;t++)T[t]=Math.floor(t*E/n);for(let t=0;t<o;t++)S[t]=Math.floor(t*F/o);const R={data:e,directionality:0,dominance:0,threshold:0,gridWidth:E,gridHeight:F,cellSelected:new Uint8Array(b),lights:[],clipped:!1},A=new Float32Array(b);let L=0,v=0,B=0,H=0;for(let t=0;t<o;t++){const e=x[t],o=S[t]*E;for(let r=0;r<n;r++){const n=u(r,t);if(!(n>0&&n<1/0))continue;const a=n*e;L+=a,v+=a*w[t]*y[r],B+=a*M[t],H+=a*w[t]*m[r];const i=o+T[r];n>A[i]&&(A[i]=n);}}if(0===L)return R;R.directionality=Math.hypot(v,B,H)/L;const U=l*L/(4*Math.PI);R.threshold=U;const G=new Int32Array(b).fill(-1),C=[],I=[],_=Math.floor(E/2);for(let t=0;t<b;t++){if(G[t]>=0||A[t]<=U)continue;const e=[];for(G[t]=C.length,I.push(t);I.length>0;){const t=I.pop(),n=t%E,o=(t-n)/E;e.push(t);for(let t=-1;t<=1;t++)for(let e=-1;e<=1;e++){if(0===e&&0===t)continue;let r=n+e,a=o+t;(a<0||a>=F)&&(a=a<0?0:F-1,r+=_),r=(r%E+E)%E;const i=a*E+r;G[i]>=0||A[i]<=U||(G[i]=C.length,I.push(i));}}C.push(e);}const D=new Int32Array(b).fill(-1);let P=0;for(const t of C)for(const e of t)D[e]=P++;const z=new Float64Array(7*P),k=new Uint8Array(P);for(let t=0;t<o;t++){const o=x[t],a=S[t]*E;for(let i=0;i<n;i++){const l=D[a+T[i]];if(l<0)continue;const c=u(i,t);if(!(c>U&&c<1/0))continue;const s=1-U/c,h=c*s*o,f=7*l;if(z[f]+=d[0]*s*o,z[f+1]+=d[1]*s*o,z[f+2]+=d[2]*s*o,z[f+3]+=h,z[f+4]+=h*w[t]*y[i],z[f+5]+=h*M[t],z[f+6]+=h*w[t]*m[i],g){const o=(t*n+i)*r;255!==e[o]&&255!==e[o+1]&&255!==e[o+2]||(k[l]=1);}}}function j(t){const e={r:0,g:0,b:0,energy:0,x:0,y:0,z:0};for(const n of t){const t=7*D[n];e.r+=z[t],e.g+=z[t+1],e.b+=z[t+2],e.energy+=z[t+3],e.x+=z[t+4],e.y+=z[t+5],e.z+=z[t+6];}return e}function O(t,e){const{r:n,g:o,b:r,energy:a,x:i,y:l,z:c}=j(t),s=Math.hypot(i,l,c),h=Math.max(n,o,r),f=s/a;return {direction:s>0?[i/s,l/s,c/s]:e,color:[n/h,o/h,r/h],intensity:h,coneAngle:Math.acos(Math.min(1,Math.max(-1,2*f-1)))}}function Y(t){const{x:e,y:n,z:o}=j(t),r=Math.hypot(e,n,o),a=[e/r,n/r,o/r],i=Math.abs(a[1])<.99?[0,1,0]:[1,0,0],l=[i[1]*a[2]-i[2]*a[1],i[2]*a[0]-i[0]*a[2],i[0]*a[1]-i[1]*a[0]],c=Math.hypot(l[0],l[1],l[2]);l[0]/=c,l[1]/=c,l[2]/=c;const s=[a[1]*l[2]-a[2]*l[1],a[2]*l[0]-a[0]*l[2],a[0]*l[1]-a[1]*l[0]],h=[];let f=0,p=0,g=0;for(const e of t){const t=7*D[e],n=z[t+3],o=Math.hypot(z[t+4],z[t+5],z[t+6]),r=z[t+4]/o,a=z[t+5]/o,i=z[t+6]/o,c=r*l[0]+a*l[1]+i*l[2],d=r*s[0]+a*s[1]+i*s[2];h.push({cell:e,e:n,px:c,py:d}),f+=n,p+=n*c,g+=n*d;}p/=f,g/=f;let d=0,u=0,m=0;for(const t of h){const e=t.px-p,n=t.py-g;d+=t.e*e*e,u+=t.e*n*n,m+=t.e*e*n;}const y=.5*Math.atan2(2*m,d-u),M=Math.cos(y),w=Math.sin(y);for(const t of h)t.projection=t.px*M+t.py*w;h.sort((t,e)=>t.projection-e.projection);let x=0,E=0;for(;x<h.length-1&&E+h[x].e<=f/2;)E+=h[x++].e;return x=Math.min(h.length-1,Math.max(1,x)),[h.slice(0,x).map(t=>t.cell),h.slice(x).map(t=>t.cell)]}function N(t,e){const n=[[t]];for(;n.length<h;){const t=n[n.length-1];let e=-1,o=0;for(let n=0;n<t.length;n++){if(t[n].length<2)continue;const{energy:r,x:a,y:i,z:l}=j(t[n]),c=r-Math.hypot(a,i,l);c>o&&(e=n,o=c);}if(e<0)break;const r=t.slice();r.splice(e,1,...Y(t[e])),n.push(r);}return n.map(t=>t.map(t=>O(t,e)))}const W=C.map(t=>j(t).energy),q=C.map((t,e)=>e).sort((t,e)=>W[e]-W[t]),V=Math.sin(s);for(const t of q){if(R.lights.length>=i)break;const e=W[t]/L;if(e<c)break;const n=C[t],o=O(n,[0,1,0]);if(!(o.direction[1]<V)){o.energyFraction=e,o.partitions=N(n,o.direction),R.lights.push(o),R.dominance+=e;for(const t of n)R.cellSelected[t]=1,1===k[D[t]]&&(R.clipped=!0);}}return R}function removeSelectedLights(t,e,n){const{width:o,height:r}=t,{gridWidth:a,gridHeight:i,cellSelected:l,threshold:c}=n,s=t.reader(e),h=t.writer(e);for(let t=0;t<i;t++){const e=Math.ceil(t*r/i),n=Math.ceil((t+1)*r/i);for(let r=0;r<a;r++){if(0===l[t*a+r])continue;const i=Math.ceil(r*o/a),f=Math.ceil((r+1)*o/a);for(let t=e;t<n;t++)for(let e=i;e<f;e++){s(e,t,_rgb);const n=.2126*_rgb.r+.7152*_rgb.g+.0722*_rgb.b;if(!(n>c&&n<1/0))continue;const o=c/n;h(e,t,_rgb.r*o,_rgb.g*o,_rgb.b*o);}}}}function readSource(t){const e=t.image;if(t.isCubeTexture||t.isCompressedTexture||t.isRenderTargetTexture||t.isData3DTexture||t.isDataArrayTexture)throw new Error("THREE.EnvironmentLightExtractor: Only equirectangular data or image textures are supported.");if(null==e)throw new Error("THREE.EnvironmentLightExtractor: The texture has no image data.");let n,o,r,a,i,l;if(void 0!==e.data){if(o=e.width,r=e.height,n=e.data.slice(),i=t.type,l=t.format,l===RGBAFormat)a=4;else {if(l!==RGBFormat)throw new Error("THREE.EnvironmentLightExtractor: Only RGB and RGBA textures are supported.");a=3;}if(i!==FloatType&&i!==HalfFloatType&&i!==UnsignedByteType)throw new Error("THREE.EnvironmentLightExtractor: Only float, half float and unsigned byte textures are supported.")}else o=e.width,r=e.height,n=readImage(e,o,r),a=4,i=UnsignedByteType,l=RGBAFormat;let c=t.colorSpace;c!==SRGBColorSpace&&c!==LinearSRGBColorSpace&&c!==NoColorSpace&&(console.warn("THREE.EnvironmentLightExtractor: Unsupported color space. Texels are read as linear."),c=LinearSRGBColorSpace);const s=c===SRGBColorSpace;let h=null;if(i===UnsignedByteType){h=new Float32Array(256);for(let t=0;t<256;t++)h[t]=s?_color.setRGB(t/255,0,0,SRGBColorSpace).r:t/255;}return {data:n,width:o,height:r,channels:a,encoding:i===FloatType?"float":i===HalfFloatType?"half":"byte",decode:h,reader:function(t){return i===FloatType?(e,n,r)=>{const i=(n*o+e)*a;r.r=t[i],r.g=t[i+1],r.b=t[i+2];}:i===HalfFloatType?(e,n,r)=>{const i=(n*o+e)*a;r.r=DataUtils.fromHalfFloat(t[i]),r.g=DataUtils.fromHalfFloat(t[i+1]),r.b=DataUtils.fromHalfFloat(t[i+2]);}:(e,n,r)=>{const i=(n*o+e)*a;r.r=h[t[i]],r.g=h[t[i+1]],r.b=h[t[i+2]];}},writer:function(t){return i===FloatType?(e,n,r,i,l)=>{const c=(n*o+e)*a;t[c]=r,t[c+1]=i,t[c+2]=l;}:i===HalfFloatType?(e,n,r,i,l)=>{const c=(n*o+e)*a;t[c]=DataUtils.toHalfFloat(r),t[c+1]=DataUtils.toHalfFloat(i),t[c+2]=DataUtils.toHalfFloat(l);}:(e,n,r,i,l)=>{const c=(n*o+e)*a;s&&(_color.setRGB(r,i,l).getRGB(_rgb,SRGBColorSpace),r=_rgb.r,i=_rgb.g,l=_rgb.b),t[c]=Math.round(255*Math.min(1,r)),t[c+1]=Math.round(255*Math.min(1,i)),t[c+2]=Math.round(255*Math.min(1,l));}},createTexture:function(e){const n=new DataTexture(e,o,r,l,i);return n.mapping=t.mapping,n.wrapS=t.wrapS,n.wrapT=t.wrapT,n.magFilter=t.magFilter,n.minFilter=t.minFilter,n.anisotropy=t.anisotropy,n.generateMipmaps=t.generateMipmaps,n.unpackAlignment=t.unpackAlignment,n.colorSpace=t.colorSpace,n.flipY=t.flipY,n.needsUpdate=!0,n}}}function readImage(t,e,n){const o=Math.min(e,4096),r=Math.min(n,4096);let a;"undefined"!=typeof document?(a=document.createElement("canvas"),a.width=o,a.height=r):a=new OffscreenCanvas(o,r);const i=a.getContext("2d",{willReadFrequently:!0}),l=new Uint8Array(e*n*4);for(let a=0;a<n;a+=r)for(let c=0;c<e;c+=o){const s=Math.min(o,e-c),h=Math.min(r,n-a);i.clearRect(0,0,s,h),i.drawImage(t,c,a,s,h,0,0,s,h);const f=i.getImageData(0,0,s,h).data;for(let t=0;t<h;t++)l.set(f.subarray(t*s*4,(t+1)*s*4),4*((a+t)*e+c));}return l}
4
+ const FACE_LINE="float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;",SHADOW_COORD="vDirectionalShadowCoord[ i ]",JITTER_PARS="\n uniform float bakeNoise; // in shadow map texels\n uniform float bakeSeed; // changes every sample\n uniform float bakeMapTexel; // 1 / shadow map size\n\n float bakeHash( vec2 p ) {\n vec3 p3 = fract( vec3( p.xyx ) * 0.1031 );\n p3 += dot( p3, p3.yzx + 33.33 );\n return fract( ( p3.x + p3.y ) * p3.z );\n }\n\n vec4 bakeShadowJitter() {\n vec2 seed = gl_FragCoord.xy + vec2( bakeSeed * 17.31, bakeSeed * 5.79 );\n vec2 offset = vec2( bakeHash( seed ), bakeHash( seed.yx + 11.7 ) ) * 2.0 - 1.0;\n return vec4( offset * bakeNoise * bakeMapTexel, 0.0, 0.0 );\n }\n",FINALIZE_FRAGMENT="\n precision highp float;\n\n uniform sampler2D uSum;\n uniform ivec2 uSize;\n uniform float uScale;\n\n #define DILATE 4\n\n void main() {\n ivec2 pixel = ivec2( gl_FragCoord.xy );\n vec4 sum = texelFetch( uSum, pixel, 0 );\n\n if ( sum.a > 0.0 ) {\n gl_FragColor = vec4( sum.rgb * uScale / sum.a, 1.0 );\n return;\n }\n\n for ( int r = 1; r <= DILATE; r ++ ) {\n for ( int y = - r; y <= r; y ++ ) {\n for ( int x = - r; x <= r; x ++ ) {\n if ( abs( x ) != r && abs( y ) != r ) continue;\n\n vec4 s = texelFetch( uSum, clamp( pixel + ivec2( x, y ), ivec2( 0 ), uSize - 1 ), 0 );\n\n if ( s.a > 0.0 ) {\n gl_FragColor = vec4( s.rgb * uScale / s.a, 1.0 );\n return;\n }\n }\n }\n }\n\n gl_FragColor = vec4( 0.0 );\n }\n",DISPLAY_VERTEX_PARS="\n attribute vec2 lightmapUvA;\n attribute vec2 lightmapUvB;\n varying vec2 vLmA;\n varying vec2 vLmB;\n varying vec2 vLmHas;\n",DISPLAY_VERTEX="\n vLmA = lightmapUvA;\n vLmB = lightmapUvB;\n vLmHas = vec2( step( 1e-6, lightmapUvA.x ), step( 1e-6, lightmapUvB.x ) );\n",DISPLAY_FRAGMENT_PARS="\n varying vec2 vLmA;\n varying vec2 vLmB;\n varying vec2 vLmHas;\n uniform sampler2D lmA;\n uniform sampler2D lmB;\n uniform float lmFrontIsA;\n uniform float lmBlend;\n uniform float lmValid;\n uniform float lmSpecularOcclusion;\n",DISPLAY_FRAGMENT="\n {\n vec3 lmUnoccluded = iblIrradiance;\n\n // NOTE The lightmap is baked at intensity 1. envMapIntensity is material.envMapIntensity or\n // scene.environmentIntensity, the same as for the environment diffuse. The unoccluded light has it already.\n #ifdef USE_ENVMAP\n float lmIntensity = envMapIntensity;\n #else\n float lmIntensity = 1.0;\n #endif\n\n vec3 lmValueA = vLmHas.x > 0.5 ? texture2D( lmA, vLmA ).rgb * lmIntensity : lmUnoccluded;\n vec3 lmValueB = vLmHas.y > 0.5 ? texture2D( lmB, vLmB ).rgb * lmIntensity : lmUnoccluded;\n vec3 lmFront = lmFrontIsA > 0.5 ? lmValueA : lmValueB;\n vec3 lmPrevious = lmFrontIsA > 0.5 ? lmValueB : lmValueA;\n vec3 lmIrradiance = lmValid > 0.5 ? mix( lmPrevious, lmFront, lmBlend ) : lmUnoccluded;\n\n vec3 lmWeights = vec3( 0.2126, 0.7152, 0.0722 );\n float lmVisibility = clamp( dot( lmIrradiance, lmWeights ) / max( 1e-6, dot( lmUnoccluded, lmWeights ) ), 0.0, 1.0 );\n\n iblIrradiance = lmIrradiance;\n radiance *= mix( 1.0, lmVisibility, lmSpecularOcclusion );\n }\n",quadGeometry=new BufferGeometry;quadGeometry.setAttribute("position",new Float32BufferAttribute([-1,3,0,-1,-1,0,3,-1,0],3));const quad=new Mesh(quadGeometry);quad.frustumCulled=!1;const quadCamera=new OrthographicCamera;const glslBackend={getSumType:e=>null!==e.getContext().getExtension("EXT_float_blend")?FloatType:HalfFloatType,createBakeMaterial(){const e={bakeNoise:{value:0},bakeSeed:{value:0},bakeMapTexel:{value:1/512}},n=new MeshLambertMaterial({color:16777215,side:DoubleSide,shadowSide:BackSide,forceSinglePass:!0,blending:CustomBlending,blendEquation:AddEquation,blendSrc:OneFactor,blendDst:OneFactor,blendSrcAlpha:OneFactor,blendDstAlpha:OneFactor,depthTest:!1,depthWrite:!1});return n.onBeforeCompile=n=>{const a=ShaderChunk.normal_fragment_begin,r=ShaderChunk.lights_fragment_begin;if(!a.includes(FACE_LINE)||!r.includes(SHADOW_COORD))throw new Error("EnvironmentShadows: Unsupported three.js shader chunks.");Object.assign(n.uniforms,e),n.vertexShader=n.vertexShader.replace("void main() {","attribute vec2 lightmapUvBake;\nvoid main() {").replace("#include <fog_vertex>","#include <fog_vertex>\ngl_Position = vec4( lightmapUvBake * 2.0 - 1.0, 0.0, 1.0 );"),n.fragmentShader=n.fragmentShader.replace("void main() {",`${JITTER_PARS}\nvoid main() {`).replace("#include <normal_fragment_begin>",a.replace(FACE_LINE,"float faceDirection = 1.0;")).replace("#include <lights_fragment_begin>",r.split(SHADOW_COORD).join(`( ${SHADOW_COORD} + bakeShadowJitter() )`));},n.customProgramCacheKey=()=>"environment-shadows-bake",{material:n,uniforms:{noise:e.bakeNoise,seed:e.bakeSeed,mapTexel:e.bakeMapTexel,shadowExtent:{value:1},lightDirection:{value:new Vector3}}}},createFinalize(e,n){const a=new ShaderMaterial({vertexShader:"void main() { gl_Position = vec4( position.xy, 0.0, 1.0 ); }",fragmentShader:FINALIZE_FRAGMENT,uniforms:{uSum:{value:e},uSize:{value:{x:n,y:n}},uScale:{value:1}},depthTest:!1,depthWrite:!1});return {material:a,uniforms:{scale:a.uniforms.uScale},dispose:()=>a.dispose()}},renderQuad(e,n){quad.material=n,e.render(quad,quadCamera);},createDisplay(){const e={lmA:{value:null},lmB:{value:null},lmFrontIsA:{value:1},lmBlend:{value:1},lmValid:{value:0},lmSpecularOcclusion:{value:1}},n=new WeakMap;return {uniforms:{a:e.lmA,b:e.lmB,frontIsA:e.lmFrontIsA,blend:e.lmBlend,valid:e.lmValid,specularOcclusion:e.lmSpecularOcclusion},refresh(){},patch(a){if(n.has(a))return;const r=a.onBeforeCompile,l=a.customProgramCacheKey;n.set(a,{onBeforeCompile:r,customProgramCacheKey:l}),a.onBeforeCompile=function(n,a){r.call(this,n,a),n.fragmentShader.includes("#include <lights_fragment_maps>")&&(Object.assign(n.uniforms,e),n.vertexShader=n.vertexShader.replace("void main() {",`${DISPLAY_VERTEX_PARS}\nvoid main() {`).replace("#include <fog_vertex>",`#include <fog_vertex>\n${DISPLAY_VERTEX}`),n.fragmentShader=n.fragmentShader.replace("void main() {",`${DISPLAY_FRAGMENT_PARS}\nvoid main() {`).replace("#include <lights_fragment_maps>",`#include <lights_fragment_maps>\n${DISPLAY_FRAGMENT}`));},a.customProgramCacheKey=function(){return `${l.call(this)}|environment-shadows`},a.dispose(),a.needsUpdate=!0;},unpatch(e){const a=n.get(e);a&&(e.onBeforeCompile=a.onBeforeCompile,e.customProgramCacheKey=a.customProgramCacheKey,n.delete(e),e.dispose(),e.needsUpdate=!0);}}}};
4
5
 
5
- const _direction=new Vector3,_position=new Vector3,getRoot=t=>{let i=t;for(;null!==i.parent;)i=i.parent;return i},isLoaded=t=>{const i=t.image;return null!=i&&(!!Array.isArray(i)||i.width>0&&i.height>0&&(void 0===i.data||i.data.length>0))};class EnvironmentShadowLights extends Group{constructor(t=null,i={}){super(),this.isEnvironmentShadowLights=!0,this.type="EnvironmentShadowLights",this.maxLights=i.maxLights??2,this.threshold=i.threshold??8,this.minEnergy=i.minEnergy??.05,this.minElevation=i.minElevation??-Math.PI/2,this.resolution=i.resolution??512,this.samples=i.samples??4,this.maxShadowMaps=i.maxShadowMaps??4,this.mapSize=i.mapSize??1024,this.relativeOccluderDistance=i.relativeOccluderDistance??.1,this.needsUpdate=!1,this.bounds=new Sphere(new Vector3,10),this.result=null,this.target=new Object3D,this.target.matrixAutoUpdate=!1,this.target.matrixWorldAutoUpdate=!1,this.add(this.target),this.lights=[],this._parts=[],this._source=null,this._sourceVersion=-1,this._residual=null,this._scene=null,this._request=null,this.addEventListener("removed",()=>this._restoreEnvironment()),null!==t&&t.add(this);}updateMatrixWorld(t){super.updateMatrixWorld(t);const i=getRoot(this);i.isScene&&this._syncEnvironment(i);const s=i.isScene?i.environmentRotation:null,e=i.isScene?i.environmentIntensity:1,{center:n,radius:r}=this.bounds;this.target.position.copy(n),this.target.matrix.makeTranslation(n),this.target.matrixWorld.copy(this.target.matrix);const o=2*r/this.mapSize;for(let t=0;t<this.lights.length;t++){const i=this.lights[t],h=this._parts[t];if(_direction.copy(h.direction),null!==s&&_direction.applyEuler(s),_position.copy(_direction).multiplyScalar(2*r).add(n),i.position.copy(_position),i.matrix.makeTranslation(_position),i.matrixWorld.copy(i.matrix),i.intensity=h.intensity*e,i.castShadow){const t=i.shadow.camera;t.left=-r,t.right=r,t.top=r,t.bottom=-r,t.near=r,t.far=3*r,t.updateProjectionMatrix(),i.shadow.normalBias=o;}}}copy(t,i=!0){if(super.copy(t,!1),this.maxLights=t.maxLights,this.threshold=t.threshold,this.minEnergy=t.minEnergy,this.minElevation=t.minElevation,this.resolution=t.resolution,this.samples=t.samples,this.maxShadowMaps=t.maxShadowMaps,this.mapSize=t.mapSize,this.relativeOccluderDistance=t.relativeOccluderDistance,this.bounds.copy(t.bounds),i)for(const i of t.children)i===t.target||t.lights.includes(i)||this.add(i.clone());return this}dispose(){this._restoreEnvironment(),this._clear(),this.removeFromParent();}_syncEnvironment(t){let i=t.environment;if(null!==i&&i===this._residual){if(!this.needsUpdate&&this._source.version===this._sourceVersion)return;i=this._source;}else if(null!==i&&i===this._source&&null!==this._residual&&!this.needsUpdate&&i.version===this._sourceVersion)return t.environment=this._residual,void(this._scene=t);const s=this._request;i===this._source||null!==s&&i===s.texture||this._clear(),null!==i&&isLoaded(i)&&(null===s||s.texture!==i||s.version!==i.version||this.needsUpdate)&&this._extract(t,i);}_extract(t,i){const s={texture:i,version:i.version};this.needsUpdate=!1,this._request=s,EnvironmentLightExtractor.extract(i,{maxLights:this.maxLights,threshold:this.threshold,minEnergy:this.minEnergy,minElevation:this.minElevation,samples:this.samples,resolution:this.resolution}).then(i=>{this._request===s?(this._request=null,this._apply(t,s,i)):i.texture.dispose();},t=>{this._request===s&&console.warn(t.message);});}_apply(t,i,s){const e=this._residual,n=t.environment;this._source=i.texture,this._sourceVersion=i.version,this._residual=s.texture,this.result={lights:s.lights,directionality:s.directionality,dominance:s.dominance,threshold:s.threshold},this._setLights(s.lights),getRoot(this)!==t||n!==this._source&&n!==e||(t.environment=this._residual,this._scene=t),null!==e&&e.dispose(),this.dispatchEvent({type:"change"});}_restoreEnvironment(){const t=this._scene;null!==t&&t.environment===this._residual&&(t.environment=this._source),this._scene=null;}_clear(){this._request=null,null!==this._residual&&this._residual.dispose(),this._source=null,this._sourceVersion=-1,this._residual=null,this._scene=null,null===this.result&&0===this.lights.length||(this.result=null,this._setLights([]),this.dispatchEvent({type:"change"}));}_setLights(t){for(const t of this.lights)this.remove(t),t.dispose();this.lights.length=0,this._parts.length=0;const i=t=>Math.tan(t)*this.relativeOccluderDistance*this.mapSize/2,s=t.map(()=>0);let e=this.maxShadowMaps;for(let i=0;i<t.length&&e>0;i++)s[i]=1,e--;for(let n=0;n<t.length&&e>0;n++){const r=t[n];if(0===s[n]||i(r.coneAngle)<=1)continue;const o=Math.min(Math.min(this.samples,r.partitions.length)-1,e);s[n]+=o,e-=o;}for(let e=0;e<t.length;e++){const n=s[e]>0,r=t[e].partitions[Math.max(1,s[e])-1];for(const t of r){const s=new DirectionalLight(t.color,t.intensity);s.matrixAutoUpdate=!1,s.matrixWorldAutoUpdate=!1,s.target=this.target,n&&(s.castShadow=!0,s.shadow.mapSize.setScalar(this.mapSize),s.shadow.radius=Math.min(8,Math.max(1,i(t.coneAngle)))),this.lights.push(s),this._parts.push(t),this.add(s);}}}}
6
+ class EnvironmentShadows extends EnvironmentShadowsBase{constructor(s,n,o={}){super(s,n,o,glslBackend);}}
6
7
 
7
- export { EnvironmentLightExtractor, EnvironmentShadowLights };
8
+ export { EnvironmentShadows };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "three-environment-shadows",
3
- "version": "1.0.1",
4
- "description": "Use HDR / EXR / UltraHDR environment maps as source of light and shadows in Three.js.",
3
+ "version": "2.1.0",
4
+ "description": "Soft, colored shadows from HDR / EXR / UltraHDR environment maps in Three.js (WebGL and WebGPU).",
5
5
  "type": "module",
6
6
  "main": "./index.js",
7
7
  "types": "./index.d.ts",
@@ -9,12 +9,17 @@
9
9
  ".": {
10
10
  "types": "./index.d.ts",
11
11
  "import": "./index.js"
12
+ },
13
+ "./webgpu": {
14
+ "types": "./webgpu.d.ts",
15
+ "import": "./webgpu.js"
12
16
  }
13
17
  },
14
18
  "sideEffects": false,
15
19
  "files": [
16
- "index.js",
17
- "index.d.ts",
20
+ "*.js",
21
+ "*.d.ts",
22
+ "xatlas-web.wasm",
18
23
  "README.md"
19
24
  ],
20
25
  "keywords": [
@@ -27,7 +32,9 @@
27
32
  "ibl",
28
33
  "lighting",
29
34
  "webgl",
30
- "webgpu"
35
+ "webgpu",
36
+ "tsl",
37
+ "lightmap"
31
38
  ],
32
39
  "scripts": {
33
40
  "build": "rollup --config ./rollup.config.mjs && cd build && npm pack",
@@ -36,6 +43,7 @@
36
43
  "format": "prettier --write src test types",
37
44
  "test": "vitest run && tsc",
38
45
  "test:build": "TEST_BUILD=1 vitest run",
46
+ "test:visual": "node test/visual/run.mjs",
39
47
  "release": "npm run build && npm run test:build && cd ./build && npm publish"
40
48
  },
41
49
  "author": {
@@ -43,13 +51,20 @@
43
51
  "url": "https://discourse.threejs.org/u/mjurczyk"
44
52
  },
45
53
  "license": "MIT",
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "git+https://github.com/mjurczyk/three-environment-shadows.git"
57
+ },
46
58
  "peerDependencies": {
47
- "three": ">=0.163.0"
59
+ "three": ">=0.162.0"
48
60
  },
49
61
  "devDependencies": {
50
62
  "@lopatnov/rollup-plugin-uglify": "^2.1.5",
51
63
  "@types/three": "^0.187.0",
64
+ "pixelmatch": "^7.2.0",
65
+ "pngjs": "^7.0.0",
52
66
  "prettier": "^3.9.0",
67
+ "puppeteer-core": "^24.43.1",
53
68
  "rollup": "^2.79.1",
54
69
  "rollup-plugin-copy": "^3.4.0",
55
70
  "rollup-plugin-delete": "^2.0.0",
@@ -57,6 +72,7 @@
57
72
  "terser": "^5.36.0",
58
73
  "three": "^0.187.0",
59
74
  "typescript": "^5.9.0",
60
- "vitest": "^5.1.0"
75
+ "vitest": "^5.1.0",
76
+ "xatlas-web": "^0.1.0"
61
77
  }
62
78
  }
package/shared.js ADDED
@@ -0,0 +1,13 @@
1
+ import { Color, RGBAFormat, HalfFloatType, DataUtils, UnsignedByteType, Vector3, SRGBColorSpace, BufferAttribute, BufferGeometry, Box3, Sphere, Matrix4, Frustum, Scene, Mesh, DirectionalLight, Object3D, OrthographicCamera, MathUtils, BasicShadowMap, WebGLRenderTarget, NearestFilter, LinearFilter } from 'three';
2
+
3
+ const _color=new Color;function halton(t,e){let o=0,a=1/e,r=t;for(;r>0;)o+=a*(r%e),r=Math.floor(r/e),a/=e;return o}function byteDecoder(t){const e=new Float32Array(256),o=t.colorSpace===SRGBColorSpace;for(let t=0;t<256;t++)e[t]=o?_color.setRGB(t/255,0,0,SRGBColorSpace).r:t/255;return t=>e[t]}function downsampleImage(t,e){const o=Math.max(1,e/2),a="undefined"!=typeof document?document.createElement("canvas"):new OffscreenCanvas(e,o);a.width=e,a.height=o;const r=a.getContext("2d",{willReadFrequently:!0});r.drawImage(t.image,0,0,e,o);const n=r.getImageData(0,0,e,o).data,l=byteDecoder(t),c=new Float32Array(e*o*3);for(let t=0;t<e*o;t++)c[3*t]=l(n[4*t]),c[3*t+1]=l(n[4*t+1]),c[3*t+2]=l(n[4*t+2]);return {data:c,width:e,height:o}}function downsampleEquirect(t,e=512){const o=t.image;if(!o)throw new Error("EnvironmentShadows: The environment map has no image.");if(void 0===o.data||null===o.data)return downsampleImage(t,e);const a=o.width,r=o.height,n=o.data,l=t.format===RGBAFormat?4:3,c=Math.max(1,e/2),i=t.type===HalfFloatType?DataUtils.fromHalfFloat:t.type===UnsignedByteType?byteDecoder(t):t=>t,h=new Float32Array(e*c*3),s=new Float32Array(e*c);for(let o=0;o<r;o++){const d=t.flipY?o:r-1-o,f=Math.min(c-1,Math.floor(d*c/r));for(let t=0;t<a;t++){const r=(o*a+t)*l,c=f*e+Math.min(e-1,Math.floor(t*e/a));h[3*c]+=i(n[r]),h[3*c+1]+=i(n[r+1]),h[3*c+2]+=i(n[r+2]),s[c]++;}}for(let t=0;t<e*c;t++){const e=Math.max(1,s[t]);h[3*t]/=e,h[3*t+1]/=e,h[3*t+2]/=e;}return {data:h,width:e,height:c}}function createEnvironmentSampler(t){const{data:e,width:o,height:a}=t,r=new Float64Array(a),n=new Float64Array(o*a),l=new Float64Array(a);let c=0;for(let t=0;t<a;t++){const i=(.5-t/a)*Math.PI,h=(.5-(t+1)/a)*Math.PI;r[t]=2*Math.PI/o*(Math.sin(i)-Math.sin(h));let s=0;for(let a=0;a<o;a++){const l=3*(t*o+a),c=.2126*e[l]+.7152*e[l+1]+.0722*e[l+2];s+=Math.max(0,c)*r[t],n[t*o+a]=s;}c+=s,l[t]=c;}const i=(t,e,o,a)=>{let r=0,n=o-1;for(;r<n;){const o=r+n>>1;t[e+o]<a?r=o+1:n=o;}return r},h=new Vector3,s=new Color;return (t,r,d,f)=>{if(c<=0)return h.set(0,1,0),s.setRGB(0,0,0),{direction:h,color:s};const m=i(l,0,a,t*c),w=m>0?l[m-1]:0,M=i(n,m*o,o,r*(l[m]-w)),p=2*((M+d)/o-.5)*Math.PI,u=(.5-(m+f)/a)*Math.PI;h.set(Math.cos(u)*Math.cos(p),Math.sin(u),Math.cos(u)*Math.sin(p));const y=3*(m*o+M),g=.2126*e[y]+.7152*e[y+1]+.0722*e[y+2],F=Math.max(1e-12,g/c);return s.setRGB(e[y]/F,e[y+1]/F,e[y+2]/F),{direction:h,color:s}}}
4
+
5
+ var xatlasSource = '\nvar Module = (function() {\n var _scriptDir = typeof document !== \'undefined\' && document.currentScript ? document.currentScript.src : undefined;\n \n return (\nfunction(Module) {\n Module = Module || {};\n\n"use strict";var Module=typeof Module!=="undefined"?Module:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)")}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}if(!(typeof window==="object"||typeof importScripts==="function"))throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{throw new Error("environment detection error")}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(!Object.getOwnPropertyDescriptor(Module,"arguments"))Object.defineProperty(Module,"arguments",{configurable:true,get:function(){abort("Module.arguments has been replaced with plain arguments_")}});if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(!Object.getOwnPropertyDescriptor(Module,"thisProgram"))Object.defineProperty(Module,"thisProgram",{configurable:true,get:function(){abort("Module.thisProgram has been replaced with plain thisProgram")}});if(Module["quit"])quit_=Module["quit"];if(!Object.getOwnPropertyDescriptor(Module,"quit"))Object.defineProperty(Module,"quit",{configurable:true,get:function(){abort("Module.quit has been replaced with plain quit_")}});assert(typeof Module["memoryInitializerPrefixURL"]==="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]==="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]==="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]==="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]==="undefined","Module.read option was removed (modify read_ in JS)");assert(typeof Module["readAsync"]==="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]==="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]==="undefined","Module.setWindowTitle option was removed (modify setWindowTitle in JS)");if(!Object.getOwnPropertyDescriptor(Module,"read"))Object.defineProperty(Module,"read",{configurable:true,get:function(){abort("Module.read has been replaced with plain read_")}});if(!Object.getOwnPropertyDescriptor(Module,"readAsync"))Object.defineProperty(Module,"readAsync",{configurable:true,get:function(){abort("Module.readAsync has been replaced with plain readAsync")}});if(!Object.getOwnPropertyDescriptor(Module,"readBinary"))Object.defineProperty(Module,"readBinary",{configurable:true,get:function(){abort("Module.readBinary has been replaced with plain readBinary")}});stackSave=stackRestore=stackAlloc=function(){abort("cannot use the stack before compiled code is ready to run, and has provided stack access")};function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var asm2wasmImports={"f64-rem":function(x,y){return x%y},"debugger":function(){debugger}};var functionPointers=new Array(0);var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(!Object.getOwnPropertyDescriptor(Module,"wasmBinary"))Object.defineProperty(Module,"wasmBinary",{configurable:true,get:function(){abort("Module.wasmBinary has been replaced with plain wasmBinary")}});var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(!Object.getOwnPropertyDescriptor(Module,"noExitRuntime"))Object.defineProperty(Module,"noExitRuntime",{configurable:true,get:function(){abort("Module.noExitRuntime has been replaced with plain noExitRuntime")}});if(typeof WebAssembly!=="object"){abort("No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.")}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":104,"maximum":104,"element":"anyfunc"});var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(u8Array[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx<endPtr){var u0=u8Array[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{if((u0&248)!=240)warnOnce("Invalid UTF-8 leading byte 0x"+u0.toString(16)+" encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!");u0=(u0&7)<<18|u1<<12|u2<<6|u8Array[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;if(u>=2097152)warnOnce("Invalid Unicode code point 0x"+u.toString(16)+" encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).");outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=10576,STACK_MAX=5253456,DYNAMIC_BASE=5253456,DYNAMICTOP_PTR=10384;assert(STACK_BASE%16===0,"stack must start aligned");assert(DYNAMIC_BASE%16===0,"heap must start aligned");var TOTAL_STACK=5242880;if(Module["TOTAL_STACK"])assert(TOTAL_STACK===Module["TOTAL_STACK"],"the stack size can no longer be determined at runtime");var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;if(!Object.getOwnPropertyDescriptor(Module,"TOTAL_MEMORY"))Object.defineProperty(Module,"TOTAL_MEMORY",{configurable:true,get:function(){abort("Module.TOTAL_MEMORY has been replaced with plain INITIAL_TOTAL_MEMORY")}});assert(INITIAL_TOTAL_MEMORY>=TOTAL_STACK,"TOTAL_MEMORY should be larger than TOTAL_STACK, was "+INITIAL_TOTAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!==undefined&&Int32Array.prototype.set!==undefined,"JS engine does not provide full typed array support");if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_TOTAL_MEMORY/WASM_PAGE_SIZE})}if(wasmMemory){buffer=wasmMemory.buffer}INITIAL_TOTAL_MEMORY=buffer.byteLength;assert(INITIAL_TOTAL_MEMORY%WASM_PAGE_SIZE===0);updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function writeStackCookie(){assert((STACK_MAX&3)==0);HEAPU32[(STACK_MAX>>2)-1]=34821223;HEAPU32[(STACK_MAX>>2)-2]=2310721022;HEAP32[0]=1668509029}function checkStackCookie(){var cookie1=HEAPU32[(STACK_MAX>>2)-1];var cookie2=HEAPU32[(STACK_MAX>>2)-2];if(cookie1!=34821223||cookie2!=2310721022){abort("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x02135467, but received 0x"+cookie2.toString(16)+" "+cookie1.toString(16))}if(HEAP32[0]!==1668509029)abort("Runtime error: The application has corrupted its heap memory area (address zero)!")}function abortStackOverflow(allocSize){abort("Stack overflow! Attempted to allocate "+allocSize+" bytes on the stack, but stack has only "+(STACK_MAX-stackSave()+allocSize)+" bytes available!")}(function(){var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw"Runtime error: expected the system to be little-endian!"})();function abortFnPtrError(ptr,sig){abort("Invalid function pointer "+ptr+" called with signature \'"+sig+"\'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this). Build with ASSERTIONS=2 for more info.")}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){checkStackCookie();assert(!runtimeInitialized);runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){checkStackCookie();callRuntimeCallbacks(__ATMAIN__)}function postRun(){checkStackCookie();if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!=="undefined"){runDependencyWatcher=setInterval(function(){if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:")}err("dependency: "+dep)}if(shown){err("(end of list)")}},1e4)}}else{err("warning: run dependency added without ID")}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id]}else{err("warning: run dependency removed without ID")}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;var output="abort("+what+") at "+stackTrace();what=output;throw new WebAssembly.RuntimeError(what)}var FS={error:function(){abort("Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -s FORCE_FILESYSTEM=1")},init:function(){FS.error()},createDataFile:function(){FS.error()},createPreloadedFile:function(){FS.error()},createLazyFile:function(){FS.error()},open:function(){FS.error()},mkdev:function(){FS.error()},registerDevice:function(){FS.error()},analyzePath:function(){FS.error()},loadFilesFromDB:function(){FS.error()},ErrnoError:function ErrnoError(){FS.error()}};Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var wasmBinaryFile="xatlas-web.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at \'"+wasmBinaryFile+"\'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary())})}function createWasm(){var info={"env":asmLibraryArg,"wasi_unstable":asmLibraryArg,"global":{"NaN":NaN,Infinity:Infinity},"global.Math":Math,"asm2wasm":asm2wasmImports};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");var trueModule=Module;function receiveInstantiatedSource(output){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return{}}Module["asm"]=createWasm;__ATINIT__.push({func:function(){globalCtors()}});var tempDoublePtr=10560;assert(tempDoublePtr%8==0);function demangle(func){warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/\\b__Z[\\w\\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\\n"+Module["extraStackTrace"]();return demangleAll(js)}var PATH={splitPath:function(filename){var splitPathRe=/^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};var SYSCALLS={buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:0,get:function(varargs){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(){var ret=UTF8ToString(SYSCALLS.get());return ret},get64:function(){var low=SYSCALLS.get(),high=SYSCALLS.get();if(low>=0)assert(high===0);else assert(high===-1);return low},getZero:function(){assert(SYSCALLS.get()===0)}};function _fd_close(fd){try{abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function ___wasi_fd_close(){return _fd_close.apply(null,arguments)}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function ___wasi_fd_seek(){return _fd_seek.apply(null,arguments)}function _fd_write(fd,iov,iovcnt,pnum){try{var num=0;for(var i=0;i<iovcnt;i++){var ptr=HEAP32[iov+i*8>>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j<len;j++){SYSCALLS.printChar(fd,HEAPU8[ptr+j])}num+=len}HEAP32[pnum>>2]=num;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function ___wasi_fd_write(){return _fd_write.apply(null,arguments)}var structRegistrations={};function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return"_"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\\n"+\' "use strict";\'+" return body.apply(this, arguments);\\n"+"};\\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\\n"+stack.replace(/^Error(:[^\\n]*)?\\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i<myTypes.length;++i){registerType(myTypes[i],myTypeConverters[i])}}var typeConverters=new Array(dependentTypes.length);var unregisteredTypes=[];var registered=0;dependentTypes.forEach(function(dt,i){if(registeredTypes.hasOwnProperty(dt)){typeConverters[i]=registeredTypes[dt]}else{unregisteredTypes.push(dt);if(!awaitingDependencies.hasOwnProperty(dt)){awaitingDependencies[dt]=[]}awaitingDependencies[dt].push(function(){typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}});if(0===unregisteredTypes.length){onComplete(typeConverters)}}function __embind_finalize_value_object(structType){var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(function(field){return field.getterReturnType}).concat(fieldRecords.map(function(field){return field.setterArgumentType}));whenDependentTypesAreResolved([structType],fieldTypes,function(fieldTypes){var fields={};fieldRecords.forEach(function(field,i){var fieldName=field.fieldName;var getterReturnType=fieldTypes[i];var getter=field.getter;var getterContext=field.getterContext;var setterArgumentType=fieldTypes[i+fieldRecords.length];var setter=field.setter;var setterContext=field.setterContext;fields[fieldName]={read:function(ptr){return getterReturnType["fromWireType"](getter(getterContext,ptr))},write:function(ptr,o){var destructors=[];setter(setterContext,ptr,setterArgumentType["toWireType"](destructors,o));runDestructors(destructors)}}});return[{name:reg.name,"fromWireType":function(ptr){var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},"toWireType":function(destructors,o){for(var fieldName in fields){if(!(fieldName in o)){throw new TypeError("Missing field")}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:rawDestructor}]})}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+size)}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}function registerType(rawType,registeredInstance,options){options=options||{};if(!("argPackAdvance"in registeredInstance)){throw new TypeError("registerType registeredInstance requires argPackAdvance")}var name=registeredInstance.name;if(!rawType){throwBindingError(\'type "\'+name+\'" must have a positive integer typeid pointer\')}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError("Cannot register type \'"+name+"\' twice")}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(function(cb){cb()})}}function __embind_register_bool(rawType,name,size,trueValue,falseValue){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(wt){return!!wt},"toWireType":function(destructors,o){return o?trueValue:falseValue},"argPackAdvance":8,"readValueFromPointer":function(pointer){var heap;if(size===1){heap=HEAP8}else if(size===2){heap=HEAP16}else if(size===4){heap=HEAP32}else{throw new TypeError("Unknown boolean type size: "+name)}return this["fromWireType"](heap[pointer>>shift])},destructorFunction:null})}var emval_free_list=[];var emval_handle_array=[{},{value:undefined},{value:null},{value:true},{value:false}];function __emval_decref(handle){if(handle>4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i<emval_handle_array.length;++i){if(emval_handle_array[i]!==undefined){++count}}return count}function get_first_emval(){for(var i=5;i<emval_handle_array.length;++i){if(emval_handle_array[i]!==undefined){return emval_handle_array[i]}}return null}function init_emval(){Module["count_emval_handles"]=count_emval_handles;Module["get_first_emval"]=get_first_emval}function __emval_register(value){switch(value){case undefined:{return 1}case null:{return 2}case true:{return 3}case false:{return 4}default:{var handle=emval_free_list.length?emval_free_list.pop():emval_handle_array.length;emval_handle_array[handle]={refcount:1,value:value};return handle}}}function __embind_register_emval(rawType,name){name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(handle){var rv=emval_handle_array[handle].value;__emval_decref(handle);return rv},"toWireType":function(destructors,value){return __emval_register(value)},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:null})}function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError(\'Cannot convert "\'+_embind_repr(value)+\'" to \'+this.name)}return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function new_(constructor,argumentList){if(!(constructor instanceof Function)){throw new TypeError("new_ called with constructor type "+typeof constructor+" which is not a function")}var dummy=createNamedFunction(constructor.name||"unknownFunctionName",function(){});dummy.prototype=constructor.prototype;var obj=new dummy;var r=constructor.apply(obj,argumentList);return r instanceof Object?r:obj}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc){var argCount=argTypes.length;if(argCount<2){throwBindingError("argTypes array size mismatch! Must at least get return value and \'this\' types!")}var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=false;for(var i=1;i<argTypes.length;++i){if(argTypes[i]!==null&&argTypes[i].destructorFunction===undefined){needsDestructorStack=true;break}}var returns=argTypes[0].name!=="void";var argsList="";var argsListWired="";for(var i=0;i<argCount-2;++i){argsList+=(i!==0?", ":"")+"arg"+i;argsListWired+=(i!==0?", ":"")+"arg"+i+"Wired"}var invokerFnBody="return function "+makeLegalFunctionName(humanName)+"("+argsList+") {\\n"+"if (arguments.length !== "+(argCount-2)+") {\\n"+"throwBindingError(\'function "+humanName+" called with \' + arguments.length + \' arguments, expected "+(argCount-2)+" args!\');\\n"+"}\\n";if(needsDestructorStack){invokerFnBody+="var destructors = [];\\n"}var dtorStack=needsDestructorStack?"destructors":"null";var args1=["throwBindingError","invoker","fn","runDestructors","retType","classParam"];var args2=[throwBindingError,cppInvokerFunc,cppTargetFunc,runDestructors,argTypes[0],argTypes[1]];if(isClassMethodFunc){invokerFnBody+="var thisWired = classParam.toWireType("+dtorStack+", this);\\n"}for(var i=0;i<argCount-2;++i){invokerFnBody+="var arg"+i+"Wired = argType"+i+".toWireType("+dtorStack+", arg"+i+"); // "+argTypes[i+2].name+"\\n";args1.push("argType"+i);args2.push(argTypes[i+2])}if(isClassMethodFunc){argsListWired="thisWired"+(argsListWired.length>0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\\n"}else{for(var i=isClassMethodFunc?1:2;i<argTypes.length;++i){var paramName=i===1?"thisWired":"arg"+(i-2)+"Wired";if(argTypes[i].destructorFunction!==null){invokerFnBody+=paramName+"_dtor("+paramName+"); // "+argTypes[i].name+"\\n";args1.push(paramName+"_dtor");args2.push(argTypes[i].destructorFunction)}}}if(returns){invokerFnBody+="var ret = retType.fromWireType(rv);\\n"+"return ret;\\n"}else{}invokerFnBody+="}\\n";args1.push(invokerFnBody);var invokerFunction=new_(Function,args1).apply(null,args2);return invokerFunction}function ensureOverloadTable(proto,methodName,humanName){if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError("Function \'"+humanName+"\' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+proto[methodName].overloadTable+")!")}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}}function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError("Cannot register public name \'"+name+"\' twice")}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError("Cannot register multiple overloads of a function with the same number of arguments ("+numArguments+")!")}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}}function heap32VectorToArray(count,firstElement){var array=[];for(var i=0;i<count;i++){array.push(HEAP32[(firstElement>>2)+i])}return array}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function embind__requireFunction(signature,rawFunction){signature=readLatin1String(signature);function makeDynCaller(dynCall){var args=[];for(var i=1;i<signature.length;++i){args.push("a"+i)}var name="dynCall_"+signature+"_"+rawFunction;var body="return function "+name+"("+args.join(", ")+") {\\n";body+=" return dynCall(rawFunction"+(args.length?", ":"")+args.join(", ")+");\\n";body+="};\\n";return new Function("dynCall","rawFunction",body)(dynCall,rawFunction)}var fp;if(Module["FUNCTION_TABLE_"+signature]!==undefined){fp=Module["FUNCTION_TABLE_"+signature][rawFunction]}else if(typeof FUNCTION_TABLE!=="undefined"){fp=FUNCTION_TABLE[rawFunction]}else{var dc=Module["dynCall_"+signature];if(dc===undefined){dc=Module["dynCall_"+signature.replace(/f/g,"d")];if(dc===undefined){throwBindingError("No dynCall invoker for signature: "+signature)}}fp=makeDynCaller(dc)}if(typeof fp!=="function"){throwBindingError("unknown function pointer with signature "+signature+": "+rawFunction)}return fp}var UnboundTypeError=undefined;function getTypeName(type){var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv}function throwUnboundTypeError(message,types){var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(message+": "+unboundTypes.map(getTypeName).join([", "]))}function __embind_register_function(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn){var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError("Cannot call "+name+" due to unbound types",argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn),argCount-1);return[]})}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=function(value){return value};if(minRange===0){var bitshift=32-8*size;fromWireType=function(value){return value<<bitshift>>>bitshift}}var isUnsignedType=name.indexOf("unsigned")!=-1;registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError(\'Cannot convert "\'+_embind_repr(value)+\'" to \'+this.name)}if(value<minRange||value>maxRange){throw new TypeError(\'Passing a number "\'+_embind_repr(value)+\'" from JS side to C/C++ side to an argument of type "\'+name+\'", which is outside the valid range [\'+minRange+", "+maxRange+"]!")}return isUnsignedType?value>>>0:value|0},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(heap["buffer"],data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var str;if(stdStringIsUTF8){var endChar=HEAPU8[value+4+length];var endCharSwap=0;if(endChar!=0){endCharSwap=endChar;HEAPU8[value+4+length]=0}var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i;if(HEAPU8[currentBytePtr]==0){var stringSegment=UTF8ToString(decodeStartPtr);if(str===undefined)str=stringSegment;else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}if(endCharSwap!=0)HEAPU8[value+4+length]=endCharSwap}else{var a=new Array(length);for(var i=0;i<length;++i){a[i]=String.fromCharCode(HEAPU8[value+4+i])}str=a.join("")}_free(value);return str},"toWireType":function(destructors,value){if(value instanceof ArrayBuffer){value=new Uint8Array(value)}var getLength;var valueIsOfTypeString=typeof value==="string";if(!(valueIsOfTypeString||value instanceof Uint8Array||value instanceof Uint8ClampedArray||value instanceof Int8Array)){throwBindingError("Cannot pass non-string to std::string")}if(stdStringIsUTF8&&valueIsOfTypeString){getLength=function(){return lengthBytesUTF8(value)}}else{getLength=function(){return value.length}}var length=getLength();var ptr=_malloc(4+length+1);HEAPU32[ptr>>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr+4,length+1)}else{if(valueIsOfTypeString){for(var i=0;i<length;++i){var charCode=value.charCodeAt(i);if(charCode>255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+4+i]=charCode}}else{for(var i=0;i<length;++i){HEAPU8[ptr+4+i]=value[i]}}}if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_std_wstring(rawType,charSize,name){name=readLatin1String(name);var getHeap,shift;if(charSize===2){getHeap=function(){return HEAPU16};shift=1}else if(charSize===4){getHeap=function(){return HEAPU32};shift=2}registerType(rawType,{name:name,"fromWireType":function(value){var HEAP=getHeap();var length=HEAPU32[value>>2];var a=new Array(length);var start=value+4>>shift;for(var i=0;i<length;++i){a[i]=String.fromCharCode(HEAP[start+i])}_free(value);return a.join("")},"toWireType":function(destructors,value){var length=value.length;var ptr=_malloc(4+length*charSize);var HEAP=getHeap();HEAPU32[ptr>>2]=length;var start=ptr+4>>shift;for(var i=0;i<length;++i){HEAP[start+i]=value.charCodeAt(i)}if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_value_object(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor){structRegistrations[rawType]={name:readLatin1String(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}}function __embind_register_value_object_field(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext){structRegistrations[structType].fields.push({fieldName:readLatin1String(fieldName),getterReturnType:getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext:getterContext,setterArgumentType:setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext:setterContext})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}function _abort(){abort()}function _emscripten_get_heap_size(){return HEAP8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){console.error("emscripten_realloc_buffer: Attempted to grow heap from "+buffer.byteLength+" bytes to "+size+" bytes, but got error: "+e)}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();assert(requestedSize>oldSize);var PAGE_MULTIPLE=65536;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){err("Cannot enlarge memory, asked to go up to "+requestedSize+" bytes, but the limit is "+LIMIT+" bytes!");return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize<requestedSize){if(newSize<=536870912){newSize=alignUp(2*newSize,PAGE_MULTIPLE)}else{newSize=Math.min(alignUp((3*newSize+2147483648)/4,PAGE_MULTIPLE),LIMIT)}if(newSize===oldSize){warnOnce("Cannot ask for more memory since we reached the practical limit in browsers (which is just below 2GB), so the request would have failed. Requesting only "+HEAP8.length)}}var replacement=emscripten_realloc_buffer(newSize);if(!replacement){err("Failed to grow the heap from "+oldSize+" bytes to "+newSize+" bytes, not enough memory!");return false}return true}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}InternalError=Module["InternalError"]=extendError(Error,"InternalError");embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");init_emval();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");function nullFunc_i(x){abortFnPtrError(x,"i")}function nullFunc_ii(x){abortFnPtrError(x,"ii")}function nullFunc_iidiiii(x){abortFnPtrError(x,"iidiiii")}function nullFunc_iii(x){abortFnPtrError(x,"iii")}function nullFunc_iiii(x){abortFnPtrError(x,"iiii")}function nullFunc_iiiiii(x){abortFnPtrError(x,"iiiiii")}function nullFunc_jiji(x){abortFnPtrError(x,"jiji")}function nullFunc_v(x){abortFnPtrError(x,"v")}function nullFunc_vi(x){abortFnPtrError(x,"vi")}function nullFunc_vii(x){abortFnPtrError(x,"vii")}function nullFunc_viii(x){abortFnPtrError(x,"viii")}function nullFunc_viiii(x){abortFnPtrError(x,"viiii")}function nullFunc_viiiii(x){abortFnPtrError(x,"viiiii")}function nullFunc_viiiiii(x){abortFnPtrError(x,"viiiiii")}var asmGlobalArg={};var asmLibraryArg={"___wasi_fd_close":___wasi_fd_close,"___wasi_fd_seek":___wasi_fd_seek,"___wasi_fd_write":___wasi_fd_write,"__embind_finalize_value_object":__embind_finalize_value_object,"__embind_register_bool":__embind_register_bool,"__embind_register_emval":__embind_register_emval,"__embind_register_float":__embind_register_float,"__embind_register_function":__embind_register_function,"__embind_register_integer":__embind_register_integer,"__embind_register_memory_view":__embind_register_memory_view,"__embind_register_std_string":__embind_register_std_string,"__embind_register_std_wstring":__embind_register_std_wstring,"__embind_register_value_object":__embind_register_value_object,"__embind_register_value_object_field":__embind_register_value_object_field,"__embind_register_void":__embind_register_void,"__memory_base":1024,"__table_base":0,"_abort":_abort,"_emscripten_get_heap_size":_emscripten_get_heap_size,"_emscripten_memcpy_big":_emscripten_memcpy_big,"_emscripten_resize_heap":_emscripten_resize_heap,"abortStackOverflow":abortStackOverflow,"memory":wasmMemory,"nullFunc_i":nullFunc_i,"nullFunc_ii":nullFunc_ii,"nullFunc_iidiiii":nullFunc_iidiiii,"nullFunc_iii":nullFunc_iii,"nullFunc_iiii":nullFunc_iiii,"nullFunc_iiiiii":nullFunc_iiiiii,"nullFunc_jiji":nullFunc_jiji,"nullFunc_v":nullFunc_v,"nullFunc_vi":nullFunc_vi,"nullFunc_vii":nullFunc_vii,"nullFunc_viii":nullFunc_viii,"nullFunc_viiii":nullFunc_viiii,"nullFunc_viiiii":nullFunc_viiiii,"nullFunc_viiiiii":nullFunc_viiiiii,"setTempRet0":setTempRet0,"table":wasmTable};var asm=Module["asm"](asmGlobalArg,asmLibraryArg,buffer);Module["asm"]=asm;var ___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["___embind_register_native_and_builtin_types"].apply(null,arguments)};var ___getTypeName=Module["___getTypeName"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["___getTypeName"].apply(null,arguments)};var _free=Module["_free"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["_free"].apply(null,arguments)};var _malloc=Module["_malloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["_malloc"].apply(null,arguments)};var establishStackSpace=Module["establishStackSpace"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["establishStackSpace"].apply(null,arguments)};var globalCtors=Module["globalCtors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["globalCtors"].apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackAlloc"].apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackRestore"].apply(null,arguments)};var stackSave=Module["stackSave"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackSave"].apply(null,arguments)};var dynCall_i=Module["dynCall_i"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_i"].apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_ii"].apply(null,arguments)};var dynCall_iidiiii=Module["dynCall_iidiiii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_iidiiii"].apply(null,arguments)};var dynCall_iii=Module["dynCall_iii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_iii"].apply(null,arguments)};var dynCall_iiii=Module["dynCall_iiii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_iiii"].apply(null,arguments)};var dynCall_iiiiii=Module["dynCall_iiiiii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_iiiiii"].apply(null,arguments)};var dynCall_jiji=Module["dynCall_jiji"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_jiji"].apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_v"].apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_vi"].apply(null,arguments)};var dynCall_vii=Module["dynCall_vii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_vii"].apply(null,arguments)};var dynCall_viii=Module["dynCall_viii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_viii"].apply(null,arguments)};var dynCall_viiii=Module["dynCall_viiii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_viiii"].apply(null,arguments)};var dynCall_viiiii=Module["dynCall_viiiii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_viiiii"].apply(null,arguments)};var dynCall_viiiiii=Module["dynCall_viiiiii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_viiiiii"].apply(null,arguments)};Module["asm"]=asm;if(!Object.getOwnPropertyDescriptor(Module,"intArrayFromString"))Module["intArrayFromString"]=function(){abort("\'intArrayFromString\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"intArrayToString"))Module["intArrayToString"]=function(){abort("\'intArrayToString\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"ccall"))Module["ccall"]=function(){abort("\'ccall\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"cwrap"))Module["cwrap"]=function(){abort("\'cwrap\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"setValue"))Module["setValue"]=function(){abort("\'setValue\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"getValue"))Module["getValue"]=function(){abort("\'getValue\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"allocate"))Module["allocate"]=function(){abort("\'allocate\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"getMemory"))Module["getMemory"]=function(){abort("\'getMemory\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"AsciiToString"))Module["AsciiToString"]=function(){abort("\'AsciiToString\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"stringToAscii"))Module["stringToAscii"]=function(){abort("\'stringToAscii\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ArrayToString"))Module["UTF8ArrayToString"]=function(){abort("\'UTF8ArrayToString\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ToString"))Module["UTF8ToString"]=function(){abort("\'UTF8ToString\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8Array"))Module["stringToUTF8Array"]=function(){abort("\'stringToUTF8Array\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8"))Module["stringToUTF8"]=function(){abort("\'stringToUTF8\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF8"))Module["lengthBytesUTF8"]=function(){abort("\'lengthBytesUTF8\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"UTF16ToString"))Module["UTF16ToString"]=function(){abort("\'UTF16ToString\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF16"))Module["stringToUTF16"]=function(){abort("\'stringToUTF16\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF16"))Module["lengthBytesUTF16"]=function(){abort("\'lengthBytesUTF16\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"UTF32ToString"))Module["UTF32ToString"]=function(){abort("\'UTF32ToString\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF32"))Module["stringToUTF32"]=function(){abort("\'stringToUTF32\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF32"))Module["lengthBytesUTF32"]=function(){abort("\'lengthBytesUTF32\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8"))Module["allocateUTF8"]=function(){abort("\'allocateUTF8\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("\'stackTrace\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreRun"))Module["addOnPreRun"]=function(){abort("\'addOnPreRun\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"addOnInit"))Module["addOnInit"]=function(){abort("\'addOnInit\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreMain"))Module["addOnPreMain"]=function(){abort("\'addOnPreMain\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"addOnExit"))Module["addOnExit"]=function(){abort("\'addOnExit\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"addOnPostRun"))Module["addOnPostRun"]=function(){abort("\'addOnPostRun\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"writeStringToMemory"))Module["writeStringToMemory"]=function(){abort("\'writeStringToMemory\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"writeArrayToMemory"))Module["writeArrayToMemory"]=function(){abort("\'writeArrayToMemory\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"writeAsciiToMemory"))Module["writeAsciiToMemory"]=function(){abort("\'writeAsciiToMemory\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"addRunDependency"))Module["addRunDependency"]=function(){abort("\'addRunDependency\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"removeRunDependency"))Module["removeRunDependency"]=function(){abort("\'removeRunDependency\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"ENV"))Module["ENV"]=function(){abort("\'ENV\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"FS"))Module["FS"]=function(){abort("\'FS\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"FS_createFolder"))Module["FS_createFolder"]=function(){abort("\'FS_createFolder\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPath"))Module["FS_createPath"]=function(){abort("\'FS_createPath\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDataFile"))Module["FS_createDataFile"]=function(){abort("\'FS_createDataFile\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPreloadedFile"))Module["FS_createPreloadedFile"]=function(){abort("\'FS_createPreloadedFile\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLazyFile"))Module["FS_createLazyFile"]=function(){abort("\'FS_createLazyFile\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLink"))Module["FS_createLink"]=function(){abort("\'FS_createLink\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDevice"))Module["FS_createDevice"]=function(){abort("\'FS_createDevice\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"FS_unlink"))Module["FS_unlink"]=function(){abort("\'FS_unlink\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")};if(!Object.getOwnPropertyDescriptor(Module,"GL"))Module["GL"]=function(){abort("\'GL\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"dynamicAlloc"))Module["dynamicAlloc"]=function(){abort("\'dynamicAlloc\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"loadDynamicLibrary"))Module["loadDynamicLibrary"]=function(){abort("\'loadDynamicLibrary\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"loadWebAssemblyModule"))Module["loadWebAssemblyModule"]=function(){abort("\'loadWebAssemblyModule\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"getLEB"))Module["getLEB"]=function(){abort("\'getLEB\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"getFunctionTables"))Module["getFunctionTables"]=function(){abort("\'getFunctionTables\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"alignFunctionTables"))Module["alignFunctionTables"]=function(){abort("\'alignFunctionTables\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"registerFunctions"))Module["registerFunctions"]=function(){abort("\'registerFunctions\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"addFunction"))Module["addFunction"]=function(){abort("\'addFunction\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"removeFunction"))Module["removeFunction"]=function(){abort("\'removeFunction\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"getFuncWrapper"))Module["getFuncWrapper"]=function(){abort("\'getFuncWrapper\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"prettyPrint"))Module["prettyPrint"]=function(){abort("\'prettyPrint\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"makeBigInt"))Module["makeBigInt"]=function(){abort("\'makeBigInt\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"dynCall"))Module["dynCall"]=function(){abort("\'dynCall\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"getCompilerSetting"))Module["getCompilerSetting"]=function(){abort("\'getCompilerSetting\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"stackSave"))Module["stackSave"]=function(){abort("\'stackSave\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"stackRestore"))Module["stackRestore"]=function(){abort("\'stackRestore\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"stackAlloc"))Module["stackAlloc"]=function(){abort("\'stackAlloc\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"establishStackSpace"))Module["establishStackSpace"]=function(){abort("\'establishStackSpace\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"print"))Module["print"]=function(){abort("\'print\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"printErr"))Module["printErr"]=function(){abort("\'printErr\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"getTempRet0"))Module["getTempRet0"]=function(){abort("\'getTempRet0\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"setTempRet0"))Module["setTempRet0"]=function(){abort("\'setTempRet0\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"callMain"))Module["callMain"]=function(){abort("\'callMain\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"abort"))Module["abort"]=function(){abort("\'abort\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"Pointer_stringify"))Module["Pointer_stringify"]=function(){abort("\'Pointer_stringify\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};if(!Object.getOwnPropertyDescriptor(Module,"warnOnce"))Module["warnOnce"]=function(){abort("\'warnOnce\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")};Module["writeStackCookie"]=writeStackCookie;Module["checkStackCookie"]=checkStackCookie;Module["abortStackOverflow"]=abortStackOverflow;if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NORMAL"))Object.defineProperty(Module,"ALLOC_NORMAL",{configurable:true,get:function(){abort("\'ALLOC_NORMAL\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_STACK"))Object.defineProperty(Module,"ALLOC_STACK",{configurable:true,get:function(){abort("\'ALLOC_STACK\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_DYNAMIC"))Object.defineProperty(Module,"ALLOC_DYNAMIC",{configurable:true,get:function(){abort("\'ALLOC_DYNAMIC\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NONE"))Object.defineProperty(Module,"ALLOC_NONE",{configurable:true,get:function(){abort("\'ALLOC_NONE\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)")}});if(!Object.getOwnPropertyDescriptor(Module,"calledRun"))Object.defineProperty(Module,"calledRun",{configurable:true,get:function(){abort("\'calledRun\' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you")}});var calledRun;Module["then"]=function(func){if(calledRun){func(Module)}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module)}}return Module};dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}writeStackCookie();preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();assert(!Module["_main"],\'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]\');postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}checkStackCookie()}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run();Module["ready"]=new Promise(function(resolve,reject){delete Module["then"];Module["onAbort"]=function(what){reject(what)};addOnPostRun(function(){resolve(Module)})});\n\n\n return Module\n}\n);\n})();\nif (typeof exports === \'object\' && typeof module === \'object\')\n module.exports = Module;\n else if (typeof define === \'function\' && define[\'amd\'])\n define([], function() { return Module; });\n else if (typeof exports === \'object\')\n exports["Module"] = Module;\n ';
6
+
7
+ const NO_PLACE=-10;function packerModule(){function t(t,e,n,a){const o=e[2*n],r=e[2*n+1];return a[0]=(t.cos*o+t.sin*r-t.minU)*t.metersPerUv,a[1]=(-t.sin*o+t.cos*r-t.minV)*t.metersPerUv,a}function e(e,n,a,o,r){const s=Math.max(1,Math.ceil((r?e.height:e.width)/a)),l=Math.max(1,Math.ceil((r?e.width:e.height)/a)),c=new Float64Array(s).fill(1/0),i=new Float64Array(s).fill(-1/0),u=[[0,0],[0,0],[0,0]],h=[],{triangles:m}=e;for(let o=0;o<m.length;o+=3){for(let s=0;s<3;s++)t(e,n,m[o+s],u[s]),r&&([u[s][0],u[s][1]]=[u[s][1],u[s][0]]),u[s][0]/=a,u[s][1]/=a;const l=Math.max(0,Math.floor(Math.min(u[0][0],u[1][0],u[2][0]))),f=Math.min(s-1,Math.floor(Math.max(u[0][0],u[1][0],u[2][0])));for(let t=l;t<=f;t++){h.length=0;for(let e=0;e<3;e++){const n=u[e],a=u[(e+1)%3];n[0]>=t&&n[0]<=t+1&&h.push(n[1]),(n[0]-t)*(a[0]-t)<0&&h.push(n[1]+(t-n[0])/(a[0]-n[0])*(a[1]-n[1])),(n[0]-t-1)*(a[0]-t-1)<0&&h.push(n[1]+(t+1-n[0])/(a[0]-n[0])*(a[1]-n[1]));}for(const e of h)c[t]=Math.min(c[t],e),i[t]=Math.max(i[t],e);}}const f=s+2*o,p=new Int32Array(f).fill(1<<30),M=new Int32Array(f).fill(-(1<<30));for(let t=0;t<s;t++){if(c[t]===1/0)continue;const e=Math.max(0,Math.floor(c[t])),n=Math.min(l,Math.ceil(i[t]));for(let a=0;a<=2*o;a++)p[t+a]=Math.min(p[t+a],e),M[t+a]=Math.max(M[t+a],n+2*o);}for(let t=0;t<f;t++)M[t]<p[t]&&(p[t]=1<<30,M[t]=-(1<<30));return {w:f,h:l+2*o,bottom:p,top:M}}function n(t){const{w:e,h:n,bottom:a,top:o}=t,r=new Int32Array(e),s=new Int32Array(e);for(let t=0;t<e;t++){const e=o[t]<a[t];r[t]=e?1<<30:n-o[t],s[t]=e?-(1<<30):n-a[t];}return {w:e,h:n,bottom:r,top:s}}function a(t){const e=[];let n=0,a=0;for(let o=0;o<t.w;o++)t.top[o]<t.bottom[o]||(e.push(o),n=Math.max(n,t.top[o]),a+=t.bottom[o]);return {...t,columns:Int32Array.from(e),topMax:n,bottomSum:a}}return {packCharts:function(o,r,s,l=(t=>t>512?2:4)(s)){const c=[];o.forEach((t,e)=>{if(r[e])for(const n of t.charts)n.metersPerUv>0&&c.push({meshIndex:e,chart:n,uv:t.uv});});const i=o.map(()=>null);if(0===c.length)return i;const u=Math.min(s,512),h=s/u,m=Math.max(1,Math.ceil(l/h)),f=t=>{const o=h/t,r=c.map(({chart:t,uv:r})=>{const s=e(t,r,o,m,!1),l=e(t,r,o,m,!0);return {area:t.worldArea,outlines:[s,l,n(s),n(l)].map(a)}}),s=function(t,e){const n=new Int32Array(e),a=new Array(t.length),o=t.map((t,e)=>e).sort((e,n)=>t[n].area-t[e].area);for(const r of o){let o=null;for(let a=0;a<4;a++){const{w:s,bottom:l,columns:c,topMax:i,bottomSum:u}=t[r].outlines[a],h=c.length;if(!(s>e||0===h))for(let t=0;t+s<=e;t++){const r=o?o.peak-i:e-i;let s=0,m=0,f=!1;for(let e=0;e<h;e++){const a=c[e],o=n[t+a],i=o-l[a];if(i>s&&(s=i,s>r)){f=!0;break}m+=o;}if(f)continue;const p=s+i,M=h*s+u-m;(!o||p<o.peak||p===o.peak&&M<o.waste)&&(o={x:t,y:s,variant:a,peak:p,waste:M});}}if(!o)return null;const{top:s,columns:l}=t[r].outlines[o.variant];for(const t of l)n[o.x+t]=o.y+s[t];a[r]=o;}return a}(r,u);return s?{placements:s,items:r,cell:o}:null},p=c.reduce((t,{chart:e})=>t+e.worldArea,0),M=s/Math.sqrt(Math.max(p,1e-9));let w=.25*M,y=M,v=f(w);for(let t=0;t<7;t++){const t=(w+y)/2,e=f(t);e?(w=t,v=e):y=t;}if(!v)return i;o.forEach((t,e)=>{r[e]&&(i[e]=new Float32Array(2*t.vertexCount).fill(-10));});const g=[0,0];return c.forEach(({meshIndex:e,chart:n,uv:a},o)=>{const r=i[e],{x:l,y:c,variant:u}=v.placements[o],{h:f}=v.items[o].outlines[u],p=1===u||3===u,M=u>=2;for(const e of n.vertices){t(n,a,e,g);let o=g[0]/v.cell,i=g[1]/v.cell;p&&([o,i]=[i,o]),i+=m,M&&(i=f-i),r[2*e]=(l+m+o)*h/s,r[2*e+1]=(c+i)*h/s;}}),i}}}function createPacker(t){const e=t.map(t=>({charts:t.userData.environmentShadowCharts??[],uv:t.geometry.attributes.lightmapUv?.array.slice()??new Float32Array(0),vertexCount:t.geometry.attributes.position.count}));let n=null,a=null;if("undefined"!=typeof Worker){const t=`const { packCharts } = ( ${packerModule.toString()} )();\n let meshData = null;\n self.onmessage = ( event ) => {\n const message = event.data;\n if ( message.type === 'init' ) { meshData = message.meshData; return; }\n const layout = packCharts( meshData, message.visible, message.atlasSize );\n self.postMessage( { id: message.id, layout }, layout.filter( Boolean ).map( ( uvs ) => uvs.buffer ) );\n };`;a=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),n=new Worker(a),n.postMessage({type:"init",meshData:e});}const{packCharts:o}=packerModule(),r=new Map;let s=0;return n&&(n.onmessage=t=>{const{id:e,layout:n}=t.data;r.get(e)?.(n),r.delete(e);}),{pack(t,a){if(!n)return Promise.resolve(o(e,t,a));const l=s++;return new Promise(e=>{r.set(l,e),n.postMessage({type:"pack",id:l,visible:t,atlasSize:a});})},dispose(){n?.terminate(),null!==a&&URL.revokeObjectURL(a),r.clear();}}}
8
+
9
+ const UV_ATTRIBUTES=["lightmapUvBake","lightmapUvA","lightmapUvB"];function unwrapModule(){function t(t,e){const r=e.attributes.position,n=r.array.length/r.itemSize,a=e.index??Uint32Array.from({length:n},(t,e)=>e);if(n>=65536)throw new Error("EnvironmentShadows: xatlas-web needs meshes with fewer than 65536 vertices.");const o=e.attributes.normal,s=e.attributes.uv;t.createAtlas();const i=t.createMesh(n,a.length,!0,!0);t.HEAPU16.set(a,i.indexOffset/2),t.HEAPF32.set(r.array,i.positionOffset/4),t.HEAPF32.set(o?o.array:new Float32Array(3*n),i.normalOffset/4),t.HEAPF32.set(s?s.array:new Float32Array(2*n),i.uvOffset/4);const l=t.addMesh();if(0!==l)throw t.destroyAtlas(),new Error(`EnvironmentShadows: xatlas could not add a mesh (${l}).`);t.generateAtlas();const u=t.getMeshData(i.meshId),f=u.newVertexCount,c=new Float32Array(t.HEAPF32.buffer,u.uvOffset,2*f).slice(),m=new Uint32Array(t.HEAPU32.buffer,u.indexOffset,u.newIndexCount).slice(),h=new Uint32Array(t.HEAPU32.buffer,u.originalIndexOffset,f).slice();t.destroyAtlas();let w=0,A=0;for(let t=0;t<f;t++)w=Math.max(w,c[2*t]),A=Math.max(A,c[2*t+1]);if(w>1.001||A>1.001)for(let t=0;t<f;t++)c[2*t]/=Math.max(w,1e-6),c[2*t+1]/=Math.max(A,1e-6);const d={};for(const t of Object.keys(e.attributes)){const{array:r,itemSize:n,normalized:a}=e.attributes[t],o=new r.constructor(f*n);for(let t=0;t<f;t++)for(let e=0;e<n;e++)o[t*n+e]=r[h[t]*n+e];d[t]={array:o,itemSize:n,normalized:a};}d.lightmapUv={array:c,itemSize:2,normalized:!1};const p=function(t,e,r,n){const a=r.length/2,o=e.array,s=e.itemSize,i=new Int32Array(a).map((t,e)=>e),l=t=>{for(;i[t]!==t;)t=i[t]=i[i[t]];return t},u=(t,e)=>{const r=l(t),n=l(e);r!==n&&(i[r]=n);};for(let e=0;e<t.length;e+=3)u(t[e],t[e+1]),u(t[e],t[e+2]);const f=(t,e)=>{const r=o[t*s],a=o[t*s+1],i=o[t*s+2];return e[0]=n[0]*r+n[4]*a+n[8]*i+n[12],e[1]=n[1]*r+n[5]*a+n[9]*i+n[13],e[2]=n[2]*r+n[6]*a+n[10]*i+n[14],e},c=[0,0,0],m=[0,0,0],h=[0,0,0],w=new Map,A=t=>{let e=w.get(t);return e||(e={vertices:[],triangles:[],worldArea:0,uvArea:0},w.set(t,e)),e};for(let t=0;t<a;t++)A(l(t)).vertices.push(t);for(let e=0;e<t.length;e+=3){const n=t[e],a=t[e+1],o=t[e+2],s=w.get(l(n));s.triangles.push(n,a,o),f(n,c),f(a,m),f(o,h);const i=m[0]-c[0],u=m[1]-c[1],A=m[2]-c[2],d=h[0]-c[0],p=h[1]-c[1],y=h[2]-c[2];s.worldArea+=Math.hypot(u*y-A*p,A*d-i*y,i*p-u*d)/2;const g=r[2*a]-r[2*n],b=r[2*a+1]-r[2*n+1],x=r[2*o]-r[2*n],U=r[2*o+1]-r[2*n+1];s.uvArea+=Math.abs(g*U-x*b)/2;}return [...w.values()].map(t=>{const e=Uint32Array.from(t.vertices),n=t.uvArea>1e-12?Math.sqrt(t.worldArea/t.uvArea):0,{cos:a,sin:o,minU:s,minV:i,maxU:l,maxV:u}=function(t,e){const r=Array.from(t,t=>[e[2*t],e[2*t+1]]),n=r.length>2?function(t){const e=t.slice().sort((t,e)=>t[0]-e[0]||t[1]-e[1]),r=(t,e,r)=>(e[0]-t[0])*(r[1]-t[1])-(e[1]-t[1])*(r[0]-t[0]),n=[],a=[];for(const t of e){for(;n.length>=2&&r(n[n.length-2],n[n.length-1],t)<=0;)n.pop();n.push(t);}for(let t=e.length-1;t>=0;t--){const n=e[t];for(;a.length>=2&&r(a[a.length-2],a[a.length-1],n)<=0;)a.pop();a.push(n);}return a.pop(),n.pop(),n.concat(a)}(r):r;let a=null;const o=(t,e)=>{let r=1/0,o=1/0,s=-1/0,i=-1/0;for(const[a,l]of n){const n=t*a+e*l,u=-e*a+t*l;r=Math.min(r,n),o=Math.min(o,u),s=Math.max(s,n),i=Math.max(i,u);}const l=(s-r)*(i-o);(!a||l<a.area-1e-12)&&(a={cos:t,sin:e,minU:r,minV:o,maxU:s,maxV:i,area:l});};o(1,0);for(let t=0;t<n.length;t++){const[e,r]=n[t],[a,s]=n[(t+1)%n.length],i=Math.hypot(a-e,s-r);i>1e-12&&o((a-e)/i,(s-r)/i);}return a}(e,r);return {vertices:e,triangles:Uint32Array.from(t.triangles),worldArea:t.worldArea,metersPerUv:n,cos:a,sin:o,minU:s,minV:i,width:(l-s)*n,height:(u-i)*n}})}(m,d.position,c,e.matrix);return {index:m,attributes:d,charts:p}}return {unwrapAll:async function(e,r,n){const a=e({wasmBinary:r});return await a.ready,n.map(e=>t(a,e))}}}const XATLAS_FACTORY=`globalThis.window ??= globalThis;\n globalThis.document ??= { currentScript: null };\n const createXAtlas = ( function () { ${xatlasSource}\n ; return Module; } )();`;let wasmPromise=null;const loadWasm=t=>(wasmPromise??=fetch(t).then(e=>{if(!e.ok)throw new Error(`EnvironmentShadows: Could not load ${t}.`);return e.arrayBuffer()}),wasmPromise);async function runUnwrap(t,e){const r=(await loadWasm(t)).slice(0);if("undefined"==typeof Worker){const{createXAtlas:t,unwrapAll:n}=new Function(`${XATLAS_FACTORY}\n return { createXAtlas, unwrapAll: ( ${unwrapModule.toString()} )().unwrapAll };`)();return n(t,r,e)}const n=`${XATLAS_FACTORY}\n const { unwrapAll } = ( ${unwrapModule.toString()} )();\n self.onmessage = async ( event ) => {\n try {\n const results = await unwrapAll( createXAtlas, event.data.wasm, event.data.meshes );\n const buffers = [];\n for ( const result of results ) {\n buffers.push( result.index.buffer );\n for ( const attribute of Object.values( result.attributes ) ) buffers.push( attribute.array.buffer );\n }\n self.postMessage( { results }, buffers );\n } catch ( error ) {\n self.postMessage( { error: error.message } );\n }\n };`,a=URL.createObjectURL(new Blob([n],{type:"application/javascript"})),o=new Worker(a);try{return await new Promise((t,n)=>{o.onmessage=e=>e.data.error?n(new Error(e.data.error)):t(e.data.results),o.onerror=t=>n(new Error(`EnvironmentShadows: Unwrap failed (${t.message}).`)),o.postMessage({wasm:r,meshes:e},[r]);})}finally{o.terminate(),URL.revokeObjectURL(a);}}const toArray=t=>{const{count:e,itemSize:r}=t,n=new Float32Array(e*r);for(let a=0;a<e;a++)for(let e=0;e<r;e++)n[a*r+e]=t.getComponent(a,e);return n};async function unwrapMeshes(t,e,r){for(const t of e){const e=t.geometry,r=e.attributes.position.count;for(const t of UV_ATTRIBUTES)e.attributes[t]||e.setAttribute(t,new BufferAttribute(new Float32Array(2*r).fill(NO_PLACE),2));}const n=t.filter(t=>!t.userData.environmentShadowCharts);if(0===n.length)return;const a=n.map(t=>{t.updateMatrixWorld();const e=t.geometry,r={};for(const t of Object.keys(e.attributes)){const n=e.attributes[t];r[t]={array:n.isInterleavedBufferAttribute?toArray(n):n.array.slice(),itemSize:n.itemSize,normalized:n.normalized};}return {index:e.index?Uint32Array.from(e.index.array):null,attributes:r,matrix:Float32Array.from(t.matrixWorld.elements)}}),o=await runUnwrap(r,a);n.forEach((t,e)=>{const{index:r,attributes:n,charts:a}=o[e],s=new BufferGeometry;for(const[t,{array:e,itemSize:r,normalized:a}]of Object.entries(n))s.setAttribute(t,new BufferAttribute(e,r,a));const i=s.attributes.position.count;for(const t of UV_ATTRIBUTES)s.setAttribute(t,new BufferAttribute(new Float32Array(2*i).fill(NO_PLACE),2));s.setIndex(new BufferAttribute(r,1)),s.computeBoundingSphere(),t.userData.environmentShadowCharts=a,t.geometry.dispose(),t.geometry=s;});}function setLayout(t,e,r){t.forEach((t,n)=>{const a=t.geometry.attributes[e];r[n]?a.array.set(r[n]):a.array.fill(NO_PLACE),a.needsUpdate=!0;});}
10
+
11
+ const SLOTS=["lightmapUvA","lightmapUvB"],_box=new Box3,_sphere=new Sphere,_matrix=new Matrix4,_frustum=new Frustum,_clearColor=new Color,_axis=new Vector3,_tangent=new Vector3,_bitangent=new Vector3;function jitterDirection(e,t,s,i){if(t<=0)return e;_axis.copy(e),_tangent.set(Math.abs(_axis.y)<.99?0:1,Math.abs(_axis.y)<.99?1:0,0).cross(_axis).normalize(),_bitangent.crossVectors(_axis,_tangent);const a=1-i*(1-Math.cos(t)),r=Math.sqrt(Math.max(0,1-a*a)),h=2*Math.PI*s;return e.copy(_axis).multiplyScalar(a).addScaledVector(_tangent,r*Math.cos(h)).addScaledVector(_bitangent,r*Math.sin(h)).normalize()}const makeTarget=(e,t,s)=>new WebGLRenderTarget(e,e,{type:t,minFilter:s,magFilter:s,depthBuffer:!1,generateMipmaps:!1});class EnvironmentShadowsBase{constructor(e,t,s={},i){this.isEnvironmentShadows=!0,this.renderer=e,this.scene=t,this.samplesPerFrame=s.samplesPerFrame??24,this.samplesPerBake=s.samplesPerBake??512,this.fadeTime=s.fadeTime??.3,this.atlasSize=s.atlasSize??1024,this.mapSize=s.mapSize??512,this.shadowNoise=s.shadowNoise??8,this.directionJitter=s.directionJitter??2,this.specularOcclusion=s.specularOcclusion??!0,this.frustumAtlas=s.frustumAtlas??!0,this.frustumMargin=s.frustumMargin??20,this.bounds=s.bounds?s.bounds.clone():null,this.needsUpdate=!1,this._backend=i,this._xatlasWasmUrl=s.xatlasWasmUrl??new URL("./xatlas-web.wasm",import.meta.url).href,this._disposed=!1,this._initialized=!1,this.ready=this._init(s.meshes??null);}async _init(e){const t=e??[];if(null===e&&this.scene.traverse(e=>e.isMesh&&t.push(e)),this.scene.updateMatrixWorld(),this._receivers=t.filter(e=>e.receiveShadow),this._meshes=t.filter(e=>e.receiveShadow||e.castShadow),await unwrapMeshes(this._receivers,this._meshes.filter(e=>!e.receiveShadow),this._xatlasWasmUrl),this._disposed)return this;if(null===this.bounds){_box.makeEmpty();for(const e of this._meshes)_box.expandByObject(e);this.bounds=_box.isEmpty()?new Sphere(new Vector3,1):_box.getBoundingSphere(new Sphere);}const s=this._backend,i=this.renderer;this._bakeScene=new Scene,this._bakeCameras=[],this._bake=s.createBakeMaterial(),this._proxies=this._meshes.map(e=>{const t=new Mesh(e.geometry,this._bake.material);return t.matrixAutoUpdate=!1,t.matrixWorldAutoUpdate=!1,t.frustumCulled=!1,t.castShadow=e.castShadow,t.receiveShadow=!0,this._bakeScene.add(t),t}),this._light=new DirectionalLight(16777215,1),this._light.castShadow=!0,this._light.shadow.mapSize.setScalar(this.mapSize),this._lightTarget=new Object3D,this._light.target=this._lightTarget,this._bakeScene.add(this._light,this._lightTarget),this._sumType=s.getSumType(i),this._display=s.createDisplay(),this._createTargets(),this._packer=createPacker(this._meshes),this._lastMatrices=this._meshes.map(e=>e.matrixWorld.clone()),this._layout=null,this._layoutKey=null,this._layoutPending=!1,this._bakeKey=null,this._bakeLayout=this._meshes.map(()=>null),this._visible=this._meshes.map(()=>!0),this._visibleKey="",this._environment=null,this._environmentVersion=-1,this._sample=null,this._sequence=0,this._baking=!1,this._dirty=!1,this._hasFront=!1,this._front=0,this._count=0,this._bakeSamples=this.samplesPerBake,this._bakeAtlasSize=this.atlasSize,this._bakeMapSize=this.mapSize,this._fade=1,this._lastTime=null;for(const e of this._receivers)this._patch(e.material);return this._initialized=!0,this}_patch(e){const t=Array.isArray(e)?e:[e];for(const e of t)this._display.patch(e);}_createTargets(){const e=this.atlasSize;this._sumTarget=makeTarget(e,this._sumType,NearestFilter),this._lightmaps=[makeTarget(e,HalfFloatType,LinearFilter),makeTarget(e,HalfFloatType,LinearFilter)],this._front=0,this._finalize=this._backend.createFinalize(this._sumTarget.texture,e);const t=this._display.uniforms;t.a.value=this._lightmaps[0].texture,t.b.value=this._lightmaps[1].texture,t.frontIsA.value=1,t.valid.value=0,this._display.refresh();}_disposeTargets(){this._sumTarget.dispose();for(const e of this._lightmaps)e.dispose();this._finalize.dispose();}_updateVisible(e){e.updateMatrixWorld(),_matrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),_frustum.setFromProjectionMatrix(_matrix,e.coordinateSystem),this._visible=this._meshes.map(e=>!!e.receiveShadow&&(!this.frustumAtlas||(null===e.geometry.boundingSphere&&e.geometry.computeBoundingSphere(),_sphere.copy(e.geometry.boundingSphere).applyMatrix4(e.matrixWorld),_sphere.radius*=1+this.frustumMargin/100,_frustum.intersectsSphere(_sphere)))),this._visibleKey=`${this._visible.map(e=>e?"1":"0").join("")}|${this.atlasSize}`;}_requestLayout(){const e=this._visibleKey;this._layoutPending=!0,this._packer.pack(this._visible.slice(),this.atlasSize).then(t=>{this._layoutPending=!1,this._disposed||(this._layout=t,this._layoutKey=e);});}_updateEnvironment(){const e=this.scene.environment,t=e&&e.image&&(e.image.data||e.image.width>0);(e!==this._environment||e&&e.version!==this._environmentVersion)&&(e&&!t||(this._environment=e,this._environmentVersion=e?e.version:-1,this._sample=e?createEnvironmentSampler(downsampleEquirect(e,512)):null,this._dirty=!0,e||(this._display.uniforms.valid.value=0)));}_detectMovement(){let e=!1;return this._meshes.forEach((t,s)=>{this._lastMatrices[s].equals(t.matrixWorld)||(this._lastMatrices[s].copy(t.matrixWorld),e=!0);}),e}_startBake(){this._meshes.forEach((e,t)=>this._proxies[t].matrixWorld.copy(e.matrixWorld)),this._bakeLayout=this._layout,this._bakeKey=this._layoutKey,setLayout(this._meshes,"lightmapUvBake",this._bakeLayout),this._hasFront||setLayout(this._meshes,SLOTS[this._front],this._bakeLayout);const e=this.renderer,t=e.getRenderTarget();e.setRenderTarget(this._sumTarget),e.setClearColor(0,0),e.clear(),e.setRenderTarget(t),this._count=0,this._bakeSamples=Math.max(1,Math.round(this.samplesPerBake)),this._baking=!0,this._dirty=!1;}_renderSamples(e){const t=this.renderer,{center:s,radius:i}=this.bounds,a=this._light,r=a.shadow.camera,h=this._bake.uniforms;t.setRenderTarget(this._sumTarget);for(let n=0;n<e;n++){const e=this._bakeCameras[n]??=new OrthographicCamera,o=++this._sequence,{direction:l,color:_}=this._sample(halton(o,2),halton(o,3),halton(o,5),halton(o,7));jitterDirection(l,MathUtils.degToRad(Math.min(180,this.directionJitter)),halton(o,11),halton(o,13)),a.position.copy(l).multiplyScalar(2*i).add(s),this._lightTarget.position.copy(s),a.color.copy(_).multiplyScalar(1/this._bakeSamples),r.left=-i,r.right=i,r.top=i,r.bottom=-i,r.near=i,r.far=3*i,r.updateProjectionMatrix(),a.shadow.normalBias=2*i/this.mapSize,h.seed.value=o%4096,h.noise.value=this.shadowNoise,h.mapTexel.value=1/this.mapSize,h.shadowExtent.value=2*i,h.lightDirection.value.copy(l),this._backend.beforeSample?.(t),t.render(this._bakeScene,e),this._count++;}}_renderFinalize(e){const t=this.renderer;this._finalize.uniforms.scale.value=this._bakeSamples,t.setRenderTarget(e),this._backend.renderQuad(t,this._finalize.material);}_rebuild(){this._disposeTargets(),this._light.shadow.mapSize.setScalar(this.mapSize),this._light.shadow.map?.dispose(),this._light.shadow.map=null,this._createTargets(),this._bakeAtlasSize=this.atlasSize,this._bakeMapSize=this.mapSize,this._hasFront=!1,this._baking=!1,this._dirty=!0,this._bakeKey=null;for(const e of SLOTS)setLayout(this._meshes,e,this._meshes.map(()=>null));}update(e){if(!this._initialized||this._disposed)return;const t=performance.now(),s=null===this._lastTime?0:Math.min(.1,(t-this._lastTime)/1e3);if(this._lastTime=t,this.atlasSize===this._bakeAtlasSize&&this.mapSize===this._bakeMapSize||this._rebuild(),this._updateEnvironment(),!this._sample)return;(this._detectMovement()||this.needsUpdate)&&(this._dirty=!0,this.needsUpdate=!1),this._updateVisible(e),this._visibleKey===this._layoutKey||this._layoutPending||this._requestLayout(),this._layoutKey!==this._bakeKey&&(this._dirty=!0),!this._baking&&this._dirty&&this._layout&&this._startBake();const i=this.renderer,a=this._display.uniforms;if(this._baking){const e=i.getRenderTarget(),t=i.autoClear,s=i.shadowMap.enabled,r=i.shadowMap.type,h=i.getClearAlpha();if(i.getClearColor(_clearColor),i.autoClear=!1,i.shadowMap.enabled=!0,i.shadowMap.type=BasicShadowMap,this._renderSamples(Math.min(Math.max(0,Math.round(this.samplesPerFrame)),this._bakeSamples-this._count)),this._hasFront||(this._renderFinalize(this._lightmaps[this._front]),a.valid.value=1,a.blend.value=1),this._count>=this._bakeSamples)if(this._baking=!1,this._hasFront){const e=1-this._front;this._renderFinalize(this._lightmaps[e]),setLayout(this._meshes,SLOTS[e],this._bakeLayout),this._front=e,a.frontIsA.value=0===e?1:0,this._fade=0,a.blend.value=0;}else this._hasFront=!0,this._fade=1;i.setRenderTarget(e),i.setClearColor(_clearColor,h),i.autoClear=t,i.shadowMap.enabled=s,i.shadowMap.type=r;}this._fade<1&&(this._fade=Math.min(1,this._fade+s/Math.max(.001,this.fadeTime)),a.blend.value=this._fade),a.specularOcclusion.value=this.specularOcclusion?1:0;}dispose(){if(this._disposed=!0,this._initialized){for(const e of this._receivers){const t=Array.isArray(e.material)?e.material:[e.material];for(const e of t)this._display.unpatch(e);}this._disposeTargets(),this._bake.material.dispose(),this._light.dispose(),this._packer.dispose();}}}
12
+
13
+ export { EnvironmentShadowsBase as E };
package/webgpu.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ import type { Camera, Scene, Sphere } from 'three';
2
+ import type { WebGPURenderer } from 'three/webgpu';
3
+ import type { EnvironmentShadowsOptions } from './index.js';
4
+
5
+ export type { EnvironmentShadowsOptions };
6
+
7
+ /**
8
+ * Soft, colored shadows from the whole environment map (`scene.environment`), for WebGPURenderer
9
+ * (WebGPU and its WebGL 2 fallback). Materials of the receivers must be node materials.
10
+ */
11
+ export class EnvironmentShadows {
12
+ constructor(renderer: WebGPURenderer, scene: Scene, options?: EnvironmentShadowsOptions);
13
+
14
+ readonly isEnvironmentShadows: true;
15
+ readonly renderer: WebGPURenderer;
16
+ readonly scene: Scene;
17
+
18
+ samplesPerFrame: number;
19
+ samplesPerBake: number;
20
+ fadeTime: number;
21
+ atlasSize: number;
22
+ mapSize: number;
23
+ shadowNoise: number;
24
+ directionJitter: number;
25
+ specularOcclusion: boolean;
26
+ frustumAtlas: boolean;
27
+ frustumMargin: number;
28
+ bounds: Sphere | null;
29
+ needsUpdate: boolean;
30
+
31
+ readonly ready: Promise<this>;
32
+
33
+ update(camera: Camera): void;
34
+
35
+ dispose(): void;
36
+ }
package/webgpu.js ADDED
@@ -0,0 +1,10 @@
1
+ import { E as EnvironmentShadowsBase } from './shared.js';
2
+ import { FloatType, HalfFloatType, Vector3, DoubleSide, CustomBlending, AddEquation, OneFactor, BackSide, Texture } from 'three';
3
+ import { QuadMesh, MeshLambertNodeMaterial, NodeMaterial, LightingNode } from 'three/webgpu';
4
+ import { uniform, attribute, vec4, float, cameraViewMatrix, modelNormalMatrix, normalLocal, select, vec3, cross, screenCoordinate, hash, positionWorld, Fn, ivec2, textureLoad, If, texture, renderGroup, reference, mix, clamp, dot, max } from 'three/tsl';
5
+
6
+ class EnvironmentShadowsLightingNode extends LightingNode{static get type(){return "EnvironmentShadowsLightingNode"}constructor(e){super(),this.display=e;}setup(e){const{iblIrradiance:t,radiance:r}=e.context,a=this.display,n=vec3(t).toVar(),o=e.material.envMap?reference("envMapIntensity","float",e.material):reference("environmentIntensity","float",e.scene),i=select(a.uvA.x.greaterThan(1e-6),a.sampleA.rgb.mul(o),n),s=select(a.uvB.x.greaterThan(1e-6),a.sampleB.rgb.mul(o),n),l=a.frontIsA.greaterThan(.5),d=select(l,i,s),u=select(l,s,i),c=select(a.valid.greaterThan(.5),mix(u,d,a.blend),n).toVar(),m=vec3(.2126,.7152,.0722),p=clamp(dot(c,m).div(max(dot(n,m),1e-6)),0,1);t.assign(c),r.mulAssign(mix(float(1),p,a.specularOcclusion));}}const quad=new QuadMesh,OFFSETS=[];for(let e=-4;e<=4;e++)for(let t=-4;t<=4;t++)0===t&&0===e||OFFSETS.push([t,e]);OFFSETS.sort((e,t)=>e[0]*e[0]+e[1]*e[1]-(t[0]*t[0]+t[1]*t[1]));const tslBackend={getSumType(e){const t=e.backend;return (t.isWebGLBackend?null!==t.gl.getExtension("EXT_float_blend"):e.hasFeature("float32-blendable"))?FloatType:HalfFloatType},createBakeMaterial(){const e={noise:uniform(0),seed:uniform(0),mapTexel:uniform(1/512),shadowExtent:uniform(1),lightDirection:uniform(new Vector3(0,1,0))},t=new MeshLambertNodeMaterial({color:16777215,side:DoubleSide,forceSinglePass:!0,blending:CustomBlending,blendEquation:AddEquation,blendSrc:OneFactor,blendDst:OneFactor,blendSrcAlpha:OneFactor,blendDstAlpha:OneFactor,depthTest:!1,depthWrite:!1});t.shadowSide=BackSide;const r=attribute("lightmapUvBake","vec2");if(t.vertexNode=vec4(r.x.mul(2).sub(1),float(1).sub(r.y.mul(2)),0,1),t.normalNode=cameraViewMatrix.mul(vec4(modelNormalMatrix.mul(normalLocal),0)).xyz.normalize(),"receivedShadowPositionNode"in t){const r=e.lightDirection.normalize(),a=select(r.y.abs().lessThan(.99),vec3(0,1,0),vec3(1,0,0)),n=cross(a,r).normalize(),o=cross(r,n),i=screenCoordinate.x.add(screenCoordinate.y.mul(4099)).add(e.seed.mul(7919)),s=n.mul(hash(i).mul(2).sub(1)).add(o.mul(hash(i.add(1337)).mul(2).sub(1))).mul(e.noise.mul(e.mapTexel).mul(e.shadowExtent));t.receivedShadowPositionNode=positionWorld.add(s);}return {material:t,uniforms:e}},createFinalize(e,t){const r=uniform(1),a=Fn(()=>{const a=ivec2(screenCoordinate.xy),n=vec4(0).toVar(),o=textureLoad(e,a);return If(o.a.greaterThan(0),()=>{n.assign(vec4(o.rgb.mul(r).div(o.a),1));}).Else(()=>{for(const[o,i]of OFFSETS)If(n.a.equal(0),()=>{const s=a.add(ivec2(o,i)).max(ivec2(0,0)).min(ivec2(t-1,t-1)),l=textureLoad(e,s);If(l.a.greaterThan(0),()=>{n.assign(vec4(l.rgb.mul(r).div(l.a),1));});});}),n}),n=new NodeMaterial;return n.fragmentNode=a(),n.depthTest=!1,n.depthWrite=!1,{material:n,uniforms:{scale:r},dispose:()=>n.dispose()}},beforeSample(e){e._nodes.nodeFrame.update();},renderQuad(e,t){quad.material=t,quad.render(e);},createDisplay(){const e=attribute("lightmapUvA","vec2"),t=attribute("lightmapUvB","vec2"),r={uvA:e,uvB:t,sampleA:texture(new Texture,e),sampleB:texture(new Texture,t),frontIsA:uniform(1).setGroup(renderGroup),blend:uniform(1).setGroup(renderGroup),valid:uniform(0).setGroup(renderGroup),specularOcclusion:uniform(1).setGroup(renderGroup)},a=new WeakSet,n=new Set;return {uniforms:{a:r.sampleA,b:r.sampleB,frontIsA:r.frontIsA,blend:r.blend,valid:r.valid,specularOcclusion:r.specularOcclusion},refresh(){for(const e of n)e.needsUpdate=!0;},patch(e){if(a.has(e))return;if(!e.isNodeMaterial)return void console.warn("EnvironmentShadows: WebGPURenderer needs node materials (e.g. MeshStandardNodeMaterial), skipped",e);const t=Object.getPrototypeOf(e);"function"==typeof t.setupMaterialLightings?e.setupMaterialLightings=function(e){const a=t.setupMaterialLightings.call(this,e);return a.push(new EnvironmentShadowsLightingNode(r)),a}:e.setupLights=function(e){const a=t.setupLights.call(this,e),n=new EnvironmentShadowsLightingNode(r);return e.renderer.lighting.createNode([...a.getLights(),n])},a.add(e),n.add(e),e.needsUpdate=!0;},unpatch(e){a.has(e)&&(delete e.setupMaterialLightings,delete e.setupLights,a.delete(e),n.delete(e),e.needsUpdate=!0);}}}};
7
+
8
+ class EnvironmentShadows extends EnvironmentShadowsBase{constructor(s,n,o={}){super(s,n,o,tslBackend);}}
9
+
10
+ export { EnvironmentShadows };
Binary file