From 08a0dc2bc0b6279b691c4e95751c605757ab8d95 Mon Sep 17 00:00:00 2001 From: FridaWang <379788704@qq.com> Date: Tue, 20 Sep 2022 13:17:16 -0400 Subject: [PATCH 1/7] add GUI / add rotation animation --- .github/workflows/build-and-deploy.yml | 3 +- README.md | 102 +- dist/texture/surface.png | Bin 0 -> 14475 bytes package-lock.json | 4086 +++++++++++++++++++++++- package.json | 5 +- src/geometry/Icosphere.ts | 179 ++ src/geometry/Square.ts | 17 +- src/geometry/cube.ts | 110 + src/geometry/fireball.ts | 0 src/main.ts | 127 +- src/rendering/gl/Drawable.ts | 36 + src/rendering/gl/OpenGLRenderer.ts | 19 +- src/rendering/gl/ShaderProgram.ts | 99 +- src/shaders/lambert-frag.glsl | 70 + src/shaders/lambert-vert.glsl | 259 ++ texture/surface.png | Bin 0 -> 14475 bytes webpack.config.js | 2 +- 17 files changed, 4970 insertions(+), 144 deletions(-) create mode 100644 dist/texture/surface.png create mode 100644 src/geometry/Icosphere.ts create mode 100644 src/geometry/cube.ts create mode 100644 src/geometry/fireball.ts create mode 100644 src/shaders/lambert-frag.glsl create mode 100644 src/shaders/lambert-vert.glsl create mode 100644 texture/surface.png diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 75bcf144..016ee562 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -1,4 +1,3 @@ - name: Build and Deploy on: push: @@ -35,4 +34,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH: gh-pages FOLDER: dist - CLEAN: false + CLEAN: true diff --git a/README.md b/README.md index 1a7646c7..b898cbb4 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,77 @@ -# [Project 1: Noise](https://github.com/CIS-566-Fall-2022/hw01-fireball-base) +# HW 0: Intro to Javascript and WebGL -## Objective - -Get comfortable with using WebGL and its shaders to generate an interesting 3D, continuous surface using a multi-octave noise algorithm. +

+ +

+

(source: Ken Perlin)

-## Getting Started +## Objective +- Check that the tools and build configuration we will be using for the class works. +- Start learning Typescript and WebGL2 +- Practice implementing noise -1. Fork and clone [this repository](https://github.com/CIS700-Procedural-Graphics/Project1-Noise). +## Forking the Code +Rather than cloning the homework repository, please __fork__ the code into your own repository using the `Fork` button in the upper-right hand corner of the Github UI. This will enable you to have your own personal repository copy of the code, and let you make a live demo (described later in this document). -2. Copy your hw0 code into your local hw1 repository. +## Running the Code -3. In the root directory of your project, run `npm install`. This will download all of those dependencies. +1. [Install Node.js](https://nodejs.org/en/download/). Node.js is a JavaScript runtime. It basically allows you to run JavaScript when not in a browser. For our purposes, this is not necessary. The important part is that with it comes `npm`, the Node Package Manager. This allows us to easily declare and install external dependencies such as [dat.GUI](https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage), and [glMatrix](http://glmatrix.net/). -4. Do either of the following (but I highly recommend the first one for reasons I will explain later). +2. Using a command terminal, run `npm install` in the root directory of your project. This will download all of those dependencies. - a. Run `npm start` and then go to `localhost:7000` in your web browser +3. Do either of the following (but we highly recommend the first one for reasons we will explain later). - b. Run `npm run build` and then go open `index.html` in your web browser + a. Run `npm start` and then go to `localhost:5660` in your web browser - You should hopefully see the framework code with a 3D cube at the center of the screen! + b. Run `npm run build` and then go open `dist/index.html` in your web browser +## Module Bundling +One of the most important dependencies of our projects is [Webpack](https://webpack.js.org/concepts/). Webpack is a module bundler which allows us to write code in separate files and use `import`s and `export`s to load classes and functions for other files. It also allows us to preprocess code before compiling to a single file. We will be using [Typescript](https://www.typescriptlang.org/docs/home.html) for this course which is Javascript augmented with type annotations. Webpack will convert Typescript files to Javascript files on compilation and in doing so will also check for proper type-safety and usage. Read more about Javascript modules in the resources section below. ## Developing Your Code -All of the JavaScript code is living inside the `src` directory. The main file that gets executed when you load the page as you may have guessed is `main.js`. Here, you can make any changes you want, import functions from other files, etc. The reason that I highly suggest you build your project with `npm start` is that doing so will start a process that watches for any changes you make to your code. If it detects anything, it'll automagically rebuild your project and then refresh your browser window for you. Wow. That's cool. If you do it the other way, you'll need to run `npm build` and then refresh your page every time you want to test something. - -## Publishing Your Code -We highly suggest that you put your code on GitHub. One of the reasons we chose to make this course using JavaScript is that the Web is highly accessible and making your awesome work public and visible can be a huge benefit when you're looking to score a job or internship. To aid you in this process, running `npm run deploy` will automatically build your project and push it to `gh-pages` where it will be visible at `username.github.io/repo-name`. - -## Setting up `main.ts` - -Alter `main.ts` so that it renders the icosphere provided, rather than the cube you built in hw0. You will be writing a WebGL shader to displace its surface to look like a fireball. You may either rewrite the shader you wrote in hw0, or make a new `ShaderProgram` instance that uses new GLSL files. +All of the JavaScript code is living inside the `src` directory. The main file that gets executed when you load the page as you may have guessed is `main.ts`. Here, you can make any changes you want, import functions from other files, etc. The reason that we highly suggest you build your project with `npm start` is that doing so will start a process that watches for any changes you make to your code. If it detects anything, it'll automagically rebuild your project and then refresh your browser window for you. Wow. That's cool. If you do it the other way, you'll need to run `npm build` and then refresh your page every time you want to test something. -## Noise Generation +We would suggest editing your project with Visual Studio Code https://code.visualstudio.com/. Microsoft develops it and Microsoft also develops Typescript so all of the features work nicely together. Sublime Text and installing the Typescript plugins should probably work as well. -Across your vertex and fragment shaders, you must implement a variety of functions of the form `h = f(x,y,z)` to displace and color your fireball's surface, where `h` is some floating-point displacement amount. +## Assignment Details +1. Take some time to go through the existing codebase so you can get an understanding of syntax and how the code is architected. Much of the code is designed to mirror the class structures used in CIS 460's OpenGL assignments, so it should hopefully be somewhat familiar. +2. Take a look at the resources linked in the section below. Definitely read about Javascript modules and Typescript. The other links provide documentation for classes used in the code. +3. Add a `Cube` class that inherits from `Drawable` and at the very least implement a constructor and its `create` function. Then, add a `Cube` instance to the scene to be rendered. +4. Read the documentation for dat.GUI below. Update the existing GUI in `main.ts` with a parameter to alter the color passed to `u_Color` in the Lambert shader. +5. Write a custom fragment shader that implements FBM, Worley Noise, or Perlin Noise based on 3D inputs (as opposed to the 2D inputs in the slides). This noise must be used to modify your fragment color. If your custom shader is particularly interesting, you'll earn some bonus points. +6. Write a custom vertex shader that uses a trigonometric function (e.g. `sin`, `tan`) to non-uniformly modify your cube's vertex positions over time. This will necessitate instantiating an incrementing variable in your Typescript code that you pass to your shader every tick. Refer to the base code's methods of passing variables to shaders if you are unsure how to do so. +7. Feel free to update any of the files when writing your code. The implementation of the `OpenGLRenderer` is currently very simple. -- Your vertex shader should apply a low-frequency, high-amplitude displacement of your sphere so as to make it less uniformly sphere-like. You might consider using a combination of sinusoidal functions for this purpose. -- Your vertex shader should also apply a higher-frequency, lower-amplitude layer of fractal Brownian motion to apply a finer level of distortion on top of the high-amplitude displacement. -- Your fragment shader should apply a gradient of colors to your fireball's surface, where the fragment color is correlated in some way to the vertex shader's displacement. -- Both the vertex and fragment shaders should alter their output based on a uniform time variable (i.e. they should be animated). You might consider making a constant animation that causes the fireball's surface to roil, or you could make an animation loop in which the fireball repeatedly explodes. -- Across both shaders, you should make use of at least four of the functions discussed in the Toolbox Functions slides. +## Making a Live Demo +When you push changes to the `master` branch of your repository on Github, a Github workflow will run automatically which builds your code and pushes the build to a new branch `gh-pages`. The configuration file which handles this is located at `.github/workflows/build-and-deploy.yml`. If you want to modify this, you can read more about workflows [here](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions). +Once your built code is pushed to `gh-pages`, Github can automatically publish a live site. Configure that by: -## Noise Application + 1. Open the Settings tab of your repository in Github. -View your noise in action by applying it as a displacement on the surface of your icosahedron, giving your icosahedron a bumpy, cloud-like appearance. Simply take the noise value as a height, and offset the vertices along the icosahedron's surface normals. You are, of course, free to alter the way your noise perturbs your icosahedron's surface as you see fit; we are simply recommending an easy way to visualize your noise. You could even apply a couple of different noise functions to perturb your surface to make it even less spherical. + 2. Scroll down to the Pages tab of the Settings (in the table on the left) and choose which branch to make the source for the deployed project. This should be the `gh-pages` branch which is automatically created after the first successful build of the `master` branch. -In order to animate the vertex displacement, use time as the third dimension or as some offset to the (x, y, z) input to the noise function. Pass the current time since start of program as a uniform to the shaders. + 3. Done! Now, any new commits on the `master` branch will be built and pushed to `gh-pages`. The project should be visible at http://username.github.io/repo-name. +  -For both visual impact and debugging help, also apply color to your geometry using the noise value at each point. There are several ways to do this. For example, you might use the noise value to create UV coordinates to read from a texture (say, a simple gradient image), or just compute the color by hand by lerping between values. +To check if everything is on the right track: -## Interactivity +1. Make sure the `gh-pages` branch of your repo has a files called `index.html`, `bundle.js`, and `bundle.js.map` -Using dat.GUI, make at least THREE aspects of your demo interactive variables. For example, you could add a slider to adjust the strength or scale of the noise, change the number of noise octaves, etc. - -Add a button that will restore your fireball to some nice-looking (courtesy of your art direction) defaults. :) - -## Extra Spice - -Choose one of the following options: - -- Background (easy-hard depending on how fancy you get): Add an interesting background or a more complex scene to place your fireball in so it's not floating in a black void -- Custom mesh (easy): Figure out how to import a custom mesh rather than using an icosahedron for a fancy-shaped cloud. -- Mouse interactivity (medium): Find out how to get the current mouse position in your scene and use it to deform your cloud, such that users can deform the cloud with their cursor. -- Music (hard): Figure out a way to use music to drive your noise animation in some way, such that your noise cloud appears to dance. +2. In the settings tab of the repo, under Pages, make sure it says your site is published at some url. ## Submission - -- Update README.md to contain a solid description of your project -- Publish your project to gh-pages. `npm run deploy`. It should now be visible at http://username.github.io/repo-name -- Create a [pull request](https://help.github.com/articles/creating-a-pull-request/) to this repository, and in the comment, include a link to your published project. -- Submit the link to your pull request on Canvas. +1. Create a pull request to this repository with your completed code. +2. Update README.md to contain a solid description of your project with a screenshot of some visuals, and a link to your live demo. +3. Submit the link to your pull request on Canvas, and add a comment to your submission with a hyperlink to your live demo. +4. Include a link to your live site. + +## Resources +- Javascript modules https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import +- Typescript https://www.typescriptlang.org/docs/home.html +- dat.gui https://workshop.chromeexperiments.com/examples/gui/ +- glMatrix http://glmatrix.net/docs/ +- WebGL + - Interfaces https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API + - Types https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Types + - Constants https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants diff --git a/dist/texture/surface.png b/dist/texture/surface.png new file mode 100644 index 0000000000000000000000000000000000000000..9b916058ed5429b9260bb071670d6c94e7c407b1 GIT binary patch literal 14475 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 F{{bH%R-pg@ literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json index e1a47a34..b282aceb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,30 +1,4048 @@ { + "name": "hw01-fireball-base", + "lockfileVersion": 2, "requires": true, - "lockfileVersion": 1, - "dependencies": { - "3d-view": { + "packages": { + "": { + "dependencies": { + "3d-view-controls": "^2.2.2", + "dat.gui": "^0.7.7", + "gl-matrix": "^3.3.0", + "stats-js": "^1.0.1" + }, + "devDependencies": { + "@types/dat.gui": "^0.7.7", + "@types/webgl2": "0.0.6", + "ts-loader": "^9.2.5", + "typescript": "^4.4.2", + "webpack": "^5.52.0", + "webpack-cli": "^4.8.0", + "webpack-dev-server": "^4.1.1", + "webpack-glsl-loader": "^1.0.1" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz", + "integrity": "sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@types/dat.gui": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@types/dat.gui/-/dat.gui-0.7.7.tgz", + "integrity": "sha512-CxLCme0He5Jk3uQwfO/fGZMyNhb/ypANzqX0yU9lviBQMlen5SOvQTBQ/Cd9x5mFlUAK5Tk8RgvTyLj1nYkz+w==", + "dev": true + }, + "node_modules/@types/eslint": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.0.tgz", + "integrity": "sha512-07XlgzX0YJUn4iG1ocY4IX9DzKSmMGUs6ESKlxWhZRaa0fatIWaHWUVapcuGa8r5HFnTqzj+4OCjd5f7EZ/i/A==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", + "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz", + "integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "9.6.61", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.61.tgz", + "integrity": "sha512-/aKAdg5c8n468cYLy2eQrcR5k6chlbNwZNGUj3TboyPa2hcO2QAJcfymlqPzMiRj8B6nYKXjzQz36minFE0RwQ==", + "dev": true + }, + "node_modules/@types/retry": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", + "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", + "dev": true + }, + "node_modules/@types/webgl2": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.6.tgz", + "integrity": "sha512-50GQhDVTq/herLMiqSQkdtRu+d5q/cWHn4VvKJtrj4DJAjo1MNkWYa2MA41BaBO1q1HgsUjuQvEOk0QHvlnAaQ==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.4.tgz", + "integrity": "sha512-cs3XLy+UcxiP6bj0A6u7MLLuwdXJ1c3Dtc0RkKg+wiI1g/Ti1om8+/2hc2A2B60NbBNAbMgyBMHvyymWm/j4wQ==", + "dev": true, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.3.0.tgz", + "integrity": "sha512-ASiVB3t9LOKHs5DyVUcxpraBXDOKubYu/ihHhU+t1UPpxsivg6Od2E2qU4gJCekfEddzRBzHhzA/Acyw/mlK/w==", + "dev": true, + "dependencies": { + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.2.tgz", + "integrity": "sha512-vgJ5OLWadI8aKjDlOH3rb+dYyPd2GTZuQC/Tihjct6F9GpXGZINo3Y/IVuZVTM1eDQB+/AOsjPUWH/WySDaXvw==", + "dev": true, + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/3d-view": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/3d-view/-/3d-view-2.0.1.tgz", "integrity": "sha512-YSLRHXNpSziaaiK2R0pI5+JKguoJVbtWmIv9YyBFtl0+q42kQwJB/JUulbFR/1zYFm58ifjKQ6kVdgZ6tyKtCA==", - "requires": { + "dependencies": { "matrix-camera-controller": "^2.1.1", "orbit-camera-controller": "^4.0.0", "turntable-camera-controller": "^3.0.0" } }, - "3d-view-controls": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/3d-view-controls/-/3d-view-controls-2.2.2.tgz", - "integrity": "sha512-WL0u3PN41lEx/4qvKqV6bJlweUYoW18FXMshW/qHb41AVdZxDReLoJNGYsI7x6jf9bYelEF62BJPQmO7yEnG2w==", - "requires": { - "3d-view": "^2.0.0", - "has-passive-events": "^1.0.0", - "mouse-change": "^1.1.1", - "mouse-event-offset": "^3.0.2", - "mouse-wheel": "^1.0.2", - "right-now": "^1.0.0" + "node_modules/3d-view-controls": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/3d-view-controls/-/3d-view-controls-2.2.2.tgz", + "integrity": "sha512-WL0u3PN41lEx/4qvKqV6bJlweUYoW18FXMshW/qHb41AVdZxDReLoJNGYsI7x6jf9bYelEF62BJPQmO7yEnG2w==", + "dependencies": { + "3d-view": "^2.0.0", + "has-passive-events": "^1.0.0", + "mouse-change": "^1.1.1", + "mouse-event-offset": "^3.0.2", + "mouse-wheel": "^1.0.2", + "right-now": "^1.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", + "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.7.6.tgz", + "integrity": "sha512-FlVvVFA1TX6l3lp8VjDnYYq7R1nyW6x3svAt4nDgrWQ9SBaSh9CnbwgSUTasgfNfOG5HlM1ehugCvM+hjo56LA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.0.tgz", + "integrity": "sha512-tAaOSrWCHF+1Ear1Z4wnJCXA9GGox4K6Ic85a5qalES2aeEwQGr7UC93mwef49536PkCYjzkp0zIxfFvexJ6zQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/binary-search-bounds": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz", + "integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==" + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "dependencies": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.0.tgz", + "integrity": "sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001254", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.830", + "escalade": "^3.1.1", + "node-releases": "^1.1.75" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001255", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001255.tgz", + "integrity": "sha512-F+A3N9jTZL882f/fg/WWVnKSu6IOo3ueLz4zwaOPbPYHNmM/ZaDUyzyJwS1mZhX7Ex5jqTyW599Gdelh5PDYLQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cubic-hermite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cubic-hermite/-/cubic-hermite-1.0.0.tgz", + "integrity": "sha1-hOOy8nKzFFToOTuZu2rtRRaMFOU=" + }, + "node_modules/dat.gui": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/dat.gui/-/dat.gui-0.7.7.tgz", + "integrity": "sha512-sRl/28gF/XRC5ywC9I4zriATTsQcpSsRG7seXCPnTkK8/EQMIbCu5NPMpICLGxX9ZEUvcXR3ArLYCtgreFoMDw==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "dev": true, + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "node_modules/dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dev": true, + "dependencies": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "dependencies": { + "buffer-indexof": "^1.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.3.832", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.832.tgz", + "integrity": "sha512-x7lO8tGoW0CyV53qON4Lb5Rok9ipDelNdBIAiYUZ03dqy4u9vohMM1qV047+s/hiyJiqUWX/3PNwkX3kexX5ig==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz", + "integrity": "sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-module-lexer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.7.1.tgz", + "integrity": "sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", + "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/filtered-vector": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/filtered-vector/-/filtered-vector-1.2.5.tgz", + "integrity": "sha512-5Vu6wdtQJ1O2nRmz39dIr9m3hEDq1skYby5k1cJQdNWK4dMgvYcUEiA/9j7NcKfNZ5LGxn8w2LSLiigyH7pTAw==", + "dependencies": { + "binary-search-bounds": "^2.0.0", + "cubic-hermite": "^1.0.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.3.tgz", + "integrity": "sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.2.tgz", + "integrity": "sha1-4fJE7zkzwbKmS9R5kTYGDQ9ZFPg=", + "dev": true + }, + "node_modules/fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gl-mat3": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-mat3/-/gl-mat3-1.0.0.tgz", + "integrity": "sha1-iWMyGcpCk3mha5GF2V1BcTRTuRI=" + }, + "node_modules/gl-mat4": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gl-mat4/-/gl-mat4-1.2.0.tgz", + "integrity": "sha512-sT5C0pwB1/e9G9AvAoLsoaJtbMGjfd/jfxo8jMCKqYYEnjZuFvqV5rehqar0538EmssjdDeiEWnKyBSTw7quoA==" + }, + "node_modules/gl-matrix": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.3.0.tgz", + "integrity": "sha512-COb7LDz+SXaHtl/h4LeaFcNdJdAQSDeVqjiIihSXNrkWObZLhDI4hIkZC11Aeqp7bcE72clzB0BnDXr2SmslRA==" + }, + "node_modules/gl-quat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-quat/-/gl-quat-1.0.0.tgz", + "integrity": "sha1-CUXskjOG9FMpvl3DV7HIwtR1hsU=", + "dependencies": { + "gl-mat3": "^1.0.0", + "gl-vec3": "^1.0.3", + "gl-vec4": "^1.0.0" + } + }, + "node_modules/gl-vec3": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gl-vec3/-/gl-vec3-1.1.3.tgz", + "integrity": "sha512-jduKUqT0SGH02l8Yl+mV1yVsDfYgQAJyXGxkJQGyxPLHRiW25DwVIRPt6uvhrEMHftJfqhqKthRcyZqNEl9Xdw==" + }, + "node_modules/gl-vec4": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-vec4/-/gl-vec4-1.0.1.tgz", + "integrity": "sha1-l9loeCgbFLUyy84QF4Xf0cs0CWQ=" + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-passive-events": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-passive-events/-/has-passive-events-1.0.0.tgz", + "integrity": "sha512-2vSj6IeIsgvsRMyeQ0JaCX5Q3lX4zMn5HpoVc7MEhQ6pv8Iq9rsXjsp+E5ZwaT7T0xhMT0KmU8gtt1EFVdbJiw==", + "dependencies": { + "is-browser": "^2.0.1" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz", + "integrity": "sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.5", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-ip": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-6.2.0.tgz", + "integrity": "sha512-D8WGsR6yDt8uq7vDMu7mjcR+yRMm3dW8yufyChmszWRjcSHuxLBkR3GdS2HZAjodsaGuCvXeEJpueisXJULghg==", + "dev": true, + "dependencies": { + "default-gateway": "^6.0.0", + "ipaddr.js": "^1.9.1", + "is-ip": "^3.1.0", + "p-event": "^4.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/internal-ip?sponsor=1" + } + }, + "node_modules/internal-ip/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "node_modules/ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.1.0.tgz", + "integrity": "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ==" + }, + "node_modules/is-core-module": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-ip": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz", + "integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==", + "dev": true, + "dependencies": { + "ip-regex": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-worker": { + "version": "27.1.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.1.1.tgz", + "integrity": "sha512-XJKCL7tu+362IUYTWvw8+3S75U7qMiYiRU6u5yqscB48bTvzwN6i8L/7wVTXiFLwkRsxARNM7TISnTvcgv9hxA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mat4-decompose": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-decompose/-/mat4-decompose-1.0.4.tgz", + "integrity": "sha1-ZetP451wh496RE60Yk1S9+frL68=", + "dependencies": { + "gl-mat4": "^1.0.1", + "gl-vec3": "^1.0.2" + } + }, + "node_modules/mat4-interpolate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-interpolate/-/mat4-interpolate-1.0.4.tgz", + "integrity": "sha1-Vf/p6zw1KV4sDVqfdyXZBoqJ/3Q=", + "dependencies": { + "gl-mat4": "^1.0.1", + "gl-vec3": "^1.0.2", + "mat4-decompose": "^1.0.3", + "mat4-recompose": "^1.0.3", + "quat-slerp": "^1.0.0" + } + }, + "node_modules/mat4-recompose": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mat4-recompose/-/mat4-recompose-1.0.4.tgz", + "integrity": "sha1-OVPCMP8kc9x3LuAUpSySXPgbDk0=", + "dependencies": { + "gl-mat4": "^1.0.1" + } + }, + "node_modules/matrix-camera-controller": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/matrix-camera-controller/-/matrix-camera-controller-2.1.4.tgz", + "integrity": "sha512-zsPGPONclrKSImNpqqKDTcqFpWLAIwMXEJtCde4IFPOw1dA9udzFg4HOFytOTosOFanchrx7+Hqq6glLATIxBA==", + "dependencies": { + "binary-search-bounds": "^2.0.0", + "gl-mat4": "^1.1.2", + "gl-vec3": "^1.0.3", + "mat4-interpolate": "^1.0.3" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mem": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "dev": true, + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/mem?sponsor=1" + } + }, + "node_modules/mem/node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/memfs": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.2.4.tgz", + "integrity": "sha512-2mDCPhuduRPOxlfgsXF9V+uqC6Jgz8zt/bNe4d4W7d5f6pCzHrWkxLNr17jKGXd4+j2kQNsAG2HARPnt74sqVQ==", + "dev": true, + "dependencies": { + "fs-monkey": "1.0.3" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", + "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.32", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", + "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", + "dev": true, + "dependencies": { + "mime-db": "1.49.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mouse-change": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/mouse-change/-/mouse-change-1.4.0.tgz", + "integrity": "sha1-wrd+W/o0pDzhRFyBV6Tk3JiVwU8=", + "dependencies": { + "mouse-event": "^1.0.0" + } + }, + "node_modules/mouse-event": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mouse-event/-/mouse-event-1.0.5.tgz", + "integrity": "sha1-s3ie23EJmX1aky0dAdqhVDpQFzI=" + }, + "node_modules/mouse-event-offset": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mouse-event-offset/-/mouse-event-offset-3.0.2.tgz", + "integrity": "sha1-39hqbiSMa6jK1TuQXVA3ogY+mYQ=" + }, + "node_modules/mouse-wheel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mouse-wheel/-/mouse-wheel-1.2.0.tgz", + "integrity": "sha1-bSkDseqPtI5h8bU7kDZ3PwQs21w=", + "dependencies": { + "right-now": "^1.0.0", + "signum": "^1.0.0", + "to-px": "^1.0.1" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "dependencies": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/node-releases": { + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/open/-/open-8.2.1.tgz", + "integrity": "sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/orbit-camera-controller": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/orbit-camera-controller/-/orbit-camera-controller-4.0.0.tgz", + "integrity": "sha1-bis28OeHhmPDMPUNqbfOaGwncAU=", + "dependencies": { + "filtered-vector": "^1.2.1", + "gl-mat4": "^1.0.3" + } + }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "dev": true, + "dependencies": { + "p-timeout": "^3.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", + "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", + "dev": true, + "dependencies": { + "@types/retry": "^0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dev": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-unit/-/parse-unit-1.0.1.tgz", + "integrity": "sha1-fhu21b7zh0wo45JSaiVBFwKR7s8=" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/path/-/path-0.11.14.tgz", + "integrity": "sha1-y8dWk1XLPIOv60rOQ+z/lSMeWn0=", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/portfinder/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/quat-slerp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/quat-slerp/-/quat-slerp-1.0.1.tgz", + "integrity": "sha1-K6oVzjprvcMkHZcusXKDE57Wnyk=", + "dependencies": { + "gl-quat": "^1.0.0" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/right-now": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/right-now/-/right-now-1.0.0.tgz", + "integrity": "sha1-bolgne69fc2vja7Mmuo5z1haCRg=" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "node_modules/selfsigned": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz", + "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==", + "dev": true, + "dependencies": { + "node-forge": "^0.10.0" + } + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "node_modules/signum": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz", + "integrity": "sha1-dKfSvyogtA66FqkrFSEk8dVZ+nc=" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sockjs": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", + "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^3.4.0", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy-transport/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/spdy/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/stats-js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stats-js/-/stats-js-1.0.1.tgz", + "integrity": "sha512-EAwEFghGNv8mlYC4CZzI5kWghsnP8uBKXw6VLRHtXkOk5xySfUKLTqTkjgJFfDluIkf/O7eZwi5MXP50VeTbUg==" + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/strip-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.0.tgz", + "integrity": "sha512-UhDTSnGF1dc0DRbUqr1aXwNoY3RgVkSWG8BrpnuFIxhP57IqbS7IRta2Gfiavds4yCxc5+fEAVVOgBZWnYkvzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tapable": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", + "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.2.tgz", + "integrity": "sha512-0Omye+RD4X7X69O0eql3lC4Heh/5iLj3ggxR/B5ketZLOtLiOqukUgjw3q4PDnNQbsrkKr3UMypqStQG3XKRvw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.3.tgz", + "integrity": "sha512-eDbuaDlXhVaaoKuLD3DTNTozKqln6xOG6Us0SzlKG5tNlazG+/cdl8pm9qiF1Di89iWScTI0HcO+CDcf2dkXiw==", + "dev": true, + "dependencies": { + "jest-worker": "^27.0.6", + "p-limit": "^3.1.0", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/to-px": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.1.0.tgz", + "integrity": "sha512-bfg3GLYrGoEzrGoE05TAL/Uw+H/qrf2ptr9V3W7U0lkjjyYnIfgxmVLUfhQ1hZpIQwin81uxhDjvUkDYsC0xWw==", + "dependencies": { + "parse-unit": "^1.0.1" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-loader": { + "version": "9.2.5", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.5.tgz", + "integrity": "sha512-al/ATFEffybdRMUIr5zMEWQdVnCGMUA9d3fXJ8dBVvBlzytPvIszoG9kZoR+94k6/i293RnVOXwMaWbXhNy9pQ==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/turntable-camera-controller": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/turntable-camera-controller/-/turntable-camera-controller-3.0.1.tgz", + "integrity": "sha1-jb0/4AVQGRxlFky4iJcQSVeK/Zk=", + "dependencies": { + "filtered-vector": "^1.2.1", + "gl-mat4": "^1.0.2", + "gl-vec3": "^1.0.2" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", + "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/watchpack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", + "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/webpack": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.52.0.tgz", + "integrity": "sha512-yRZOat8jWGwBwHpco3uKQhVU7HYaNunZiJ4AkAVQkPCUGoZk/tiIXiwG+8HIy/F+qsiZvSOa+GLQOj3q5RKRYg==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.50", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.8.0", + "es-module-lexer": "^0.7.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.2.0", + "webpack-sources": "^3.2.0" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.8.0.tgz", + "integrity": "sha512-+iBSWsX16uVna5aAYN6/wjhJy1q/GKk4KjKvfg90/6hykCTSgozbfz5iRgDTSJt/LgSbYxdBX3KBHeobIs+ZEw==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.0.4", + "@webpack-cli/info": "^1.3.0", + "@webpack-cli/serve": "^1.5.2", + "colorette": "^1.2.1", + "commander": "^7.0.0", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "v8-compile-cache": "^2.2.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.0.0.tgz", + "integrity": "sha512-9zng2Z60pm6A98YoRcA0wSxw1EYn7B7y5owX/Tckyt9KGyULTkLtiavjaXlWqOMkM0YtqGgL3PvMOFgyFLq8vw==", + "dev": true, + "dependencies": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.1.1.tgz", + "integrity": "sha512-Kl1mnCEw8Cy1Kw173gCxLIB242LfPKEOj9WoKhKz/MbryZTNrILzOJTk8kiczw/YUEPzn3gcltCQv6hDsLudRg==", + "dev": true, + "dependencies": { + "ansi-html-community": "^0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^3.5.1", + "colorette": "^1.2.2", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "del": "^6.0.0", + "express": "^4.17.1", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.0", + "internal-ip": "^6.2.0", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "portfinder": "^1.0.28", + "schema-utils": "^3.1.0", + "selfsigned": "^1.10.11", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "spdy": "^4.0.2", + "strip-ansi": "^7.0.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^5.0.0", + "ws": "^8.1.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-glsl-loader": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/webpack-glsl-loader/-/webpack-glsl-loader-1.0.1.tgz", + "integrity": "sha1-cqDjAZK9V5R9YNbVBckVvmgNCsw=", + "dev": true, + "dependencies": { + "fs": "0.0.2", + "path": "^0.11.14" + } + }, + "node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/ws": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.2.tgz", + "integrity": "sha512-Q6B6H2oc8QY3llc3cB8kVmQ6pnJWVQbP7Q5algTcIxx7YEpc0oU4NBVHlztA7Ekzfhw2r0rPducMUiCGWKQRzw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { "@discoveryjs/json-ext": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz", @@ -272,7 +4290,8 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.4.tgz", "integrity": "sha512-cs3XLy+UcxiP6bj0A6u7MLLuwdXJ1c3Dtc0RkKg+wiI1g/Ti1om8+/2hc2A2B60NbBNAbMgyBMHvyymWm/j4wQ==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/info": { "version": "1.3.0", @@ -287,7 +4306,8 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.2.tgz", "integrity": "sha512-vgJ5OLWadI8aKjDlOH3rb+dYyPd2GTZuQC/Tihjct6F9GpXGZINo3Y/IVuZVTM1eDQB+/AOsjPUWH/WySDaXvw==", - "dev": true + "dev": true, + "requires": {} }, "@xtuc/ieee754": { "version": "1.2.0", @@ -301,6 +4321,29 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "3d-view": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/3d-view/-/3d-view-2.0.1.tgz", + "integrity": "sha512-YSLRHXNpSziaaiK2R0pI5+JKguoJVbtWmIv9YyBFtl0+q42kQwJB/JUulbFR/1zYFm58ifjKQ6kVdgZ6tyKtCA==", + "requires": { + "matrix-camera-controller": "^2.1.1", + "orbit-camera-controller": "^4.0.0", + "turntable-camera-controller": "^3.0.0" + } + }, + "3d-view-controls": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/3d-view-controls/-/3d-view-controls-2.2.2.tgz", + "integrity": "sha512-WL0u3PN41lEx/4qvKqV6bJlweUYoW18FXMshW/qHb41AVdZxDReLoJNGYsI7x6jf9bYelEF62BJPQmO7yEnG2w==", + "requires": { + "3d-view": "^2.0.0", + "has-passive-events": "^1.0.0", + "mouse-change": "^1.1.1", + "mouse-event-offset": "^3.0.2", + "mouse-wheel": "^1.0.2", + "right-now": "^1.0.0" + } + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -321,7 +4364,8 @@ "version": "1.7.6", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.7.6.tgz", "integrity": "sha512-FlVvVFA1TX6l3lp8VjDnYYq7R1nyW6x3svAt4nDgrWQ9SBaSh9CnbwgSUTasgfNfOG5HlM1ehugCvM+hjo56LA==", - "dev": true + "dev": true, + "requires": {} }, "aggregate-error": { "version": "3.1.0", @@ -349,7 +4393,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "ansi-html-community": { "version": "0.0.8", @@ -3102,7 +7147,8 @@ "version": "8.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.2.tgz", "integrity": "sha512-Q6B6H2oc8QY3llc3cB8kVmQ6pnJWVQbP7Q5algTcIxx7YEpc0oU4NBVHlztA7Ekzfhw2r0rPducMUiCGWKQRzw==", - "dev": true + "dev": true, + "requires": {} }, "yallist": { "version": "4.0.0", diff --git a/package.json b/package.json index b7820dea..16277910 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "build": "webpack" }, "devDependencies": { + "@types/dat.gui": "^0.7.7", "@types/webgl2": "0.0.6", "ts-loader": "^9.2.5", "typescript": "^4.4.2", @@ -14,6 +15,8 @@ }, "dependencies": { "3d-view-controls": "^2.2.2", - "gl-matrix": "^3.3.0" + "dat.gui": "^0.7.7", + "gl-matrix": "^3.3.0", + "stats-js": "^1.0.1" } } diff --git a/src/geometry/Icosphere.ts b/src/geometry/Icosphere.ts new file mode 100644 index 00000000..412995ba --- /dev/null +++ b/src/geometry/Icosphere.ts @@ -0,0 +1,179 @@ +import {vec3, vec4} from 'gl-matrix'; +import Drawable from '../rendering/gl/Drawable'; +import {gl} from '../globals'; + +class Icosphere extends Drawable { + buffer: ArrayBuffer; + indices: Uint32Array; + positions: Float32Array; + normals: Float32Array; + center: vec4; + + constructor(center: vec3, public radius: number, public subdivisions: number) { + super(); // Call the constructor of the super class. This is required. + this.center = vec4.fromValues(center[0], center[1], center[2], 1); + } + + create() { + const X = 0.525731112119133606; + const Z = 0.850650808352039932; + const N = 0; + + let maxIndexCount = 20 * Math.pow(4, this.subdivisions); + let maxVertexCount = 10 * Math.pow(4, this.subdivisions) + 2; + + // Create buffers to back geometry data + // Index data will ping pong back and forth between buffer0 and buffer1 during creation + // All data will be in buffer0 at the end + const buffer0 = new ArrayBuffer( + maxIndexCount * 3 * Uint32Array.BYTES_PER_ELEMENT + + maxVertexCount * 4 * Float32Array.BYTES_PER_ELEMENT + + maxVertexCount * 4 * Float32Array.BYTES_PER_ELEMENT + ); + const buffer1 = new ArrayBuffer( + maxIndexCount * 3 * Uint32Array.BYTES_PER_ELEMENT + ); + const buffers = [buffer0, buffer1]; + let b = 0; + + const indexByteOffset = 0; + const vertexByteOffset = maxIndexCount * 3 * Uint32Array.BYTES_PER_ELEMENT; + const normalByteOffset = vertexByteOffset; + const positionByteOffset = vertexByteOffset + maxVertexCount * 4 * Float32Array.BYTES_PER_ELEMENT; + + // Create 3-uint buffer views into the backing buffer to represent triangles + // The C++ analogy to this would be something like: + // triangles[i] = reinterpret_cast*>(&buffer[offset]); + let triangles: Array = new Array(20); + let nextTriangles: Array = new Array(); + for (let i = 0; i < 20; ++i) { + triangles[i] = new Uint32Array(buffers[b], indexByteOffset + i * 3 * Uint32Array.BYTES_PER_ELEMENT, 3); + } + + // Create 3-float buffer views into the backing buffer to represent positions + let vertices: Array = new Array(12); + for (let i = 0; i < 12; ++i) { + vertices[i] =new Float32Array(buffer0, vertexByteOffset + i * 4 * Float32Array.BYTES_PER_ELEMENT, 4); + } + + // Initialize normals for a 20-sided icosahedron + vertices[0].set([ -X,N,Z,0 ]); + vertices[1].set([ X,N,Z,0 ]); + vertices[2].set([ -X,N,-Z,0 ]); + vertices[3].set([ X,N,-Z,0 ]); + vertices[4].set([ N,Z,X,0 ]); + vertices[5].set([ N,Z,-X,0 ]); + vertices[6].set([ N,-Z,X,0 ]); + vertices[7].set([ N,-Z,-X,0 ]); + vertices[8].set([ Z,X,N,0 ]); + vertices[9].set([ -Z,X, N,0 ]); + vertices[10].set([ Z,-X,N,0 ]); + vertices[11].set([ -Z,-X,N,0 ]); + + // Initialize indices for a 20-sided icosahedron + triangles[0].set([ 0,4,1 ]); + triangles[1].set([ 0,9,4 ]); + triangles[2].set([ 9,5,4 ]); + triangles[3].set([ 4,5,8 ]); + triangles[4].set([ 4,8,1 ]); + triangles[5].set([ 8,10,1 ]); + triangles[6].set([ 8,3,10 ]); + triangles[7].set([ 5,3,8 ]); + triangles[8].set([ 5,2,3 ]); + triangles[9].set([ 2,7,3 ]); + triangles[10].set([ 7,10,3 ]); + triangles[11].set([ 7,6,10 ]); + triangles[12].set([ 7,11,6 ]); + triangles[13].set([ 11,0,6 ]); + triangles[14].set([ 0,1,6 ],); + triangles[15].set([ 6,1,10 ]); + triangles[16].set([ 9,0,11 ]); + triangles[17].set([ 9,11,2 ]); + triangles[18].set([ 9,2,5 ]); + triangles[19].set([ 7,2,11 ]); + + // This loop subdivides the icosahedron + for (let s = 0; s < this.subdivisions; ++s) { + b = 1 - b; + nextTriangles.length = triangles.length * 4; + let triangleIdx = 0; + + // edgeMap maps a pair of vertex indices to a vertex index at their midpoint + // The function `mid` will get that midpoint vertex if it has already been created + // or it will create the vertex and add it to the map + let edgeMap: Map = new Map(); + function mid(v0: number, v1: number): number { + let key = [v0, v1].sort().join('_'); + if (!edgeMap.has(key)) { + let midpoint = new Float32Array(buffer0, vertexByteOffset + vertices.length * 4 * Float32Array.BYTES_PER_ELEMENT, 4); + vec4.add(midpoint, vertices[v0], vertices[v1]); + vec4.normalize(midpoint, midpoint); + edgeMap.set(key, vertices.length); + vertices.push(midpoint); + } + return edgeMap.get(key); + } + + for (let t = 0; t < triangles.length; ++t) { + let v0 = triangles[t][0]; + let v1 = triangles[t][1]; + let v2 = triangles[t][2]; + let v3 = mid(v0, v1); // Get or create a vertex between these two vertices + let v4 = mid(v1, v2); + let v5 = mid(v2, v0); + + let t0 = nextTriangles[triangleIdx] = new Uint32Array(buffers[b], indexByteOffset + (triangleIdx++) * 3 * Uint32Array.BYTES_PER_ELEMENT, 3); + let t1 = nextTriangles[triangleIdx] = new Uint32Array(buffers[b], indexByteOffset + (triangleIdx++) * 3 * Uint32Array.BYTES_PER_ELEMENT, 3); + let t2 = nextTriangles[triangleIdx] = new Uint32Array(buffers[b], indexByteOffset + (triangleIdx++) * 3 * Uint32Array.BYTES_PER_ELEMENT, 3); + let t3 = nextTriangles[triangleIdx] = new Uint32Array(buffers[b], indexByteOffset + (triangleIdx++) * 3 * Uint32Array.BYTES_PER_ELEMENT, 3); + + let triangleOffset = nextTriangles.length; + t0.set([v0, v3, v5]); + t1.set([v3, v4, v5]); + t2.set([v3, v1, v4]); + t3.set([v5, v4, v2]); + } + + // swap buffers + let temp = triangles; + triangles = nextTriangles; + nextTriangles = temp; + } + + if (b === 1) { + // if indices did not end up in buffer0, copy them there now + let temp0 = new Uint32Array(buffer0, 0, 3 * triangles.length); + let temp1 = new Uint32Array(buffer1, 0, 3 * triangles.length); + temp0.set(temp1); + } + + // Populate one position for each normal + for (let i = 0; i < vertices.length; ++i) { + let pos = new Float32Array(buffer0, positionByteOffset + i * 4 * Float32Array.BYTES_PER_ELEMENT, 4); + vec4.scaleAndAdd(pos, this.center, vertices[i], this.radius); + } + + this.buffer = buffer0; + this.indices = new Uint32Array(this.buffer, indexByteOffset, triangles.length * 3); + this.normals = new Float32Array(this.buffer, normalByteOffset, vertices.length * 4); + this.positions = new Float32Array(this.buffer, positionByteOffset, vertices.length * 4); + + this.generateIdx(); + this.generatePos(); + this.generateNor(); + + this.count = this.indices.length; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufIdx); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufNor); + gl.bufferData(gl.ARRAY_BUFFER, this.normals, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufPos); + gl.bufferData(gl.ARRAY_BUFFER, this.positions, gl.STATIC_DRAW); + + console.log(`Created icosphere with ${vertices.length} vertices`); + } +}; + +export default Icosphere; diff --git a/src/geometry/Square.ts b/src/geometry/Square.ts index f2ee9471..1a21a10d 100644 --- a/src/geometry/Square.ts +++ b/src/geometry/Square.ts @@ -5,6 +5,7 @@ import {gl} from '../globals'; class Square extends Drawable { indices: Uint32Array; positions: Float32Array; + normals: Float32Array; center: vec4; constructor(center: vec3) { @@ -16,18 +17,26 @@ class Square extends Drawable { this.indices = new Uint32Array([0, 1, 2, 0, 2, 3]); - this.positions = new Float32Array([-1, -1, 0.999, 1, - 1, -1, 0.999, 1, - 1, 1, 0.999, 1, - -1, 1, 0.999, 1]); + this.normals = new Float32Array([0, 0, 1, 0, + 0, 0, 1, 0, + 0, 0, 1, 0, + 0, 0, 1, 0]); + this.positions = new Float32Array([-1, -1, 0, 1, + 1, -1, 0, 1, + 1, 1, 0, 1, + -1, 1, 0, 1]); this.generateIdx(); this.generatePos(); + this.generateNor(); this.count = this.indices.length; gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufIdx); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufNor); + gl.bufferData(gl.ARRAY_BUFFER, this.normals, gl.STATIC_DRAW); + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufPos); gl.bufferData(gl.ARRAY_BUFFER, this.positions, gl.STATIC_DRAW); diff --git a/src/geometry/cube.ts b/src/geometry/cube.ts new file mode 100644 index 00000000..5c014c18 --- /dev/null +++ b/src/geometry/cube.ts @@ -0,0 +1,110 @@ +import {vec3, vec4} from 'gl-matrix'; +import Drawable from '../rendering/gl/Drawable'; +import {gl} from '../globals'; + +class Cube extends Drawable { + indices: Uint32Array; + positions: Float32Array; + normals: Float32Array; + center: vec4; + + constructor(center: vec3) { + super(); // Call the constructor of the super class. This is required. + this.center = vec4.fromValues(center[0], center[1], center[2], 1); + } + + + create() { + + this.indices = new Uint32Array([0, 1, 2, + 0, 2, 3, + 4, 5, 6, + 4, 6, 7, + 8, 9, 10, + 8, 10, 11, + 12, 13, 14, + 12, 14, 15, + 16, 17, 18, + 16, 18, 19, + 20, 21, 22, + 20, 22, 23]); + +this.normals = new Float32Array([0, 0, 1, 0, + 0, 0, 1, 0, + 0, 0, 1, 0, + 0, 0, 1, 0, + + 0, 0, -1, 0, + 0, 0, -1, 0, + 0, 0, -1, 0, + 0, 0, -1, 0, + + -1, 0, 0, 0, + -1, 0, 0, 0, + -1, 0, 0, 0, + -1, 0, 0, 0, + + 1, 0, 0, 0, + 1, 0, 0, 0, + 1, 0, 0, 0, + 1, 0, 0, 0, + + 0, 1, 0, 0, + 0, 1, 0, 0, + 0, 1, 0, 0, + 0, 1, 0, 0, + + 0, -1, 0, 0, + 0, -1, 0, 0, + 0, -1, 0, 0, + 0, -1, 0, 0]); + +this.positions = new Float32Array([-0.5, -0.5, 0.5, 1, + 0.5, -0.5, 0.5, 1, + 0.5, 0.5, 0.5, 1, + -0.5, 0.5, 0.5, 1, + + -0.5, -0.5, -0.5, 1, + 0.5, -0.5, -0.5, 1, + 0.5, 0.5, -0.5, 1, + -0.5, 0.5, -0.5, 1, + + -0.5, -0.5, -0.5, 1, + -0.5, -0.5, 0.5, 1, + -0.5, 0.5, 0.5, 1, + -0.5, 0.5, -0.5, 1, + + 0.5, -0.5, -0.5, 1, + 0.5, -0.5, 0.5, 1, + 0.5, 0.5, 0.5, 1, + 0.5, 0.5, -0.5, 1, + + -0.5, 0.5, -0.5, 1, + -0.5, 0.5, 0.5, 1, + 0.5, 0.5, 0.5, 1, + 0.5, 0.5, -0.5, 1, + + -0.5, -0.5, -0.5, 1, + -0.5, -0.5, 0.5, 1, + 0.5, -0.5, 0.5, 1, + 0.5, -0.5, -0.5, 1]); + + this.generateIdx(); + this.generatePos(); + this.generateNor(); + + this.count = this.indices.length; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufIdx); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufNor); + gl.bufferData(gl.ARRAY_BUFFER, this.normals, gl.STATIC_DRAW); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufPos); + gl.bufferData(gl.ARRAY_BUFFER, this.positions, gl.STATIC_DRAW); + + console.log(`Created cube`); + } +}; + +export default Cube; diff --git a/src/geometry/fireball.ts b/src/geometry/fireball.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/main.ts b/src/main.ts index fe526f99..f8458cdd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,52 +1,58 @@ -import {vec2, vec3} from 'gl-matrix'; -// import * as Stats from 'stats-js'; -// import * as DAT from 'dat-gui'; +import {vec2, vec3, vec4} from 'gl-matrix'; +const Stats = require('stats-js'); +import * as DAT from 'dat.gui'; +import Icosphere from './geometry/Icosphere'; import Square from './geometry/Square'; import OpenGLRenderer from './rendering/gl/OpenGLRenderer'; import Camera from './Camera'; import {setGL} from './globals'; import ShaderProgram, {Shader} from './rendering/gl/ShaderProgram'; +import Cube from './geometry/cube'; // Define an object with application parameters and button callbacks // This will be referred to by dat.GUI's functions that add GUI elements. const controls = { tesselations: 5, 'Load Scene': loadScene, // A function pointer, essentially + color: [ 255, 255, 0, 255 ], // RGB with alpha + intensity: 2.2, + freq: 2, }; +let icosphere: Icosphere; let square: Square; +let prevTesselations: number = 5; +let preGeoColor: number[] = [255, 255, 0, 255]; +let cube: Cube; let time: number = 0; +let prevPerlinScale: number = 1.8; +let prevFreq: number = 3; function loadScene() { + icosphere = new Icosphere(vec3.fromValues(0, 0, 0), 1, controls.tesselations); + icosphere.create(); + cube = new Cube(vec3.fromValues(0, 0, 0)); + cube.create(); square = new Square(vec3.fromValues(0, 0, 0)); square.create(); - // time = 0; } function main() { - window.addEventListener('keypress', function (e) { - // console.log(e.key); - switch(e.key) { - // Use this if you wish - } - }, false); - - window.addEventListener('keyup', function (e) { - switch(e.key) { - // Use this if you wish - } - }, false); - // Initial display for framerate - // const stats = Stats(); - // stats.setMode(0); - // stats.domElement.style.position = 'absolute'; - // stats.domElement.style.left = '0px'; - // stats.domElement.style.top = '0px'; - // document.body.appendChild(stats.domElement); + const stats = Stats(); + stats.setMode(0); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.left = '0px'; + stats.domElement.style.top = '0px'; + document.body.appendChild(stats.domElement); // Add controls to the gui - // const gui = new DAT.GUI(); + const gui = new DAT.GUI(); + gui.add(controls, 'tesselations', 0, 8).step(1); + gui.add(controls, 'Load Scene'); + gui.addColor(controls, 'color'); + gui.add(controls, 'intensity', 1, 10).step(0.2); + gui.add(controls, 'freq', 1, 10).step(1); // get canvas and webgl context const canvas = document.getElementById('canvas'); @@ -61,49 +67,88 @@ function main() { // Initial call to load scene loadScene(); - const camera = new Camera(vec3.fromValues(0, 0, -10), vec3.fromValues(0, 0, 0)); + const camera = new Camera(vec3.fromValues(0, 0, 5), vec3.fromValues(0, 0, 0)); const renderer = new OpenGLRenderer(canvas); - renderer.setClearColor(164.0 / 255.0, 233.0 / 255.0, 1.0, 1); + renderer.setClearColor(0.2, 0.2, 0.2, 1); gl.enable(gl.DEPTH_TEST); - const flat = new ShaderProgram([ - new Shader(gl.VERTEX_SHADER, require('./shaders/flat-vert.glsl')), - new Shader(gl.FRAGMENT_SHADER, require('./shaders/flat-frag.glsl')), + // --------- load texture ----------- + function loadTexture(url: string) { + const texture = gl.createTexture(); + + const image = new Image(); + + image.onload = function() { + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,gl.UNSIGNED_BYTE, image); + gl.generateMipmap(gl.TEXTURE_2D); + }; + image.src = url; + + return texture; + } + + const surfaceTex = loadTexture('../texture/surface.png'); + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, surfaceTex); + // ----------------------------------- + + + const lambert = new ShaderProgram([ + new Shader(gl.VERTEX_SHADER, require('./shaders/lambert-vert.glsl')), + new Shader(gl.FRAGMENT_SHADER, require('./shaders/lambert-frag.glsl')), ]); - function processKeyPresses() { - // Use this if you wish - } + lambert.setTexture(0); // This function will be called every frame function tick() { camera.update(); - // stats.begin(); + stats.begin(); gl.viewport(0, 0, window.innerWidth, window.innerHeight); renderer.clear(); - processKeyPresses(); - renderer.render(camera, flat, [ - square, - ], time); - time++; - // stats.end(); + if(controls.tesselations != prevTesselations) + { + prevTesselations = controls.tesselations; + // icosphere = new Icosphere(vec3.fromValues(0, 0, 0), 1, prevTesselations); + // icosphere.create(); + } + if (controls.color != preGeoColor) { + preGeoColor = controls.color; + renderer.setGeoColor(preGeoColor[0], preGeoColor[1], preGeoColor[2], preGeoColor[3]); + } + if (controls.freq != prevFreq) { + prevFreq = controls.freq; + } + if (controls.intensity != prevPerlinScale) { + prevPerlinScale = controls.intensity; + } + + renderer.render(camera, lambert, [ + icosphere, + // square, + // cube, + ]); + stats.end(); // Tell the browser to call `tick` again whenever it renders a new frame requestAnimationFrame(tick); + lambert.setTime(++time); + lambert.setResolution(vec2.fromValues(window.innerWidth, window.innerHeight)); + lambert.setFreq(prevFreq); + lambert.setPerlinScale(prevPerlinScale); } window.addEventListener('resize', function() { renderer.setSize(window.innerWidth, window.innerHeight); camera.setAspectRatio(window.innerWidth / window.innerHeight); camera.updateProjectionMatrix(); - flat.setDimensions(window.innerWidth, window.innerHeight); }, false); renderer.setSize(window.innerWidth, window.innerHeight); camera.setAspectRatio(window.innerWidth / window.innerHeight); camera.updateProjectionMatrix(); - flat.setDimensions(window.innerWidth, window.innerHeight); // Start the render loop tick(); diff --git a/src/rendering/gl/Drawable.ts b/src/rendering/gl/Drawable.ts index d658d6fa..84c88b2e 100644 --- a/src/rendering/gl/Drawable.ts +++ b/src/rendering/gl/Drawable.ts @@ -5,15 +5,22 @@ abstract class Drawable { bufIdx: WebGLBuffer; bufPos: WebGLBuffer; + bufNor: WebGLBuffer; idxBound: boolean = false; posBound: boolean = false; + norBound: boolean = false; + texBound: boolean = false; + + texture: WebGLTexture; abstract create() : void; destory() { gl.deleteBuffer(this.bufIdx); gl.deleteBuffer(this.bufPos); + gl.deleteBuffer(this.bufNor); + gl.deleteTexture(this.texture); } generateIdx() { @@ -26,6 +33,17 @@ abstract class Drawable { this.bufPos = gl.createBuffer(); } + generateNor() { + this.norBound = true; + this.bufNor = gl.createBuffer(); + } + + generateTex(): WebGLTexture{ + this.texBound = true; + this.texture = gl.createTexture(); + return this.texture; + } + bindIdx(): boolean { if (this.idxBound) { gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufIdx); @@ -40,6 +58,24 @@ abstract class Drawable { return this.posBound; } + bindNor(): boolean { + if (this.norBound) { + gl.bindBuffer(gl.ARRAY_BUFFER, this.bufNor); + } + return this.norBound; + } + + bindTex(): boolean { + if(this.texBound) { + gl.bindTexture(gl.TEXTURE_2D, this.texture); + } + return this.texBound; + } + + getTex(): WebGLTexture{ + return this.texture; + } + elemCount(): number { return this.count; } diff --git a/src/rendering/gl/OpenGLRenderer.ts b/src/rendering/gl/OpenGLRenderer.ts index 10b91c61..b7dab26a 100644 --- a/src/rendering/gl/OpenGLRenderer.ts +++ b/src/rendering/gl/OpenGLRenderer.ts @@ -6,6 +6,8 @@ import ShaderProgram from './ShaderProgram'; // In this file, `gl` is accessible because it is imported above class OpenGLRenderer { + geoCol: vec4; + constructor(public canvas: HTMLCanvasElement) { } @@ -18,13 +20,24 @@ class OpenGLRenderer { this.canvas.height = height; } + setGeoColor(r: number, g: number, b: number, a: number) { + this.geoCol = vec4.fromValues(r/255, g/255, b/255, a/255); + } + clear() { gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); } - render(camera: Camera, prog: ShaderProgram, drawables: Array, time: number) { - prog.setEyeRefUp(camera.controls.eye, camera.controls.center, camera.controls.up); - prog.setTime(time); + render(camera: Camera, prog: ShaderProgram, drawables: Array) { + let model = mat4.create(); + let viewProj = mat4.create(); + let color = vec4.fromValues(1, 0, 0, 1); + + mat4.identity(model); + mat4.multiply(viewProj, camera.projectionMatrix, camera.viewMatrix); + prog.setModelMatrix(model); + prog.setViewProjMatrix(viewProj); + prog.setGeometryColor(this.geoCol); for (let drawable of drawables) { prog.draw(drawable); diff --git a/src/rendering/gl/ShaderProgram.ts b/src/rendering/gl/ShaderProgram.ts index d1ef5be5..a02e2b8d 100644 --- a/src/rendering/gl/ShaderProgram.ts +++ b/src/rendering/gl/ShaderProgram.ts @@ -1,4 +1,4 @@ -import {vec2, vec3, vec4, mat4} from 'gl-matrix'; +import {vec4, mat4, vec2} from 'gl-matrix'; import Drawable from './Drawable'; import {gl} from '../../globals'; @@ -23,12 +23,17 @@ class ShaderProgram { attrPos: number; attrNor: number; + attrCol: number; - unifRef: WebGLUniformLocation; - unifEye: WebGLUniformLocation; - unifUp: WebGLUniformLocation; - unifDimensions: WebGLUniformLocation; + unifModel: WebGLUniformLocation; + unifModelInvTr: WebGLUniformLocation; + unifViewProj: WebGLUniformLocation; + unifColor: WebGLUniformLocation; unifTime: WebGLUniformLocation; + unifTexture: WebGLUniformLocation; + unifResolution: WebGLUniformLocation; + unifFreq: WebGLUniformLocation; + unifPerlinScale: WebGLUniformLocation; constructor(shaders: Array) { this.prog = gl.createProgram(); @@ -42,11 +47,17 @@ class ShaderProgram { } this.attrPos = gl.getAttribLocation(this.prog, "vs_Pos"); - this.unifEye = gl.getUniformLocation(this.prog, "u_Eye"); - this.unifRef = gl.getUniformLocation(this.prog, "u_Ref"); - this.unifUp = gl.getUniformLocation(this.prog, "u_Up"); - this.unifDimensions = gl.getUniformLocation(this.prog, "u_Dimensions"); - this.unifTime = gl.getUniformLocation(this.prog, "u_Time"); + this.attrNor = gl.getAttribLocation(this.prog, "vs_Nor"); + this.attrCol = gl.getAttribLocation(this.prog, "vs_Col"); + this.unifModel = gl.getUniformLocation(this.prog, "u_Model"); + this.unifModelInvTr = gl.getUniformLocation(this.prog, "u_ModelInvTr"); + this.unifViewProj = gl.getUniformLocation(this.prog, "u_ViewProj"); + this.unifColor = gl.getUniformLocation(this.prog, "u_Color"); + this.unifTime = gl.getUniformLocation(this.prog, "u_Time"); + this.unifTexture = gl.getUniformLocation(this.prog, "u_Texture"); + this.unifResolution = gl.getUniformLocation(this.prog, "u_Resolution"); + this.unifFreq = gl.getUniformLocation(this.prog, "u_Freq"); + this.unifPerlinScale = gl.getUniformLocation(this.prog, "u_PerlinScale"); } use() { @@ -56,30 +67,66 @@ class ShaderProgram { } } - setEyeRefUp(eye: vec3, ref: vec3, up: vec3) { + setModelMatrix(model: mat4) { this.use(); - if(this.unifEye !== -1) { - gl.uniform3f(this.unifEye, eye[0], eye[1], eye[2]); + if (this.unifModel !== -1) { + gl.uniformMatrix4fv(this.unifModel, false, model); } - if(this.unifRef !== -1) { - gl.uniform3f(this.unifRef, ref[0], ref[1], ref[2]); + + if (this.unifModelInvTr !== -1) { + let modelinvtr: mat4 = mat4.create(); + mat4.transpose(modelinvtr, model); + mat4.invert(modelinvtr, modelinvtr); + gl.uniformMatrix4fv(this.unifModelInvTr, false, modelinvtr); + } + } + + setViewProjMatrix(vp: mat4) { + this.use(); + if (this.unifViewProj !== -1) { + gl.uniformMatrix4fv(this.unifViewProj, false, vp); + } + } + + setGeometryColor(color: vec4) { + this.use(); + if (this.unifColor !== -1) { + gl.uniform4fv(this.unifColor, color); + } + } + + setTime(time: number){ + this.use(); + if (this.unifTime !== -1){ + gl.uniform1f(this.unifTime, time); } - if(this.unifUp !== -1) { - gl.uniform3f(this.unifUp, up[0], up[1], up[2]); + } + + setTexture(slot: number) { + this.use(); + if (this.unifTexture !== -1) { + gl.uniform1i(this.unifTexture, slot); } } - setDimensions(width: number, height: number) { + setResolution(resolution: vec2) { this.use(); - if(this.unifDimensions !== -1) { - gl.uniform2f(this.unifDimensions, width, height); + if (this.unifResolution !== -1) { + gl.uniform2fv(this.unifResolution, resolution); } } - setTime(t: number) { + setPerlinScale(scale: number){ this.use(); - if(this.unifTime !== -1) { - gl.uniform1f(this.unifTime, t); + if (this.unifPerlinScale !== -1){ + gl.uniform1f(this.unifPerlinScale, scale); + } + } + + setFreq(freq: number){ + this.use(); + if (this.unifFreq !== -1){ + gl.uniform1f(this.unifFreq, freq); } } @@ -91,10 +138,16 @@ class ShaderProgram { gl.vertexAttribPointer(this.attrPos, 4, gl.FLOAT, false, 0, 0); } + if (this.attrNor != -1 && d.bindNor()) { + gl.enableVertexAttribArray(this.attrNor); + gl.vertexAttribPointer(this.attrNor, 4, gl.FLOAT, false, 0, 0); + } + d.bindIdx(); gl.drawElements(d.drawMode(), d.elemCount(), gl.UNSIGNED_INT, 0); if (this.attrPos != -1) gl.disableVertexAttribArray(this.attrPos); + if (this.attrNor != -1) gl.disableVertexAttribArray(this.attrNor); } }; diff --git a/src/shaders/lambert-frag.glsl b/src/shaders/lambert-frag.glsl new file mode 100644 index 00000000..33e9a55a --- /dev/null +++ b/src/shaders/lambert-frag.glsl @@ -0,0 +1,70 @@ +#version 300 es + +// This is a fragment shader. If you've opened this file first, please +// open and read lambert.vert.glsl before reading on. +// Unlike the vertex shader, the fragment shader actually does compute +// the shading of geometry. For every pixel in your program's output +// screen, the fragment shader is run for every bit of geometry that +// particular pixel overlaps. By implicitly interpolating the position +// data passed into the fragment shader by the vertex shader, the fragment shader +// can compute what color to apply to its pixel based on things like vertex +// position, light position, and vertex color. +precision highp float; + +uniform vec4 u_Color; // The color with which to render this instance of geometry. + +uniform float u_Time; +uniform sampler2D u_Texture; +uniform vec2 u_Resolution; + +// These are the interpolated values out of the rasterizer, so you can't know +// their specific values without knowing the vertices that contributed to them +in vec4 fs_Nor; +in vec4 fs_LightVec; +in vec4 fs_Col; +in vec4 fs_Pos; + +out vec4 out_Col; // This is the final output color that you will see on your + // screen for the pixel that is currently being processed. + + +float snoise(vec3 uv, float res) +{ + const vec3 s = vec3(1e0, 1e2, 1e3); + + uv *= res; + + vec3 uv0 = floor(mod(uv, res))*s; + vec3 uv1 = floor(mod(uv+vec3(1.), res))*s; + + vec3 f = fract(uv); f = f*f*(3.0-2.0*f); + + vec4 v = vec4(uv0.x+uv0.y+uv0.z, uv1.x+uv0.y+uv0.z, + uv0.x+uv1.y+uv0.z, uv1.x+uv1.y+uv0.z); + + vec4 r = fract(sin(v*1e-1)*1e3); + float r0 = mix(mix(r.x, r.y, f.x), mix(r.z, r.w, f.x), f.y); + + r = fract(sin((v + uv1.z - uv0.z)*1e-1)*1e3); + float r1 = mix(mix(r.x, r.y, f.x), mix(r.z, r.w, f.x), f.y); + + return mix(r0, r1, f.z)*2.-1.; +} + +void main() +{ + vec3 p = vec3(fs_Pos.xyz); + float dist = length(p - vec3(0,0,0)); + if (dist < 1.02) { + out_Col = vec4(0.8 * max(0.8, abs(sin(u_Time * 0.02 + 0.4))),0,0,1); + } + else if (dist < 1.05) { + out_Col = vec4(1.0 * max(0.5, abs(cos(u_Time * 0.01 + 0.2))),0,0,1); + } + else if (dist < 1.1) { + out_Col = vec4(1, 0.5, 0,1); + } + else { + out_Col = vec4(1,1,1.0 * max(0.7, sin(u_Time * 0.3 + 0.4)),1); + } +} diff --git a/src/shaders/lambert-vert.glsl b/src/shaders/lambert-vert.glsl new file mode 100644 index 00000000..0a8727f1 --- /dev/null +++ b/src/shaders/lambert-vert.glsl @@ -0,0 +1,259 @@ +#version 300 es + +//This is a vertex shader. While it is called a "shader" due to outdated conventions, this file +//is used to apply matrix transformations to the arrays of vertex data passed to it. +//Since this code is run on your GPU, each vertex is transformed simultaneously. +//If it were run on your CPU, each vertex would have to be processed in a FOR loop, one at a time. +//This simultaneous transformation allows your program to run much faster, especially when rendering +//geometry with millions of vertices. + +uniform mat4 u_Model; // The matrix that defines the transformation of the + // object we're rendering. In this assignment, + // this will be the result of traversing your scene graph. + +uniform mat4 u_ModelInvTr; // The inverse transpose of the model matrix. + // This allows us to transform the object's normals properly + // if the object has been non-uniformly scaled. + +uniform mat4 u_ViewProj; // The matrix that defines the camera's transformation. + // We've written a static matrix for you to use for HW2, + // but in HW3 you'll have to generate one yourself + +uniform float u_Time; +uniform float u_Freq; +uniform float u_PerlinScale; + +in vec4 vs_Pos; // The array of vertex positions passed to the shader + +in vec4 vs_Nor; // The array of vertex normals passed to the shader + +in vec4 vs_Col; // The array of vertex colors passed to the shader. + +out vec4 fs_Nor; // The array of normals that has been transformed by u_ModelInvTr. This is implicitly passed to the fragment shader. +out vec4 fs_LightVec; // The direction in which our virtual light lies, relative to each vertex. This is implicitly passed to the fragment shader. +out vec4 fs_Col; // The color of each vertex. This is implicitly passed to the fragment shader. +out vec4 fs_Pos; + +const vec4 lightPos = vec4(5, 5, 3, 1); //The position of our virtual light, which is used to compute the shading of + //the geometry in the fragment shader. + +// reference: https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83 +vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} +vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} +vec4 fade(vec4 t) {return t*t*t*(t*(t*6.0-15.0)+10.0);} + +vec3 random3( vec3 p ) { + return fract(sin(vec3(dot(p,vec3(127.1, 311.7, 191.999)), + dot(p,vec3(269.5, 183.3, 765.54)), + dot(p, vec3(420.69, 631.2,109.21)))) + *43758.5453); +} + +float surflet(vec3 p, vec3 gridPoint) { + // Compute the distance between p and the grid point along each axis, and warp it with a + // quintic function so we can smooth our cells + vec3 t2 = abs(p - gridPoint); + vec3 t = vec3(1.0) - 6.0 * vec3(pow(t2.x, 5.0), pow(t2.y, 5.0), pow(t2.z, 5.0)) + 15.0 * vec3(pow(t2.x, 4.0), pow(t2.y, 4.0), pow(t2.z, 4.0)) - 10.0 * vec3(pow(t2.x, 3.0), pow(t2.y, 3.0), pow(t2.z, 3.0)); + + vec3 gradient = random3(gridPoint) * 2.0 - vec3(1.0); + // Get the vector from the grid point to P + vec3 diff = p - gridPoint; + // Get the value of our height field by dotting grid->P with our gradient + float height = dot(diff, gradient); + // Scale our height field (i.e. reduce it) by our polynomial falloff function + return height * t.x * t.y * t.z; +} + +float perlinNoise3D(vec3 p) { + float surfletSum = 0.0; + // Iterate over the four integer corners surrounding uv + for(int dx = 0; dx <= 1; ++dx) { + for(int dy = 0; dy <= 1; ++dy) { + for(int dz = 0; dz <= 1; ++dz) { + surfletSum += surflet(p, floor(p) + vec3(dx, dy, dz)); + } + } + } + return surfletSum; +} + + +float cnoise(vec4 P){ + vec4 Pi0 = floor(P); // Integer part for indexing + vec4 Pi1 = Pi0 + 1.0; // Integer part + 1 + Pi0 = mod(Pi0, 289.0); + Pi1 = mod(Pi1, 289.0); + vec4 Pf0 = fract(P); // Fractional part for interpolation + vec4 Pf1 = Pf0 - 1.0; // Fractional part - 1.0 + vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec4 iy = vec4(Pi0.yy, Pi1.yy); + vec4 iz0 = vec4(Pi0.zzzz); + vec4 iz1 = vec4(Pi1.zzzz); + vec4 iw0 = vec4(Pi0.wwww); + vec4 iw1 = vec4(Pi1.wwww); + + vec4 ixy = permute(permute(ix) + iy); + vec4 ixy0 = permute(ixy + iz0); + vec4 ixy1 = permute(ixy + iz1); + vec4 ixy00 = permute(ixy0 + iw0); + vec4 ixy01 = permute(ixy0 + iw1); + vec4 ixy10 = permute(ixy1 + iw0); + vec4 ixy11 = permute(ixy1 + iw1); + + vec4 gx00 = ixy00 / 7.0; + vec4 gy00 = floor(gx00) / 7.0; + vec4 gz00 = floor(gy00) / 6.0; + gx00 = fract(gx00) - 0.5; + gy00 = fract(gy00) - 0.5; + gz00 = fract(gz00) - 0.5; + vec4 gw00 = vec4(0.75) - abs(gx00) - abs(gy00) - abs(gz00); + vec4 sw00 = step(gw00, vec4(0.0)); + gx00 -= sw00 * (step(0.0, gx00) - 0.5); + gy00 -= sw00 * (step(0.0, gy00) - 0.5); + + vec4 gx01 = ixy01 / 7.0; + vec4 gy01 = floor(gx01) / 7.0; + vec4 gz01 = floor(gy01) / 6.0; + gx01 = fract(gx01) - 0.5; + gy01 = fract(gy01) - 0.5; + gz01 = fract(gz01) - 0.5; + vec4 gw01 = vec4(0.75) - abs(gx01) - abs(gy01) - abs(gz01); + vec4 sw01 = step(gw01, vec4(0.0)); + gx01 -= sw01 * (step(0.0, gx01) - 0.5); + gy01 -= sw01 * (step(0.0, gy01) - 0.5); + + vec4 gx10 = ixy10 / 7.0; + vec4 gy10 = floor(gx10) / 7.0; + vec4 gz10 = floor(gy10) / 6.0; + gx10 = fract(gx10) - 0.5; + gy10 = fract(gy10) - 0.5; + gz10 = fract(gz10) - 0.5; + vec4 gw10 = vec4(0.75) - abs(gx10) - abs(gy10) - abs(gz10); + vec4 sw10 = step(gw10, vec4(0.0)); + gx10 -= sw10 * (step(0.0, gx10) - 0.5); + gy10 -= sw10 * (step(0.0, gy10) - 0.5); + + vec4 gx11 = ixy11 / 7.0; + vec4 gy11 = floor(gx11) / 7.0; + vec4 gz11 = floor(gy11) / 6.0; + gx11 = fract(gx11) - 0.5; + gy11 = fract(gy11) - 0.5; + gz11 = fract(gz11) - 0.5; + vec4 gw11 = vec4(0.75) - abs(gx11) - abs(gy11) - abs(gz11); + vec4 sw11 = step(gw11, vec4(0.0)); + gx11 -= sw11 * (step(0.0, gx11) - 0.5); + gy11 -= sw11 * (step(0.0, gy11) - 0.5); + + vec4 g0000 = vec4(gx00.x,gy00.x,gz00.x,gw00.x); + vec4 g1000 = vec4(gx00.y,gy00.y,gz00.y,gw00.y); + vec4 g0100 = vec4(gx00.z,gy00.z,gz00.z,gw00.z); + vec4 g1100 = vec4(gx00.w,gy00.w,gz00.w,gw00.w); + vec4 g0010 = vec4(gx10.x,gy10.x,gz10.x,gw10.x); + vec4 g1010 = vec4(gx10.y,gy10.y,gz10.y,gw10.y); + vec4 g0110 = vec4(gx10.z,gy10.z,gz10.z,gw10.z); + vec4 g1110 = vec4(gx10.w,gy10.w,gz10.w,gw10.w); + vec4 g0001 = vec4(gx01.x,gy01.x,gz01.x,gw01.x); + vec4 g1001 = vec4(gx01.y,gy01.y,gz01.y,gw01.y); + vec4 g0101 = vec4(gx01.z,gy01.z,gz01.z,gw01.z); + vec4 g1101 = vec4(gx01.w,gy01.w,gz01.w,gw01.w); + vec4 g0011 = vec4(gx11.x,gy11.x,gz11.x,gw11.x); + vec4 g1011 = vec4(gx11.y,gy11.y,gz11.y,gw11.y); + vec4 g0111 = vec4(gx11.z,gy11.z,gz11.z,gw11.z); + vec4 g1111 = vec4(gx11.w,gy11.w,gz11.w,gw11.w); + + vec4 norm00 = taylorInvSqrt(vec4(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100))); + g0000 *= norm00.x; + g0100 *= norm00.y; + g1000 *= norm00.z; + g1100 *= norm00.w; + + vec4 norm01 = taylorInvSqrt(vec4(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101))); + g0001 *= norm01.x; + g0101 *= norm01.y; + g1001 *= norm01.z; + g1101 *= norm01.w; + + vec4 norm10 = taylorInvSqrt(vec4(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110))); + g0010 *= norm10.x; + g0110 *= norm10.y; + g1010 *= norm10.z; + g1110 *= norm10.w; + + vec4 norm11 = taylorInvSqrt(vec4(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111))); + g0011 *= norm11.x; + g0111 *= norm11.y; + g1011 *= norm11.z; + g1111 *= norm11.w; + + float n0000 = dot(g0000, Pf0); + float n1000 = dot(g1000, vec4(Pf1.x, Pf0.yzw)); + float n0100 = dot(g0100, vec4(Pf0.x, Pf1.y, Pf0.zw)); + float n1100 = dot(g1100, vec4(Pf1.xy, Pf0.zw)); + float n0010 = dot(g0010, vec4(Pf0.xy, Pf1.z, Pf0.w)); + float n1010 = dot(g1010, vec4(Pf1.x, Pf0.y, Pf1.z, Pf0.w)); + float n0110 = dot(g0110, vec4(Pf0.x, Pf1.yz, Pf0.w)); + float n1110 = dot(g1110, vec4(Pf1.xyz, Pf0.w)); + float n0001 = dot(g0001, vec4(Pf0.xyz, Pf1.w)); + float n1001 = dot(g1001, vec4(Pf1.x, Pf0.yz, Pf1.w)); + float n0101 = dot(g0101, vec4(Pf0.x, Pf1.y, Pf0.z, Pf1.w)); + float n1101 = dot(g1101, vec4(Pf1.xy, Pf0.z, Pf1.w)); + float n0011 = dot(g0011, vec4(Pf0.xy, Pf1.zw)); + float n1011 = dot(g1011, vec4(Pf1.x, Pf0.y, Pf1.zw)); + float n0111 = dot(g0111, vec4(Pf0.x, Pf1.yzw)); + float n1111 = dot(g1111, Pf1); + + vec4 fade_xyzw = fade(Pf0); + vec4 n_0w = mix(vec4(n0000, n1000, n0100, n1100), vec4(n0001, n1001, n0101, n1101), fade_xyzw.w); + vec4 n_1w = mix(vec4(n0010, n1010, n0110, n1110), vec4(n0011, n1011, n0111, n1111), fade_xyzw.w); + vec4 n_zw = mix(n_0w, n_1w, fade_xyzw.z); + vec2 n_yzw = mix(n_zw.xy, n_zw.zw, fade_xyzw.y); + float n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x); + return 2.2 * n_xyzw; +} + +float bias(float t, float b) { + return (t / ((((1.0/b) - 2.0)*(1.0 - t))+1.0)); +} + +vec3 rotatePoint3d(vec3 pos, float angle) +{ + vec3 center = vec3(0,0,0); + vec3 rotatedPoint = vec3(pos.x - center.x, pos.y - center.y, pos.z - center.z); + rotatedPoint.x = cos(angle) * rotatedPoint.x - sin(angle) * rotatedPoint.y; + rotatedPoint.y = sin(angle) * rotatedPoint.x + cos(angle) * rotatedPoint.y; + rotatedPoint.z = pos.z; + return rotatedPoint; +} + + + +void main() +{ + fs_Col = vs_Col; // Pass the vertex colors to the fragment shader for interpolation + + mat3 invTranspose = mat3(u_ModelInvTr); + fs_Nor = vec4(invTranspose * vec3(vs_Nor), 0); // Pass the vertex normals to the fragment shader for interpolation. + // Transform the geometry's normals by the inverse transpose of the + // model matrix. This is necessary to ensure the normals remain + // perpendicular to the surface after the surface is transformed by + // the model matrix. + + vec4 modelposition = vs_Pos; // Temporarily store the transformed vertex positions for use below + + vec3 pos = vec3(vs_Pos.x + u_Time * u_Freq / 300.0, vs_Pos.y + u_Time * u_Freq / 400.0, vs_Pos.z + u_Time * u_Freq / 500.0); + vec4 targetPos = normalize(vs_Nor) * 2.f; + float k = sin(u_Time * u_Freq / 100.0) * 0.5 + 0.5; + float perlinScale = u_PerlinScale; + float t = perlinNoise3D(perlinScale * pos) + 0.4 * perlinNoise3D(perlinScale * 1.5 * pos) + 0.3 * cnoise(perlinScale * 4.0 * vec4(pos, 1.0)); + + + vec4 tmpPos = vs_Pos + 0.4f * (k + 0.2) * vs_Nor * abs(t); // * fbm(vs_Pos.xyz); + + modelposition = tmpPos; + fs_Pos = modelposition; + + fs_LightVec = lightPos - modelposition; // Compute the direction in which the light source lies + + gl_Position = u_ViewProj * modelposition * u_Model;// gl_Position is a built-in variable of OpenGL which is + // used to render the final positions of the geometry's vertices +} \ No newline at end of file diff --git a/texture/surface.png b/texture/surface.png new file mode 100644 index 0000000000000000000000000000000000000000..9b916058ed5429b9260bb071670d6c94e7c407b1 GIT binary patch literal 14475 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 F{{bH%R-pg@ literal 0 HcmV?d00001 diff --git a/webpack.config.js b/webpack.config.js index 2cce33bb..2ccfbdc7 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -26,7 +26,7 @@ module.exports = { }, devtool: 'source-map', devServer: { - port: 5660, + port: 7000, static: { directory: path.join(__dirname, 'dist'), }, From 51ba513e06657eb916777c586c7b60e6fe7b368d Mon Sep 17 00:00:00 2001 From: Wenqing Wang <33616958+FridaWang@users.noreply.github.com> Date: Tue, 20 Sep 2022 13:18:17 -0400 Subject: [PATCH 2/7] Update README.md --- README.md | 102 ++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index b898cbb4..1a7646c7 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,73 @@ -# HW 0: Intro to Javascript and WebGL - -

- -

-

(source: Ken Perlin)

+# [Project 1: Noise](https://github.com/CIS-566-Fall-2022/hw01-fireball-base) ## Objective -- Check that the tools and build configuration we will be using for the class works. -- Start learning Typescript and WebGL2 -- Practice implementing noise -## Forking the Code -Rather than cloning the homework repository, please __fork__ the code into your own repository using the `Fork` button in the upper-right hand corner of the Github UI. This will enable you to have your own personal repository copy of the code, and let you make a live demo (described later in this document). +Get comfortable with using WebGL and its shaders to generate an interesting 3D, continuous surface using a multi-octave noise algorithm. + +## Getting Started + +1. Fork and clone [this repository](https://github.com/CIS700-Procedural-Graphics/Project1-Noise). -## Running the Code +2. Copy your hw0 code into your local hw1 repository. -1. [Install Node.js](https://nodejs.org/en/download/). Node.js is a JavaScript runtime. It basically allows you to run JavaScript when not in a browser. For our purposes, this is not necessary. The important part is that with it comes `npm`, the Node Package Manager. This allows us to easily declare and install external dependencies such as [dat.GUI](https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage), and [glMatrix](http://glmatrix.net/). +3. In the root directory of your project, run `npm install`. This will download all of those dependencies. -2. Using a command terminal, run `npm install` in the root directory of your project. This will download all of those dependencies. +4. Do either of the following (but I highly recommend the first one for reasons I will explain later). -3. Do either of the following (but we highly recommend the first one for reasons we will explain later). + a. Run `npm start` and then go to `localhost:7000` in your web browser - a. Run `npm start` and then go to `localhost:5660` in your web browser + b. Run `npm run build` and then go open `index.html` in your web browser - b. Run `npm run build` and then go open `dist/index.html` in your web browser + You should hopefully see the framework code with a 3D cube at the center of the screen! -## Module Bundling -One of the most important dependencies of our projects is [Webpack](https://webpack.js.org/concepts/). Webpack is a module bundler which allows us to write code in separate files and use `import`s and `export`s to load classes and functions for other files. It also allows us to preprocess code before compiling to a single file. We will be using [Typescript](https://www.typescriptlang.org/docs/home.html) for this course which is Javascript augmented with type annotations. Webpack will convert Typescript files to Javascript files on compilation and in doing so will also check for proper type-safety and usage. Read more about Javascript modules in the resources section below. ## Developing Your Code -All of the JavaScript code is living inside the `src` directory. The main file that gets executed when you load the page as you may have guessed is `main.ts`. Here, you can make any changes you want, import functions from other files, etc. The reason that we highly suggest you build your project with `npm start` is that doing so will start a process that watches for any changes you make to your code. If it detects anything, it'll automagically rebuild your project and then refresh your browser window for you. Wow. That's cool. If you do it the other way, you'll need to run `npm build` and then refresh your page every time you want to test something. +All of the JavaScript code is living inside the `src` directory. The main file that gets executed when you load the page as you may have guessed is `main.js`. Here, you can make any changes you want, import functions from other files, etc. The reason that I highly suggest you build your project with `npm start` is that doing so will start a process that watches for any changes you make to your code. If it detects anything, it'll automagically rebuild your project and then refresh your browser window for you. Wow. That's cool. If you do it the other way, you'll need to run `npm build` and then refresh your page every time you want to test something. + +## Publishing Your Code +We highly suggest that you put your code on GitHub. One of the reasons we chose to make this course using JavaScript is that the Web is highly accessible and making your awesome work public and visible can be a huge benefit when you're looking to score a job or internship. To aid you in this process, running `npm run deploy` will automatically build your project and push it to `gh-pages` where it will be visible at `username.github.io/repo-name`. + +## Setting up `main.ts` + +Alter `main.ts` so that it renders the icosphere provided, rather than the cube you built in hw0. You will be writing a WebGL shader to displace its surface to look like a fireball. You may either rewrite the shader you wrote in hw0, or make a new `ShaderProgram` instance that uses new GLSL files. -We would suggest editing your project with Visual Studio Code https://code.visualstudio.com/. Microsoft develops it and Microsoft also develops Typescript so all of the features work nicely together. Sublime Text and installing the Typescript plugins should probably work as well. +## Noise Generation -## Assignment Details -1. Take some time to go through the existing codebase so you can get an understanding of syntax and how the code is architected. Much of the code is designed to mirror the class structures used in CIS 460's OpenGL assignments, so it should hopefully be somewhat familiar. -2. Take a look at the resources linked in the section below. Definitely read about Javascript modules and Typescript. The other links provide documentation for classes used in the code. -3. Add a `Cube` class that inherits from `Drawable` and at the very least implement a constructor and its `create` function. Then, add a `Cube` instance to the scene to be rendered. -4. Read the documentation for dat.GUI below. Update the existing GUI in `main.ts` with a parameter to alter the color passed to `u_Color` in the Lambert shader. -5. Write a custom fragment shader that implements FBM, Worley Noise, or Perlin Noise based on 3D inputs (as opposed to the 2D inputs in the slides). This noise must be used to modify your fragment color. If your custom shader is particularly interesting, you'll earn some bonus points. -6. Write a custom vertex shader that uses a trigonometric function (e.g. `sin`, `tan`) to non-uniformly modify your cube's vertex positions over time. This will necessitate instantiating an incrementing variable in your Typescript code that you pass to your shader every tick. Refer to the base code's methods of passing variables to shaders if you are unsure how to do so. -7. Feel free to update any of the files when writing your code. The implementation of the `OpenGLRenderer` is currently very simple. +Across your vertex and fragment shaders, you must implement a variety of functions of the form `h = f(x,y,z)` to displace and color your fireball's surface, where `h` is some floating-point displacement amount. -## Making a Live Demo -When you push changes to the `master` branch of your repository on Github, a Github workflow will run automatically which builds your code and pushes the build to a new branch `gh-pages`. The configuration file which handles this is located at `.github/workflows/build-and-deploy.yml`. If you want to modify this, you can read more about workflows [here](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions). +- Your vertex shader should apply a low-frequency, high-amplitude displacement of your sphere so as to make it less uniformly sphere-like. You might consider using a combination of sinusoidal functions for this purpose. +- Your vertex shader should also apply a higher-frequency, lower-amplitude layer of fractal Brownian motion to apply a finer level of distortion on top of the high-amplitude displacement. +- Your fragment shader should apply a gradient of colors to your fireball's surface, where the fragment color is correlated in some way to the vertex shader's displacement. +- Both the vertex and fragment shaders should alter their output based on a uniform time variable (i.e. they should be animated). You might consider making a constant animation that causes the fireball's surface to roil, or you could make an animation loop in which the fireball repeatedly explodes. +- Across both shaders, you should make use of at least four of the functions discussed in the Toolbox Functions slides. -Once your built code is pushed to `gh-pages`, Github can automatically publish a live site. Configure that by: - 1. Open the Settings tab of your repository in Github. +## Noise Application - 2. Scroll down to the Pages tab of the Settings (in the table on the left) and choose which branch to make the source for the deployed project. This should be the `gh-pages` branch which is automatically created after the first successful build of the `master` branch. +View your noise in action by applying it as a displacement on the surface of your icosahedron, giving your icosahedron a bumpy, cloud-like appearance. Simply take the noise value as a height, and offset the vertices along the icosahedron's surface normals. You are, of course, free to alter the way your noise perturbs your icosahedron's surface as you see fit; we are simply recommending an easy way to visualize your noise. You could even apply a couple of different noise functions to perturb your surface to make it even less spherical. - 3. Done! Now, any new commits on the `master` branch will be built and pushed to `gh-pages`. The project should be visible at http://username.github.io/repo-name. -  +In order to animate the vertex displacement, use time as the third dimension or as some offset to the (x, y, z) input to the noise function. Pass the current time since start of program as a uniform to the shaders. -To check if everything is on the right track: +For both visual impact and debugging help, also apply color to your geometry using the noise value at each point. There are several ways to do this. For example, you might use the noise value to create UV coordinates to read from a texture (say, a simple gradient image), or just compute the color by hand by lerping between values. -1. Make sure the `gh-pages` branch of your repo has a files called `index.html`, `bundle.js`, and `bundle.js.map` +## Interactivity -2. In the settings tab of the repo, under Pages, make sure it says your site is published at some url. +Using dat.GUI, make at least THREE aspects of your demo interactive variables. For example, you could add a slider to adjust the strength or scale of the noise, change the number of noise octaves, etc. + +Add a button that will restore your fireball to some nice-looking (courtesy of your art direction) defaults. :) + +## Extra Spice + +Choose one of the following options: + +- Background (easy-hard depending on how fancy you get): Add an interesting background or a more complex scene to place your fireball in so it's not floating in a black void +- Custom mesh (easy): Figure out how to import a custom mesh rather than using an icosahedron for a fancy-shaped cloud. +- Mouse interactivity (medium): Find out how to get the current mouse position in your scene and use it to deform your cloud, such that users can deform the cloud with their cursor. +- Music (hard): Figure out a way to use music to drive your noise animation in some way, such that your noise cloud appears to dance. ## Submission -1. Create a pull request to this repository with your completed code. -2. Update README.md to contain a solid description of your project with a screenshot of some visuals, and a link to your live demo. -3. Submit the link to your pull request on Canvas, and add a comment to your submission with a hyperlink to your live demo. -4. Include a link to your live site. - -## Resources -- Javascript modules https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import -- Typescript https://www.typescriptlang.org/docs/home.html -- dat.gui https://workshop.chromeexperiments.com/examples/gui/ -- glMatrix http://glmatrix.net/docs/ -- WebGL - - Interfaces https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API - - Types https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Types - - Constants https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants + +- Update README.md to contain a solid description of your project +- Publish your project to gh-pages. `npm run deploy`. It should now be visible at http://username.github.io/repo-name +- Create a [pull request](https://help.github.com/articles/creating-a-pull-request/) to this repository, and in the comment, include a link to your published project. +- Submit the link to your pull request on Canvas. From 9774dc8bff188e52db0cfc58483dcc4c30e508d7 Mon Sep 17 00:00:00 2001 From: FridaWang <379788704@qq.com> Date: Tue, 20 Sep 2022 21:27:23 -0400 Subject: [PATCH 3/7] add background --- src/geometry/Square.ts | 8 +++--- src/main.ts | 20 ++++++++++---- src/shaders/bkg-frag.glsl | 53 +++++++++++++++++++++++++++++++++++++ src/shaders/bkg-vert.glsl | 54 ++++++++++++++++++++++++++++++++++++++ src/shaders/flat-frag.glsl | 13 --------- src/shaders/flat-vert.glsl | 12 --------- 6 files changed, 126 insertions(+), 34 deletions(-) create mode 100644 src/shaders/bkg-frag.glsl create mode 100644 src/shaders/bkg-vert.glsl delete mode 100644 src/shaders/flat-frag.glsl delete mode 100644 src/shaders/flat-vert.glsl diff --git a/src/geometry/Square.ts b/src/geometry/Square.ts index 1a21a10d..d20b053f 100644 --- a/src/geometry/Square.ts +++ b/src/geometry/Square.ts @@ -21,10 +21,10 @@ class Square extends Drawable { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0]); - this.positions = new Float32Array([-1, -1, 0, 1, - 1, -1, 0, 1, - 1, 1, 0, 1, - -1, 1, 0, 1]); + this.positions = new Float32Array([-30, -30, -10, 1, + 30, -30, -10, 1, + 30, 30, -10, 1, + -30, 30, -10, 1]); this.generateIdx(); this.generatePos(); diff --git a/src/main.ts b/src/main.ts index f8458cdd..904bf31e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,7 +14,7 @@ import Cube from './geometry/cube'; const controls = { tesselations: 5, 'Load Scene': loadScene, // A function pointer, essentially - color: [ 255, 255, 0, 255 ], // RGB with alpha + color: [ 242, 207, 33, 255 ], // RGB with alpha intensity: 2.2, freq: 2, }; @@ -22,7 +22,7 @@ const controls = { let icosphere: Icosphere; let square: Square; let prevTesselations: number = 5; -let preGeoColor: number[] = [255, 255, 0, 255]; +let preGeoColor: number[] = [ 242, 207, 33, 255 ]; let cube: Cube; let time: number = 0; let prevPerlinScale: number = 1.8; @@ -100,6 +100,11 @@ function main() { new Shader(gl.FRAGMENT_SHADER, require('./shaders/lambert-frag.glsl')), ]); + const bkg = new ShaderProgram([ + new Shader(gl.VERTEX_SHADER, require('./shaders/bkg-vert.glsl')), + new Shader(gl.FRAGMENT_SHADER, require('./shaders/bkg-frag.glsl')), + ]); + lambert.setTexture(0); // This function will be called every frame @@ -127,14 +132,19 @@ function main() { renderer.render(camera, lambert, [ icosphere, - // square, - // cube, ]); + + renderer.render(camera, bkg, [ + square, + ]); + stats.end(); // Tell the browser to call `tick` again whenever it renders a new frame requestAnimationFrame(tick); - lambert.setTime(++time); + bkg.setTime(++time); + + lambert.setTime(time); lambert.setResolution(vec2.fromValues(window.innerWidth, window.innerHeight)); lambert.setFreq(prevFreq); lambert.setPerlinScale(prevPerlinScale); diff --git a/src/shaders/bkg-frag.glsl b/src/shaders/bkg-frag.glsl new file mode 100644 index 00000000..967f9e43 --- /dev/null +++ b/src/shaders/bkg-frag.glsl @@ -0,0 +1,53 @@ +#version 300 es + +// This is a fragment shader. If you've opened this file first, please +// open and read lambert.vert.glsl before reading on. +// Unlike the vertex shader, the fragment shader actually does compute +// the shading of geometry. For every pixel in your program's output +// screen, the fragment shader is run for every bit of geometry that +// particular pixel overlaps. By implicitly interpolating the position +// data passed into the fragment shader by the vertex shader, the fragment shader +// can compute what color to apply to its pixel based on things like vertex +// position, light position, and vertex color. +precision highp float; + +uniform vec4 u_Color; // The color with which to render this instance of geometry. +uniform float u_Time; + +// These are the interpolated values out of the rasterizer, so you can't know +// their specific values without knowing the vertices that contributed to them +in vec4 fs_Pos; +in vec4 fs_Nor; +in vec4 fs_LightVec; +in vec4 fs_Col; + +out vec4 out_Col; // This is the final output color that you will see on your + // screen for the pixel that is currently being processed. + +void main() +{ + // Material base color (before shading) + vec3 center = vec3(0,0,-10); + vec3 tmpPos = fs_Pos.xyz; + float scale = 6.0; + float freq = 0.01; + tmpPos += sin(freq * u_Time) * scale * normalize(fs_Nor.xyz); + + float dis = length(vec3(tmpPos - center)); + + vec4 diffuseColor = vec4(max(0.0, u_Color.x - dis * 0.1), max(0.0, u_Color.y - dis * 0.1), max(0.0, u_Color.z - dis * 0.1), 1.0); + + // Calculate the diffuse term for Lambert shading + float diffuseTerm = dot(normalize(fs_Nor), normalize(fs_LightVec)); + // Avoid negative lighting values + // diffuseTerm = clamp(diffuseTerm, 0, 1); + + float ambientTerm = 0.2; + + float lightIntensity = diffuseTerm + ambientTerm; //Add a small float value to the color multiplier + //to simulate ambient lighting. This ensures that faces that are not + //lit by our point light are not completely black. + + // Compute final shaded color + out_Col = vec4(diffuseColor.rgb * lightIntensity, diffuseColor.a); +} \ No newline at end of file diff --git a/src/shaders/bkg-vert.glsl b/src/shaders/bkg-vert.glsl new file mode 100644 index 00000000..c7242050 --- /dev/null +++ b/src/shaders/bkg-vert.glsl @@ -0,0 +1,54 @@ +#version 300 es + +//This is a vertex shader. While it is called a "shader" due to outdated conventions, this file +//is used to apply matrix transformations to the arrays of vertex data passed to it. +//Since this code is run on your GPU, each vertex is transformed simultaneously. +//If it were run on your CPU, each vertex would have to be processed in a FOR loop, one at a time. +//This simultaneous transformation allows your program to run much faster, especially when rendering +//geometry with millions of vertices. + +uniform mat4 u_Model; // The matrix that defines the transformation of the + // object we're rendering. In this assignment, + // this will be the result of traversing your scene graph. + +uniform mat4 u_ModelInvTr; // The inverse transpose of the model matrix. + // This allows us to transform the object's normals properly + // if the object has been non-uniformly scaled. + +uniform mat4 u_ViewProj; // The matrix that defines the camera's transformation. + // We've written a static matrix for you to use for HW2, + // but in HW3 you'll have to generate one yourself + +in vec4 vs_Pos; // The array of vertex positions passed to the shader + +in vec4 vs_Nor; // The array of vertex normals passed to the shader + +in vec4 vs_Col; // The array of vertex colors passed to the shader. + +out vec4 fs_Pos; +out vec4 fs_Nor; // The array of normals that has been transformed by u_ModelInvTr. This is implicitly passed to the fragment shader. +out vec4 fs_LightVec; // The direction in which our virtual light lies, relative to each vertex. This is implicitly passed to the fragment shader. +out vec4 fs_Col; // The color of each vertex. This is implicitly passed to the fragment shader. + +const vec4 lightPos = vec4(5, 5, 3, 1); //The position of our virtual light, which is used to compute the shading of + //the geometry in the fragment shader. + +void main() +{ + fs_Col = vs_Col; // Pass the vertex colors to the fragment shader for interpolation + + mat3 invTranspose = mat3(u_ModelInvTr); + fs_Nor = vec4(invTranspose * vec3(vs_Nor), 0); // Pass the vertex normals to the fragment shader for interpolation. + // Transform the geometry's normals by the inverse transpose of the + // model matrix. This is necessary to ensure the normals remain + // perpendicular to the surface after the surface is transformed by + // the model matrix. + + + vec4 modelposition = u_Model * vs_Pos; // Temporarily store the transformed vertex positions for use below + fs_Pos = modelposition; + fs_LightVec = lightPos - modelposition; // Compute the direction in which the light source lies + + gl_Position = u_ViewProj * modelposition;// gl_Position is a built-in variable of OpenGL which is + // used to render the final positions of the geometry's vertices +} \ No newline at end of file diff --git a/src/shaders/flat-frag.glsl b/src/shaders/flat-frag.glsl deleted file mode 100644 index 50434bd8..00000000 --- a/src/shaders/flat-frag.glsl +++ /dev/null @@ -1,13 +0,0 @@ -#version 300 es -precision highp float; - -uniform vec3 u_Eye, u_Ref, u_Up; -uniform vec2 u_Dimensions; -uniform float u_Time; - -in vec2 fs_Pos; -out vec4 out_Col; - -void main() { - out_Col = vec4(0.5 * (fs_Pos + vec2(1.0)), 0.5 * (sin(u_Time * 3.14159 * 0.01) + 1.0), 1.0); -} diff --git a/src/shaders/flat-vert.glsl b/src/shaders/flat-vert.glsl deleted file mode 100644 index 7d913da8..00000000 --- a/src/shaders/flat-vert.glsl +++ /dev/null @@ -1,12 +0,0 @@ -#version 300 es -precision highp float; - -// The vertex shader used to render the background of the scene - -in vec4 vs_Pos; -out vec2 fs_Pos; - -void main() { - fs_Pos = vs_Pos.xy; - gl_Position = vs_Pos; -} From c59e95c3e46cc9087689ea5e3ac43fc0e9ec9ca6 Mon Sep 17 00:00:00 2001 From: FridaWang <379788704@qq.com> Date: Tue, 20 Sep 2022 22:34:22 -0400 Subject: [PATCH 4/7] tiny --- src/main.ts | 4 ++-- src/shaders/bkg-frag.glsl | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main.ts b/src/main.ts index 904bf31e..00420fcb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,7 +14,7 @@ import Cube from './geometry/cube'; const controls = { tesselations: 5, 'Load Scene': loadScene, // A function pointer, essentially - color: [ 242, 207, 33, 255 ], // RGB with alpha + color: [ 242, 206, 33, 255 ], // RGB with alpha intensity: 2.2, freq: 2, }; @@ -22,7 +22,7 @@ const controls = { let icosphere: Icosphere; let square: Square; let prevTesselations: number = 5; -let preGeoColor: number[] = [ 242, 207, 33, 255 ]; +let preGeoColor: number[] = [ 242, 206, 33, 255 ]; let cube: Cube; let time: number = 0; let prevPerlinScale: number = 1.8; diff --git a/src/shaders/bkg-frag.glsl b/src/shaders/bkg-frag.glsl index 967f9e43..63c1a148 100644 --- a/src/shaders/bkg-frag.glsl +++ b/src/shaders/bkg-frag.glsl @@ -24,6 +24,21 @@ in vec4 fs_Col; out vec4 out_Col; // This is the final output color that you will see on your // screen for the pixel that is currently being processed. +float GetBias(float time, float bias) +{ + return (time / ((((1.0/bias) - 2.0)*(1.0 - time))+1.0)); +} + +float GetGain(float time, float gain) +{ + if(time < 0.5) { + return GetBias(time * 2.0,gain)/2.0; + } + else { + return GetBias(time * 2.0 - 1.0,1.0 - gain)/2.0 + 0.5; + } +} + void main() { // Material base color (before shading) @@ -31,7 +46,7 @@ void main() vec3 tmpPos = fs_Pos.xyz; float scale = 6.0; float freq = 0.01; - tmpPos += sin(freq * u_Time) * scale * normalize(fs_Nor.xyz); + tmpPos += GetGain(abs(sin(freq * u_Time)), 0.3) * scale * normalize(fs_Nor.xyz); float dis = length(vec3(tmpPos - center)); From 0d7715b1a79742479def1f68a369daa06c770555 Mon Sep 17 00:00:00 2001 From: Wenqing Wang <33616958+FridaWang@users.noreply.github.com> Date: Wed, 21 Sep 2022 00:18:48 -0400 Subject: [PATCH 5/7] Update README.md --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 1a7646c7..5b3a5d33 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,20 @@ # [Project 1: Noise](https://github.com/CIS-566-Fall-2022/hw01-fireball-base) +## Fireball +### Live Demo +Link: https://fridawang.github.io/hw01-fireball-base/ + +Interactive parameters: +* Background gradient base color +* Noise intensity +* Rotation speed + + +![fireball](https://user-images.githubusercontent.com/33616958/191404734-28cf103c-81a8-4421-af37-b4ebcbc5f6af.gif) + +![fireball-2](https://user-images.githubusercontent.com/33616958/191409128-8a8e9d32-e97c-42f8-877c-736c914b1b42.gif) + + ## Objective Get comfortable with using WebGL and its shaders to generate an interesting 3D, continuous surface using a multi-octave noise algorithm. From b9833c9028bdbea3131cb5ca2654371f82ffb1cf Mon Sep 17 00:00:00 2001 From: FridaWang <379788704@qq.com> Date: Wed, 21 Sep 2022 00:20:28 -0400 Subject: [PATCH 6/7] tiny fix --- src/main.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.ts b/src/main.ts index 00420fcb..95389b08 100644 --- a/src/main.ts +++ b/src/main.ts @@ -16,7 +16,7 @@ const controls = { 'Load Scene': loadScene, // A function pointer, essentially color: [ 242, 206, 33, 255 ], // RGB with alpha intensity: 2.2, - freq: 2, + speed: 2, }; let icosphere: Icosphere; @@ -52,7 +52,7 @@ function main() { gui.add(controls, 'Load Scene'); gui.addColor(controls, 'color'); gui.add(controls, 'intensity', 1, 10).step(0.2); - gui.add(controls, 'freq', 1, 10).step(1); + gui.add(controls, 'speed', 1, 10).step(1); // get canvas and webgl context const canvas = document.getElementById('canvas'); @@ -123,8 +123,8 @@ function main() { preGeoColor = controls.color; renderer.setGeoColor(preGeoColor[0], preGeoColor[1], preGeoColor[2], preGeoColor[3]); } - if (controls.freq != prevFreq) { - prevFreq = controls.freq; + if (controls.speed != prevFreq) { + prevFreq = controls.speed; } if (controls.intensity != prevPerlinScale) { prevPerlinScale = controls.intensity; From 2ed52d5ba49e231c06005703645bf2af3e9e6add Mon Sep 17 00:00:00 2001 From: Wenqing Wang <33616958+FridaWang@users.noreply.github.com> Date: Wed, 21 Sep 2022 20:49:27 -0400 Subject: [PATCH 7/7] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b3a5d33..58257c61 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,17 @@ ### Live Demo Link: https://fridawang.github.io/hw01-fireball-base/ -Interactive parameters: +### Interactive parameters: * Background gradient base color * Noise intensity * Rotation speed +### Main features: +* Use a combination of `perlinNoise3D()` and `cnosie()` to calculate the vectex offset on the sphere. +* Uses `vs_Pos` plus `u_Time` as parameters for noise generation. +* The radius of the circle in the background is determined by the distance between the pixel and centroid, which varies over time. `bias()` and `gain()` are used so that the radius does not change at a uniform rate. +### Results preview: ![fireball](https://user-images.githubusercontent.com/33616958/191404734-28cf103c-81a8-4421-af37-b4ebcbc5f6af.gif) ![fireball-2](https://user-images.githubusercontent.com/33616958/191409128-8a8e9d32-e97c-42f8-877c-736c914b1b42.gif)