├── .gitignore
├── LICENSE
├── README.md
├── cover.jpg
├── dist
├── assets
│ ├── bead.glb
│ └── normal.png
├── index-6ca6b2e6.css
├── index-be83070f.js
└── index.html
├── package-lock.json
├── package.json
├── src
├── app
│ ├── _sketch-template.js
│ ├── app.js
│ ├── audio-repeater.js
│ ├── is-ios.js
│ ├── shader
│ │ ├── bead.frag.glsl
│ │ ├── bead.vert.glsl
│ │ ├── blur.frag.glsl
│ │ ├── blur.vert.glsl
│ │ ├── composite.frag.glsl
│ │ ├── composite.vert.glsl
│ │ ├── highpass.frag.glsl
│ │ ├── highpass.vert.glsl
│ │ ├── light-depth.frag.glsl
│ │ ├── sph
│ │ │ ├── draw.frag.glsl
│ │ │ ├── draw.vert.glsl
│ │ │ ├── force.frag.glsl
│ │ │ ├── force.vert.glsl
│ │ │ ├── indices.frag.glsl
│ │ │ ├── indices.vert.glsl
│ │ │ ├── integrate.frag.glsl
│ │ │ ├── integrate.vert.glsl
│ │ │ ├── offset.frag.glsl
│ │ │ ├── offset.vert.glsl
│ │ │ ├── pressure.frag.glsl
│ │ │ ├── pressure.vert.glsl
│ │ │ ├── sort.frag.glsl
│ │ │ ├── sort.vert.glsl
│ │ │ └── utils
│ │ │ │ └── particle-utils.glsl
│ │ ├── test.frag.glsl
│ │ └── test.vert.glsl
│ ├── sketch.js
│ └── utils
│ │ ├── glb-builder.js
│ │ └── modernizr.js
├── assets
│ ├── bead.glb
│ ├── env-map-01.jpg
│ ├── env-map-02.jpg
│ └── normal.png
├── index.html
└── styles.css
└── vite.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 |
84 | # Gatsby files
85 | .cache/
86 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
87 | # https://nextjs.org/blog/next-9-1#public-directory-support
88 | # public
89 |
90 | # vuepress build output
91 | .vuepress/dist
92 |
93 | # Serverless directories
94 | .serverless/
95 |
96 | # FuseBox cache
97 | .fusebox/
98 |
99 | # DynamoDB Local files
100 | .dynamodb/
101 |
102 | # TernJS port file
103 | .tern-port
104 |
105 | src/libs/**
106 | .DS_Store
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Robert Leitl
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Liquid-Geo
2 |
3 | 
4 |
5 | This web experiment is inspired by the liquid-geo interface designs form the movie [Man of Steel](https://en.wikipedia.org/wiki/Man_of_Steel_(film)). It allows the user to record a short audio snippet. This snippet can then be played back in a distorted version and the sphere responds to the audio signal. In addition, the beads on the surface of the sphere can be manipulated by touch or mouse movement.
6 |
7 | [DEMO](https://robert-leitl.github.io/liquid-geo/dist/?debug=true)
8 |
9 | ### Features
10 | - SPH fluid simulation on sphere surface [Github Repo](https://robert-leitl.github.io/gpgpu-2d-sph-fluid-simulation)
11 | - Screen-space halo and bloom effect inspired by this [article](https://john-chapman.github.io/2017/11/05/pseudo-lens-flare.html) from John Chapman.
12 | - Audio recording and distorted playback using web audio API and tone.js.
--------------------------------------------------------------------------------
/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robert-leitl/liquid-geo/ec7c6907c7c14bf54a63eca593bf7716575866ba/cover.jpg
--------------------------------------------------------------------------------
/dist/assets/bead.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robert-leitl/liquid-geo/ec7c6907c7c14bf54a63eca593bf7716575866ba/dist/assets/bead.glb
--------------------------------------------------------------------------------
/dist/assets/normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robert-leitl/liquid-geo/ec7c6907c7c14bf54a63eca593bf7716575866ba/dist/assets/normal.png
--------------------------------------------------------------------------------
/dist/index-6ca6b2e6.css:
--------------------------------------------------------------------------------
1 | *{box-sizing:border-box}html,body{padding:0;margin:0;width:100%;height:100%;width:100dvw;height:100dvh;font-family:Arial,Helvetica Neue,Helvetica,sans-serif;font-size:18px;overflow:hidden;touch-action:none;background-color:#000}body{position:relative}@media screen and (max-width: 640px){body,html{font-size:14px}}canvas{width:100%;height:100%}.github-link{position:absolute;right:0;bottom:0;color:#aaa;mix-blend-mode:difference;text-transform:uppercase;text-decoration:none;padding:.7em 1em;font-size:.8em}.audio-controls{position:absolute;bottom:0;left:0;width:100%;display:flex;align-items:center;justify-content:center;padding:3em 0;pointer-events:none}.audio-controls button{pointer-events:all;cursor:pointer;background:none;border:2px solid #eee;border-radius:10rem;display:flex;align-items:center;min-height:4.25em;width:16em;justify-content:center}@media screen and (min-width: 641px){.audio-controls button{min-height:6em}}.audio-controls button:hover{background:#333}.audio-controls button:disabled{opacity:.4;pointer-events:none}.audio-controls button label{color:#eee;font-size:1.25rem;pointer-events:none}.audio-controls svg{height:2rem;width:2rem;margin-right:.5rem;pointer-events:none}@media (min-aspect-ratio: 7/5){.audio-controls{flex-direction:column;height:100%;padding:0 2em;align-items:flex-end}.audio-controls button+button{margin-top:1em}}@media (max-aspect-ratio: 5/8){.audio-controls{flex-direction:column}.audio-controls button+button{margin-top:1em;margin-left:0!important}}.audio-controls button+button{margin-left:1em}#playback-button svg{width:1.7rem;height:1.7rem}#record-button.is-recording:before{content:"";display:block;width:1.5rem;height:1.5rem;margin-right:.5rem;background:#f22;border-radius:100%}#record-button.is-recording svg{display:none}
2 |
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | liquid-geo
7 |
8 |
9 |
10 |
11 |
12 |
13 | github
14 |
15 |
16 |
22 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "liquid-geo",
3 | "version": "2.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "liquid-geo",
9 | "version": "2.0.0",
10 | "dependencies": {
11 | "@loaders.gl/core": "^3.2.3",
12 | "@loaders.gl/gltf": "^3.2.3",
13 | "gl-matrix": "^3.4.3",
14 | "rxjs": "^7.5.6",
15 | "tone": "^14.7.77",
16 | "tweakpane": "^3.1.0",
17 | "twgl.js": "^5.0.4"
18 | },
19 | "devDependencies": {
20 | "terser": "^5.14.2",
21 | "vite": "^3.0.0",
22 | "vite-plugin-glsl": "^0.3.0"
23 | }
24 | },
25 | "node_modules/@babel/runtime": {
26 | "version": "7.20.1",
27 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.1.tgz",
28 | "integrity": "sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==",
29 | "dependencies": {
30 | "regenerator-runtime": "^0.13.10"
31 | },
32 | "engines": {
33 | "node": ">=6.9.0"
34 | }
35 | },
36 | "node_modules/@esbuild/android-arm": {
37 | "version": "0.15.13",
38 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.13.tgz",
39 | "integrity": "sha512-RY2fVI8O0iFUNvZirXaQ1vMvK0xhCcl0gqRj74Z6yEiO1zAUa7hbsdwZM1kzqbxHK7LFyMizipfXT3JME+12Hw==",
40 | "cpu": [
41 | "arm"
42 | ],
43 | "dev": true,
44 | "optional": true,
45 | "os": [
46 | "android"
47 | ],
48 | "engines": {
49 | "node": ">=12"
50 | }
51 | },
52 | "node_modules/@esbuild/linux-loong64": {
53 | "version": "0.15.13",
54 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.13.tgz",
55 | "integrity": "sha512-+BoyIm4I8uJmH/QDIH0fu7MG0AEx9OXEDXnqptXCwKOlOqZiS4iraH1Nr7/ObLMokW3sOCeBNyD68ATcV9b9Ag==",
56 | "cpu": [
57 | "loong64"
58 | ],
59 | "dev": true,
60 | "optional": true,
61 | "os": [
62 | "linux"
63 | ],
64 | "engines": {
65 | "node": ">=12"
66 | }
67 | },
68 | "node_modules/@jridgewell/gen-mapping": {
69 | "version": "0.3.2",
70 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
71 | "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
72 | "dev": true,
73 | "dependencies": {
74 | "@jridgewell/set-array": "^1.0.1",
75 | "@jridgewell/sourcemap-codec": "^1.4.10",
76 | "@jridgewell/trace-mapping": "^0.3.9"
77 | },
78 | "engines": {
79 | "node": ">=6.0.0"
80 | }
81 | },
82 | "node_modules/@jridgewell/resolve-uri": {
83 | "version": "3.1.0",
84 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
85 | "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
86 | "dev": true,
87 | "engines": {
88 | "node": ">=6.0.0"
89 | }
90 | },
91 | "node_modules/@jridgewell/set-array": {
92 | "version": "1.1.2",
93 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
94 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
95 | "dev": true,
96 | "engines": {
97 | "node": ">=6.0.0"
98 | }
99 | },
100 | "node_modules/@jridgewell/source-map": {
101 | "version": "0.3.2",
102 | "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
103 | "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
104 | "dev": true,
105 | "dependencies": {
106 | "@jridgewell/gen-mapping": "^0.3.0",
107 | "@jridgewell/trace-mapping": "^0.3.9"
108 | }
109 | },
110 | "node_modules/@jridgewell/sourcemap-codec": {
111 | "version": "1.4.14",
112 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
113 | "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
114 | "dev": true
115 | },
116 | "node_modules/@jridgewell/trace-mapping": {
117 | "version": "0.3.17",
118 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
119 | "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
120 | "dev": true,
121 | "dependencies": {
122 | "@jridgewell/resolve-uri": "3.1.0",
123 | "@jridgewell/sourcemap-codec": "1.4.14"
124 | }
125 | },
126 | "node_modules/@loaders.gl/core": {
127 | "version": "3.2.11",
128 | "resolved": "https://registry.npmjs.org/@loaders.gl/core/-/core-3.2.11.tgz",
129 | "integrity": "sha512-uWQM1ZAuN0VYWEMMMwrlTKE1c4gor9SgCQXn8TlAW/4+9sL9KJ09T6AxgzYYAFdJmzTmT8BtC5aPUEYv031nRQ==",
130 | "dependencies": {
131 | "@babel/runtime": "^7.3.1",
132 | "@loaders.gl/loader-utils": "3.2.11",
133 | "@loaders.gl/worker-utils": "3.2.11",
134 | "@probe.gl/log": "^3.5.0",
135 | "probe.gl": "^3.4.0"
136 | }
137 | },
138 | "node_modules/@loaders.gl/draco": {
139 | "version": "3.2.11",
140 | "resolved": "https://registry.npmjs.org/@loaders.gl/draco/-/draco-3.2.11.tgz",
141 | "integrity": "sha512-cGLcMWFe/AP5ExVEPt23Q4uo8Ewbo6hCBvcFX+b9VDfz/mIbUNa0DLRRtSi7eKgCJBRCQ/MLLz3SCm5OL5CjEA==",
142 | "dependencies": {
143 | "@babel/runtime": "^7.3.1",
144 | "@loaders.gl/loader-utils": "3.2.11",
145 | "@loaders.gl/schema": "3.2.11",
146 | "@loaders.gl/worker-utils": "3.2.11",
147 | "draco3d": "1.4.1"
148 | }
149 | },
150 | "node_modules/@loaders.gl/gltf": {
151 | "version": "3.2.11",
152 | "resolved": "https://registry.npmjs.org/@loaders.gl/gltf/-/gltf-3.2.11.tgz",
153 | "integrity": "sha512-jhVFjNWMPydWB7MJVxSGGGdd3zhVgD94WsFKq9L/HcrdMY6s3nQtinALHXErh/G4XjH3efnjkZXfrE8KDzaJsw==",
154 | "dependencies": {
155 | "@loaders.gl/draco": "3.2.11",
156 | "@loaders.gl/images": "3.2.11",
157 | "@loaders.gl/loader-utils": "3.2.11",
158 | "@loaders.gl/textures": "3.2.11"
159 | }
160 | },
161 | "node_modules/@loaders.gl/images": {
162 | "version": "3.2.11",
163 | "resolved": "https://registry.npmjs.org/@loaders.gl/images/-/images-3.2.11.tgz",
164 | "integrity": "sha512-ch5JRXptb8JISYo2PQeASCvuiwdJjJx7ucejDT3EoeKfVHBL7vVjNkHY/UjOMQvljYoF2jD0NfmOJoll5DWjTQ==",
165 | "dependencies": {
166 | "@loaders.gl/loader-utils": "3.2.11"
167 | }
168 | },
169 | "node_modules/@loaders.gl/loader-utils": {
170 | "version": "3.2.11",
171 | "resolved": "https://registry.npmjs.org/@loaders.gl/loader-utils/-/loader-utils-3.2.11.tgz",
172 | "integrity": "sha512-/eQjBLQI1x+5MG3b235xrUcMdKl9ALtzOPMINYeA9TI1TJBULv1xNWBg6HqVdS2ZfaC+JFc9vMxrPI7YaklqNw==",
173 | "dependencies": {
174 | "@babel/runtime": "^7.3.1",
175 | "@loaders.gl/worker-utils": "3.2.11",
176 | "@probe.gl/stats": "^3.5.0"
177 | }
178 | },
179 | "node_modules/@loaders.gl/schema": {
180 | "version": "3.2.11",
181 | "resolved": "https://registry.npmjs.org/@loaders.gl/schema/-/schema-3.2.11.tgz",
182 | "integrity": "sha512-Fz0cWtHwE5Os0HxhEYxLCnJz5LD7djpZnNWk+lPVzIJ6HWPFlxI6lbD4zc1auN5omD2EXFkJigi8on8l3i63fQ==",
183 | "dependencies": {
184 | "@types/geojson": "^7946.0.7",
185 | "apache-arrow": "^4.0.0"
186 | }
187 | },
188 | "node_modules/@loaders.gl/textures": {
189 | "version": "3.2.11",
190 | "resolved": "https://registry.npmjs.org/@loaders.gl/textures/-/textures-3.2.11.tgz",
191 | "integrity": "sha512-GapLQ9XzCfVygVp2uFggk+Gr736hAkm0aZVRyGRi9hQjXffD7IvPOMh+cqNkHuxTcO5vHHR6jnQqYc5gtUODlg==",
192 | "dependencies": {
193 | "@loaders.gl/images": "3.2.11",
194 | "@loaders.gl/loader-utils": "3.2.11",
195 | "@loaders.gl/schema": "3.2.11",
196 | "@loaders.gl/worker-utils": "3.2.11",
197 | "ktx-parse": "^0.0.4",
198 | "texture-compressor": "^1.0.2"
199 | }
200 | },
201 | "node_modules/@loaders.gl/worker-utils": {
202 | "version": "3.2.11",
203 | "resolved": "https://registry.npmjs.org/@loaders.gl/worker-utils/-/worker-utils-3.2.11.tgz",
204 | "integrity": "sha512-2DyBkBJGDU66XbLz+eBByTlfbjUD3OarjzqAifenIrOaX1IuOcSqa8r6w2FOgsjlpT1ujcn0d4QO/o0zM8IWJA==",
205 | "dependencies": {
206 | "@babel/runtime": "^7.3.1"
207 | }
208 | },
209 | "node_modules/@probe.gl/env": {
210 | "version": "3.5.2",
211 | "resolved": "https://registry.npmjs.org/@probe.gl/env/-/env-3.5.2.tgz",
212 | "integrity": "sha512-JlNvJ2p6+ObWX7es6n3TycGPTv5CfVrCS8vblI1eHhrFCcZ6RxIo727ffRVwldpp0YTzdgjx3/4fB/1dnVYElw==",
213 | "dependencies": {
214 | "@babel/runtime": "^7.0.0"
215 | }
216 | },
217 | "node_modules/@probe.gl/log": {
218 | "version": "3.5.2",
219 | "resolved": "https://registry.npmjs.org/@probe.gl/log/-/log-3.5.2.tgz",
220 | "integrity": "sha512-5yo8Dg8LrSltuPBdGlLh/WOvt4LdU7DDHu75GMeiS0fKM+J4IACRpGV8SOrktCj1MWZ6JVHcNQkJnoyZ6G7p/w==",
221 | "dependencies": {
222 | "@babel/runtime": "^7.0.0",
223 | "@probe.gl/env": "3.5.2"
224 | }
225 | },
226 | "node_modules/@probe.gl/stats": {
227 | "version": "3.5.2",
228 | "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-3.5.2.tgz",
229 | "integrity": "sha512-YKaYXiHF//fgy1OkX38JD70Lc8qxg2Viw8Q2CTNMwGPDJe12wda7kEmMKPJNw2oYLyFUfTzv00KJMA5h18z02w==",
230 | "dependencies": {
231 | "@babel/runtime": "^7.0.0"
232 | }
233 | },
234 | "node_modules/@rollup/pluginutils": {
235 | "version": "4.2.1",
236 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
237 | "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==",
238 | "dev": true,
239 | "dependencies": {
240 | "estree-walker": "^2.0.1",
241 | "picomatch": "^2.2.2"
242 | },
243 | "engines": {
244 | "node": ">= 8.0.0"
245 | }
246 | },
247 | "node_modules/@types/flatbuffers": {
248 | "version": "1.10.0",
249 | "resolved": "https://registry.npmjs.org/@types/flatbuffers/-/flatbuffers-1.10.0.tgz",
250 | "integrity": "sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA=="
251 | },
252 | "node_modules/@types/geojson": {
253 | "version": "7946.0.10",
254 | "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
255 | "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA=="
256 | },
257 | "node_modules/@types/node": {
258 | "version": "14.18.33",
259 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.33.tgz",
260 | "integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg=="
261 | },
262 | "node_modules/@types/text-encoding-utf-8": {
263 | "version": "1.0.2",
264 | "resolved": "https://registry.npmjs.org/@types/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz",
265 | "integrity": "sha512-AQ6zewa0ucLJvtUi5HsErbOFKAcQfRLt9zFLlUOvcXBy2G36a+ZDpCHSGdzJVUD8aNURtIjh9aSjCStNMRCcRQ=="
266 | },
267 | "node_modules/acorn": {
268 | "version": "8.8.1",
269 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
270 | "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
271 | "dev": true,
272 | "bin": {
273 | "acorn": "bin/acorn"
274 | },
275 | "engines": {
276 | "node": ">=0.4.0"
277 | }
278 | },
279 | "node_modules/ansi-styles": {
280 | "version": "3.2.1",
281 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
282 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
283 | "dependencies": {
284 | "color-convert": "^1.9.0"
285 | },
286 | "engines": {
287 | "node": ">=4"
288 | }
289 | },
290 | "node_modules/apache-arrow": {
291 | "version": "4.0.1",
292 | "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-4.0.1.tgz",
293 | "integrity": "sha512-DyF7GXCbSjsw4P5C8b+qW7OnJKa6w9mJI0mhV0+EfZbVZCmhfiF6ffqcnrI/kzBrRqn9hH/Ft9n5+m4DTbBJpg==",
294 | "dependencies": {
295 | "@types/flatbuffers": "^1.10.0",
296 | "@types/node": "^14.14.37",
297 | "@types/text-encoding-utf-8": "^1.0.1",
298 | "command-line-args": "5.1.1",
299 | "command-line-usage": "6.1.1",
300 | "flatbuffers": "1.12.0",
301 | "json-bignum": "^0.0.3",
302 | "pad-left": "^2.1.0",
303 | "text-encoding-utf-8": "^1.0.2",
304 | "tslib": "^2.2.0"
305 | },
306 | "bin": {
307 | "arrow2csv": "bin/arrow2csv.js"
308 | }
309 | },
310 | "node_modules/argparse": {
311 | "version": "1.0.10",
312 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
313 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
314 | "dependencies": {
315 | "sprintf-js": "~1.0.2"
316 | }
317 | },
318 | "node_modules/array-back": {
319 | "version": "3.1.0",
320 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz",
321 | "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==",
322 | "engines": {
323 | "node": ">=6"
324 | }
325 | },
326 | "node_modules/automation-events": {
327 | "version": "4.0.23",
328 | "resolved": "https://registry.npmjs.org/automation-events/-/automation-events-4.0.23.tgz",
329 | "integrity": "sha512-3Q/moBk0NeWZb5jm5WtjmpAV5lxCoS00W+PQmQLp5mU0ra8AqU/lfjsIJly7Ze1drBE4aNfZIMGlbU+sTtJQJw==",
330 | "dependencies": {
331 | "@babel/runtime": "^7.20.1",
332 | "tslib": "^2.4.1"
333 | },
334 | "engines": {
335 | "node": ">=12.20.1"
336 | }
337 | },
338 | "node_modules/buffer-from": {
339 | "version": "1.1.2",
340 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
341 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
342 | "dev": true
343 | },
344 | "node_modules/chalk": {
345 | "version": "2.4.2",
346 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
347 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
348 | "dependencies": {
349 | "ansi-styles": "^3.2.1",
350 | "escape-string-regexp": "^1.0.5",
351 | "supports-color": "^5.3.0"
352 | },
353 | "engines": {
354 | "node": ">=4"
355 | }
356 | },
357 | "node_modules/color-convert": {
358 | "version": "1.9.3",
359 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
360 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
361 | "dependencies": {
362 | "color-name": "1.1.3"
363 | }
364 | },
365 | "node_modules/color-name": {
366 | "version": "1.1.3",
367 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
368 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
369 | },
370 | "node_modules/command-line-args": {
371 | "version": "5.1.1",
372 | "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz",
373 | "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==",
374 | "dependencies": {
375 | "array-back": "^3.0.1",
376 | "find-replace": "^3.0.0",
377 | "lodash.camelcase": "^4.3.0",
378 | "typical": "^4.0.0"
379 | },
380 | "engines": {
381 | "node": ">=4.0.0"
382 | }
383 | },
384 | "node_modules/command-line-usage": {
385 | "version": "6.1.1",
386 | "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.1.tgz",
387 | "integrity": "sha512-F59pEuAR9o1SF/bD0dQBDluhpT4jJQNWUHEuVBqpDmCUo6gPjCi+m9fCWnWZVR/oG6cMTUms4h+3NPl74wGXvA==",
388 | "dependencies": {
389 | "array-back": "^4.0.1",
390 | "chalk": "^2.4.2",
391 | "table-layout": "^1.0.1",
392 | "typical": "^5.2.0"
393 | },
394 | "engines": {
395 | "node": ">=8.0.0"
396 | }
397 | },
398 | "node_modules/command-line-usage/node_modules/array-back": {
399 | "version": "4.0.2",
400 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz",
401 | "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==",
402 | "engines": {
403 | "node": ">=8"
404 | }
405 | },
406 | "node_modules/command-line-usage/node_modules/typical": {
407 | "version": "5.2.0",
408 | "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
409 | "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==",
410 | "engines": {
411 | "node": ">=8"
412 | }
413 | },
414 | "node_modules/commander": {
415 | "version": "2.20.3",
416 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
417 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
418 | "dev": true
419 | },
420 | "node_modules/deep-extend": {
421 | "version": "0.6.0",
422 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
423 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
424 | "engines": {
425 | "node": ">=4.0.0"
426 | }
427 | },
428 | "node_modules/draco3d": {
429 | "version": "1.4.1",
430 | "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.4.1.tgz",
431 | "integrity": "sha512-9Rxonc70xiovBC+Bq1h57SNZIHzWTibU1VfIGp5z3Xx8dPtv4yT5uGhiH7P5uvJRR2jkrvHafRxR7bTANkvfpg=="
432 | },
433 | "node_modules/esbuild": {
434 | "version": "0.15.13",
435 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.13.tgz",
436 | "integrity": "sha512-Cu3SC84oyzzhrK/YyN4iEVy2jZu5t2fz66HEOShHURcjSkOSAVL8C/gfUT+lDJxkVHpg8GZ10DD0rMHRPqMFaQ==",
437 | "dev": true,
438 | "hasInstallScript": true,
439 | "bin": {
440 | "esbuild": "bin/esbuild"
441 | },
442 | "engines": {
443 | "node": ">=12"
444 | },
445 | "optionalDependencies": {
446 | "@esbuild/android-arm": "0.15.13",
447 | "@esbuild/linux-loong64": "0.15.13",
448 | "esbuild-android-64": "0.15.13",
449 | "esbuild-android-arm64": "0.15.13",
450 | "esbuild-darwin-64": "0.15.13",
451 | "esbuild-darwin-arm64": "0.15.13",
452 | "esbuild-freebsd-64": "0.15.13",
453 | "esbuild-freebsd-arm64": "0.15.13",
454 | "esbuild-linux-32": "0.15.13",
455 | "esbuild-linux-64": "0.15.13",
456 | "esbuild-linux-arm": "0.15.13",
457 | "esbuild-linux-arm64": "0.15.13",
458 | "esbuild-linux-mips64le": "0.15.13",
459 | "esbuild-linux-ppc64le": "0.15.13",
460 | "esbuild-linux-riscv64": "0.15.13",
461 | "esbuild-linux-s390x": "0.15.13",
462 | "esbuild-netbsd-64": "0.15.13",
463 | "esbuild-openbsd-64": "0.15.13",
464 | "esbuild-sunos-64": "0.15.13",
465 | "esbuild-windows-32": "0.15.13",
466 | "esbuild-windows-64": "0.15.13",
467 | "esbuild-windows-arm64": "0.15.13"
468 | }
469 | },
470 | "node_modules/esbuild-android-64": {
471 | "version": "0.15.13",
472 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.13.tgz",
473 | "integrity": "sha512-yRorukXBlokwTip+Sy4MYskLhJsO0Kn0/Fj43s1krVblfwP+hMD37a4Wmg139GEsMLl+vh8WXp2mq/cTA9J97g==",
474 | "cpu": [
475 | "x64"
476 | ],
477 | "dev": true,
478 | "optional": true,
479 | "os": [
480 | "android"
481 | ],
482 | "engines": {
483 | "node": ">=12"
484 | }
485 | },
486 | "node_modules/esbuild-android-arm64": {
487 | "version": "0.15.13",
488 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.13.tgz",
489 | "integrity": "sha512-TKzyymLD6PiVeyYa4c5wdPw87BeAiTXNtK6amWUcXZxkV51gOk5u5qzmDaYSwiWeecSNHamFsaFjLoi32QR5/w==",
490 | "cpu": [
491 | "arm64"
492 | ],
493 | "dev": true,
494 | "optional": true,
495 | "os": [
496 | "android"
497 | ],
498 | "engines": {
499 | "node": ">=12"
500 | }
501 | },
502 | "node_modules/esbuild-darwin-64": {
503 | "version": "0.15.13",
504 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.13.tgz",
505 | "integrity": "sha512-WAx7c2DaOS6CrRcoYCgXgkXDliLnFv3pQLV6GeW1YcGEZq2Gnl8s9Pg7ahValZkpOa0iE/ojRVQ87sbUhF1Cbg==",
506 | "cpu": [
507 | "x64"
508 | ],
509 | "dev": true,
510 | "optional": true,
511 | "os": [
512 | "darwin"
513 | ],
514 | "engines": {
515 | "node": ">=12"
516 | }
517 | },
518 | "node_modules/esbuild-darwin-arm64": {
519 | "version": "0.15.13",
520 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.13.tgz",
521 | "integrity": "sha512-U6jFsPfSSxC3V1CLiQqwvDuj3GGrtQNB3P3nNC3+q99EKf94UGpsG9l4CQ83zBs1NHrk1rtCSYT0+KfK5LsD8A==",
522 | "cpu": [
523 | "arm64"
524 | ],
525 | "dev": true,
526 | "optional": true,
527 | "os": [
528 | "darwin"
529 | ],
530 | "engines": {
531 | "node": ">=12"
532 | }
533 | },
534 | "node_modules/esbuild-freebsd-64": {
535 | "version": "0.15.13",
536 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.13.tgz",
537 | "integrity": "sha512-whItJgDiOXaDG/idy75qqevIpZjnReZkMGCgQaBWZuKHoElDJC1rh7MpoUgupMcdfOd+PgdEwNQW9DAE6i8wyA==",
538 | "cpu": [
539 | "x64"
540 | ],
541 | "dev": true,
542 | "optional": true,
543 | "os": [
544 | "freebsd"
545 | ],
546 | "engines": {
547 | "node": ">=12"
548 | }
549 | },
550 | "node_modules/esbuild-freebsd-arm64": {
551 | "version": "0.15.13",
552 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.13.tgz",
553 | "integrity": "sha512-6pCSWt8mLUbPtygv7cufV0sZLeylaMwS5Fznj6Rsx9G2AJJsAjQ9ifA+0rQEIg7DwJmi9it+WjzNTEAzzdoM3Q==",
554 | "cpu": [
555 | "arm64"
556 | ],
557 | "dev": true,
558 | "optional": true,
559 | "os": [
560 | "freebsd"
561 | ],
562 | "engines": {
563 | "node": ">=12"
564 | }
565 | },
566 | "node_modules/esbuild-linux-32": {
567 | "version": "0.15.13",
568 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.13.tgz",
569 | "integrity": "sha512-VbZdWOEdrJiYApm2kkxoTOgsoCO1krBZ3quHdYk3g3ivWaMwNIVPIfEE0f0XQQ0u5pJtBsnk2/7OPiCFIPOe/w==",
570 | "cpu": [
571 | "ia32"
572 | ],
573 | "dev": true,
574 | "optional": true,
575 | "os": [
576 | "linux"
577 | ],
578 | "engines": {
579 | "node": ">=12"
580 | }
581 | },
582 | "node_modules/esbuild-linux-64": {
583 | "version": "0.15.13",
584 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.13.tgz",
585 | "integrity": "sha512-rXmnArVNio6yANSqDQlIO4WiP+Cv7+9EuAHNnag7rByAqFVuRusLbGi2697A5dFPNXoO//IiogVwi3AdcfPC6A==",
586 | "cpu": [
587 | "x64"
588 | ],
589 | "dev": true,
590 | "optional": true,
591 | "os": [
592 | "linux"
593 | ],
594 | "engines": {
595 | "node": ">=12"
596 | }
597 | },
598 | "node_modules/esbuild-linux-arm": {
599 | "version": "0.15.13",
600 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.13.tgz",
601 | "integrity": "sha512-Ac6LpfmJO8WhCMQmO253xX2IU2B3wPDbl4IvR0hnqcPrdfCaUa2j/lLMGTjmQ4W5JsJIdHEdW12dG8lFS0MbxQ==",
602 | "cpu": [
603 | "arm"
604 | ],
605 | "dev": true,
606 | "optional": true,
607 | "os": [
608 | "linux"
609 | ],
610 | "engines": {
611 | "node": ">=12"
612 | }
613 | },
614 | "node_modules/esbuild-linux-arm64": {
615 | "version": "0.15.13",
616 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.13.tgz",
617 | "integrity": "sha512-alEMGU4Z+d17U7KQQw2IV8tQycO6T+rOrgW8OS22Ua25x6kHxoG6Ngry6Aq6uranC+pNWNMB6aHFPh7aTQdORQ==",
618 | "cpu": [
619 | "arm64"
620 | ],
621 | "dev": true,
622 | "optional": true,
623 | "os": [
624 | "linux"
625 | ],
626 | "engines": {
627 | "node": ">=12"
628 | }
629 | },
630 | "node_modules/esbuild-linux-mips64le": {
631 | "version": "0.15.13",
632 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.13.tgz",
633 | "integrity": "sha512-47PgmyYEu+yN5rD/MbwS6DxP2FSGPo4Uxg5LwIdxTiyGC2XKwHhHyW7YYEDlSuXLQXEdTO7mYe8zQ74czP7W8A==",
634 | "cpu": [
635 | "mips64el"
636 | ],
637 | "dev": true,
638 | "optional": true,
639 | "os": [
640 | "linux"
641 | ],
642 | "engines": {
643 | "node": ">=12"
644 | }
645 | },
646 | "node_modules/esbuild-linux-ppc64le": {
647 | "version": "0.15.13",
648 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.13.tgz",
649 | "integrity": "sha512-z6n28h2+PC1Ayle9DjKoBRcx/4cxHoOa2e689e2aDJSaKug3jXcQw7mM+GLg+9ydYoNzj8QxNL8ihOv/OnezhA==",
650 | "cpu": [
651 | "ppc64"
652 | ],
653 | "dev": true,
654 | "optional": true,
655 | "os": [
656 | "linux"
657 | ],
658 | "engines": {
659 | "node": ">=12"
660 | }
661 | },
662 | "node_modules/esbuild-linux-riscv64": {
663 | "version": "0.15.13",
664 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.13.tgz",
665 | "integrity": "sha512-+Lu4zuuXuQhgLUGyZloWCqTslcCAjMZH1k3Xc9MSEJEpEFdpsSU0sRDXAnk18FKOfEjhu4YMGaykx9xjtpA6ow==",
666 | "cpu": [
667 | "riscv64"
668 | ],
669 | "dev": true,
670 | "optional": true,
671 | "os": [
672 | "linux"
673 | ],
674 | "engines": {
675 | "node": ">=12"
676 | }
677 | },
678 | "node_modules/esbuild-linux-s390x": {
679 | "version": "0.15.13",
680 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.13.tgz",
681 | "integrity": "sha512-BMeXRljruf7J0TMxD5CIXS65y7puiZkAh+s4XFV9qy16SxOuMhxhVIXYLnbdfLrsYGFzx7U9mcdpFWkkvy/Uag==",
682 | "cpu": [
683 | "s390x"
684 | ],
685 | "dev": true,
686 | "optional": true,
687 | "os": [
688 | "linux"
689 | ],
690 | "engines": {
691 | "node": ">=12"
692 | }
693 | },
694 | "node_modules/esbuild-netbsd-64": {
695 | "version": "0.15.13",
696 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.13.tgz",
697 | "integrity": "sha512-EHj9QZOTel581JPj7UO3xYbltFTYnHy+SIqJVq6yd3KkCrsHRbapiPb0Lx3EOOtybBEE9EyqbmfW1NlSDsSzvQ==",
698 | "cpu": [
699 | "x64"
700 | ],
701 | "dev": true,
702 | "optional": true,
703 | "os": [
704 | "netbsd"
705 | ],
706 | "engines": {
707 | "node": ">=12"
708 | }
709 | },
710 | "node_modules/esbuild-openbsd-64": {
711 | "version": "0.15.13",
712 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.13.tgz",
713 | "integrity": "sha512-nkuDlIjF/sfUhfx8SKq0+U+Fgx5K9JcPq1mUodnxI0x4kBdCv46rOGWbuJ6eof2n3wdoCLccOoJAbg9ba/bT2w==",
714 | "cpu": [
715 | "x64"
716 | ],
717 | "dev": true,
718 | "optional": true,
719 | "os": [
720 | "openbsd"
721 | ],
722 | "engines": {
723 | "node": ">=12"
724 | }
725 | },
726 | "node_modules/esbuild-sunos-64": {
727 | "version": "0.15.13",
728 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.13.tgz",
729 | "integrity": "sha512-jVeu2GfxZQ++6lRdY43CS0Tm/r4WuQQ0Pdsrxbw+aOrHQPHV0+LNOLnvbN28M7BSUGnJnHkHm2HozGgNGyeIRw==",
730 | "cpu": [
731 | "x64"
732 | ],
733 | "dev": true,
734 | "optional": true,
735 | "os": [
736 | "sunos"
737 | ],
738 | "engines": {
739 | "node": ">=12"
740 | }
741 | },
742 | "node_modules/esbuild-windows-32": {
743 | "version": "0.15.13",
744 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.13.tgz",
745 | "integrity": "sha512-XoF2iBf0wnqo16SDq+aDGi/+QbaLFpkiRarPVssMh9KYbFNCqPLlGAWwDvxEVz+ywX6Si37J2AKm+AXq1kC0JA==",
746 | "cpu": [
747 | "ia32"
748 | ],
749 | "dev": true,
750 | "optional": true,
751 | "os": [
752 | "win32"
753 | ],
754 | "engines": {
755 | "node": ">=12"
756 | }
757 | },
758 | "node_modules/esbuild-windows-64": {
759 | "version": "0.15.13",
760 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.13.tgz",
761 | "integrity": "sha512-Et6htEfGycjDrtqb2ng6nT+baesZPYQIW+HUEHK4D1ncggNrDNk3yoboYQ5KtiVrw/JaDMNttz8rrPubV/fvPQ==",
762 | "cpu": [
763 | "x64"
764 | ],
765 | "dev": true,
766 | "optional": true,
767 | "os": [
768 | "win32"
769 | ],
770 | "engines": {
771 | "node": ">=12"
772 | }
773 | },
774 | "node_modules/esbuild-windows-arm64": {
775 | "version": "0.15.13",
776 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.13.tgz",
777 | "integrity": "sha512-3bv7tqntThQC9SWLRouMDmZnlOukBhOCTlkzNqzGCmrkCJI7io5LLjwJBOVY6kOUlIvdxbooNZwjtBvj+7uuVg==",
778 | "cpu": [
779 | "arm64"
780 | ],
781 | "dev": true,
782 | "optional": true,
783 | "os": [
784 | "win32"
785 | ],
786 | "engines": {
787 | "node": ">=12"
788 | }
789 | },
790 | "node_modules/escape-string-regexp": {
791 | "version": "1.0.5",
792 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
793 | "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
794 | "engines": {
795 | "node": ">=0.8.0"
796 | }
797 | },
798 | "node_modules/estree-walker": {
799 | "version": "2.0.2",
800 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
801 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
802 | "dev": true
803 | },
804 | "node_modules/find-replace": {
805 | "version": "3.0.0",
806 | "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz",
807 | "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==",
808 | "dependencies": {
809 | "array-back": "^3.0.1"
810 | },
811 | "engines": {
812 | "node": ">=4.0.0"
813 | }
814 | },
815 | "node_modules/flatbuffers": {
816 | "version": "1.12.0",
817 | "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-1.12.0.tgz",
818 | "integrity": "sha512-c7CZADjRcl6j0PlvFy0ZqXQ67qSEZfrVPynmnL+2zPc+NtMvrF8Y0QceMo7QqnSPc7+uWjUIAbvCQ5WIKlMVdQ=="
819 | },
820 | "node_modules/fsevents": {
821 | "version": "2.3.2",
822 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
823 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
824 | "dev": true,
825 | "hasInstallScript": true,
826 | "optional": true,
827 | "os": [
828 | "darwin"
829 | ],
830 | "engines": {
831 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
832 | }
833 | },
834 | "node_modules/function-bind": {
835 | "version": "1.1.1",
836 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
837 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
838 | "dev": true
839 | },
840 | "node_modules/gl-matrix": {
841 | "version": "3.4.3",
842 | "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
843 | "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
844 | },
845 | "node_modules/has": {
846 | "version": "1.0.3",
847 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
848 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
849 | "dev": true,
850 | "dependencies": {
851 | "function-bind": "^1.1.1"
852 | },
853 | "engines": {
854 | "node": ">= 0.4.0"
855 | }
856 | },
857 | "node_modules/has-flag": {
858 | "version": "3.0.0",
859 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
860 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
861 | "engines": {
862 | "node": ">=4"
863 | }
864 | },
865 | "node_modules/image-size": {
866 | "version": "0.7.5",
867 | "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.7.5.tgz",
868 | "integrity": "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g==",
869 | "bin": {
870 | "image-size": "bin/image-size.js"
871 | },
872 | "engines": {
873 | "node": ">=6.9.0"
874 | }
875 | },
876 | "node_modules/is-core-module": {
877 | "version": "2.11.0",
878 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
879 | "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
880 | "dev": true,
881 | "dependencies": {
882 | "has": "^1.0.3"
883 | },
884 | "funding": {
885 | "url": "https://github.com/sponsors/ljharb"
886 | }
887 | },
888 | "node_modules/json-bignum": {
889 | "version": "0.0.3",
890 | "resolved": "https://registry.npmjs.org/json-bignum/-/json-bignum-0.0.3.tgz",
891 | "integrity": "sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg==",
892 | "engines": {
893 | "node": ">=0.8"
894 | }
895 | },
896 | "node_modules/ktx-parse": {
897 | "version": "0.0.4",
898 | "resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-0.0.4.tgz",
899 | "integrity": "sha512-LY3nrmfXl+wZZdPxgJ3ZmLvG+wkOZZP3/dr4RbQj1Pk3Qwz44esOOSFFVQJcNWpXAtiNIC66WgXufX/SYgYz6A=="
900 | },
901 | "node_modules/lodash.camelcase": {
902 | "version": "4.3.0",
903 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
904 | "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
905 | },
906 | "node_modules/nanoid": {
907 | "version": "3.3.4",
908 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
909 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
910 | "dev": true,
911 | "bin": {
912 | "nanoid": "bin/nanoid.cjs"
913 | },
914 | "engines": {
915 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
916 | }
917 | },
918 | "node_modules/pad-left": {
919 | "version": "2.1.0",
920 | "resolved": "https://registry.npmjs.org/pad-left/-/pad-left-2.1.0.tgz",
921 | "integrity": "sha512-HJxs9K9AztdIQIAIa/OIazRAUW/L6B9hbQDxO4X07roW3eo9XqZc2ur9bn1StH9CnbbI9EgvejHQX7CBpCF1QA==",
922 | "dependencies": {
923 | "repeat-string": "^1.5.4"
924 | },
925 | "engines": {
926 | "node": ">=0.10.0"
927 | }
928 | },
929 | "node_modules/path-parse": {
930 | "version": "1.0.7",
931 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
932 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
933 | "dev": true
934 | },
935 | "node_modules/picocolors": {
936 | "version": "1.0.0",
937 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
938 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
939 | "dev": true
940 | },
941 | "node_modules/picomatch": {
942 | "version": "2.3.1",
943 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
944 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
945 | "dev": true,
946 | "engines": {
947 | "node": ">=8.6"
948 | },
949 | "funding": {
950 | "url": "https://github.com/sponsors/jonschlinkert"
951 | }
952 | },
953 | "node_modules/postcss": {
954 | "version": "8.4.18",
955 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz",
956 | "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==",
957 | "dev": true,
958 | "funding": [
959 | {
960 | "type": "opencollective",
961 | "url": "https://opencollective.com/postcss/"
962 | },
963 | {
964 | "type": "tidelift",
965 | "url": "https://tidelift.com/funding/github/npm/postcss"
966 | }
967 | ],
968 | "dependencies": {
969 | "nanoid": "^3.3.4",
970 | "picocolors": "^1.0.0",
971 | "source-map-js": "^1.0.2"
972 | },
973 | "engines": {
974 | "node": "^10 || ^12 || >=14"
975 | }
976 | },
977 | "node_modules/probe.gl": {
978 | "version": "3.5.2",
979 | "resolved": "https://registry.npmjs.org/probe.gl/-/probe.gl-3.5.2.tgz",
980 | "integrity": "sha512-8lFQVmi7pMQZkqfj8+VjX4GU9HTkyxgRm5/h/xxA/4/IvZPv3qtP996L+awPwZsrPRKEw99t12SvqEHqSls/sA==",
981 | "dependencies": {
982 | "@babel/runtime": "^7.0.0",
983 | "@probe.gl/env": "3.5.2",
984 | "@probe.gl/log": "3.5.2",
985 | "@probe.gl/stats": "3.5.2"
986 | }
987 | },
988 | "node_modules/reduce-flatten": {
989 | "version": "2.0.0",
990 | "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz",
991 | "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==",
992 | "engines": {
993 | "node": ">=6"
994 | }
995 | },
996 | "node_modules/regenerator-runtime": {
997 | "version": "0.13.10",
998 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz",
999 | "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw=="
1000 | },
1001 | "node_modules/repeat-string": {
1002 | "version": "1.6.1",
1003 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
1004 | "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
1005 | "engines": {
1006 | "node": ">=0.10"
1007 | }
1008 | },
1009 | "node_modules/resolve": {
1010 | "version": "1.22.1",
1011 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
1012 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
1013 | "dev": true,
1014 | "dependencies": {
1015 | "is-core-module": "^2.9.0",
1016 | "path-parse": "^1.0.7",
1017 | "supports-preserve-symlinks-flag": "^1.0.0"
1018 | },
1019 | "bin": {
1020 | "resolve": "bin/resolve"
1021 | },
1022 | "funding": {
1023 | "url": "https://github.com/sponsors/ljharb"
1024 | }
1025 | },
1026 | "node_modules/rollup": {
1027 | "version": "2.79.1",
1028 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
1029 | "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
1030 | "dev": true,
1031 | "bin": {
1032 | "rollup": "dist/bin/rollup"
1033 | },
1034 | "engines": {
1035 | "node": ">=10.0.0"
1036 | },
1037 | "optionalDependencies": {
1038 | "fsevents": "~2.3.2"
1039 | }
1040 | },
1041 | "node_modules/rxjs": {
1042 | "version": "7.5.7",
1043 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz",
1044 | "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==",
1045 | "dependencies": {
1046 | "tslib": "^2.1.0"
1047 | }
1048 | },
1049 | "node_modules/source-map": {
1050 | "version": "0.6.1",
1051 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
1052 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
1053 | "dev": true,
1054 | "engines": {
1055 | "node": ">=0.10.0"
1056 | }
1057 | },
1058 | "node_modules/source-map-js": {
1059 | "version": "1.0.2",
1060 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
1061 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
1062 | "dev": true,
1063 | "engines": {
1064 | "node": ">=0.10.0"
1065 | }
1066 | },
1067 | "node_modules/source-map-support": {
1068 | "version": "0.5.21",
1069 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
1070 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
1071 | "dev": true,
1072 | "dependencies": {
1073 | "buffer-from": "^1.0.0",
1074 | "source-map": "^0.6.0"
1075 | }
1076 | },
1077 | "node_modules/sprintf-js": {
1078 | "version": "1.0.3",
1079 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
1080 | "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
1081 | },
1082 | "node_modules/standardized-audio-context": {
1083 | "version": "25.3.34",
1084 | "resolved": "https://registry.npmjs.org/standardized-audio-context/-/standardized-audio-context-25.3.34.tgz",
1085 | "integrity": "sha512-SL8FQYqpfOifYGhAVfnAgC9o86mFNhy+W3xp28lHI6HgOQMbLTMcBoSN3FT0SwE51br7I9tmgjwiLggg7WWD/Q==",
1086 | "dependencies": {
1087 | "@babel/runtime": "^7.20.1",
1088 | "automation-events": "^4.0.23",
1089 | "tslib": "^2.4.1"
1090 | }
1091 | },
1092 | "node_modules/supports-color": {
1093 | "version": "5.5.0",
1094 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
1095 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
1096 | "dependencies": {
1097 | "has-flag": "^3.0.0"
1098 | },
1099 | "engines": {
1100 | "node": ">=4"
1101 | }
1102 | },
1103 | "node_modules/supports-preserve-symlinks-flag": {
1104 | "version": "1.0.0",
1105 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1106 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1107 | "dev": true,
1108 | "engines": {
1109 | "node": ">= 0.4"
1110 | },
1111 | "funding": {
1112 | "url": "https://github.com/sponsors/ljharb"
1113 | }
1114 | },
1115 | "node_modules/table-layout": {
1116 | "version": "1.0.2",
1117 | "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz",
1118 | "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==",
1119 | "dependencies": {
1120 | "array-back": "^4.0.1",
1121 | "deep-extend": "~0.6.0",
1122 | "typical": "^5.2.0",
1123 | "wordwrapjs": "^4.0.0"
1124 | },
1125 | "engines": {
1126 | "node": ">=8.0.0"
1127 | }
1128 | },
1129 | "node_modules/table-layout/node_modules/array-back": {
1130 | "version": "4.0.2",
1131 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz",
1132 | "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==",
1133 | "engines": {
1134 | "node": ">=8"
1135 | }
1136 | },
1137 | "node_modules/table-layout/node_modules/typical": {
1138 | "version": "5.2.0",
1139 | "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
1140 | "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==",
1141 | "engines": {
1142 | "node": ">=8"
1143 | }
1144 | },
1145 | "node_modules/terser": {
1146 | "version": "5.15.1",
1147 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz",
1148 | "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==",
1149 | "dev": true,
1150 | "dependencies": {
1151 | "@jridgewell/source-map": "^0.3.2",
1152 | "acorn": "^8.5.0",
1153 | "commander": "^2.20.0",
1154 | "source-map-support": "~0.5.20"
1155 | },
1156 | "bin": {
1157 | "terser": "bin/terser"
1158 | },
1159 | "engines": {
1160 | "node": ">=10"
1161 | }
1162 | },
1163 | "node_modules/text-encoding-utf-8": {
1164 | "version": "1.0.2",
1165 | "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz",
1166 | "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg=="
1167 | },
1168 | "node_modules/texture-compressor": {
1169 | "version": "1.0.2",
1170 | "resolved": "https://registry.npmjs.org/texture-compressor/-/texture-compressor-1.0.2.tgz",
1171 | "integrity": "sha512-dStVgoaQ11mA5htJ+RzZ51ZxIZqNOgWKAIvtjLrW1AliQQLCmrDqNzQZ8Jh91YealQ95DXt4MEduLzJmbs6lig==",
1172 | "dependencies": {
1173 | "argparse": "^1.0.10",
1174 | "image-size": "^0.7.4"
1175 | },
1176 | "bin": {
1177 | "texture-compressor": "bin/texture-compressor.js"
1178 | }
1179 | },
1180 | "node_modules/tone": {
1181 | "version": "14.7.77",
1182 | "resolved": "https://registry.npmjs.org/tone/-/tone-14.7.77.tgz",
1183 | "integrity": "sha512-tCfK73IkLHyzoKUvGq47gyDyxiKLFvKiVCOobynGgBB9Dl0NkxTM2p+eRJXyCYrjJwy9Y0XCMqD3uOYsYt2Fdg==",
1184 | "dependencies": {
1185 | "standardized-audio-context": "^25.1.8",
1186 | "tslib": "^2.0.1"
1187 | }
1188 | },
1189 | "node_modules/tslib": {
1190 | "version": "2.4.1",
1191 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
1192 | "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
1193 | },
1194 | "node_modules/tweakpane": {
1195 | "version": "3.1.0",
1196 | "resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-3.1.0.tgz",
1197 | "integrity": "sha512-PGAp/LPQdHwzL7/iAW4lV1p9iPQTti7YMjMWO48CoYjvZRS59RmgQnhEGzKzqST1JnmOYmQUjTe8bdhlZRJs5A==",
1198 | "funding": {
1199 | "url": "https://github.com/sponsors/cocopon"
1200 | }
1201 | },
1202 | "node_modules/twgl.js": {
1203 | "version": "5.2.0",
1204 | "resolved": "https://registry.npmjs.org/twgl.js/-/twgl.js-5.2.0.tgz",
1205 | "integrity": "sha512-DuiCzdjO3PNOrxbxHMYuhvVPhBaH0f3WThJSixFU4eNnpe0NzECMeaEEe/aznt+EJ5JAU3pXyeXiYSgEJHJH4A=="
1206 | },
1207 | "node_modules/typical": {
1208 | "version": "4.0.0",
1209 | "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz",
1210 | "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==",
1211 | "engines": {
1212 | "node": ">=8"
1213 | }
1214 | },
1215 | "node_modules/vite": {
1216 | "version": "3.2.2",
1217 | "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.2.tgz",
1218 | "integrity": "sha512-pLrhatFFOWO9kS19bQ658CnRYzv0WLbsPih6R+iFeEEhDOuYgYCX2rztUViMz/uy/V8cLCJvLFeiOK7RJEzHcw==",
1219 | "dev": true,
1220 | "dependencies": {
1221 | "esbuild": "^0.15.9",
1222 | "postcss": "^8.4.18",
1223 | "resolve": "^1.22.1",
1224 | "rollup": "^2.79.1"
1225 | },
1226 | "bin": {
1227 | "vite": "bin/vite.js"
1228 | },
1229 | "engines": {
1230 | "node": "^14.18.0 || >=16.0.0"
1231 | },
1232 | "optionalDependencies": {
1233 | "fsevents": "~2.3.2"
1234 | },
1235 | "peerDependencies": {
1236 | "less": "*",
1237 | "sass": "*",
1238 | "stylus": "*",
1239 | "sugarss": "*",
1240 | "terser": "^5.4.0"
1241 | },
1242 | "peerDependenciesMeta": {
1243 | "less": {
1244 | "optional": true
1245 | },
1246 | "sass": {
1247 | "optional": true
1248 | },
1249 | "stylus": {
1250 | "optional": true
1251 | },
1252 | "sugarss": {
1253 | "optional": true
1254 | },
1255 | "terser": {
1256 | "optional": true
1257 | }
1258 | }
1259 | },
1260 | "node_modules/vite-plugin-glsl": {
1261 | "version": "0.3.0",
1262 | "resolved": "https://registry.npmjs.org/vite-plugin-glsl/-/vite-plugin-glsl-0.3.0.tgz",
1263 | "integrity": "sha512-cH7ni+Y3Vz1yOumvrP/71hXVdyTxZIaYYNDeK7KMvO5nzo0uGZZrrkwEVUaESS8/5dYemb/6G0YBj3jsP2sW1A==",
1264 | "dev": true,
1265 | "dependencies": {
1266 | "@rollup/pluginutils": "^4.2.1"
1267 | },
1268 | "engines": {
1269 | "node": ">= 14.18.0",
1270 | "npm": ">= 6.14.17"
1271 | }
1272 | },
1273 | "node_modules/wordwrapjs": {
1274 | "version": "4.0.1",
1275 | "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz",
1276 | "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==",
1277 | "dependencies": {
1278 | "reduce-flatten": "^2.0.0",
1279 | "typical": "^5.2.0"
1280 | },
1281 | "engines": {
1282 | "node": ">=8.0.0"
1283 | }
1284 | },
1285 | "node_modules/wordwrapjs/node_modules/typical": {
1286 | "version": "5.2.0",
1287 | "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
1288 | "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==",
1289 | "engines": {
1290 | "node": ">=8"
1291 | }
1292 | }
1293 | },
1294 | "dependencies": {
1295 | "@babel/runtime": {
1296 | "version": "7.20.1",
1297 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.1.tgz",
1298 | "integrity": "sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==",
1299 | "requires": {
1300 | "regenerator-runtime": "^0.13.10"
1301 | }
1302 | },
1303 | "@esbuild/android-arm": {
1304 | "version": "0.15.13",
1305 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.13.tgz",
1306 | "integrity": "sha512-RY2fVI8O0iFUNvZirXaQ1vMvK0xhCcl0gqRj74Z6yEiO1zAUa7hbsdwZM1kzqbxHK7LFyMizipfXT3JME+12Hw==",
1307 | "dev": true,
1308 | "optional": true
1309 | },
1310 | "@esbuild/linux-loong64": {
1311 | "version": "0.15.13",
1312 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.13.tgz",
1313 | "integrity": "sha512-+BoyIm4I8uJmH/QDIH0fu7MG0AEx9OXEDXnqptXCwKOlOqZiS4iraH1Nr7/ObLMokW3sOCeBNyD68ATcV9b9Ag==",
1314 | "dev": true,
1315 | "optional": true
1316 | },
1317 | "@jridgewell/gen-mapping": {
1318 | "version": "0.3.2",
1319 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
1320 | "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
1321 | "dev": true,
1322 | "requires": {
1323 | "@jridgewell/set-array": "^1.0.1",
1324 | "@jridgewell/sourcemap-codec": "^1.4.10",
1325 | "@jridgewell/trace-mapping": "^0.3.9"
1326 | }
1327 | },
1328 | "@jridgewell/resolve-uri": {
1329 | "version": "3.1.0",
1330 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
1331 | "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
1332 | "dev": true
1333 | },
1334 | "@jridgewell/set-array": {
1335 | "version": "1.1.2",
1336 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
1337 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
1338 | "dev": true
1339 | },
1340 | "@jridgewell/source-map": {
1341 | "version": "0.3.2",
1342 | "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
1343 | "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
1344 | "dev": true,
1345 | "requires": {
1346 | "@jridgewell/gen-mapping": "^0.3.0",
1347 | "@jridgewell/trace-mapping": "^0.3.9"
1348 | }
1349 | },
1350 | "@jridgewell/sourcemap-codec": {
1351 | "version": "1.4.14",
1352 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
1353 | "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
1354 | "dev": true
1355 | },
1356 | "@jridgewell/trace-mapping": {
1357 | "version": "0.3.17",
1358 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
1359 | "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
1360 | "dev": true,
1361 | "requires": {
1362 | "@jridgewell/resolve-uri": "3.1.0",
1363 | "@jridgewell/sourcemap-codec": "1.4.14"
1364 | }
1365 | },
1366 | "@loaders.gl/core": {
1367 | "version": "3.2.11",
1368 | "resolved": "https://registry.npmjs.org/@loaders.gl/core/-/core-3.2.11.tgz",
1369 | "integrity": "sha512-uWQM1ZAuN0VYWEMMMwrlTKE1c4gor9SgCQXn8TlAW/4+9sL9KJ09T6AxgzYYAFdJmzTmT8BtC5aPUEYv031nRQ==",
1370 | "requires": {
1371 | "@babel/runtime": "^7.3.1",
1372 | "@loaders.gl/loader-utils": "3.2.11",
1373 | "@loaders.gl/worker-utils": "3.2.11",
1374 | "@probe.gl/log": "^3.5.0",
1375 | "probe.gl": "^3.4.0"
1376 | }
1377 | },
1378 | "@loaders.gl/draco": {
1379 | "version": "3.2.11",
1380 | "resolved": "https://registry.npmjs.org/@loaders.gl/draco/-/draco-3.2.11.tgz",
1381 | "integrity": "sha512-cGLcMWFe/AP5ExVEPt23Q4uo8Ewbo6hCBvcFX+b9VDfz/mIbUNa0DLRRtSi7eKgCJBRCQ/MLLz3SCm5OL5CjEA==",
1382 | "requires": {
1383 | "@babel/runtime": "^7.3.1",
1384 | "@loaders.gl/loader-utils": "3.2.11",
1385 | "@loaders.gl/schema": "3.2.11",
1386 | "@loaders.gl/worker-utils": "3.2.11",
1387 | "draco3d": "1.4.1"
1388 | }
1389 | },
1390 | "@loaders.gl/gltf": {
1391 | "version": "3.2.11",
1392 | "resolved": "https://registry.npmjs.org/@loaders.gl/gltf/-/gltf-3.2.11.tgz",
1393 | "integrity": "sha512-jhVFjNWMPydWB7MJVxSGGGdd3zhVgD94WsFKq9L/HcrdMY6s3nQtinALHXErh/G4XjH3efnjkZXfrE8KDzaJsw==",
1394 | "requires": {
1395 | "@loaders.gl/draco": "3.2.11",
1396 | "@loaders.gl/images": "3.2.11",
1397 | "@loaders.gl/loader-utils": "3.2.11",
1398 | "@loaders.gl/textures": "3.2.11"
1399 | }
1400 | },
1401 | "@loaders.gl/images": {
1402 | "version": "3.2.11",
1403 | "resolved": "https://registry.npmjs.org/@loaders.gl/images/-/images-3.2.11.tgz",
1404 | "integrity": "sha512-ch5JRXptb8JISYo2PQeASCvuiwdJjJx7ucejDT3EoeKfVHBL7vVjNkHY/UjOMQvljYoF2jD0NfmOJoll5DWjTQ==",
1405 | "requires": {
1406 | "@loaders.gl/loader-utils": "3.2.11"
1407 | }
1408 | },
1409 | "@loaders.gl/loader-utils": {
1410 | "version": "3.2.11",
1411 | "resolved": "https://registry.npmjs.org/@loaders.gl/loader-utils/-/loader-utils-3.2.11.tgz",
1412 | "integrity": "sha512-/eQjBLQI1x+5MG3b235xrUcMdKl9ALtzOPMINYeA9TI1TJBULv1xNWBg6HqVdS2ZfaC+JFc9vMxrPI7YaklqNw==",
1413 | "requires": {
1414 | "@babel/runtime": "^7.3.1",
1415 | "@loaders.gl/worker-utils": "3.2.11",
1416 | "@probe.gl/stats": "^3.5.0"
1417 | }
1418 | },
1419 | "@loaders.gl/schema": {
1420 | "version": "3.2.11",
1421 | "resolved": "https://registry.npmjs.org/@loaders.gl/schema/-/schema-3.2.11.tgz",
1422 | "integrity": "sha512-Fz0cWtHwE5Os0HxhEYxLCnJz5LD7djpZnNWk+lPVzIJ6HWPFlxI6lbD4zc1auN5omD2EXFkJigi8on8l3i63fQ==",
1423 | "requires": {
1424 | "@types/geojson": "^7946.0.7",
1425 | "apache-arrow": "^4.0.0"
1426 | }
1427 | },
1428 | "@loaders.gl/textures": {
1429 | "version": "3.2.11",
1430 | "resolved": "https://registry.npmjs.org/@loaders.gl/textures/-/textures-3.2.11.tgz",
1431 | "integrity": "sha512-GapLQ9XzCfVygVp2uFggk+Gr736hAkm0aZVRyGRi9hQjXffD7IvPOMh+cqNkHuxTcO5vHHR6jnQqYc5gtUODlg==",
1432 | "requires": {
1433 | "@loaders.gl/images": "3.2.11",
1434 | "@loaders.gl/loader-utils": "3.2.11",
1435 | "@loaders.gl/schema": "3.2.11",
1436 | "@loaders.gl/worker-utils": "3.2.11",
1437 | "ktx-parse": "^0.0.4",
1438 | "texture-compressor": "^1.0.2"
1439 | }
1440 | },
1441 | "@loaders.gl/worker-utils": {
1442 | "version": "3.2.11",
1443 | "resolved": "https://registry.npmjs.org/@loaders.gl/worker-utils/-/worker-utils-3.2.11.tgz",
1444 | "integrity": "sha512-2DyBkBJGDU66XbLz+eBByTlfbjUD3OarjzqAifenIrOaX1IuOcSqa8r6w2FOgsjlpT1ujcn0d4QO/o0zM8IWJA==",
1445 | "requires": {
1446 | "@babel/runtime": "^7.3.1"
1447 | }
1448 | },
1449 | "@probe.gl/env": {
1450 | "version": "3.5.2",
1451 | "resolved": "https://registry.npmjs.org/@probe.gl/env/-/env-3.5.2.tgz",
1452 | "integrity": "sha512-JlNvJ2p6+ObWX7es6n3TycGPTv5CfVrCS8vblI1eHhrFCcZ6RxIo727ffRVwldpp0YTzdgjx3/4fB/1dnVYElw==",
1453 | "requires": {
1454 | "@babel/runtime": "^7.0.0"
1455 | }
1456 | },
1457 | "@probe.gl/log": {
1458 | "version": "3.5.2",
1459 | "resolved": "https://registry.npmjs.org/@probe.gl/log/-/log-3.5.2.tgz",
1460 | "integrity": "sha512-5yo8Dg8LrSltuPBdGlLh/WOvt4LdU7DDHu75GMeiS0fKM+J4IACRpGV8SOrktCj1MWZ6JVHcNQkJnoyZ6G7p/w==",
1461 | "requires": {
1462 | "@babel/runtime": "^7.0.0",
1463 | "@probe.gl/env": "3.5.2"
1464 | }
1465 | },
1466 | "@probe.gl/stats": {
1467 | "version": "3.5.2",
1468 | "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-3.5.2.tgz",
1469 | "integrity": "sha512-YKaYXiHF//fgy1OkX38JD70Lc8qxg2Viw8Q2CTNMwGPDJe12wda7kEmMKPJNw2oYLyFUfTzv00KJMA5h18z02w==",
1470 | "requires": {
1471 | "@babel/runtime": "^7.0.0"
1472 | }
1473 | },
1474 | "@rollup/pluginutils": {
1475 | "version": "4.2.1",
1476 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
1477 | "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==",
1478 | "dev": true,
1479 | "requires": {
1480 | "estree-walker": "^2.0.1",
1481 | "picomatch": "^2.2.2"
1482 | }
1483 | },
1484 | "@types/flatbuffers": {
1485 | "version": "1.10.0",
1486 | "resolved": "https://registry.npmjs.org/@types/flatbuffers/-/flatbuffers-1.10.0.tgz",
1487 | "integrity": "sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA=="
1488 | },
1489 | "@types/geojson": {
1490 | "version": "7946.0.10",
1491 | "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
1492 | "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA=="
1493 | },
1494 | "@types/node": {
1495 | "version": "14.18.33",
1496 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.33.tgz",
1497 | "integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg=="
1498 | },
1499 | "@types/text-encoding-utf-8": {
1500 | "version": "1.0.2",
1501 | "resolved": "https://registry.npmjs.org/@types/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz",
1502 | "integrity": "sha512-AQ6zewa0ucLJvtUi5HsErbOFKAcQfRLt9zFLlUOvcXBy2G36a+ZDpCHSGdzJVUD8aNURtIjh9aSjCStNMRCcRQ=="
1503 | },
1504 | "acorn": {
1505 | "version": "8.8.1",
1506 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
1507 | "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
1508 | "dev": true
1509 | },
1510 | "ansi-styles": {
1511 | "version": "3.2.1",
1512 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
1513 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
1514 | "requires": {
1515 | "color-convert": "^1.9.0"
1516 | }
1517 | },
1518 | "apache-arrow": {
1519 | "version": "4.0.1",
1520 | "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-4.0.1.tgz",
1521 | "integrity": "sha512-DyF7GXCbSjsw4P5C8b+qW7OnJKa6w9mJI0mhV0+EfZbVZCmhfiF6ffqcnrI/kzBrRqn9hH/Ft9n5+m4DTbBJpg==",
1522 | "requires": {
1523 | "@types/flatbuffers": "^1.10.0",
1524 | "@types/node": "^14.14.37",
1525 | "@types/text-encoding-utf-8": "^1.0.1",
1526 | "command-line-args": "5.1.1",
1527 | "command-line-usage": "6.1.1",
1528 | "flatbuffers": "1.12.0",
1529 | "json-bignum": "^0.0.3",
1530 | "pad-left": "^2.1.0",
1531 | "text-encoding-utf-8": "^1.0.2",
1532 | "tslib": "^2.2.0"
1533 | }
1534 | },
1535 | "argparse": {
1536 | "version": "1.0.10",
1537 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
1538 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
1539 | "requires": {
1540 | "sprintf-js": "~1.0.2"
1541 | }
1542 | },
1543 | "array-back": {
1544 | "version": "3.1.0",
1545 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz",
1546 | "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q=="
1547 | },
1548 | "automation-events": {
1549 | "version": "4.0.23",
1550 | "resolved": "https://registry.npmjs.org/automation-events/-/automation-events-4.0.23.tgz",
1551 | "integrity": "sha512-3Q/moBk0NeWZb5jm5WtjmpAV5lxCoS00W+PQmQLp5mU0ra8AqU/lfjsIJly7Ze1drBE4aNfZIMGlbU+sTtJQJw==",
1552 | "requires": {
1553 | "@babel/runtime": "^7.20.1",
1554 | "tslib": "^2.4.1"
1555 | }
1556 | },
1557 | "buffer-from": {
1558 | "version": "1.1.2",
1559 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
1560 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
1561 | "dev": true
1562 | },
1563 | "chalk": {
1564 | "version": "2.4.2",
1565 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
1566 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
1567 | "requires": {
1568 | "ansi-styles": "^3.2.1",
1569 | "escape-string-regexp": "^1.0.5",
1570 | "supports-color": "^5.3.0"
1571 | }
1572 | },
1573 | "color-convert": {
1574 | "version": "1.9.3",
1575 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
1576 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
1577 | "requires": {
1578 | "color-name": "1.1.3"
1579 | }
1580 | },
1581 | "color-name": {
1582 | "version": "1.1.3",
1583 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
1584 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
1585 | },
1586 | "command-line-args": {
1587 | "version": "5.1.1",
1588 | "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz",
1589 | "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==",
1590 | "requires": {
1591 | "array-back": "^3.0.1",
1592 | "find-replace": "^3.0.0",
1593 | "lodash.camelcase": "^4.3.0",
1594 | "typical": "^4.0.0"
1595 | }
1596 | },
1597 | "command-line-usage": {
1598 | "version": "6.1.1",
1599 | "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.1.tgz",
1600 | "integrity": "sha512-F59pEuAR9o1SF/bD0dQBDluhpT4jJQNWUHEuVBqpDmCUo6gPjCi+m9fCWnWZVR/oG6cMTUms4h+3NPl74wGXvA==",
1601 | "requires": {
1602 | "array-back": "^4.0.1",
1603 | "chalk": "^2.4.2",
1604 | "table-layout": "^1.0.1",
1605 | "typical": "^5.2.0"
1606 | },
1607 | "dependencies": {
1608 | "array-back": {
1609 | "version": "4.0.2",
1610 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz",
1611 | "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg=="
1612 | },
1613 | "typical": {
1614 | "version": "5.2.0",
1615 | "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
1616 | "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg=="
1617 | }
1618 | }
1619 | },
1620 | "commander": {
1621 | "version": "2.20.3",
1622 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
1623 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
1624 | "dev": true
1625 | },
1626 | "deep-extend": {
1627 | "version": "0.6.0",
1628 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
1629 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
1630 | },
1631 | "draco3d": {
1632 | "version": "1.4.1",
1633 | "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.4.1.tgz",
1634 | "integrity": "sha512-9Rxonc70xiovBC+Bq1h57SNZIHzWTibU1VfIGp5z3Xx8dPtv4yT5uGhiH7P5uvJRR2jkrvHafRxR7bTANkvfpg=="
1635 | },
1636 | "esbuild": {
1637 | "version": "0.15.13",
1638 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.13.tgz",
1639 | "integrity": "sha512-Cu3SC84oyzzhrK/YyN4iEVy2jZu5t2fz66HEOShHURcjSkOSAVL8C/gfUT+lDJxkVHpg8GZ10DD0rMHRPqMFaQ==",
1640 | "dev": true,
1641 | "requires": {
1642 | "@esbuild/android-arm": "0.15.13",
1643 | "@esbuild/linux-loong64": "0.15.13",
1644 | "esbuild-android-64": "0.15.13",
1645 | "esbuild-android-arm64": "0.15.13",
1646 | "esbuild-darwin-64": "0.15.13",
1647 | "esbuild-darwin-arm64": "0.15.13",
1648 | "esbuild-freebsd-64": "0.15.13",
1649 | "esbuild-freebsd-arm64": "0.15.13",
1650 | "esbuild-linux-32": "0.15.13",
1651 | "esbuild-linux-64": "0.15.13",
1652 | "esbuild-linux-arm": "0.15.13",
1653 | "esbuild-linux-arm64": "0.15.13",
1654 | "esbuild-linux-mips64le": "0.15.13",
1655 | "esbuild-linux-ppc64le": "0.15.13",
1656 | "esbuild-linux-riscv64": "0.15.13",
1657 | "esbuild-linux-s390x": "0.15.13",
1658 | "esbuild-netbsd-64": "0.15.13",
1659 | "esbuild-openbsd-64": "0.15.13",
1660 | "esbuild-sunos-64": "0.15.13",
1661 | "esbuild-windows-32": "0.15.13",
1662 | "esbuild-windows-64": "0.15.13",
1663 | "esbuild-windows-arm64": "0.15.13"
1664 | }
1665 | },
1666 | "esbuild-android-64": {
1667 | "version": "0.15.13",
1668 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.13.tgz",
1669 | "integrity": "sha512-yRorukXBlokwTip+Sy4MYskLhJsO0Kn0/Fj43s1krVblfwP+hMD37a4Wmg139GEsMLl+vh8WXp2mq/cTA9J97g==",
1670 | "dev": true,
1671 | "optional": true
1672 | },
1673 | "esbuild-android-arm64": {
1674 | "version": "0.15.13",
1675 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.13.tgz",
1676 | "integrity": "sha512-TKzyymLD6PiVeyYa4c5wdPw87BeAiTXNtK6amWUcXZxkV51gOk5u5qzmDaYSwiWeecSNHamFsaFjLoi32QR5/w==",
1677 | "dev": true,
1678 | "optional": true
1679 | },
1680 | "esbuild-darwin-64": {
1681 | "version": "0.15.13",
1682 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.13.tgz",
1683 | "integrity": "sha512-WAx7c2DaOS6CrRcoYCgXgkXDliLnFv3pQLV6GeW1YcGEZq2Gnl8s9Pg7ahValZkpOa0iE/ojRVQ87sbUhF1Cbg==",
1684 | "dev": true,
1685 | "optional": true
1686 | },
1687 | "esbuild-darwin-arm64": {
1688 | "version": "0.15.13",
1689 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.13.tgz",
1690 | "integrity": "sha512-U6jFsPfSSxC3V1CLiQqwvDuj3GGrtQNB3P3nNC3+q99EKf94UGpsG9l4CQ83zBs1NHrk1rtCSYT0+KfK5LsD8A==",
1691 | "dev": true,
1692 | "optional": true
1693 | },
1694 | "esbuild-freebsd-64": {
1695 | "version": "0.15.13",
1696 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.13.tgz",
1697 | "integrity": "sha512-whItJgDiOXaDG/idy75qqevIpZjnReZkMGCgQaBWZuKHoElDJC1rh7MpoUgupMcdfOd+PgdEwNQW9DAE6i8wyA==",
1698 | "dev": true,
1699 | "optional": true
1700 | },
1701 | "esbuild-freebsd-arm64": {
1702 | "version": "0.15.13",
1703 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.13.tgz",
1704 | "integrity": "sha512-6pCSWt8mLUbPtygv7cufV0sZLeylaMwS5Fznj6Rsx9G2AJJsAjQ9ifA+0rQEIg7DwJmi9it+WjzNTEAzzdoM3Q==",
1705 | "dev": true,
1706 | "optional": true
1707 | },
1708 | "esbuild-linux-32": {
1709 | "version": "0.15.13",
1710 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.13.tgz",
1711 | "integrity": "sha512-VbZdWOEdrJiYApm2kkxoTOgsoCO1krBZ3quHdYk3g3ivWaMwNIVPIfEE0f0XQQ0u5pJtBsnk2/7OPiCFIPOe/w==",
1712 | "dev": true,
1713 | "optional": true
1714 | },
1715 | "esbuild-linux-64": {
1716 | "version": "0.15.13",
1717 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.13.tgz",
1718 | "integrity": "sha512-rXmnArVNio6yANSqDQlIO4WiP+Cv7+9EuAHNnag7rByAqFVuRusLbGi2697A5dFPNXoO//IiogVwi3AdcfPC6A==",
1719 | "dev": true,
1720 | "optional": true
1721 | },
1722 | "esbuild-linux-arm": {
1723 | "version": "0.15.13",
1724 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.13.tgz",
1725 | "integrity": "sha512-Ac6LpfmJO8WhCMQmO253xX2IU2B3wPDbl4IvR0hnqcPrdfCaUa2j/lLMGTjmQ4W5JsJIdHEdW12dG8lFS0MbxQ==",
1726 | "dev": true,
1727 | "optional": true
1728 | },
1729 | "esbuild-linux-arm64": {
1730 | "version": "0.15.13",
1731 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.13.tgz",
1732 | "integrity": "sha512-alEMGU4Z+d17U7KQQw2IV8tQycO6T+rOrgW8OS22Ua25x6kHxoG6Ngry6Aq6uranC+pNWNMB6aHFPh7aTQdORQ==",
1733 | "dev": true,
1734 | "optional": true
1735 | },
1736 | "esbuild-linux-mips64le": {
1737 | "version": "0.15.13",
1738 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.13.tgz",
1739 | "integrity": "sha512-47PgmyYEu+yN5rD/MbwS6DxP2FSGPo4Uxg5LwIdxTiyGC2XKwHhHyW7YYEDlSuXLQXEdTO7mYe8zQ74czP7W8A==",
1740 | "dev": true,
1741 | "optional": true
1742 | },
1743 | "esbuild-linux-ppc64le": {
1744 | "version": "0.15.13",
1745 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.13.tgz",
1746 | "integrity": "sha512-z6n28h2+PC1Ayle9DjKoBRcx/4cxHoOa2e689e2aDJSaKug3jXcQw7mM+GLg+9ydYoNzj8QxNL8ihOv/OnezhA==",
1747 | "dev": true,
1748 | "optional": true
1749 | },
1750 | "esbuild-linux-riscv64": {
1751 | "version": "0.15.13",
1752 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.13.tgz",
1753 | "integrity": "sha512-+Lu4zuuXuQhgLUGyZloWCqTslcCAjMZH1k3Xc9MSEJEpEFdpsSU0sRDXAnk18FKOfEjhu4YMGaykx9xjtpA6ow==",
1754 | "dev": true,
1755 | "optional": true
1756 | },
1757 | "esbuild-linux-s390x": {
1758 | "version": "0.15.13",
1759 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.13.tgz",
1760 | "integrity": "sha512-BMeXRljruf7J0TMxD5CIXS65y7puiZkAh+s4XFV9qy16SxOuMhxhVIXYLnbdfLrsYGFzx7U9mcdpFWkkvy/Uag==",
1761 | "dev": true,
1762 | "optional": true
1763 | },
1764 | "esbuild-netbsd-64": {
1765 | "version": "0.15.13",
1766 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.13.tgz",
1767 | "integrity": "sha512-EHj9QZOTel581JPj7UO3xYbltFTYnHy+SIqJVq6yd3KkCrsHRbapiPb0Lx3EOOtybBEE9EyqbmfW1NlSDsSzvQ==",
1768 | "dev": true,
1769 | "optional": true
1770 | },
1771 | "esbuild-openbsd-64": {
1772 | "version": "0.15.13",
1773 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.13.tgz",
1774 | "integrity": "sha512-nkuDlIjF/sfUhfx8SKq0+U+Fgx5K9JcPq1mUodnxI0x4kBdCv46rOGWbuJ6eof2n3wdoCLccOoJAbg9ba/bT2w==",
1775 | "dev": true,
1776 | "optional": true
1777 | },
1778 | "esbuild-sunos-64": {
1779 | "version": "0.15.13",
1780 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.13.tgz",
1781 | "integrity": "sha512-jVeu2GfxZQ++6lRdY43CS0Tm/r4WuQQ0Pdsrxbw+aOrHQPHV0+LNOLnvbN28M7BSUGnJnHkHm2HozGgNGyeIRw==",
1782 | "dev": true,
1783 | "optional": true
1784 | },
1785 | "esbuild-windows-32": {
1786 | "version": "0.15.13",
1787 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.13.tgz",
1788 | "integrity": "sha512-XoF2iBf0wnqo16SDq+aDGi/+QbaLFpkiRarPVssMh9KYbFNCqPLlGAWwDvxEVz+ywX6Si37J2AKm+AXq1kC0JA==",
1789 | "dev": true,
1790 | "optional": true
1791 | },
1792 | "esbuild-windows-64": {
1793 | "version": "0.15.13",
1794 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.13.tgz",
1795 | "integrity": "sha512-Et6htEfGycjDrtqb2ng6nT+baesZPYQIW+HUEHK4D1ncggNrDNk3yoboYQ5KtiVrw/JaDMNttz8rrPubV/fvPQ==",
1796 | "dev": true,
1797 | "optional": true
1798 | },
1799 | "esbuild-windows-arm64": {
1800 | "version": "0.15.13",
1801 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.13.tgz",
1802 | "integrity": "sha512-3bv7tqntThQC9SWLRouMDmZnlOukBhOCTlkzNqzGCmrkCJI7io5LLjwJBOVY6kOUlIvdxbooNZwjtBvj+7uuVg==",
1803 | "dev": true,
1804 | "optional": true
1805 | },
1806 | "escape-string-regexp": {
1807 | "version": "1.0.5",
1808 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
1809 | "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
1810 | },
1811 | "estree-walker": {
1812 | "version": "2.0.2",
1813 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
1814 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
1815 | "dev": true
1816 | },
1817 | "find-replace": {
1818 | "version": "3.0.0",
1819 | "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz",
1820 | "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==",
1821 | "requires": {
1822 | "array-back": "^3.0.1"
1823 | }
1824 | },
1825 | "flatbuffers": {
1826 | "version": "1.12.0",
1827 | "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-1.12.0.tgz",
1828 | "integrity": "sha512-c7CZADjRcl6j0PlvFy0ZqXQ67qSEZfrVPynmnL+2zPc+NtMvrF8Y0QceMo7QqnSPc7+uWjUIAbvCQ5WIKlMVdQ=="
1829 | },
1830 | "fsevents": {
1831 | "version": "2.3.2",
1832 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
1833 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
1834 | "dev": true,
1835 | "optional": true
1836 | },
1837 | "function-bind": {
1838 | "version": "1.1.1",
1839 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
1840 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
1841 | "dev": true
1842 | },
1843 | "gl-matrix": {
1844 | "version": "3.4.3",
1845 | "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
1846 | "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
1847 | },
1848 | "has": {
1849 | "version": "1.0.3",
1850 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
1851 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
1852 | "dev": true,
1853 | "requires": {
1854 | "function-bind": "^1.1.1"
1855 | }
1856 | },
1857 | "has-flag": {
1858 | "version": "3.0.0",
1859 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
1860 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
1861 | },
1862 | "image-size": {
1863 | "version": "0.7.5",
1864 | "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.7.5.tgz",
1865 | "integrity": "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g=="
1866 | },
1867 | "is-core-module": {
1868 | "version": "2.11.0",
1869 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
1870 | "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
1871 | "dev": true,
1872 | "requires": {
1873 | "has": "^1.0.3"
1874 | }
1875 | },
1876 | "json-bignum": {
1877 | "version": "0.0.3",
1878 | "resolved": "https://registry.npmjs.org/json-bignum/-/json-bignum-0.0.3.tgz",
1879 | "integrity": "sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg=="
1880 | },
1881 | "ktx-parse": {
1882 | "version": "0.0.4",
1883 | "resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-0.0.4.tgz",
1884 | "integrity": "sha512-LY3nrmfXl+wZZdPxgJ3ZmLvG+wkOZZP3/dr4RbQj1Pk3Qwz44esOOSFFVQJcNWpXAtiNIC66WgXufX/SYgYz6A=="
1885 | },
1886 | "lodash.camelcase": {
1887 | "version": "4.3.0",
1888 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
1889 | "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
1890 | },
1891 | "nanoid": {
1892 | "version": "3.3.4",
1893 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
1894 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
1895 | "dev": true
1896 | },
1897 | "pad-left": {
1898 | "version": "2.1.0",
1899 | "resolved": "https://registry.npmjs.org/pad-left/-/pad-left-2.1.0.tgz",
1900 | "integrity": "sha512-HJxs9K9AztdIQIAIa/OIazRAUW/L6B9hbQDxO4X07roW3eo9XqZc2ur9bn1StH9CnbbI9EgvejHQX7CBpCF1QA==",
1901 | "requires": {
1902 | "repeat-string": "^1.5.4"
1903 | }
1904 | },
1905 | "path-parse": {
1906 | "version": "1.0.7",
1907 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
1908 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
1909 | "dev": true
1910 | },
1911 | "picocolors": {
1912 | "version": "1.0.0",
1913 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
1914 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
1915 | "dev": true
1916 | },
1917 | "picomatch": {
1918 | "version": "2.3.1",
1919 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
1920 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
1921 | "dev": true
1922 | },
1923 | "postcss": {
1924 | "version": "8.4.18",
1925 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz",
1926 | "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==",
1927 | "dev": true,
1928 | "requires": {
1929 | "nanoid": "^3.3.4",
1930 | "picocolors": "^1.0.0",
1931 | "source-map-js": "^1.0.2"
1932 | }
1933 | },
1934 | "probe.gl": {
1935 | "version": "3.5.2",
1936 | "resolved": "https://registry.npmjs.org/probe.gl/-/probe.gl-3.5.2.tgz",
1937 | "integrity": "sha512-8lFQVmi7pMQZkqfj8+VjX4GU9HTkyxgRm5/h/xxA/4/IvZPv3qtP996L+awPwZsrPRKEw99t12SvqEHqSls/sA==",
1938 | "requires": {
1939 | "@babel/runtime": "^7.0.0",
1940 | "@probe.gl/env": "3.5.2",
1941 | "@probe.gl/log": "3.5.2",
1942 | "@probe.gl/stats": "3.5.2"
1943 | }
1944 | },
1945 | "reduce-flatten": {
1946 | "version": "2.0.0",
1947 | "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz",
1948 | "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w=="
1949 | },
1950 | "regenerator-runtime": {
1951 | "version": "0.13.10",
1952 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz",
1953 | "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw=="
1954 | },
1955 | "repeat-string": {
1956 | "version": "1.6.1",
1957 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
1958 | "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w=="
1959 | },
1960 | "resolve": {
1961 | "version": "1.22.1",
1962 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
1963 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
1964 | "dev": true,
1965 | "requires": {
1966 | "is-core-module": "^2.9.0",
1967 | "path-parse": "^1.0.7",
1968 | "supports-preserve-symlinks-flag": "^1.0.0"
1969 | }
1970 | },
1971 | "rollup": {
1972 | "version": "2.79.1",
1973 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
1974 | "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
1975 | "dev": true,
1976 | "requires": {
1977 | "fsevents": "~2.3.2"
1978 | }
1979 | },
1980 | "rxjs": {
1981 | "version": "7.5.7",
1982 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz",
1983 | "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==",
1984 | "requires": {
1985 | "tslib": "^2.1.0"
1986 | }
1987 | },
1988 | "source-map": {
1989 | "version": "0.6.1",
1990 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
1991 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
1992 | "dev": true
1993 | },
1994 | "source-map-js": {
1995 | "version": "1.0.2",
1996 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
1997 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
1998 | "dev": true
1999 | },
2000 | "source-map-support": {
2001 | "version": "0.5.21",
2002 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
2003 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
2004 | "dev": true,
2005 | "requires": {
2006 | "buffer-from": "^1.0.0",
2007 | "source-map": "^0.6.0"
2008 | }
2009 | },
2010 | "sprintf-js": {
2011 | "version": "1.0.3",
2012 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
2013 | "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
2014 | },
2015 | "standardized-audio-context": {
2016 | "version": "25.3.34",
2017 | "resolved": "https://registry.npmjs.org/standardized-audio-context/-/standardized-audio-context-25.3.34.tgz",
2018 | "integrity": "sha512-SL8FQYqpfOifYGhAVfnAgC9o86mFNhy+W3xp28lHI6HgOQMbLTMcBoSN3FT0SwE51br7I9tmgjwiLggg7WWD/Q==",
2019 | "requires": {
2020 | "@babel/runtime": "^7.20.1",
2021 | "automation-events": "^4.0.23",
2022 | "tslib": "^2.4.1"
2023 | }
2024 | },
2025 | "supports-color": {
2026 | "version": "5.5.0",
2027 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
2028 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
2029 | "requires": {
2030 | "has-flag": "^3.0.0"
2031 | }
2032 | },
2033 | "supports-preserve-symlinks-flag": {
2034 | "version": "1.0.0",
2035 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
2036 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
2037 | "dev": true
2038 | },
2039 | "table-layout": {
2040 | "version": "1.0.2",
2041 | "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz",
2042 | "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==",
2043 | "requires": {
2044 | "array-back": "^4.0.1",
2045 | "deep-extend": "~0.6.0",
2046 | "typical": "^5.2.0",
2047 | "wordwrapjs": "^4.0.0"
2048 | },
2049 | "dependencies": {
2050 | "array-back": {
2051 | "version": "4.0.2",
2052 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz",
2053 | "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg=="
2054 | },
2055 | "typical": {
2056 | "version": "5.2.0",
2057 | "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
2058 | "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg=="
2059 | }
2060 | }
2061 | },
2062 | "terser": {
2063 | "version": "5.15.1",
2064 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz",
2065 | "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==",
2066 | "dev": true,
2067 | "requires": {
2068 | "@jridgewell/source-map": "^0.3.2",
2069 | "acorn": "^8.5.0",
2070 | "commander": "^2.20.0",
2071 | "source-map-support": "~0.5.20"
2072 | }
2073 | },
2074 | "text-encoding-utf-8": {
2075 | "version": "1.0.2",
2076 | "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz",
2077 | "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg=="
2078 | },
2079 | "texture-compressor": {
2080 | "version": "1.0.2",
2081 | "resolved": "https://registry.npmjs.org/texture-compressor/-/texture-compressor-1.0.2.tgz",
2082 | "integrity": "sha512-dStVgoaQ11mA5htJ+RzZ51ZxIZqNOgWKAIvtjLrW1AliQQLCmrDqNzQZ8Jh91YealQ95DXt4MEduLzJmbs6lig==",
2083 | "requires": {
2084 | "argparse": "^1.0.10",
2085 | "image-size": "^0.7.4"
2086 | }
2087 | },
2088 | "tone": {
2089 | "version": "14.7.77",
2090 | "resolved": "https://registry.npmjs.org/tone/-/tone-14.7.77.tgz",
2091 | "integrity": "sha512-tCfK73IkLHyzoKUvGq47gyDyxiKLFvKiVCOobynGgBB9Dl0NkxTM2p+eRJXyCYrjJwy9Y0XCMqD3uOYsYt2Fdg==",
2092 | "requires": {
2093 | "standardized-audio-context": "^25.1.8",
2094 | "tslib": "^2.0.1"
2095 | }
2096 | },
2097 | "tslib": {
2098 | "version": "2.4.1",
2099 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
2100 | "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
2101 | },
2102 | "tweakpane": {
2103 | "version": "3.1.0",
2104 | "resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-3.1.0.tgz",
2105 | "integrity": "sha512-PGAp/LPQdHwzL7/iAW4lV1p9iPQTti7YMjMWO48CoYjvZRS59RmgQnhEGzKzqST1JnmOYmQUjTe8bdhlZRJs5A=="
2106 | },
2107 | "twgl.js": {
2108 | "version": "5.2.0",
2109 | "resolved": "https://registry.npmjs.org/twgl.js/-/twgl.js-5.2.0.tgz",
2110 | "integrity": "sha512-DuiCzdjO3PNOrxbxHMYuhvVPhBaH0f3WThJSixFU4eNnpe0NzECMeaEEe/aznt+EJ5JAU3pXyeXiYSgEJHJH4A=="
2111 | },
2112 | "typical": {
2113 | "version": "4.0.0",
2114 | "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz",
2115 | "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw=="
2116 | },
2117 | "vite": {
2118 | "version": "3.2.2",
2119 | "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.2.tgz",
2120 | "integrity": "sha512-pLrhatFFOWO9kS19bQ658CnRYzv0WLbsPih6R+iFeEEhDOuYgYCX2rztUViMz/uy/V8cLCJvLFeiOK7RJEzHcw==",
2121 | "dev": true,
2122 | "requires": {
2123 | "esbuild": "^0.15.9",
2124 | "fsevents": "~2.3.2",
2125 | "postcss": "^8.4.18",
2126 | "resolve": "^1.22.1",
2127 | "rollup": "^2.79.1"
2128 | }
2129 | },
2130 | "vite-plugin-glsl": {
2131 | "version": "0.3.0",
2132 | "resolved": "https://registry.npmjs.org/vite-plugin-glsl/-/vite-plugin-glsl-0.3.0.tgz",
2133 | "integrity": "sha512-cH7ni+Y3Vz1yOumvrP/71hXVdyTxZIaYYNDeK7KMvO5nzo0uGZZrrkwEVUaESS8/5dYemb/6G0YBj3jsP2sW1A==",
2134 | "dev": true,
2135 | "requires": {
2136 | "@rollup/pluginutils": "^4.2.1"
2137 | }
2138 | },
2139 | "wordwrapjs": {
2140 | "version": "4.0.1",
2141 | "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz",
2142 | "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==",
2143 | "requires": {
2144 | "reduce-flatten": "^2.0.0",
2145 | "typical": "^5.2.0"
2146 | },
2147 | "dependencies": {
2148 | "typical": {
2149 | "version": "5.2.0",
2150 | "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz",
2151 | "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg=="
2152 | }
2153 | }
2154 | }
2155 | }
2156 | }
2157 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "liquid-geo",
3 | "private": true,
4 | "version": "2.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "start": "vite serve",
8 | "build": "vite build --emptyOutDir --base=/liquid-geo/dist/",
9 | "preview": "vite preview"
10 | },
11 | "devDependencies": {
12 | "terser": "^5.14.2",
13 | "vite": "^3.0.0",
14 | "vite-plugin-glsl": "^0.3.0"
15 | },
16 | "dependencies": {
17 | "@loaders.gl/core": "^3.2.3",
18 | "@loaders.gl/gltf": "^3.2.3",
19 | "gl-matrix": "^3.4.3",
20 | "rxjs": "^7.5.6",
21 | "tone": "^14.7.77",
22 | "tweakpane": "^3.1.0",
23 | "twgl.js": "^5.0.4"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/_sketch-template.js:
--------------------------------------------------------------------------------
1 | import { vec2 } from "gl-matrix";
2 |
3 | export class Sketch {
4 |
5 | TARGET_FRAME_DURATION = 16;
6 | #time = 0; // total time
7 | #deltaTime = 0; // duration betweent the previous and the current animation frame
8 | #frames = 0; // total framecount according to the target frame duration
9 | // relative frames according to the target frame duration (1 = 60 fps)
10 | // gets smaller with higher framerates --> use to adapt animation timing
11 | #deltaFrames = 0;
12 |
13 | constructor(canvasElm, onInit = null) {
14 | this.canvas = canvasElm;
15 | this.onInit = onInit;
16 |
17 | this.#init();
18 | }
19 |
20 | run(time = 0) {
21 | this.#deltaTime = Math.min(32, time - this.#time);
22 | this.#time = time;
23 | this.#deltaFrames = this.#deltaTime / this.TARGET_FRAME_DURATION;
24 | this.#frames += this.#deltaFrames
25 |
26 | this.#animate(this.#deltaTime);
27 | this.#render();
28 |
29 | requestAnimationFrame((t) => this.run(t));
30 | }
31 |
32 | resize() {
33 | this.viewportSize = vec2.set(
34 | this.viewportSize,
35 | this.canvas.clientWidth,
36 | this.canvas.clientHeight
37 | );
38 | }
39 |
40 | #init() {
41 | this.viewportSize = vec2.fromValues(
42 | this.canvas.clientWidth,
43 | this.canvas.clientHeight
44 | );
45 |
46 | if (this.onInit) this.onInit(this);
47 | }
48 |
49 | #animate(deltaTime) {
50 |
51 | }
52 |
53 | #render() {
54 |
55 | }
56 | }
--------------------------------------------------------------------------------
/src/app/app.js:
--------------------------------------------------------------------------------
1 | import { concatAll, take, count, debounceTime, delay, filter, forkJoin, from, fromEvent, map, scan, withLatestFrom, of, switchMap, tap, distinctUntilChanged } from 'rxjs';
2 | import { Sketch } from './sketch';
3 | import { Pane } from 'tweakpane';
4 | import * as modernizr from './utils/modernizr';
5 | import { AudioRepeater } from './audio-repeater';
6 |
7 | const queryString = window.location.search;
8 | const urlParams = new URLSearchParams(queryString);
9 | const hasDebugParam = urlParams.get('debug');
10 | const isDev = import.meta.env.MODE === 'development';
11 | let sketch;
12 | let audioRepeater;
13 | let pane;
14 |
15 | if (isDev) {
16 | import('https://greggman.github.io/webgl-lint/webgl-lint.js');
17 | }
18 |
19 | if (hasDebugParam || isDev) {
20 | pane = new Pane({ title: 'Settings', expanded: isDev });
21 | }
22 |
23 | const resize = () => {
24 | // explicitly set the width and height to compensate for missing dvh and dvw support
25 | document.body.style.width = `${document.documentElement.clientWidth}px`;
26 | document.body.style.height = `${document.documentElement.clientHeight}px`;
27 |
28 | if (sketch) {
29 | sketch.resize();
30 | }
31 | }
32 |
33 | // add a debounced resize listener
34 | fromEvent(window, 'resize').pipe(debounceTime(100)).subscribe(() => resize());
35 |
36 | // resize initially on load
37 | fromEvent(window, 'load').pipe(take(1)).subscribe(() => resize());
38 |
39 | // INIT APP
40 | const canvasElm = document.querySelector('canvas');
41 | const recordBtnElm = document.querySelector('#record-button');
42 | const playbackBtnElm = document.querySelector('#playback-button');
43 | audioRepeater = new AudioRepeater(recordBtnElm, playbackBtnElm, isDev, pane);
44 | sketch = new Sketch(canvasElm, audioRepeater, (instance) => instance.run(), isDev, pane);
45 | resize();
46 |
--------------------------------------------------------------------------------
/src/app/audio-repeater.js:
--------------------------------------------------------------------------------
1 | import * as Tone from 'tone';
2 |
3 | export class AudioRepeater {
4 |
5 | MAX_RECORD_LENGTH = 5; // seconds
6 | FFT_BUFFER_SIZE = 256;
7 |
8 | isRecording = false;
9 | isRecordingTimeoutId = null;
10 |
11 | MIN_DB = -100;
12 |
13 | constructor(recordBtnElm, playbackBtnElm, isDev = false, pane = null) {
14 | this.isDev = isDev;
15 | this.pane = pane;
16 | this.recordBtnElm = recordBtnElm;
17 | this.recordBtnLabelElm = recordBtnElm.querySelector('label');
18 | this.playbackBtnElm = playbackBtnElm;
19 | this.playbackBtnLabelElm = playbackBtnElm.querySelector('label');
20 | this.playbackBtnElm.setAttribute('disabled', true);
21 |
22 | this.init();
23 | }
24 |
25 | init() {
26 | this.recordBtnLabelElm.innerHTML = 'RECORD';
27 | this.playbackBtnLabelElm.innerHTML = 'PLAY';
28 | this.playbackBtnElm.setAttribute('disabled', true);
29 |
30 | this.recordBtnElm.addEventListener('click', () => this.onRecordButtonClicked());
31 | this.playbackBtnElm.addEventListener('click', () => this.onPlaybackButtonClicked());
32 | }
33 |
34 | initAudio() {
35 | this.audioContext = new AudioContext();
36 | Tone.setContext(this.audioContext);
37 |
38 | this.gain = this.audioContext.createGain();
39 |
40 | this.analyser = this.audioContext.createAnalyser();
41 | this.analyser.fftSize = this.FFT_BUFFER_SIZE;
42 | this.analyser.minDecibels = -90;
43 | this.bufferLength = this.analyser.frequencyBinCount;
44 | this.buffer = new Uint8Array(this.bufferLength);
45 | this.smoothedBuffer1 = new Float32Array(this.bufferLength);
46 | this.smoothedBuffer2 = new Float32Array(this.bufferLength);
47 | this.buffer.fill(0);
48 | this.smoothedBuffer1.fill(0);
49 | this.smoothedBuffer2.fill(0);
50 | // calculate the frequency bin bandwidth
51 | this.freqBandwidth = (this.audioContext.sampleRate / 2) / this.bufferLength;
52 |
53 | this.dist = new Tone.Distortion(0.3);
54 | this.pitchShift = new Tone.PitchShift(-2);
55 | this.reverb = new Tone.Reverb(3);
56 |
57 | Tone.connect(this.dist, this.pitchShift);
58 | Tone.connect(this.pitchShift, this.reverb);
59 | this.reverb.toDestination();
60 | }
61 |
62 | startPlayback() {
63 | this.audio.currentTime = 0;
64 | this.audio.play();
65 | }
66 |
67 | pausePlayback() {
68 | this.audio.pause();
69 | }
70 |
71 | onPlaybackButtonClicked() {
72 | this.startPlayback();
73 | }
74 |
75 | async onRecordButtonClicked() {
76 | if (!this.audioContext) this.initAudio();
77 |
78 | if (this.isRecording) {
79 | this.stopRecording();
80 | } else {
81 | await this.startRecording();
82 | }
83 | }
84 |
85 | async startRecording() {
86 | if (this.audio) {
87 | this.audio.pause();
88 | }
89 |
90 | this.recordBtnElm.classList.add('is-recording');
91 | this.playbackBtnElm.setAttribute('disabled', true);
92 | this.recordBtnLabelElm.innerHTML = 'STOP';
93 | this.isRecording = true;
94 | this.audioChunks = [];
95 |
96 | if (!this.mediaRecorder) {
97 | const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
98 | this.mediaRecorder = new MediaRecorder(stream);
99 |
100 | this.mediaRecorder.addEventListener("dataavailable", event => {
101 | this.audioChunks.push(event.data);
102 | });
103 |
104 | this.mediaRecorder.addEventListener("stop", () => {
105 | this.audioBlob = new Blob(this.audioChunks, { type: "audio/mpeg" });
106 | this.audioUrl = URL.createObjectURL(this.audioBlob);
107 | this.audio = new Audio(this.audioUrl);
108 |
109 | this.source = this.audioContext.createMediaElementSource(this.audio);
110 | Tone.connect(this.source, this.dist);
111 | Tone.connect(this.source, this.analyser);
112 | });
113 | }
114 | this.mediaRecorder.start();
115 |
116 | this.isRecordingTimeoutId = setTimeout(() => this.stopRecording(), this.MAX_RECORD_LENGTH * 1000);
117 | }
118 |
119 | stopRecording() {
120 | this.recordBtnElm.classList.remove('is-recording');
121 | this.playbackBtnElm.removeAttribute('disabled');
122 | this.isRecording = false;
123 | this.recordBtnLabelElm.innerHTML = 'RECORD';
124 | clearTimeout(this.isRecordingTimeoutId);
125 | this.mediaRecorder.stop();
126 | }
127 |
128 | getSpectrum(){
129 | if (this.audioContext) {
130 | if (this.audio && !this.audio.paused) {
131 | this.analyser.getByteFrequencyData( this.buffer );
132 | } else {
133 | this.buffer.fill(0);
134 | }
135 |
136 | if (this.buffer) {
137 | for(let i=0; i u_twoStagePmS1) )
33 | // must copy -> compare with self
34 | compare = 0.0;
35 | else
36 | // must sort
37 | if ( mod((j + u_passModStage) / u_ppass, 2.0) < 1.0)
38 | // we are on the left side -> compare with partner on the right
39 | compare = 1.0;
40 | else
41 | // we are on the right side -> compare with partner on the left
42 | compare = -1.0;
43 |
44 | // get the partner
45 | float adr = i + compare * u_ppass;
46 | uvec4 partner = texture(u_indicesTexture, vec2(floor(mod(adr, width)) / width, floor(adr / width) / height));
47 |
48 | // on the left it's a < operation; on the right it's a >= operation
49 | outIndices = (float(self.x) * compare < float(partner.x) * compare) ? self : partner;
50 | }
51 |
--------------------------------------------------------------------------------
/src/app/shader/sph/sort.vert.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | in vec2 a_position;
4 |
5 | void main() {
6 | gl_Position = vec4(a_position, 0., 1.);
7 | }
--------------------------------------------------------------------------------
/src/app/shader/sph/utils/particle-utils.glsl:
--------------------------------------------------------------------------------
1 |
2 | ivec2 ndx2tex(ivec2 dimensions, int index) {
3 | int y = index / dimensions.x;
4 | int x = index % dimensions.x;
5 | return ivec2(x, y);
6 | }
7 |
8 | int tex2ndx(ivec2 dimensions, ivec2 tex) {
9 | return tex.x + tex.y * dimensions.x;
10 | }
11 |
12 | float sphericalDistance(vec3 pi, vec3 pj) {
13 | return (acos(dot(pj, pi)));
14 | }
15 |
16 | float sqrParticleDist(vec3 pi, vec3 pj) {
17 | vec3 pij = pj - pi;
18 | return dot(pij, pij);
19 | }
20 |
21 | ivec2 pos2CellIndex(vec2 p, ivec2 cellTexSize, vec2 domainScale, float cellSize) {
22 | vec2 pi = p * 0.5 + 0.5;
23 | pi = clamp(pi, vec2(0.001), vec2(.999));
24 | pi *= domainScale;
25 | return ivec2(pi / cellSize);
26 | }
27 |
28 | int pos2CellId(vec2 p, ivec2 cellTexSize, vec2 domainScale, float cellSize) {
29 | ivec2 cellIndex = pos2CellIndex(p, cellTexSize, domainScale, cellSize);
30 | return tex2ndx(cellTexSize, cellIndex);
31 | }
32 |
33 | int getFlatCellIndex(ivec2 cellIndex, int numGridCells) {
34 | int p1 = 73856093; // some large primes
35 | int p2 = 19349663;
36 | int n = p1 * cellIndex.x ^ p2 * cellIndex.y;
37 | n %= numGridCells;
38 | return n;
39 | }
40 |
41 | float mod289(float x){return x - floor(x * (1.0 / 289.0)) * 289.0;}
42 | vec4 mod289(vec4 x){return x - floor(x * (1.0 / 289.0)) * 289.0;}
43 | vec4 perm(vec4 x){return mod289(((x * 34.0) + 1.0) * x);}
44 |
45 | float noise(vec3 p){
46 | vec3 a = floor(p);
47 | vec3 d = p - a;
48 | d = d * d * (3.0 - 2.0 * d);
49 |
50 | vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0);
51 | vec4 k1 = perm(b.xyxy);
52 | vec4 k2 = perm(k1.xyxy + b.zzww);
53 |
54 | vec4 c = k2 + a.zzzz;
55 | vec4 k3 = perm(c);
56 | vec4 k4 = perm(c + 1.0);
57 |
58 | vec4 o1 = fract(k3 * (1.0 / 41.0));
59 | vec4 o2 = fract(k4 * (1.0 / 41.0));
60 |
61 | vec4 o3 = o2 * d.z + o1 * (1.0 - d.z);
62 | vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);
63 |
64 | return o4.y * d.y + o4.x * (1.0 - d.y);
65 | }
66 |
67 | vec3 snoiseVec3( vec3 x ){
68 | float s = noise(vec3( x ));
69 | float s1 = noise(vec3( x.y - 19.1 , x.z + 33.4 , x.x + 47.2 ));
70 | float s2 = noise(vec3( x.z + 74.2 , x.x - 124.5 , x.y + 99.4 ));
71 | vec3 c = vec3( s , s1 , s2 );
72 | return c;
73 | }
74 |
75 | vec3 curlNoise( vec3 p ){
76 | const float e = .1;
77 | vec3 dx = vec3( e , 0.0 , 0.0 );
78 | vec3 dy = vec3( 0.0 , e , 0.0 );
79 | vec3 dz = vec3( 0.0 , 0.0 , e );
80 |
81 | vec3 p_x0 = snoiseVec3( p - dx );
82 | vec3 p_x1 = snoiseVec3( p + dx );
83 | vec3 p_y0 = snoiseVec3( p - dy );
84 | vec3 p_y1 = snoiseVec3( p + dy );
85 | vec3 p_z0 = snoiseVec3( p - dz );
86 | vec3 p_z1 = snoiseVec3( p + dz );
87 |
88 | float x = p_y1.z - p_y0.z - p_z1.y + p_z0.y;
89 | float y = p_z1.x - p_z0.x - p_x1.z + p_x0.z;
90 | float z = p_x1.y - p_x0.y - p_y1.x + p_y0.x;
91 |
92 | const float divisor = 1.0 / ( 2.0 * e );
93 | return normalize( vec3( x , y , z ) * divisor );
94 | }
--------------------------------------------------------------------------------
/src/app/shader/test.frag.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision highp float;
4 |
5 | uniform sampler2D u_texture;
6 |
7 | out vec4 outColor;
8 |
9 | in vec2 v_uv;
10 |
11 | void main() {
12 | outColor = vec4(texture(u_texture, v_uv));
13 | }
--------------------------------------------------------------------------------
/src/app/shader/test.vert.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | in vec2 a_position;
4 |
5 | out vec2 v_uv;
6 |
7 | void main() {
8 | v_uv = 0.5 * a_position + 0.5;
9 | gl_Position = vec4(a_position, 0., 1.);
10 | }
--------------------------------------------------------------------------------
/src/app/sketch.js:
--------------------------------------------------------------------------------
1 | import { mat4, vec2, vec3, vec4 } from "gl-matrix";
2 | import { filter, fromEvent, merge, throwIfEmpty } from "rxjs";
3 | import * as twgl from "twgl.js";
4 | import { GLBBuilder } from "./utils/glb-builder";
5 |
6 | import drawVert from './shader/sph/draw.vert.glsl';
7 | import drawFrag from './shader/sph/draw.frag.glsl';
8 | import integrateVert from './shader/sph/integrate.vert.glsl';
9 | import integrateFrag from './shader/sph/integrate.frag.glsl';
10 | import pressureVert from './shader/sph/pressure.vert.glsl';
11 | import pressureFrag from './shader/sph/pressure.frag.glsl';
12 | import forceVert from './shader/sph/force.vert.glsl';
13 | import forceFrag from './shader/sph/force.frag.glsl';
14 | import testVert from './shader/test.vert.glsl';
15 | import testFrag from './shader/test.frag.glsl';
16 | import beadVert from './shader/bead.vert.glsl';
17 | import beadFrag from './shader/bead.frag.glsl';
18 | import lightDepthFrag from './shader/light-depth.frag.glsl';
19 | import highpassVert from './shader/highpass.vert.glsl';
20 | import highpassFrag from './shader/highpass.frag.glsl';
21 | import blurVert from './shader/blur.vert.glsl';
22 | import blurFrag from './shader/blur.frag.glsl';
23 | import compositeVert from './shader/composite.vert.glsl';
24 | import compositeFrag from './shader/composite.frag.glsl';
25 | import {isIOS} from './is-ios.js';
26 |
27 | export class Sketch {
28 |
29 | TARGET_FRAME_DURATION = 16;
30 | #time = 0; // total time
31 | #deltaTime = 0; // duration betweent the previous and the current animation frame
32 | #frames = 0; // total framecount according to the target frame duration
33 | // relative frames according to the target frame duration (1 = 60 fps)
34 | // gets smaller with higher framerates --> use to adapt animation timing
35 | #deltaFrames = 0;
36 |
37 | // particle constants
38 | NUM_PARTICLES = 500;
39 |
40 | // the scale factor for the bloom and lensflare highpass texture
41 | SS_FX_SCALE = 0.2;
42 |
43 | simulationParams = {
44 | H: 1, // kernel radius
45 | MASS: 1, // particle mass
46 | REST_DENS: 1.5, // rest density
47 | GAS_CONST: 400, // gas constant
48 | VISC: 18.5, // viscosity constant
49 |
50 | // these are calculated from the above constants
51 | POLY6: 0,
52 | HSQ: 0,
53 | SPIKY_GRAD: 0,
54 | VISC_LAP: 0,
55 |
56 | PARTICLE_COUNT: 0,
57 | DOMAIN_SCALE: vec4.fromValues(1, 1, 1, 1),
58 |
59 | STEPS: 0
60 | };
61 |
62 | pointerParams = {
63 | RADIUS: .5,
64 | STRENGTH: 20,
65 | }
66 |
67 | camera = {
68 | matrix: mat4.create(),
69 | near: 4,
70 | far: 6,
71 | fov: Math.PI / 3,
72 | aspect: 1,
73 | position: vec3.fromValues(0, 0, 6),
74 | up: vec3.fromValues(0, 1, 0),
75 | matrices: {
76 | view: mat4.create(),
77 | projection: mat4.create(),
78 | inversProjection: mat4.create(),
79 | inversViewProjection: mat4.create()
80 | }
81 | };
82 |
83 | light = {
84 | matrix: mat4.create(),
85 | position: vec3.scale(vec3.create(), vec3.normalize(vec3.create(), vec3.fromValues(1, 1, 1)), 6),
86 | up: vec3.fromValues(0, 1, 0),
87 | size: 2.4,
88 | near: 4,
89 | far: 7,
90 | textureSize: 1024,
91 | matrices: {
92 | view: mat4.create(),
93 | projection: mat4.create(),
94 | viewProjection: mat4.create()
95 | }
96 | }
97 |
98 | constructor(canvasElm, audioRepeater, onInit = null, isDev = false, pane = null) {
99 | this.canvas = canvasElm;
100 | this.onInit = onInit;
101 | this.isDev = isDev;
102 | this.pane = pane;
103 | this.audioRepeater = audioRepeater;
104 |
105 | this.#init().then(() => {
106 | if (this.onInit) this.onInit(this)
107 | });
108 | }
109 |
110 | run(time = 0) {
111 | this.#deltaTime = Math.min(16, time - this.#time);
112 | this.#time = time;
113 | this.#deltaFrames = this.#deltaTime / this.TARGET_FRAME_DURATION;
114 | this.#frames += this.#deltaFrames;
115 |
116 | this.#animate(this.#deltaTime);
117 | this.#render();
118 |
119 | requestAnimationFrame((t) => this.run(t));
120 | }
121 |
122 | resize() {
123 | /** @type {WebGLRenderingContext} */
124 | const gl = this.gl;
125 |
126 | this.viewportSize = vec2.set(
127 | this.viewportSize,
128 | this.canvas.clientWidth,
129 | this.canvas.clientHeight
130 | );
131 |
132 | const needsResize = twgl.resizeCanvasToDisplaySize(this.canvas);
133 |
134 | const maxViewportSide = Math.max(this.viewportSize[0], this.viewportSize[1]);
135 | this.SS_FX_SCALE = Math.min(1, 256 / maxViewportSide);
136 |
137 | if (needsResize) {
138 | gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
139 |
140 | if (this.highpassFBO) {
141 | twgl.resizeFramebufferInfo(gl, this.highpassFBO, [{attachmentPoint: gl.COLOR_ATTACHMENT0}],
142 | this.viewportSize[0] * this.SS_FX_SCALE, this.viewportSize[1] * this.SS_FX_SCALE);
143 | }
144 |
145 | if (this.blurFBO) {
146 | twgl.resizeFramebufferInfo(gl, this.blurFBO, [{attachmentPoint: gl.COLOR_ATTACHMENT0}],
147 | this.viewportSize[0] * this.SS_FX_SCALE, this.viewportSize[1] * this.SS_FX_SCALE);
148 | }
149 |
150 | if (this.drawFBO) {
151 | twgl.resizeFramebufferInfo(gl, this.drawFBO, this.drawFBOAttachements, this.viewportSize[0], this.viewportSize[1]);
152 | }
153 | }
154 |
155 | this.#updateProjectionMatrix(gl);
156 | }
157 |
158 | async #init() {
159 | this.gl = this.canvas.getContext('webgl2', { antialias: false, alpha: false });
160 |
161 | this.touchevents = Modernizr.touchevents;
162 |
163 | /** @type {WebGLRenderingContext} */
164 | const gl = this.gl;
165 |
166 | twgl.addExtensionsToContext(gl);
167 |
168 | this.viewportSize = vec2.fromValues(
169 | this.canvas.clientWidth,
170 | this.canvas.clientHeight
171 | );
172 |
173 | this.#initTextures();
174 | this.#initLight();
175 | await this.#initEnvMap();
176 | await this.#initNormalMap();
177 |
178 | // Setup Programs
179 | this.drawPrg = twgl.createProgramInfo(gl, [drawVert, drawFrag]);
180 | this.integratePrg = twgl.createProgramInfo(gl, [integrateVert, integrateFrag]);
181 | this.pressurePrg = twgl.createProgramInfo(gl, [pressureVert, pressureFrag]);
182 | this.forcePrg = twgl.createProgramInfo(gl, [forceVert, forceFrag]);
183 | this.beadPrg = twgl.createProgramInfo(gl, [beadVert, beadFrag]);
184 | this.testPrg = twgl.createProgramInfo(gl, [testVert, testFrag]);
185 | this.lightDepthPrg = twgl.createProgramInfo(gl, [beadVert, lightDepthFrag]);
186 | this.highpassPrg = twgl.createProgramInfo(gl, [highpassVert, highpassFrag]);
187 | this.blurPrg = twgl.createProgramInfo(gl, [blurVert, blurFrag]);
188 | this.compositePrg = twgl.createProgramInfo(gl, [compositeVert, compositeFrag]);
189 |
190 | // Setup uinform blocks
191 | this.simulationParamsUBO = twgl.createUniformBlockInfo(gl, this.pressurePrg, 'u_SimulationParams');
192 | this.pointerParamsUBO = twgl.createUniformBlockInfo(gl, this.integratePrg, 'u_PointerParams');
193 | this.simulationParamsNeedUpdate = true;
194 |
195 | // Setup Meshes
196 | this.quadBufferInfo = twgl.createBufferInfoFromArrays(gl, { a_position: { numComponents: 2, data: [-1, -1, 3, -1, -1, 3] }});
197 | this.quadVAO = twgl.createVAOAndSetAttributes(gl, this.pressurePrg.attribSetters, this.quadBufferInfo.attribs, this.quadBufferInfo.indices);
198 |
199 | // load the bead model
200 | this.glbBuilder = new GLBBuilder(gl);
201 | await this.glbBuilder.load(new URL('../assets/bead.glb', import.meta.url));
202 | this.beadPrimitive = this.glbBuilder.getPrimitiveDataByMeshName('bead');
203 | this.beadBuffers = this.beadPrimitive.buffers;
204 | this.beadBufferInfo = twgl.createBufferInfoFromArrays(gl, {
205 | a_position: {...this.beadBuffers.vertices, numComponents: this.beadBuffers.vertices.numberOfComponents},
206 | a_normal: {...this.beadBuffers.normals, numComponents: this.beadBuffers.normals.numberOfComponents},
207 | a_texcoord: {...this.beadBuffers.texcoords, numComponents: this.beadBuffers.texcoords.numberOfComponents},
208 | a_tangent: {...this.beadBuffers.tangents, numComponents: this.beadBuffers.tangents.numberOfComponents},
209 | indices: {...this.beadBuffers.indices, numComponents: this.beadBuffers.indices.numberOfComponents}
210 | });
211 | this.beadVAO = twgl.createVAOAndSetAttributes(gl, this.beadPrg.attribSetters, this.beadBufferInfo.attribs, this.beadBufferInfo.indices);
212 |
213 | // Setup Framebuffers
214 | this.pressureFBO = twgl.createFramebufferInfo(gl, [{attachment: this.textures.densityPressure}], this.textureSize, this.textureSize);
215 | this.forceFBO = twgl.createFramebufferInfo(gl, [{attachment: this.textures.force}], this.textureSize, this.textureSize);
216 | this.inFBO = twgl.createFramebufferInfo(gl, [{attachment: this.textures.position1},{attachment: this.textures.velocity1}], this.textureSize, this.textureSize);
217 | this.outFBO = twgl.createFramebufferInfo(gl, [{attachment: this.textures.position2},{attachment: this.textures.velocity2}], this.textureSize, this.textureSize);
218 | this.lightDepthFBO = twgl.createFramebufferInfo(gl, [{
219 | attachmentPoint: gl.DEPTH_ATTACHMENT,
220 | attachment: this.lightDepthTexture
221 | }], this.light.textureSize, this.light.textureSize);
222 | this.drawFBOAttachements = [
223 | {format: gl.RGBA, internalFormat: gl.RGBA32F, min: isIOS ? gl.NEAREST : gl.LINEAR, mag: isIOS ? gl.NEAREST : gl.LINEAR},
224 | {attachmentPoint: gl.DEPTH_ATTACHMENT, format: gl.DEPTH_COMPONENT, internalFormat: gl.DEPTH_COMPONENT32F}
225 | ];
226 | this.drawFBO = twgl.createFramebufferInfo(gl, this.drawFBOAttachements, this.viewportSize[0], this.viewportSize[1]);
227 | this.colorTexture = this.drawFBO.attachments[0];
228 | this.highpassFBO = twgl.createFramebufferInfo(
229 | gl,
230 | [{attachmentPoint: gl.COLOR_ATTACHMENT0}],
231 | this.viewportSize[0] * this.SS_FX_SCALE,
232 | this.viewportSize[1] * this.SS_FX_SCALE
233 | );
234 | this.highpassTexture = this.highpassFBO.attachments[0];
235 | this.blurFBO = twgl.createFramebufferInfo(
236 | gl,
237 | [{attachmentPoint: gl.COLOR_ATTACHMENT0}],
238 | this.viewportSize[0] * this.SS_FX_SCALE,
239 | this.viewportSize[1] * this.SS_FX_SCALE
240 | );
241 | this.blurTexture = this.blurFBO.attachments[0];
242 |
243 | this.worldMatrix = mat4.create();
244 |
245 | this.#initEvents();
246 | this.#updateSimulationParams();
247 | this.#initTweakpane();
248 | this.#updateCameraMatrix();
249 | this.#updateProjectionMatrix(gl);
250 |
251 | this.resize();
252 | }
253 |
254 | #initEvents() {
255 | this.isPointerDown = false;
256 | this.pointerLeft = true;
257 | this.pointer = vec2.create();
258 | this.pointerLerp = vec2.create();
259 | this.pointerLerpPrev = vec2.create();
260 | this.pointerLerpDelta = vec2.create();
261 | this.arcPointer = vec3.create();
262 | this.arcPointerPrev = vec3.create();
263 | this.arcPointerDelta = vec3.create();
264 |
265 | fromEvent(this.canvas, 'pointerdown').subscribe((e) => {
266 | this.isPointerDown = true;
267 | this.pointerLeft = false;
268 | this.pointer = vec2.fromValues(e.clientX, e.clientY);
269 | vec2.copy(this.pointerLerp, this.pointer);
270 | vec2.copy(this.pointerLerpPrev, this.pointerLerp);
271 | });
272 | merge(
273 | fromEvent(this.canvas, 'pointerup'),
274 | fromEvent(this.canvas, 'pointerleave')
275 | ).subscribe(() => {
276 | this.isPointerDown = false;
277 | this.leftSphere = true;
278 | this.pointerLeft = true;
279 | });
280 |
281 | fromEvent(this.canvas, 'pointermove').subscribe((e) => {
282 | this.pointer = vec2.fromValues(e.clientX, e.clientY);
283 | if (this.pointerLeft) {
284 | this.pointerLerp = vec2.clone(this.pointer);
285 | this.pointerLerpPrev = vec2.clone(this.pointer);
286 | }
287 | this.pointerLeft = false;
288 | });
289 |
290 | fromEvent(window.document, 'keyup').subscribe(() => this.debugKey = true);
291 | }
292 |
293 | #updateSimulationParams() {
294 | const sim = this.simulationParams
295 | sim.HSQ = sim.H * sim.H;
296 | sim.POLY6 = 315.0 / (64. * Math.PI * Math.pow(sim.H, 9.));
297 | sim.SPIKY_GRAD = -45.0 / (Math.PI * Math.pow(sim.H, 6.));
298 | sim.VISC_LAP = 45.0 / (Math.PI * Math.pow(sim.H, 5.));
299 |
300 | this.simulationParamsNeedUpdate = true;
301 | }
302 |
303 | #initTextures() {
304 | /** @type {WebGLRenderingContext} */
305 | const gl = this.gl;
306 |
307 | // get a power of two texture size
308 | this.textureSize = 2**Math.ceil(Math.log2(Math.sqrt(this.NUM_PARTICLES)));
309 |
310 | // update the particle size to fill the texture space
311 | this.NUM_PARTICLES = this.textureSize * this.textureSize;
312 | this.simulationParams.PARTICLE_COUNT = this.NUM_PARTICLES;
313 | this.simulationParamsNeedUpdate = true;
314 |
315 | console.log('number of particles:', this.NUM_PARTICLES);
316 |
317 | this.spectrumTextureSize = Math.sqrt(this.audioRepeater.bufferLength);
318 |
319 | const initVelocities = new Float32Array(this.NUM_PARTICLES * 4);
320 | const initForces = new Float32Array(this.NUM_PARTICLES * 4);
321 | const initPositions = new Float32Array(this.NUM_PARTICLES * 4);
322 |
323 | for(let i=0; i {
394 | this.envMapTexture = twgl.createTexture(gl, {
395 | src: new URL('../assets/env-map-02.jpg', import.meta.url).toString(),
396 | }, () => resolve());
397 | });
398 | }
399 |
400 | #initNormalMap() {
401 | /** @type {WebGLRenderingContext} */
402 | const gl = this.gl;
403 |
404 | return new Promise((resolve) => {
405 | this.normalMapTexture = twgl.createTexture(gl, {
406 | src: new URL('../assets/normal.png', import.meta.url).toString(),
407 | }, () => resolve());
408 | });
409 | }
410 |
411 | #initTweakpane() {
412 | if (!this.pane) return;
413 |
414 | const sim = this.pane.addFolder({ title: 'Simulation' });
415 | sim.addInput(this.simulationParams, 'MASS', { min: 0.01, max: 5, });
416 | sim.addInput(this.simulationParams, 'REST_DENS', { min: 0.1, max: 5, });
417 | sim.addInput(this.simulationParams, 'GAS_CONST', { min: 10, max: 500, });
418 | sim.addInput(this.simulationParams, 'VISC', { min: 1, max: 20, });
419 | sim.addInput(this.simulationParams, 'STEPS', { min: 0, max: 6, step: 1 });
420 |
421 | const pointer = this.pane.addFolder({ title: 'Pointer' });
422 | pointer.addInput(this.pointerParams, 'RADIUS', { min: 0.1, max: 5, });
423 | pointer.addInput(this.pointerParams, 'STRENGTH', { min: 1, max: 35, });
424 |
425 | sim.on('change', () => this.#updateSimulationParams());
426 | pointer.on('change', () => this.pointerParamsNeedUpdate = true);
427 | }
428 |
429 | #initLight() {
430 | mat4.targetTo(this.light.matrix, this.light.position, [0, 0, 0], this.light.up);
431 | mat4.invert(this.light.matrices.view, this.light.matrix);
432 | mat4.ortho(
433 | this.light.matrices.projection,
434 | -this.light.size / 2,
435 | this.light.size / 2,
436 | -this.light.size / 2,
437 | this.light.size / 2,
438 | this.light.near,
439 | this.light.far
440 | );
441 | mat4.multiply(this.light.matrices.viewProjection, this.light.matrices.projection, this.light.matrices.view);
442 | }
443 |
444 | #updatePointer() {
445 | this.pointerLerp[0] += (this.pointer[0] - this.pointerLerp[0]) / 5;
446 | this.pointerLerp[1] += (this.pointer[1] - this.pointerLerp[1]) / 5;
447 |
448 | let newArcPointer = null;
449 | if (!this.touchevents || this.isPointerDown)
450 | newArcPointer = this.#screenToSpherePos(this.pointerLerp);
451 |
452 | if (newArcPointer !== null) {
453 | this.arcPointer = newArcPointer;
454 | if (this.leftSphere) {
455 | vec3.copy(this.arcPointerPrev, this.arcPointer);
456 | this.leftSphere = false;
457 | }
458 | } else {
459 | this.leftSphere = true;
460 | }
461 |
462 |
463 | this.arcPointerDelta = vec3.subtract(this.arcPointerDelta, this.arcPointer, this.arcPointerPrev);
464 | vec3.copy(this.arcPointerPrev, this.arcPointer);
465 |
466 | vec2.subtract(this.pointerLerpDelta, this.pointerLerp, this.pointerLerpPrev);
467 | vec2.copy(this.pointerLerpPrev, this.pointerLerp);
468 | }
469 |
470 | #simulate(deltaTime) {
471 | /** @type {WebGLRenderingContext} */
472 | const gl = this.gl;
473 |
474 | if (this.simulationParamsNeedUpdate) {
475 | twgl.setBlockUniforms(
476 | this.simulationParamsUBO,
477 | {
478 | ...this.simulationParams,
479 | }
480 | );
481 | twgl.setUniformBlock(gl, this.pressurePrg, this.simulationParamsUBO);
482 | this.simulationParamsNeedUpdate = false;
483 | } else {
484 | twgl.bindUniformBlock(gl, this.pressurePrg, this.simulationParamsUBO);
485 | }
486 |
487 |
488 | // calculate density and pressure for every particle
489 | gl.useProgram(this.pressurePrg.program);
490 | twgl.bindFramebufferInfo(gl, this.pressureFBO);
491 | gl.bindVertexArray(this.quadVAO);
492 | twgl.setUniforms(this.pressurePrg, {
493 | u_positionTexture: this.inFBO.attachments[0]
494 | });
495 | twgl.drawBufferInfo(gl, this.quadBufferInfo);
496 |
497 |
498 | // calculate pressure-, viscosity- and boundary forces for every particle
499 | gl.useProgram(this.forcePrg.program);
500 | twgl.bindFramebufferInfo(gl, this.forceFBO);
501 | twgl.setUniforms(this.forcePrg, {
502 | u_densityPressureTexture: this.pressureFBO.attachments[0],
503 | u_positionTexture: this.inFBO.attachments[0],
504 | u_velocityTexture: this.inFBO.attachments[1]
505 | });
506 | twgl.drawBufferInfo(gl, this.quadBufferInfo);
507 |
508 | // perform the integration to update the particles position and velocity
509 | gl.useProgram(this.integratePrg.program);
510 | twgl.bindFramebufferInfo(gl, this.outFBO);
511 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
512 | twgl.setUniforms(this.integratePrg, {
513 | u_positionTexture: this.inFBO.attachments[0],
514 | u_velocityTexture: this.inFBO.attachments[1],
515 | u_forceTexture: this.forceFBO.attachments[0],
516 | u_densityPressureTexture: this.pressureFBO.attachments[0],
517 | u_dt: deltaTime,
518 | u_time: this.#time,
519 | u_domainScale: this.simulationParams.DOMAIN_SCALE
520 | });
521 | twgl.setBlockUniforms(
522 | this.pointerParamsUBO,
523 | {
524 | pointerRadius: this.pointerParams.RADIUS,
525 | pointerStrength: this.pointerParams.STRENGTH,
526 | pointerPos: this.arcPointer,
527 | pointerVelocity: this.arcPointerDelta
528 | }
529 | );
530 | twgl.setUniformBlock(gl, this.integratePrg, this.pointerParamsUBO);
531 | twgl.drawBufferInfo(gl, this.quadBufferInfo);
532 |
533 | // update the current result textures
534 | this.currentPositionTexture = this.outFBO.attachments[0];
535 | this.currentVelocityTexture = this.outFBO.attachments[1];
536 |
537 | // swap the integrate FBOs
538 | const tmp = this.inFBO;
539 | this.inFBO = this.outFBO;
540 | this.outFBO = tmp;
541 | }
542 |
543 | #animate(deltaTime) {
544 | /** @type {WebGLRenderingContext} */
545 | const gl = this.gl;
546 |
547 | this.#updatePointer();
548 |
549 | // use a fixed deltaTime of 10 ms adapted to
550 | // device frame rate
551 | deltaTime = 16 * this.#deltaFrames;
552 |
553 | // simulate at least once
554 | this.#simulate(deltaTime);
555 |
556 | // clear the pointer force so that it wont add up during
557 | // subsequent simulation steps
558 | vec2.set(this.pointerLerpDelta, 0, 0);
559 |
560 | // additional simulation steps
561 | for(let i=0; i 1) {
692 | this.camera.fov = 2 * Math.atan( height / distance );
693 | } else {
694 | this.camera.fov = 2 * Math.atan( (height / this.camera.aspect) / distance );
695 | }
696 |
697 | mat4.perspective(this.camera.matrices.projection, this.camera.fov, this.camera.aspect, this.camera.near, this.camera.far);
698 | mat4.invert(this.camera.matrices.inversProjection, this.camera.matrices.projection);
699 | mat4.multiply(this.camera.matrices.inversViewProjection, this.camera.matrix, this.camera.matrices.inversProjection)
700 | }
701 |
702 | #screenToSpherePos(screenPos) {
703 | // map to -1 to 1
704 | const x = (screenPos[0] / this.viewportSize[0]) * 2. - 1;
705 | const y = (1 - (screenPos[1] / this.viewportSize[1])) * 2. - 1;
706 |
707 | // l(t) = p + t * u
708 | const p = this.#screenToWorldPosition(x, y, 0);
709 | const u = vec3.subtract(vec3.create(), p, this.camera.position);
710 | vec3.normalize(u, u);
711 |
712 | // sphere at origin intersection
713 | const radius = 1.05;
714 | const c = vec3.dot(p, p) - radius * radius;
715 | const b = vec3.dot(u, p) * 2;
716 | const a = 1;
717 | const d = b * b - 4 * a * c;
718 |
719 | if (d < 0) {
720 | // No solution
721 | return null;
722 | } else {
723 | const sd = Math.sqrt(d);
724 | const t1 = (-b + sd) / (2 * a);
725 | const t2 = (-b - sd) / (2 * a);
726 | const t = Math.min(t1, t2);
727 |
728 | vec3.scale(u, u, t);
729 | const i = vec3.add(vec3.create(), p, u);
730 |
731 | return i;
732 | }
733 | }
734 |
735 | #screenToWorldPosition(x, y, z) {
736 | const ndcPos = vec3.fromValues(x, y, z);
737 | const worldPos = vec4.transformMat4(vec4.create(), vec4.fromValues(ndcPos[0], ndcPos[1], ndcPos[2], 1), this.camera.matrices.inversViewProjection);
738 | if (worldPos[3] !== 0){
739 | vec4.scale(worldPos, worldPos, 1 / worldPos[3]);
740 | }
741 |
742 | return worldPos;
743 | }
744 | }
--------------------------------------------------------------------------------
/src/app/utils/glb-builder.js:
--------------------------------------------------------------------------------
1 | import {load} from '@loaders.gl/core';
2 | import {GLBLoader} from '@loaders.gl/gltf';
3 |
4 | /**
5 | * Based on https://github.com/visgl/loaders.gl/blob/master/examples/experimental/gltf-with-raw-webgl/GlbBuilder.js
6 | */
7 | export class GLBBuilder {
8 |
9 | constructor(gl) {
10 | this.gl = gl;
11 | }
12 |
13 | async load(url) {
14 | this.glb = await load(fetch(url), GLBLoader);
15 |
16 | this.primitives = [];
17 | for (let mesh of this.glb.json.meshes) {
18 | for (let primitiveDef of mesh.primitives) {
19 | const primitive = await this.loadPrimitive(this.glb, mesh.name, primitiveDef);
20 | if (primitive) {
21 | this.primitives.push(primitive);
22 | }
23 | }
24 | }
25 |
26 | return this.primitives;
27 | }
28 |
29 | getPrimitiveDataByMeshName(meshName) {
30 | return this.primitives.find(item => item.meshName == meshName);
31 | }
32 |
33 | async loadPrimitive(glb, meshName, primitiveDef) {
34 | /** @type {WebGLRenderingContext} */
35 | const gl = this.gl;
36 |
37 | const indices = GLBBuilder.getAccessorData(glb, primitiveDef.indices);
38 | const vertices = GLBBuilder.getAccessorData(glb, primitiveDef.attributes.POSITION);
39 | const normals = GLBBuilder.getAccessorData(glb, primitiveDef.attributes.NORMAL);
40 | const texcoords = GLBBuilder.getAccessorData(glb, primitiveDef.attributes.TEXCOORD_0);
41 | const tangents = GLBBuilder.getAccessorData(glb, primitiveDef.attributes.TANGENT);
42 |
43 | if (!indices || !vertices || !normals || !texcoords || !tangents) return null;
44 |
45 | // Create buffers:
46 | const indicesBuffer = gl.createBuffer();
47 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
48 | gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
49 |
50 | const verticesBuffer = gl.createBuffer();
51 | gl.bindBuffer(gl.ARRAY_BUFFER, verticesBuffer);
52 | gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
53 |
54 | const normalsBuffer = gl.createBuffer();
55 | gl.bindBuffer(gl.ARRAY_BUFFER, normalsBuffer);
56 | gl.bufferData(gl.ARRAY_BUFFER, normals, gl.STATIC_DRAW);
57 |
58 | const texcoordsBuffer = gl.createBuffer();
59 | gl.bindBuffer(gl.ARRAY_BUFFER, texcoordsBuffer);
60 | gl.bufferData(gl.ARRAY_BUFFER, texcoords, gl.STATIC_DRAW);
61 |
62 | const tangentsBuffer = gl.createBuffer();
63 | gl.bindBuffer(gl.ARRAY_BUFFER, tangentsBuffer);
64 | gl.bufferData(gl.ARRAY_BUFFER, tangents, gl.STATIC_DRAW);
65 |
66 | const buffers = {
67 |
68 | indices: {
69 | data: indices,
70 | webglBuffer: indicesBuffer,
71 | length: indices.length,
72 | dataType: GLBBuilder.getAccessorDataType(gl, glb, primitiveDef.indices),
73 | numberOfComponents: GLBBuilder.getAccessorNumberOfComponents(glb, primitiveDef.indices)
74 | },
75 |
76 | vertices: {
77 | data: vertices,
78 | webglBuffer: verticesBuffer,
79 | length: vertices.length,
80 | dataType: GLBBuilder.getAccessorDataType(gl, glb, primitiveDef.attributes.POSITION),
81 | numberOfComponents: GLBBuilder.getAccessorNumberOfComponents(glb, primitiveDef.attributes.POSITION),
82 | stride: glb.json.bufferViews[glb.json.accessors[primitiveDef.attributes.POSITION].bufferView].byteStride || 0
83 | },
84 |
85 | normals: {
86 | data: normals,
87 | webglBuffer: normalsBuffer,
88 | length: normals.length,
89 | dataType: GLBBuilder.getAccessorDataType(gl, glb, primitiveDef.attributes.NORMAL),
90 | numberOfComponents: GLBBuilder.getAccessorNumberOfComponents(glb, primitiveDef.attributes.NORMAL),
91 | stride: glb.json.bufferViews[glb.json.accessors[primitiveDef.attributes.NORMAL].bufferView].byteStride || 0
92 | },
93 |
94 | texcoords: {
95 | data: texcoords,
96 | webglBuffer: texcoordsBuffer,
97 | length: texcoords.length,
98 | dataType: GLBBuilder.getAccessorDataType(gl, glb, primitiveDef.attributes.TEXCOORD_0),
99 | numberOfComponents: GLBBuilder.getAccessorNumberOfComponents(glb, primitiveDef.attributes.TEXCOORD_0),
100 | stride: glb.json.bufferViews[glb.json.accessors[primitiveDef.attributes.TEXCOORD_0].bufferView].byteStride || 0
101 | },
102 |
103 | tangents: {
104 | data: tangents,
105 | webglBuffer: tangentsBuffer,
106 | length: tangents.length,
107 | dataType: GLBBuilder.getAccessorDataType(gl, glb, primitiveDef.attributes.TANGENT),
108 | numberOfComponents: GLBBuilder.getAccessorNumberOfComponents(glb, primitiveDef.attributes.TANGENT),
109 | stride: glb.json.bufferViews[glb.json.accessors[primitiveDef.attributes.TANGENT].bufferView].byteStride || 0
110 | }
111 | };
112 |
113 | return {
114 | meshName,
115 | buffers: buffers
116 | }
117 | }
118 |
119 | static getAccessorData(glb, accessorIndex) {
120 |
121 | const accessorDef = glb.json.accessors[accessorIndex];
122 |
123 | if (accessorDef) {
124 |
125 | const binChunk = glb.binChunks[0];
126 |
127 | const bufferViewDef = glb.json.bufferViews[accessorDef.bufferView];
128 | const componentType = accessorDef.componentType;
129 | const count = accessorDef.count;
130 |
131 | const byteOffset = binChunk.byteOffset + (accessorDef.byteOffset || 0) + bufferViewDef.byteOffset;
132 |
133 | let numberOfComponents = GLBBuilder.getAccessorNumberOfComponents(glb, accessorIndex);
134 |
135 | switch (componentType) {
136 | case 5120: { return new Int8Array(binChunk.arrayBuffer, byteOffset, count * numberOfComponents); }
137 | case 5121: { return new Uint8Array(binChunk.arrayBuffer, byteOffset, count * numberOfComponents); }
138 | case 5122: { return new Int16Array(binChunk.arrayBuffer, byteOffset, count * numberOfComponents); }
139 | case 5123: { return new Uint16Array(binChunk.arrayBuffer, byteOffset, count * numberOfComponents); }
140 | case 5125: { return new Uint32Array(binChunk.arrayBuffer, byteOffset, count * numberOfComponents); }
141 | case 5126: { return new Float32Array(binChunk.arrayBuffer, byteOffset, count * numberOfComponents); }
142 | }
143 | }
144 |
145 | return null;
146 | }
147 |
148 | static getAccessorNumberOfComponents(glb, accessorIndex) {
149 |
150 | const accessorDef = glb.json.accessors[accessorIndex];
151 |
152 | switch (accessorDef.type) {
153 | case "SCALAR": return 1;
154 | case "VEC2": return 2;
155 | case "VEC3": return 3;
156 | case "VEC4": return 4;
157 | case "MAT2": return 4;
158 | case "MAT3": return 9;
159 | case "MAT4": return 16;
160 | }
161 |
162 | return null;
163 | }
164 |
165 | static getAccessorDataType(gl, glb, accessorIndex) {
166 |
167 | const accessorDef = glb.json.accessors[accessorIndex];
168 | const componentType = accessorDef.componentType;
169 |
170 | switch (componentType) {
171 | case 5120: { return gl.BYTE; }
172 | case 5121: { return gl.UNSIGNED_BYTE; }
173 | case 5122: { return gl.SHORT; }
174 | case 5123: { return gl.UNSIGNED_SHORT; }
175 | case 5125: { return gl.UNSIGNED_INT; }
176 | case 5126: { return gl.FLOAT; }
177 | }
178 | }
179 | }
--------------------------------------------------------------------------------
/src/app/utils/modernizr.js:
--------------------------------------------------------------------------------
1 | /*! modernizr 3.6.0 (Custom Build) | MIT *
2 | * https://modernizr.com/download/?-touchevents-setclasses !*/
3 | !function(e,n,t){function o(e){var n=c.className,t=Modernizr._config.classPrefix||"";if(d&&(n=n.baseVal),Modernizr._config.enableJSClass){var o=new RegExp("(^|\\s)"+t+"no-js(\\s|$)");n=n.replace(o,"$1"+t+"js$2")}Modernizr._config.enableClasses&&(n+=" "+t+e.join(" "+t),d?c.className.baseVal=n:c.className=n)}function s(e,n){return typeof e===n}function a(){var e,n,t,o,a,i,r;for(var l in u)if(u.hasOwnProperty(l)){if(e=[],n=u[l],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(t=0;t
2 |
3 |
4 |
5 |
6 | liquid-geo
7 |
8 |
9 |
10 |
11 | github
12 |
13 |
14 |
20 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | html, body {
6 | padding: 0;
7 | margin: 0;
8 | width: 100%;
9 | height: 100%;
10 | width: 100dvw;
11 | height: 100dvh;
12 | font-family: Arial,"Helvetica Neue",Helvetica,sans-serif;
13 | font-size: 18px;
14 | overflow: hidden;
15 | touch-action: none;
16 | background-color: black;
17 | }
18 |
19 | body {
20 | position: relative;
21 | }
22 |
23 | @media screen and (max-width: 640px) {
24 | body, html {
25 | font-size: 14px;
26 | }
27 | }
28 |
29 | canvas {
30 | width: 100%;
31 | height: 100%;
32 | }
33 |
34 | .github-link {
35 | position: absolute;
36 | right: 0;
37 | bottom: 0;
38 | color: #aaa;
39 | mix-blend-mode: difference;
40 | text-transform: uppercase;
41 | text-decoration: none;
42 | padding: 0.7em 1em;
43 | font-size: 0.8em;
44 | }
45 |
46 | .audio-controls {
47 | position: absolute;
48 | bottom: 0;
49 | left: 0;
50 | width: 100%;
51 | display: flex;
52 | align-items: center;
53 | justify-content: center;
54 | padding: 3em 0;
55 | pointer-events: none;
56 | }
57 |
58 | .audio-controls button {
59 | pointer-events: all;
60 | cursor: pointer;
61 | background: none;
62 | border: 2px solid #eee;
63 | border-radius: 10rem;
64 | display: flex;
65 | align-items: center;
66 | min-height: 4.25em;
67 | width: 16em;
68 | justify-content: center;
69 | }
70 |
71 | @media screen and (min-width: 641px) {
72 | .audio-controls button {
73 | min-height: 6em;
74 | }
75 | }
76 |
77 | .audio-controls button:hover {
78 | background: #333;
79 | }
80 |
81 | .audio-controls button:disabled {
82 | opacity: 0.4;
83 | pointer-events: none;
84 | }
85 |
86 | .audio-controls button label {
87 | color: #eee;
88 | font-size: 1.25rem;
89 | pointer-events: none;
90 | }
91 |
92 | .audio-controls svg {
93 | height: 2rem;
94 | width: 2rem;
95 | margin-right: 0.5rem;
96 | pointer-events: none;
97 | }
98 |
99 | @media (min-aspect-ratio: 7/5) {
100 | .audio-controls {
101 | flex-direction: column;
102 | height: 100%;
103 | padding: 0 2em;
104 | align-items: flex-end;
105 | }
106 |
107 | .audio-controls button + button {
108 | margin-top: 1em;
109 | }
110 | }
111 |
112 | @media (max-aspect-ratio: 5/8) {
113 | .audio-controls {
114 | flex-direction: column;
115 | }
116 |
117 | .audio-controls button + button {
118 | margin-top: 1em;
119 | margin-left: 0 !important;
120 | }
121 | }
122 |
123 | .audio-controls button + button {
124 | margin-left: 1em;
125 | }
126 |
127 | #playback-button svg {
128 | width: 1.7rem;
129 | height: 1.7rem;
130 | }
131 |
132 | #record-button.is-recording::before {
133 | content: '';
134 | display: block;
135 | width: 1.5rem;
136 | height: 1.5rem;
137 | margin-right: 0.5rem;
138 | background: #f22;
139 | border-radius: 100%;
140 | }
141 |
142 | #record-button.is-recording svg {
143 | display: none;
144 | }
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import glsl from 'vite-plugin-glsl';
2 | import { defineConfig } from 'vite';
3 | import path from 'path'
4 |
5 | export default defineConfig({
6 | root: './src',
7 | server: {
8 | open: true
9 | },
10 | plugins: [glsl({
11 | exclude: undefined, // File paths/extensions to ignore
12 | include: /\.(glsl|wgsl|vert|frag|vs|fs)$/i, // File paths/extensions to import
13 | defaultExtension: 'glsl', // Shader suffix when no extension is specified
14 | warnDuplicatedImports: true, // Warn if the same chunk was imported multiple times
15 | compress: false // Compress the resulting shader code
16 | })],
17 | build: {
18 | outDir: '../dist',
19 | minify: 'terser',
20 | assetsDir: 'assets',
21 | rollupOptions: {
22 | output: {
23 | entryFileNames: '[name]-[hash].js',
24 | chunkFileNames: '[name]-[hash].js',
25 | assetFileNames: (assetInfo) => {
26 | let extType = path.extname(assetInfo.name);
27 | if (!/js|css/i.test(extType)) {
28 | return `assets/[name][extname]`;
29 | }
30 | return '[name]-[hash][extname]';
31 | }
32 | }
33 | }
34 | }
35 | });
--------------------------------------------------------------------------------