diff --git a/.gitignore b/.gitignore
index fdea720..cfbaeaa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,8 @@ build/Release
# Dependency directories
node_modules/
+# unless node_modules is in this directory
+!/public/node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
diff --git a/LICENSE b/LICENSE
index 5775dce..9d04efb 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,28 @@
-MIT License
+BSD 3-Clause License
-Copyright (c) 2023 David Walter Proctor
+Copyright (c) 2023, David 'Duppy' Proctor, Interface Arts
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
index 74a134e..676b367 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,37 @@
# does-it-glider
-Import a seed for Conway's Life from Discord (or others in the future) and see if it creates a glider.
-
-# Getting Started
-This project uses firebase cloud functions and database.
-
-1. Create a Firebase Project
-1. Add realtime database, firestore database, and (cloud) functions
-1. Example: https://console.firebase.google.com/project/does-it-glider/overview
-1. $ npm install -g firebase
-1. $ npm install -g firebase-tools (to get the CLI)
-1. $ cd Github project directory (Ex: ~/GitHub/does-it-glider)
-1. $ firebase login (will open a browser window for Auth)
-1. $ firebase init
- 1. I selected 'y' to automatic deploys with GitHub
- 1. configured secrets at https://github.com/duppypro/does-it-glider/settings/secrets/actions
- 1. Created branch 'web-live' instead of default 'main'
- 1. ```Error: Cloud resource location is not set for this project but the operation you are attempting to perform in Cloud Storage requires it. Please see this documentation for more details: https://firebase.google.com/docs/projects/locations```
- 1. Fixed: Must configure Storage on https://console.firebase.google.com/project/does-it-glider/storage
- 1. now getting ```Error: Failed to get or create a stack using the given initialization details: FirebaseError: Unable to parse JSON: SyntaxError: Unexpected token '<', "Life
+
+ [Wordle Life Mojo](https://warofwordcraft.com/cgi-bin/wordle-life-mojo.cgi)
+
+## Open Source with attribution required
+
+### Copy liberally but please acknowledge where you got it.
+
+That's why I don't minify or uglify the source code.
+
+## Motivation
+
+I am making this as much for the fun of using it as for practicing 'good' or 'clean' coding practices. My first realization is that the definition of 'good' or 'clean' is subjective or at least depends on the goals.
+
+These are some example goals that can change the way the code is implemented:
+
+* **I just want to see the idea working and play with it.**
+ * hard code constants everywhere making fragile assumptions about screen size, memory size, speed, browser version
+ * no attempt at accessibility or internationalization friendly
+ * no instructions, attract mode, onboarding, or help
+ * goal is to get something you can play with quick
+* **I want my friends to use it on different devices and browsers.**
+ * spend some time abstracting the functions that are different across a decent size but incomplete set of targets
+ * replace some hard coded constants with values from a config file
+ * no automated repeatable tests, test manually
+* **Only one developer, maybe two.**
+ * conventions for variable naming and folder structure not documented (or even followed consistently)
+ * limited modularity
+* **Large dev team**
+ * add modularity, smaller files
+ * add an .env or config file for often used constants
+ * consider using a framework
+ * add automated tests so if your changes break other function, it is detected early
diff --git a/functions/index.js b/functions/index.js
index e81477f..ad9db93 100644
--- a/functions/index.js
+++ b/functions/index.js
@@ -13,7 +13,9 @@ const logger = require("firebase-functions/logger");
// Create and deploy your first functions
// https://firebase.google.com/docs/functions/get-started
-// exports.helloWorld = onRequest((request, response) => {
-// logger.info("Hello logs!", {structuredData: true});
-// response.send("Hello from Firebase!");
-// });
+exports.helloWorld = onRequest((request, response) => {
+ logger.info("Hello logs!", {structuredData: true});
+ // log the request body
+ logger.info(request.body, {structuredData: true});
+ response.send("Hello from Firebase!");
+});
diff --git a/functions/package-lock.json b/functions/package-lock.json
index 2cc3607..95657b3 100644
--- a/functions/package-lock.json
+++ b/functions/package-lock.json
@@ -8,7 +8,9 @@
"dependencies": {
"discord.js": "^14.13.0",
"firebase-admin": "^11.8.0",
- "firebase-functions": "^4.3.1"
+ "firebase-functions": "^4.5.0",
+ "gl-mat3": "^2.0.0",
+ "gl-matrix": "^3.4.3"
},
"devDependencies": {
"firebase-functions-test": "^3.1.0"
@@ -3123,9 +3125,9 @@
}
},
"node_modules/firebase-functions": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-4.4.1.tgz",
- "integrity": "sha512-3no53Lg12ToNlPSgLZtAFLQAz6si7ilHvzO8NC3/2EybyUwegpj5YhHwNiCw839lmAWp3znjATJDTvADFiZMrg==",
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-4.5.0.tgz",
+ "integrity": "sha512-y6HsasHtGLfXCp3Pfrz+JA19lO9hSzYiNxFDIDMffrfcsG7UbXzv0zfi2ASadMVRoDCaox5ppZBa1QJxZbctPQ==",
"dependencies": {
"@types/cors": "^2.8.5",
"@types/express": "4.17.3",
@@ -3298,6 +3300,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/gl-mat3": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/gl-mat3/-/gl-mat3-2.0.0.tgz",
+ "integrity": "sha512-/RfKyizhztkG+gH07lA0/OI9uXVEqDrvjza1U8kZc3Sjvn/iT1a99jyL1WtLzXMn/BYp0geE2/DsNp9GCXp28Q=="
+ },
+ "node_modules/gl-matrix": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
+ "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
+ },
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
diff --git a/functions/package.json b/functions/package.json
index b542abd..4bb32e4 100644
--- a/functions/package.json
+++ b/functions/package.json
@@ -15,7 +15,9 @@
"dependencies": {
"discord.js": "^14.13.0",
"firebase-admin": "^11.8.0",
- "firebase-functions": "^4.3.1"
+ "firebase-functions": "^4.5.0",
+ "gl-mat3": "^2.0.0",
+ "gl-matrix": "^3.4.3"
},
"devDependencies": {
"firebase-functions-test": "^3.1.0"
diff --git a/package-lock.json b/package-lock.json
index 46110e7..aa49182 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
"fast-deep-equal": "^3.1.3",
"firebase": "^10.5.2",
"firebase-tools": "^12.8.0",
+ "gl-matrix": "^3.4.3",
"lodash": "^4.17.21",
"lodash.snakecase": "^4.1.1",
"magic-bytes.js": "^1.5.0",
@@ -3525,6 +3526,11 @@
"assert-plus": "^1.0.0"
}
},
+ "node_modules/gl-matrix": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
+ "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
+ },
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
diff --git a/package.json b/package.json
index c7561f5..63e1080 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"fast-deep-equal": "^3.1.3",
"firebase": "^10.5.2",
"firebase-tools": "^12.8.0",
+ "gl-matrix": "^3.4.3",
"lodash": "^4.17.21",
"lodash.snakecase": "^4.1.1",
"magic-bytes.js": "^1.5.0",
diff --git a/public/css/does-it-glider.css b/public/css/does-it-glider.css
index 4e78580..f9085b2 100644
--- a/public/css/does-it-glider.css
+++ b/public/css/does-it-glider.css
@@ -1,12 +1,15 @@
-/* CSS for does-it-glider */
-
-.does-it-glider-app {
- /* width: 100%;
- height: 100vh; */
- /* z-index: 1; */
- /* pointer-events: none;
- user-select: none; */
- overflow: hidden;
+/*******************************************************************************
+ * (c) 2023, David 'Duppy' Proctor, Interface Arts
+ *
+ * does-it-glider
+ * css
+ *
+ ******************************************************************************/
+
+.does-it-glider-app
+{ /* this is the topmost parent element for the web app */
+ height: 100vh;
+ /* height: 100mvh; */
--green: #6aaa64;
--darkendGreen: #40a030;
--yellow: #c9b458;
@@ -16,6 +19,7 @@
--darkGray: #939598;
--white: #fff;
--black: #212121;
+ --vscode-blue: #026ec1;/* VSCode 'blue' = #026ec1; */
/* high contrast */
--orange: #f5793a;
--blue: #85c0f9;
@@ -27,10 +31,19 @@
touch-action: manipulation;
}
-.does-it-glider-app .paste-line,
-.does-it-glider-app .title {
+.touch-target
+{
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ text-align: center;
+}
+
+.paste-line,
+.title
+{
background-color: rgba(0, 0, 0, 0.4);
- /* pointer-events: none; */
user-select: none;
padding-top: 0.25em;
text-align: center;
@@ -38,24 +51,100 @@
width: 100%;
color: var(--darkendYellow);
font-weight: bold;
- /* -webkit-text-stroke-width: 1px; */
- /* -webkit-text-stroke-color: var(--black); */
}
-.does-it-glider-app .paste-line,
-.does-it-glider-app .sub-title {
+.paste-line,
+.sub-title
+{
font-size: 1em;
padding-bottom: 0.25em;
+ opacity: 60%;
}
-.does-it-glider-app .touch-target {
- z-index: 10;
-}
-
-.does-it-glider-app .paste-line {
+.paste-line
+{
color: var(--white);
min-height: 1em;
padding: 0;
text-align: left;
}
+@keyframes rainbow-color
+{
+ 0% {color: red;}
+ 14% {color: orange;}
+ 28% {color: yellow;}
+ 42% {color: lime;}
+ 57% {color: blue;}
+ 71% {color: indigo;}
+ 85% {color: violet;}
+ 100% {color: red;}
+}
+
+@keyframes rainbow-fill
+{
+ 0% {fill: red;}
+ 14% {fill: orange;}
+ 28% {fill: yellow;}
+ 42% {fill: lime;}
+ 57% {fill: blue;}
+ 71% {fill: indigo;}
+ 85% {fill: violet;}
+ 100% {fill: red;}
+}
+
+.cell,
+.cell.dead,
+.cell.β¬
+{ /* this is first in css so all cell common styles go here */
+ fill: transparent;
+}
+
+.pattern-line
+{
+ stroke: #666;
+ stroke-width: 1;
+}
+
+.pattern-background
+{
+ fill: #111;
+}
+
+.grid-fill
+{
+ fill: url(#grid-pattern);
+}
+
+.cell.live,
+.cell.β¬
+{
+ fill: var(--white);
+}
+
+.cell.red-team,
+.cell.π₯
+{
+ fill: red;
+ stroke: #333;
+ stroke-width: 1.5;
+}
+
+.cell.blue-team,
+.cell.π¦
+{
+ fill: blue;
+ stroke: #333;
+ stroke-width: 1.5;
+}
+
+.cell.β¬,
+.cell.glider
+{
+ animation: rainbow-fill 16ms linear infinite;
+}
+
+.arcade-attract-text
+{
+ animation: rainbow-color 16ms linear infinite;
+}
\ No newline at end of file
diff --git a/public/css/old-style.css b/public/css/old-style.css
deleted file mode 100644
index d5646ab..0000000
--- a/public/css/old-style.css
+++ /dev/null
@@ -1,174 +0,0 @@
-shtml {
- --green: #6aaa64;
- --darkendGreen: #40a030;
- --yellow: #c9b458;
- --darkendYellow: #ddaa11;
- --lightGray: #d8d8d8;
- --gray: #86888a;
- --darkGray: #939598;
- --white: #fff;
- --black: #212121;
- /* high contrast */
- --orange: #f5793a;
- --blue: #85c0f9;
- font-family: 'Clear Sans', 'Helvetica Neue', Arial, sans-serif;
- font-size: 18px;
- --header-height: 28px;
- --score-height: 80px;
- --keyboard-height: 152px;
- --game-max-width: 1280px;
-}
-
-/* too bright */
-html {
- --color-tone-1: #000000;
- --color-tone-2: #787c7e;
- --color-tone-3: #878a8c;
- --color-tone-4: #d3d6da;
- --color-tone-5: #edeff1;
- --color-tone-6: #f6f7f8;
- --color-tone-7: #ffffff;
- --color-nav-hover: #f4f4f4;
- --opacity-50: rgba(255, 255, 255, 0.5);
-}
-
-/* night mode */
-.nightmode {
- --color-tone-1: #ffffff;
- --color-tone-2: #818384;
- --color-tone-3: #565758;
- --color-tone-4: #3a3a3c;
- --color-tone-5: #272729;
- --color-tone-6: #1a1a1b;
- --color-tone-7: #121213;
- --color-nav-hover: #2f2f31;
- --opacity-50: rgba(0, 0, 0, 0.5);
-}
-
-/* Constant colors and colors derived from theme */
-html {
- --color-background: var(--color-tone-7);
- --color-present: var(--yellow);
- --color-correct: var(--green);
- --color-invalid: #941919;
- --color-absent: var(--color-tone-1);
- --tile-text-color: var(--color-tone-7);
- --key-text-color: var(--color-tone-1);
- --key-evaluated-text-color: var(--color-tone-7);
- --key-bg: var(--color-tone-3);
- --key-bg-present: var(--color-present);
- --key-bg-correct: var(--color-correct);
- --key-bg-absent: var(--color-absent);
- --modal-content-bg: var(--color-tone-7);
- /* try a fix I found */
- /* https://allthingssmitty.com/2020/05/11/css-fix-for-100vh-in-mobile-webkit/ */
- height: -webkit-fill-available;
- width: -webkit-fill-available;
-}
-
-.nightmode {
- --color-present: var(--darkendYellow);
- --color-correct: var(--darkendGreen);
- --color-invalid: #700000;
- --color-absent: var(--color-tone-5);
- --tile-text-color: var(--color-tone-1);
- --key-text-color: var(--color-tone-1);
- --key-evaluated-text-color: var(--color-tone-1);
- --key-bg: var(--color-tone-4);
- --key-bg-present: var(--color-present);
- --key-bg-correct: var(--color-correct);
- --key-bg-absent: var(--color-absent);
- --modal-content-bg: var(--color-tone-7);
-}
-
-.colorblind {
- --color-correct: var(--orange);
- --color-present: var(--blue);
- --tile-text-color: var(--white);
- --key-bg-present: var(--color-present);
- --key-bg-correct: var(--color-correct);
- --key-bg-absent: var(--color-absent);
-}
-
-body {
- min-height: 100vh;
- min-width: 100vw;
- /* mobile viewport bug fix */
- /* https://allthingssmitty.com/2020/05/11/css-fix-for-100vh-in-mobile-webkit/ */
- min-height: -webkit-fill-available;
- min-width: -webkit-fill-available;
- background-color: var(--color-background);
- margin: 0;
- padding: 0;
- /* Prevent scrollbar appearing on page transition */
- overflow: hidden;
- -moz-user-select: none;
- -webkit-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-
-.does-it-glide {
- max-width: var(--game-max-width);
- margin: 0 auto;
- display: flex;
- flex-direction: column;
-}
-
-header {
- width: 100%;
- max-width: var(--game-max-width);
- margin: 0 auto;
- height: var(--header-height);
- display: flex;
- color: var(--color-tone-1);
- border-bottom: 1px solid var(--color-tone-4);
-}
-
-header .title {
- margin: auto auto auto 4px;
- font-weight: bold;
- font-size: larger;
- line-height: 90%;
- text-align: bottom;
-}
-
-header .uid {
- margin: auto;
- font-family: 'Clear Sans', 'Helvetica Neue', Arial, sans-serif;
- font-weight: 200;
- font-size: normal;
- line-height: 90%;
- text-align: center;
-}
-
-.example {
- height: var(--score-height);
- width: calc(var(--game-max-width)-0);
- display: grid;
- grid-template-columns: repeat(5, 1fr);
- color: var(--color-tone-1);
- border-bottom: 1px solid var(--color-tone-4);
- padding: 4px;
-}
-
-.puzzle {
- position: absolute;
- display: grid;
- gap: 5px;
- padding: 0px 0px 10px 0px;
- box-sizing: border-box;
- color: var(--color-tone-1);
- width: calc(var(--game-max-width) * .75);
-}
-
-
-@media (max-width: 360px) {
- html {
- font-size: 15px;
- --header-height: 24px;
- --score-height: 68px;
- --keyboard-height: 120px;
- --game-max-width: 320px;
- }
-}
\ No newline at end of file
diff --git a/public/css/style.css b/public/css/style.css
deleted file mode 100644
index 23c601d..0000000
--- a/public/css/style.css
+++ /dev/null
@@ -1,25 +0,0 @@
-.title-bar {
- text-align: center;
- padding: 20px;
- background-color: #f8f8f8;
-}
-
-.title-bar h1 {
- margin: 0;
- font-size: 2em;
-}
-
-.title-bar svg {
- margin-top: 20px;
-}
-
-@media (max-width: 600px) {
- .title-bar h1 {
- font-size: 1.5em;
- }
-
- .title-bar svg {
- width: 30px;
- height: 30px;
- }
-}
\ No newline at end of file
diff --git a/public/css/wordum-challenge.css b/public/css/wordum-challenge.css
deleted file mode 100644
index 85a5f66..0000000
--- a/public/css/wordum-challenge.css
+++ /dev/null
@@ -1,412 +0,0 @@
- html {
- --green: #6aaa64;
- --darkendGreen: #40a030;
- --yellow: #c9b458;
- --darkendYellow: #ddaa11;
- --lightGray: #d8d8d8;
- --gray: #86888a;
- --darkGray: #939598;
- --white: #fff;
- --black: #212121;
- /* high contrast */
- --orange: #f5793a;
- --blue: #85c0f9;
- font-family: 'Clear Sans', 'Helvetica Neue', Arial, sans-serif;
- font-size: 18px;
- --header-height: 28px;
- --score-height: 80px;
- --keyboard-height: 152px;
- --game-max-width: 375px;
- }
-
- /* too bright */
- html {
- --color-tone-1: #000000;
- --color-tone-2: #787c7e;
- --color-tone-3: #878a8c;
- --color-tone-4: #d3d6da;
- --color-tone-5: #edeff1;
- --color-tone-6: #f6f7f8;
- --color-tone-7: #ffffff;
- --color-nav-hover: #f4f4f4;
- --opacity-50: rgba(255, 255, 255, 0.5);
- }
-
- /* night mode */
- .nightmode {
- --color-tone-1: #ffffff;
- --color-tone-2: #818384;
- --color-tone-3: #565758;
- --color-tone-4: #3a3a3c;
- --color-tone-5: #272729;
- --color-tone-6: #1a1a1b;
- --color-tone-7: #121213;
- --color-nav-hover: #2f2f31;
- --opacity-50: rgba(0, 0, 0, 0.5);
- }
-
- /* Constant colors and colors derived from theme */
- html,
- .nightmode {
- --color-background: var(--color-tone-7);
- }
-
- html {
- --color-present: var(--yellow);
- --color-correct: var(--green);
- --color-invalid: #941919;
- --color-absent: var(--color-tone-1);
- --tile-text-color: var(--color-tone-7);
- --key-text-color: var(--color-tone-1);
- --key-evaluated-text-color: var(--color-tone-7);
- --key-bg: var(--color-tone-3);
- --key-bg-present: var(--color-present);
- --key-bg-correct: var(--color-correct);
- --key-bg-absent: var(--color-absent);
- --modal-content-bg: var(--color-tone-7);
- }
-
- .nightmode {
- --color-present: var(--darkendYellow);
- --color-correct: var(--darkendGreen);
- --color-invalid: #700000;
- --color-absent: var(--color-tone-5);
- --tile-text-color: var(--color-tone-1);
- --key-text-color: var(--color-tone-1);
- --key-evaluated-text-color: var(--color-tone-1);
- --key-bg: var(--color-tone-4);
- --key-bg-present: var(--color-present);
- --key-bg-correct: var(--color-correct);
- --key-bg-absent: var(--color-absent);
- --modal-content-bg: var(--color-tone-7);
- }
-
- .colorblind {
- --color-correct: var(--orange);
- --color-present: var(--blue);
- --tile-text-color: var(--white);
- --key-bg-present: var(--color-present);
- --key-bg-correct: var(--color-correct);
- --key-bg-absent: var(--color-absent);
- }
-
- body {
- min-height: 100vh;
- min-width: 100vw;
- /* mobile viewport bug fix */
- /* https://allthingssmitty.com/2020/05/11/css-fix-for-100vh-in-mobile-webkit/ */
- min-height: -webkit-fill-available;
- min-width: -webkit-fill-available;
- }
-
- body {
- background-color: var(--color-background);
- margin: 0;
- padding: 0;
- /* Prevent scrollbar appearing on page transition */
- overflow: hidden;
- -moz-user-select: none;
- -webkit-user-select: none;
- -ms-user-select: none;
- user-select: none;
- }
-
- html {
- /* try a fix I found */
- /* https://allthingssmitty.com/2020/05/11/css-fix-for-100vh-in-mobile-webkit/ */
- height: -webkit-fill-available;
- width: -webkit-fill-available;
- }
-
- #challenge {
- max-width: var(--game-max-width);
- margin: 0 auto;
- display: flex;
- flex-direction: column;
- }
-
- header {
- width: 100%;
- max-width: var(--game-max-width);
- margin: 0 auto;
- height: var(--header-height);
- display: flex;
- color: var(--color-tone-1);
- border-bottom: 1px solid var(--color-tone-4);
- }
-
- header .title {
- margin: auto auto auto 4px;
- font-weight: bold;
- font-size: larger;
- line-height: 90%;
- text-align: bottom;
- }
-
- header .uid {
- margin: auto;
- font-family: 'Clear Sans', 'Helvetica Neue', Arial, sans-serif;
- font-weight: 200;
- font-size: normal;
- line-height: 90%;
- text-align: center;
- }
-
- #challenge-score {
- height: var(--score-height);
- width: calc(var(--game-max-width)-0);
- display: grid;
- grid-template-columns: repeat(5, 1fr);
- color: var(--color-tone-1);
- border-bottom: 1px solid var(--color-tone-4);
- padding: 4px;
- }
-
- .mini-puzzle {
- margin-left: 0px;
- display: grid;
- grid-template-rows: repeat(6, 1fr);
- gap: 4px;
- color: var(--color-tone-1);
- }
-
- .mini-row {
- display: grid;
- grid-template-columns: repeat(6, 1fr);
- gap: 2px;
- }
-
- .mini-tile {
- background-color: magenta;
- width: 10px;
- }
-
- .mini-tile[clue='tbd'] {
- background-color: var(--color-tone-3);
- }
-
- .mini-tile[clue='correct'] {
- background-color: var(--color-correct);
- }
-
- .mini-tile[clue='present'] {
- background-color: var(--color-present);
- }
-
- .mini-tile[clue='absent'] {
- background-color: var(--color-absent);
- }
-
- .mini-tile[clue='invalid'] {
- background-color: var(--color-invalid);
- }
-
- .mini-tile[clue='solution'] {
- background-color: transparent;
- }
-
- .mini-tile[clue='finished'] {
- background-color: transparent;
- }
-
- #challenge-puzzles {
- overflow: hidden;
- width: var(--game-max-width);
- height: calc(1rem + var(--game-max-width)*.75*6/5);
- color: var(--tile-text-color);
- position: relative;
- }
-
- .puzzle {
- position: absolute;
- display: grid;
- gap: 5px;
- padding: 0px 0px 10px 0px;
- box-sizing: border-box;
- color: var(--color-tone-1);
- width: calc(var(--game-max-width) * .75);
- }
-
- .puzzle .row {
- display: grid;
- grid-template-columns: repeat(5, 1fr);
- gap: 5px;
- }
-
- .puzzle .tile {
- width: 100%;
- display: inline-flex;
- justify-content: center;
- align-items: center;
- font-size: 2rem;
- line-height: 1.5rem;
- font-weight: bold;
- vertical-align: middle;
- box-sizing: border-box;
- color: var(--tile-text-color);
- text-transform: uppercase;
- }
-
- .puzzle .tile::before {
- content: '';
- padding-bottom: 100%;
- }
-
- .puzzle .tile[clue='tbd'] {
- background-color: var(--key-bg);
- border: 2px solid var(--color-tone-2);
- }
-
- .puzzle .tile[clue='correct'] {
- background-color: var(--color-correct);
- }
-
- .puzzle .tile[clue='present'] {
- background-color: var(--color-present);
- }
-
- .puzzle .tile[clue='absent'] {
- background-color: var(--color-absent);
- }
-
- .puzzle .tile[clue='invalid'] {
- background-color: var(--color-invalid);
- }
-
- .puzzle .tile[clue='finished'] {
- background-color:transparent;
- /* Hide the text. */
- color: transparent;
- }
-
- .puzzle .tile[clue='solution-reveal'] {
- background-color: transparent
- ;
- /* Hide the text. */
- color: transparent;
- }
-
- .puzzle .tile[clue='solution'] {
- width: 100%;
- display: inline-flex;
- justify-content: center;
- align-items: center;
- font-size: 2rem;
- line-height: 1.5rem;
- font-weight: bold;
- vertical-align: middle;
- box-sizing: border-box;
- background-color: var(--color-tone-1);
- color: #000000;
- text-transform: uppercase;
- }
-
- /* Finish and Share Screen */
-
- #challenge div.finish-and-share {
- color: var(--color-tone-1);
- background-color: var(--color-tone-4);
- }
-
- #challenge div.finish-and-share {
- color: var(--color-tone-1);
- background-color: var(--key-bg-correct);
- }
-
- #keyboard {
- display: grid;
- gap: 2px;
- }
-
- #keyboard .row {
- display: flex;
- width: 100%;
- gap: 2px;
- /* https://stackoverflow.com/questions/46167604/ios-html-disable-double-tap-to-zoom */
- touch-action: manipulation;
- }
-
- #keyboard button {
- font-size: 1.1rem;
- font-weight: bold;
- border: 1px solid;
- padding: 0;
- margin: 0;
- height: 52px;
- border-radius: 8px;
- background-color: var(--key-bg);
- color: var(--key-text-color);
- flex: 1;
- display: flex;
- justify-content: center;
- align-items: center;
- text-transform: uppercase;
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0.3);
- cursor: pointer;
- }
-
- #keyboard button:focus {
- outline: none;
- }
-
- #keyboard button.fade {
- transition: background-color 0.1s ease, color 0.1s ease;
- }
-
- #keyboard button:last-of-type {
- margin: 0;
- }
-
- #keyboard .half {
- flex: 0.5;
- }
-
- #keyboard .one {
- flex: 1;
- }
-
- #keyboard .one-and-a-half {
- flex: 1.5;
- font-size: 12px;
- }
-
- #keyboard .two {
- flex: 2;
- }
-
- #keyboard button[clue='tbd'] {
- background-color: var(--key-bg);
- color: var(--key-evaluated-text-color);
- }
-
- #keyboard button[clue='correct'] {
- background-color: var(--key-bg-correct);
- color: var(--key-evaluated-text-color);
- border: 0;
- }
-
- #keyboard button[clue='present'] {
- background-color: var(--key-bg-present);
- color: var(--key-evaluated-text-color);
- border: 0;
- }
-
- #keyboard button[clue='absent'] {
- background-color: var(--key-bg-absent);
- color: var(--key-evaluated-text-color);
- border: 0;
- }
-
- @media (max-width: 360px) {
- html {
- font-size: 15px;
- --header-height: 24px;
- --score-height: 68px;
- --keyboard-height: 120px;
- --game-max-width: 320px;
- }
-
- #keyboard button {
- height: 2rem;
- }
- }
diff --git a/public/index.html b/public/index.html
index 7596808..b4a41cd 100644
--- a/public/index.html
+++ b/public/index.html
@@ -6,12 +6,9 @@
-
-
-
-
+
-
-
+
+
diff --git a/public/lib/d3-helper.js b/public/lib/d3-helper.js
new file mode 100644
index 0000000..f4ca8e3
--- /dev/null
+++ b/public/lib/d3-helper.js
@@ -0,0 +1,177 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// d3-helper.js
+// (c) 2023, David 'Duppy' Proctor, Interface Arts
+//
+// d3-helper.js contains helper functions for d3
+//
+////////////////////////////////////////////////////////////////////////////////
+
+export const d3_plus = (() => {
+ d3.selection.prototype.mynew = function (selector, where) {
+ var match = selector.match(/^(\w+)(?:#([\w-]+))?(?:\.([\w-.]+))?$/);
+ if (!match) {
+ this.insert(selector, where);
+ // throw new Error('Invalid selector')
+ }
+
+ var tag = match[1];
+ var id = match[2];
+ var classes = match[3];
+
+ var selection = this.insert(tag, where);
+
+ if (id && id.trim()) {
+ selection.attr('id', id);
+ }
+
+ if (classes && classes.trim()) {
+ selection.attr('class', classes.replace(/\./g, ' '));
+ }
+
+ return selection;
+ };
+ // add a function called emmet to d3 selection that parses an emmet abbreviation string and calls d3.selection.append() or insert() as appropriate
+ // Here is the syntax for emmet abbreviations:
+ /*
+ Abbreviations Syntax
+ Emmet uses syntax similar to CSS selectors for describing elementsβ positions inside generated tree and elementsβ attributes.
+ ...
+ */
+ d3.selection.prototype.emmetBETA = function (selector, where) {
+ // Split the selector into individual parts
+ const parts = selector.split(/(?=[>+^])/);
+
+ // Initialize the current selection as the current d3 selection
+ let currentSelection = this;
+
+ // Loop through each part of the selector
+ for (let i = 0; i < parts.length; i++) {
+ const part = parts[i].trim();
+
+ // Check if the part is a child operator
+ if (part === '>') {
+ // Move to the next child level
+ currentSelection = currentSelection.append('div');
+ }
+
+ // Check if the part is a sibling operator
+ else if (part === '+') {
+ // Move to the next sibling level
+ currentSelection = currentSelection.insert('div', where);
+ }
+
+ // Check if the part is a climb-up operator
+ else if (part === '^') {
+ // Move to the parent level
+ currentSelection = currentSelection.node().parentNode;
+ }
+
+ // Check if the part is a multiplication operator
+ else if (part.includes('*')) {
+ // Split the part into element and count
+ const [element, count] = part.split('*');
+
+ // Get the number of repetitions
+ const repetitions = parseInt(count, 10);
+
+ // Repeat the element
+ for (let j = 0; j < repetitions; j++) {
+ currentSelection = currentSelection.append(element);
+ }
+ }
+
+ // Check if the part is a group
+ else if (part.includes('(') && part.includes(')')) {
+ // Extract the group content
+ const groupContent = part.substring(part.indexOf('(') + 1, part.lastIndexOf(')'));
+
+ // Parse the group content recursively
+ const groupSelection = d3.select(document.createElement('div')).emmet(groupContent);
+
+ // Append the group selection to the current selection
+ currentSelection = currentSelection.append(() => groupSelection.node().childNodes);
+ }
+
+ // Check if the part is an element with attributes
+ else if (part.includes('#') || part.includes('.')) {
+ // Split the part into element and attributes
+ const [element, attributes] = part.split(/(?=[.#])/);
+
+ // Extract the element name
+ const elementName = element.trim();
+
+ // Create the element with the specified attributes
+ const elementSelection = currentSelection.append(elementName);
+
+ // Parse and apply the attributes
+ attributes.split('.').forEach((attr) => {
+ if (attr.startsWith('#')) {
+ // Set the id attribute
+ const id = attr.substring(1);
+ elementSelection.attr('id', id);
+ } else {
+ // Set the class attribute
+ const className = attr.trim();
+ elementSelection.classed(className, true);
+ }
+ });
+
+ // Update the current selection
+ currentSelection = elementSelection;
+ }
+
+ // Check if the part is a text element
+ else if (part.startsWith('{') && part.endsWith('}')) {
+ // Extract the text content
+ const textContent = part.substring(1, part.length - 1);
+
+ // Append the text content to the current selection
+ currentSelection.append('text').text(textContent);
+ }
+
+ // Check if the part is a numbered element
+ else if (part.includes('$')) {
+ // Split the part into element and number
+ const [element, number] = part.split('$');
+
+ // Get the current number
+ const currentNumber = i + 1;
+
+ // Replace the number placeholder with the current number
+ const elementName = element.replace('$', currentNumber);
+
+ // Create the numbered element
+ const elementSelection = currentSelection.append(elementName);
+
+ // Update the current selection
+ currentSelection = elementSelection;
+ }
+
+ // Check if the part is a custom attribute
+ else if (part.includes('[') && part.includes(']')) {
+ // Extract the attribute content
+ const attributeContent = part.substring(part.indexOf('[') + 1, part.lastIndexOf(']'));
+
+ // Split the attribute content into individual attributes
+ const attributes = attributeContent.split(',');
+
+ // Loop through each attribute
+ attributes.forEach((attribute) => {
+ // Split the attribute into name and value
+ const [name, value] = attribute.split('=');
+
+ // Remove any surrounding quotes from the value
+ const trimmedValue = value ? value.replace(/['"]/g, '') : '';
+
+ // Set the attribute on the current selection
+ currentSelection.attr(name.trim(), trimmedValue);
+ });
+ }
+ }
+
+ return currentSelection;
+ };
+
+ return d3
+})() // end of add helpers to d3
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/LICENSE.md b/public/node_modules/gl-matrix/LICENSE.md
new file mode 100644
index 0000000..3a96fca
--- /dev/null
+++ b/public/node_modules/gl-matrix/LICENSE.md
@@ -0,0 +1,19 @@
+Copyright (c) 2015-2021, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/README.md b/public/node_modules/gl-matrix/README.md
new file mode 100644
index 0000000..a58a53f
--- /dev/null
+++ b/public/node_modules/gl-matrix/README.md
@@ -0,0 +1,33 @@
+glMatrix
+=======================
+[![NPM Version](https://img.shields.io/npm/v/gl-matrix.svg)](https://www.npmjs.com/package/gl-matrix)
+[![Build Status](https://travis-ci.org/toji/gl-matrix.svg)](https://travis-ci.org/toji/gl-matrix)
+
+Javascript has evolved into a language capable of handling realtime 3D graphics,
+via WebGL, and computationally intensive tasks such as physics simulations.
+These types of applications demand high performance vector and matrix math,
+which is something that Javascript doesn't provide by default.
+glMatrix to the rescue!
+
+glMatrix is designed to perform vector and matrix operations stupidly fast! By
+hand-tuning each function for maximum performance and encouraging efficient
+usage patterns through API conventions, glMatrix will help you get the most out
+of your browsers Javascript engine.
+
+Learn More
+----------------------
+For documentation and news, visit the [glMatrix Homepage](http://glmatrix.net/)
+
+For a tutorial, see [the "introducing glMatrix" section of _Introduction to Computer Graphics_ by David J. Eck](http://math.hws.edu/graphicsbook/c7/s1.html#webgl3d.1.2)
+
+For a babel plugin to make writing the API nicer, see [babel-plugin-transfrom-gl-matrix](https://github.com/akira-cn/babel-plugin-transform-gl-matrix)
+
+Regarding the current performance in modern web browsers, calling `glMatrix.setMatrixArrayType(Array)` to use normal arrays instead of Float32Arrays can greatly increase the performance.
+
+Contributing Guidelines
+----------------------
+See [CONTRIBUTING.md](./CONTRIBUTING.md)
+
+Building
+----------------------
+See [BUILDING.md](./BUILDING.md)
diff --git a/public/node_modules/gl-matrix/cjs/common.js b/public/node_modules/gl-matrix/cjs/common.js
new file mode 100644
index 0000000..fc38b2d
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/common.js
@@ -0,0 +1,67 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.setMatrixArrayType = setMatrixArrayType;
+exports.toRadian = toRadian;
+exports.equals = equals;
+exports.RANDOM = exports.ARRAY_TYPE = exports.EPSILON = void 0;
+
+/**
+ * Common utilities
+ * @module glMatrix
+ */
+// Configuration Constants
+var EPSILON = 0.000001;
+exports.EPSILON = EPSILON;
+var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
+exports.ARRAY_TYPE = ARRAY_TYPE;
+var RANDOM = Math.random;
+/**
+ * Sets the type of array used when creating new vectors and matrices
+ *
+ * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array
+ */
+
+exports.RANDOM = RANDOM;
+
+function setMatrixArrayType(type) {
+ exports.ARRAY_TYPE = ARRAY_TYPE = type;
+}
+
+var degree = Math.PI / 180;
+/**
+ * Convert Degree To Radian
+ *
+ * @param {Number} a Angle in Degrees
+ */
+
+function toRadian(a) {
+ return a * degree;
+}
+/**
+ * Tests whether or not the arguments have approximately the same value, within an absolute
+ * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less
+ * than or equal to 1.0, and a relative tolerance is used for larger values)
+ *
+ * @param {Number} a The first number to test.
+ * @param {Number} b The second number to test.
+ * @returns {Boolean} True if the numbers are approximately equal, false otherwise.
+ */
+
+
+function equals(a, b) {
+ return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));
+}
+
+if (!Math.hypot) Math.hypot = function () {
+ var y = 0,
+ i = arguments.length;
+
+ while (i--) {
+ y += arguments[i] * arguments[i];
+ }
+
+ return Math.sqrt(y);
+};
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/cjs/index.js b/public/node_modules/gl-matrix/cjs/index.js
new file mode 100644
index 0000000..bb06493
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/index.js
@@ -0,0 +1,52 @@
+"use strict";
+
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.vec4 = exports.vec3 = exports.vec2 = exports.quat2 = exports.quat = exports.mat4 = exports.mat3 = exports.mat2d = exports.mat2 = exports.glMatrix = void 0;
+
+var glMatrix = _interopRequireWildcard(require("./common.js"));
+
+exports.glMatrix = glMatrix;
+
+var mat2 = _interopRequireWildcard(require("./mat2.js"));
+
+exports.mat2 = mat2;
+
+var mat2d = _interopRequireWildcard(require("./mat2d.js"));
+
+exports.mat2d = mat2d;
+
+var mat3 = _interopRequireWildcard(require("./mat3.js"));
+
+exports.mat3 = mat3;
+
+var mat4 = _interopRequireWildcard(require("./mat4.js"));
+
+exports.mat4 = mat4;
+
+var quat = _interopRequireWildcard(require("./quat.js"));
+
+exports.quat = quat;
+
+var quat2 = _interopRequireWildcard(require("./quat2.js"));
+
+exports.quat2 = quat2;
+
+var vec2 = _interopRequireWildcard(require("./vec2.js"));
+
+exports.vec2 = vec2;
+
+var vec3 = _interopRequireWildcard(require("./vec3.js"));
+
+exports.vec3 = vec3;
+
+var vec4 = _interopRequireWildcard(require("./vec4.js"));
+
+exports.vec4 = vec4;
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/cjs/mat2.js b/public/node_modules/gl-matrix/cjs/mat2.js
new file mode 100644
index 0000000..b8b2b30
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/mat2.js
@@ -0,0 +1,495 @@
+"use strict";
+
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.create = create;
+exports.clone = clone;
+exports.copy = copy;
+exports.identity = identity;
+exports.fromValues = fromValues;
+exports.set = set;
+exports.transpose = transpose;
+exports.invert = invert;
+exports.adjoint = adjoint;
+exports.determinant = determinant;
+exports.multiply = multiply;
+exports.rotate = rotate;
+exports.scale = scale;
+exports.fromRotation = fromRotation;
+exports.fromScaling = fromScaling;
+exports.str = str;
+exports.frob = frob;
+exports.LDU = LDU;
+exports.add = add;
+exports.subtract = subtract;
+exports.exactEquals = exactEquals;
+exports.equals = equals;
+exports.multiplyScalar = multiplyScalar;
+exports.multiplyScalarAndAdd = multiplyScalarAndAdd;
+exports.sub = exports.mul = void 0;
+
+var glMatrix = _interopRequireWildcard(require("./common.js"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+/**
+ * 2x2 Matrix
+ * @module mat2
+ */
+
+/**
+ * Creates a new identity mat2
+ *
+ * @returns {mat2} a new 2x2 matrix
+ */
+function create() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ }
+
+ out[0] = 1;
+ out[3] = 1;
+ return out;
+}
+/**
+ * Creates a new mat2 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat2} a matrix to clone
+ * @returns {mat2} a new 2x2 matrix
+ */
+
+
+function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Copy the values from one mat2 to another
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+
+function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Set a mat2 to the identity matrix
+ *
+ * @param {mat2} out the receiving matrix
+ * @returns {mat2} out
+ */
+
+
+function identity(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+}
+/**
+ * Create a new mat2 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m10 Component in column 1, row 0 position (index 2)
+ * @param {Number} m11 Component in column 1, row 1 position (index 3)
+ * @returns {mat2} out A new 2x2 matrix
+ */
+
+
+function fromValues(m00, m01, m10, m11) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m10;
+ out[3] = m11;
+ return out;
+}
+/**
+ * Set the components of a mat2 to the given values
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m10 Component in column 1, row 0 position (index 2)
+ * @param {Number} m11 Component in column 1, row 1 position (index 3)
+ * @returns {mat2} out
+ */
+
+
+function set(out, m00, m01, m10, m11) {
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m10;
+ out[3] = m11;
+ return out;
+}
+/**
+ * Transpose the values of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+
+function transpose(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache
+ // some values
+ if (out === a) {
+ var a1 = a[1];
+ out[1] = a[2];
+ out[2] = a1;
+ } else {
+ out[0] = a[0];
+ out[1] = a[2];
+ out[2] = a[1];
+ out[3] = a[3];
+ }
+
+ return out;
+}
+/**
+ * Inverts a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+
+function invert(out, a) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3]; // Calculate the determinant
+
+ var det = a0 * a3 - a2 * a1;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = a3 * det;
+ out[1] = -a1 * det;
+ out[2] = -a2 * det;
+ out[3] = a0 * det;
+ return out;
+}
+/**
+ * Calculates the adjugate of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+
+function adjoint(out, a) {
+ // Caching this value is nessecary if out == a
+ var a0 = a[0];
+ out[0] = a[3];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a0;
+ return out;
+}
+/**
+ * Calculates the determinant of a mat2
+ *
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+
+function determinant(a) {
+ return a[0] * a[3] - a[2] * a[1];
+}
+/**
+ * Multiplies two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+
+
+function multiply(out, a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ out[0] = a0 * b0 + a2 * b1;
+ out[1] = a1 * b0 + a3 * b1;
+ out[2] = a0 * b2 + a2 * b3;
+ out[3] = a1 * b2 + a3 * b3;
+ return out;
+}
+/**
+ * Rotates a mat2 by the given angle
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+
+
+function rotate(out, a, rad) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ out[0] = a0 * c + a2 * s;
+ out[1] = a1 * c + a3 * s;
+ out[2] = a0 * -s + a2 * c;
+ out[3] = a1 * -s + a3 * c;
+ return out;
+}
+/**
+ * Scales the mat2 by the dimensions in the given vec2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to rotate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat2} out
+ **/
+
+
+function scale(out, a, v) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var v0 = v[0],
+ v1 = v[1];
+ out[0] = a0 * v0;
+ out[1] = a1 * v0;
+ out[2] = a2 * v1;
+ out[3] = a3 * v1;
+ return out;
+}
+/**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.rotate(dest, dest, rad);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+
+
+function fromRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = -s;
+ out[3] = c;
+ return out;
+}
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.scale(dest, dest, vec);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat2} out
+ */
+
+
+function fromScaling(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = v[1];
+ return out;
+}
+/**
+ * Returns a string representation of a mat2
+ *
+ * @param {ReadonlyMat2} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+
+function str(a) {
+ return "mat2(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")";
+}
+/**
+ * Returns Frobenius norm of a mat2
+ *
+ * @param {ReadonlyMat2} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+
+function frob(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3]);
+}
+/**
+ * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
+ * @param {ReadonlyMat2} L the lower triangular matrix
+ * @param {ReadonlyMat2} D the diagonal matrix
+ * @param {ReadonlyMat2} U the upper triangular matrix
+ * @param {ReadonlyMat2} a the input matrix to factorize
+ */
+
+
+function LDU(L, D, U, a) {
+ L[2] = a[2] / a[0];
+ U[0] = a[0];
+ U[1] = a[1];
+ U[3] = a[3] - L[2] * U[1];
+ return [L, D, U];
+}
+/**
+ * Adds two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+
+
+function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ return out;
+}
+/**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+
+
+function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ return out;
+}
+/**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat2} a The first matrix.
+ * @param {ReadonlyMat2} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+
+function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
+}
+/**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat2} a The first matrix.
+ * @param {ReadonlyMat2} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+
+function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3));
+}
+/**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat2} out
+ */
+
+
+function multiplyScalar(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ return out;
+}
+/**
+ * Adds two mat2's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat2} out the receiving vector
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat2} out
+ */
+
+
+function multiplyScalarAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ return out;
+}
+/**
+ * Alias for {@link mat2.multiply}
+ * @function
+ */
+
+
+var mul = multiply;
+/**
+ * Alias for {@link mat2.subtract}
+ * @function
+ */
+
+exports.mul = mul;
+var sub = subtract;
+exports.sub = sub;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/cjs/mat2d.js b/public/node_modules/gl-matrix/cjs/mat2d.js
new file mode 100644
index 0000000..249caa5
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/mat2d.js
@@ -0,0 +1,547 @@
+"use strict";
+
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.create = create;
+exports.clone = clone;
+exports.copy = copy;
+exports.identity = identity;
+exports.fromValues = fromValues;
+exports.set = set;
+exports.invert = invert;
+exports.determinant = determinant;
+exports.multiply = multiply;
+exports.rotate = rotate;
+exports.scale = scale;
+exports.translate = translate;
+exports.fromRotation = fromRotation;
+exports.fromScaling = fromScaling;
+exports.fromTranslation = fromTranslation;
+exports.str = str;
+exports.frob = frob;
+exports.add = add;
+exports.subtract = subtract;
+exports.multiplyScalar = multiplyScalar;
+exports.multiplyScalarAndAdd = multiplyScalarAndAdd;
+exports.exactEquals = exactEquals;
+exports.equals = equals;
+exports.sub = exports.mul = void 0;
+
+var glMatrix = _interopRequireWildcard(require("./common.js"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+/**
+ * 2x3 Matrix
+ * @module mat2d
+ * @description
+ * A mat2d contains six elements defined as:
+ *
+ * [a, b,
+ * c, d,
+ * tx, ty]
+ *
+ * This is a short form for the 3x3 matrix:
+ *
+ * [a, b, 0,
+ * c, d, 0,
+ * tx, ty, 1]
+ *
+ * The last column is ignored so the array is shorter and operations are faster.
+ */
+
+/**
+ * Creates a new identity mat2d
+ *
+ * @returns {mat2d} a new 2x3 matrix
+ */
+function create() {
+ var out = new glMatrix.ARRAY_TYPE(6);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ out[4] = 0;
+ out[5] = 0;
+ }
+
+ out[0] = 1;
+ out[3] = 1;
+ return out;
+}
+/**
+ * Creates a new mat2d initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat2d} a matrix to clone
+ * @returns {mat2d} a new 2x3 matrix
+ */
+
+
+function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(6);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ return out;
+}
+/**
+ * Copy the values from one mat2d to another
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+
+
+function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ return out;
+}
+/**
+ * Set a mat2d to the identity matrix
+ *
+ * @param {mat2d} out the receiving matrix
+ * @returns {mat2d} out
+ */
+
+
+function identity(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+}
+/**
+ * Create a new mat2d with the given values
+ *
+ * @param {Number} a Component A (index 0)
+ * @param {Number} b Component B (index 1)
+ * @param {Number} c Component C (index 2)
+ * @param {Number} d Component D (index 3)
+ * @param {Number} tx Component TX (index 4)
+ * @param {Number} ty Component TY (index 5)
+ * @returns {mat2d} A new mat2d
+ */
+
+
+function fromValues(a, b, c, d, tx, ty) {
+ var out = new glMatrix.ARRAY_TYPE(6);
+ out[0] = a;
+ out[1] = b;
+ out[2] = c;
+ out[3] = d;
+ out[4] = tx;
+ out[5] = ty;
+ return out;
+}
+/**
+ * Set the components of a mat2d to the given values
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {Number} a Component A (index 0)
+ * @param {Number} b Component B (index 1)
+ * @param {Number} c Component C (index 2)
+ * @param {Number} d Component D (index 3)
+ * @param {Number} tx Component TX (index 4)
+ * @param {Number} ty Component TY (index 5)
+ * @returns {mat2d} out
+ */
+
+
+function set(out, a, b, c, d, tx, ty) {
+ out[0] = a;
+ out[1] = b;
+ out[2] = c;
+ out[3] = d;
+ out[4] = tx;
+ out[5] = ty;
+ return out;
+}
+/**
+ * Inverts a mat2d
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+
+
+function invert(out, a) {
+ var aa = a[0],
+ ab = a[1],
+ ac = a[2],
+ ad = a[3];
+ var atx = a[4],
+ aty = a[5];
+ var det = aa * ad - ab * ac;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = ad * det;
+ out[1] = -ab * det;
+ out[2] = -ac * det;
+ out[3] = aa * det;
+ out[4] = (ac * aty - ad * atx) * det;
+ out[5] = (ab * atx - aa * aty) * det;
+ return out;
+}
+/**
+ * Calculates the determinant of a mat2d
+ *
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+
+function determinant(a) {
+ return a[0] * a[3] - a[1] * a[2];
+}
+/**
+ * Multiplies two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+
+
+function multiply(out, a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5];
+ out[0] = a0 * b0 + a2 * b1;
+ out[1] = a1 * b0 + a3 * b1;
+ out[2] = a0 * b2 + a2 * b3;
+ out[3] = a1 * b2 + a3 * b3;
+ out[4] = a0 * b4 + a2 * b5 + a4;
+ out[5] = a1 * b4 + a3 * b5 + a5;
+ return out;
+}
+/**
+ * Rotates a mat2d by the given angle
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+
+
+function rotate(out, a, rad) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ out[0] = a0 * c + a2 * s;
+ out[1] = a1 * c + a3 * s;
+ out[2] = a0 * -s + a2 * c;
+ out[3] = a1 * -s + a3 * c;
+ out[4] = a4;
+ out[5] = a5;
+ return out;
+}
+/**
+ * Scales the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to translate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat2d} out
+ **/
+
+
+function scale(out, a, v) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var v0 = v[0],
+ v1 = v[1];
+ out[0] = a0 * v0;
+ out[1] = a1 * v0;
+ out[2] = a2 * v1;
+ out[3] = a3 * v1;
+ out[4] = a4;
+ out[5] = a5;
+ return out;
+}
+/**
+ * Translates the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to translate
+ * @param {ReadonlyVec2} v the vec2 to translate the matrix by
+ * @returns {mat2d} out
+ **/
+
+
+function translate(out, a, v) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var v0 = v[0],
+ v1 = v[1];
+ out[0] = a0;
+ out[1] = a1;
+ out[2] = a2;
+ out[3] = a3;
+ out[4] = a0 * v0 + a2 * v1 + a4;
+ out[5] = a1 * v0 + a3 * v1 + a5;
+ return out;
+}
+/**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.rotate(dest, dest, rad);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+
+
+function fromRotation(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = -s;
+ out[3] = c;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+}
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.scale(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat2d} out
+ */
+
+
+function fromScaling(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = v[1];
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+}
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.translate(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {ReadonlyVec2} v Translation vector
+ * @returns {mat2d} out
+ */
+
+
+function fromTranslation(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = v[0];
+ out[5] = v[1];
+ return out;
+}
+/**
+ * Returns a string representation of a mat2d
+ *
+ * @param {ReadonlyMat2d} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+
+function str(a) {
+ return "mat2d(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ")";
+}
+/**
+ * Returns Frobenius norm of a mat2d
+ *
+ * @param {ReadonlyMat2d} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+
+function frob(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], 1);
+}
+/**
+ * Adds two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+
+
+function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ return out;
+}
+/**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+
+
+function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ out[4] = a[4] - b[4];
+ out[5] = a[5] - b[5];
+ return out;
+}
+/**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat2d} out
+ */
+
+
+function multiplyScalar(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ return out;
+}
+/**
+ * Adds two mat2d's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat2d} out the receiving vector
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat2d} out
+ */
+
+
+function multiplyScalarAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ out[4] = a[4] + b[4] * scale;
+ out[5] = a[5] + b[5] * scale;
+ return out;
+}
+/**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat2d} a The first matrix.
+ * @param {ReadonlyMat2d} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+
+function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5];
+}
+/**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat2d} a The first matrix.
+ * @param {ReadonlyMat2d} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+
+function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5));
+}
+/**
+ * Alias for {@link mat2d.multiply}
+ * @function
+ */
+
+
+var mul = multiply;
+/**
+ * Alias for {@link mat2d.subtract}
+ * @function
+ */
+
+exports.mul = mul;
+var sub = subtract;
+exports.sub = sub;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/cjs/mat3.js b/public/node_modules/gl-matrix/cjs/mat3.js
new file mode 100644
index 0000000..afb6247
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/mat3.js
@@ -0,0 +1,853 @@
+"use strict";
+
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.create = create;
+exports.fromMat4 = fromMat4;
+exports.clone = clone;
+exports.copy = copy;
+exports.fromValues = fromValues;
+exports.set = set;
+exports.identity = identity;
+exports.transpose = transpose;
+exports.invert = invert;
+exports.adjoint = adjoint;
+exports.determinant = determinant;
+exports.multiply = multiply;
+exports.translate = translate;
+exports.rotate = rotate;
+exports.scale = scale;
+exports.fromTranslation = fromTranslation;
+exports.fromRotation = fromRotation;
+exports.fromScaling = fromScaling;
+exports.fromMat2d = fromMat2d;
+exports.fromQuat = fromQuat;
+exports.normalFromMat4 = normalFromMat4;
+exports.projection = projection;
+exports.str = str;
+exports.frob = frob;
+exports.add = add;
+exports.subtract = subtract;
+exports.multiplyScalar = multiplyScalar;
+exports.multiplyScalarAndAdd = multiplyScalarAndAdd;
+exports.exactEquals = exactEquals;
+exports.equals = equals;
+exports.sub = exports.mul = void 0;
+
+var glMatrix = _interopRequireWildcard(require("./common.js"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+/**
+ * 3x3 Matrix
+ * @module mat3
+ */
+
+/**
+ * Creates a new identity mat3
+ *
+ * @returns {mat3} a new 3x3 matrix
+ */
+function create() {
+ var out = new glMatrix.ARRAY_TYPE(9);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ }
+
+ out[0] = 1;
+ out[4] = 1;
+ out[8] = 1;
+ return out;
+}
+/**
+ * Copies the upper-left 3x3 values into the given mat3.
+ *
+ * @param {mat3} out the receiving 3x3 matrix
+ * @param {ReadonlyMat4} a the source 4x4 matrix
+ * @returns {mat3} out
+ */
+
+
+function fromMat4(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[4];
+ out[4] = a[5];
+ out[5] = a[6];
+ out[6] = a[8];
+ out[7] = a[9];
+ out[8] = a[10];
+ return out;
+}
+/**
+ * Creates a new mat3 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat3} a matrix to clone
+ * @returns {mat3} a new 3x3 matrix
+ */
+
+
+function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(9);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+}
+/**
+ * Copy the values from one mat3 to another
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+
+function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+}
+/**
+ * Create a new mat3 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m10 Component in column 1, row 0 position (index 3)
+ * @param {Number} m11 Component in column 1, row 1 position (index 4)
+ * @param {Number} m12 Component in column 1, row 2 position (index 5)
+ * @param {Number} m20 Component in column 2, row 0 position (index 6)
+ * @param {Number} m21 Component in column 2, row 1 position (index 7)
+ * @param {Number} m22 Component in column 2, row 2 position (index 8)
+ * @returns {mat3} A new mat3
+ */
+
+
+function fromValues(m00, m01, m02, m10, m11, m12, m20, m21, m22) {
+ var out = new glMatrix.ARRAY_TYPE(9);
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m10;
+ out[4] = m11;
+ out[5] = m12;
+ out[6] = m20;
+ out[7] = m21;
+ out[8] = m22;
+ return out;
+}
+/**
+ * Set the components of a mat3 to the given values
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m10 Component in column 1, row 0 position (index 3)
+ * @param {Number} m11 Component in column 1, row 1 position (index 4)
+ * @param {Number} m12 Component in column 1, row 2 position (index 5)
+ * @param {Number} m20 Component in column 2, row 0 position (index 6)
+ * @param {Number} m21 Component in column 2, row 1 position (index 7)
+ * @param {Number} m22 Component in column 2, row 2 position (index 8)
+ * @returns {mat3} out
+ */
+
+
+function set(out, m00, m01, m02, m10, m11, m12, m20, m21, m22) {
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m10;
+ out[4] = m11;
+ out[5] = m12;
+ out[6] = m20;
+ out[7] = m21;
+ out[8] = m22;
+ return out;
+}
+/**
+ * Set a mat3 to the identity matrix
+ *
+ * @param {mat3} out the receiving matrix
+ * @returns {mat3} out
+ */
+
+
+function identity(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+}
+/**
+ * Transpose the values of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+
+function transpose(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a01 = a[1],
+ a02 = a[2],
+ a12 = a[5];
+ out[1] = a[3];
+ out[2] = a[6];
+ out[3] = a01;
+ out[5] = a[7];
+ out[6] = a02;
+ out[7] = a12;
+ } else {
+ out[0] = a[0];
+ out[1] = a[3];
+ out[2] = a[6];
+ out[3] = a[1];
+ out[4] = a[4];
+ out[5] = a[7];
+ out[6] = a[2];
+ out[7] = a[5];
+ out[8] = a[8];
+ }
+
+ return out;
+}
+/**
+ * Inverts a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+
+function invert(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ var b01 = a22 * a11 - a12 * a21;
+ var b11 = -a22 * a10 + a12 * a20;
+ var b21 = a21 * a10 - a11 * a20; // Calculate the determinant
+
+ var det = a00 * b01 + a01 * b11 + a02 * b21;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = b01 * det;
+ out[1] = (-a22 * a01 + a02 * a21) * det;
+ out[2] = (a12 * a01 - a02 * a11) * det;
+ out[3] = b11 * det;
+ out[4] = (a22 * a00 - a02 * a20) * det;
+ out[5] = (-a12 * a00 + a02 * a10) * det;
+ out[6] = b21 * det;
+ out[7] = (-a21 * a00 + a01 * a20) * det;
+ out[8] = (a11 * a00 - a01 * a10) * det;
+ return out;
+}
+/**
+ * Calculates the adjugate of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+
+function adjoint(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ out[0] = a11 * a22 - a12 * a21;
+ out[1] = a02 * a21 - a01 * a22;
+ out[2] = a01 * a12 - a02 * a11;
+ out[3] = a12 * a20 - a10 * a22;
+ out[4] = a00 * a22 - a02 * a20;
+ out[5] = a02 * a10 - a00 * a12;
+ out[6] = a10 * a21 - a11 * a20;
+ out[7] = a01 * a20 - a00 * a21;
+ out[8] = a00 * a11 - a01 * a10;
+ return out;
+}
+/**
+ * Calculates the determinant of a mat3
+ *
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+
+function determinant(a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
+}
+/**
+ * Multiplies two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+
+
+function multiply(out, a, b) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ var b00 = b[0],
+ b01 = b[1],
+ b02 = b[2];
+ var b10 = b[3],
+ b11 = b[4],
+ b12 = b[5];
+ var b20 = b[6],
+ b21 = b[7],
+ b22 = b[8];
+ out[0] = b00 * a00 + b01 * a10 + b02 * a20;
+ out[1] = b00 * a01 + b01 * a11 + b02 * a21;
+ out[2] = b00 * a02 + b01 * a12 + b02 * a22;
+ out[3] = b10 * a00 + b11 * a10 + b12 * a20;
+ out[4] = b10 * a01 + b11 * a11 + b12 * a21;
+ out[5] = b10 * a02 + b11 * a12 + b12 * a22;
+ out[6] = b20 * a00 + b21 * a10 + b22 * a20;
+ out[7] = b20 * a01 + b21 * a11 + b22 * a21;
+ out[8] = b20 * a02 + b21 * a12 + b22 * a22;
+ return out;
+}
+/**
+ * Translate a mat3 by the given vector
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to translate
+ * @param {ReadonlyVec2} v vector to translate by
+ * @returns {mat3} out
+ */
+
+
+function translate(out, a, v) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a10 = a[3],
+ a11 = a[4],
+ a12 = a[5],
+ a20 = a[6],
+ a21 = a[7],
+ a22 = a[8],
+ x = v[0],
+ y = v[1];
+ out[0] = a00;
+ out[1] = a01;
+ out[2] = a02;
+ out[3] = a10;
+ out[4] = a11;
+ out[5] = a12;
+ out[6] = x * a00 + y * a10 + a20;
+ out[7] = x * a01 + y * a11 + a21;
+ out[8] = x * a02 + y * a12 + a22;
+ return out;
+}
+/**
+ * Rotates a mat3 by the given angle
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+
+
+function rotate(out, a, rad) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a10 = a[3],
+ a11 = a[4],
+ a12 = a[5],
+ a20 = a[6],
+ a21 = a[7],
+ a22 = a[8],
+ s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c * a00 + s * a10;
+ out[1] = c * a01 + s * a11;
+ out[2] = c * a02 + s * a12;
+ out[3] = c * a10 - s * a00;
+ out[4] = c * a11 - s * a01;
+ out[5] = c * a12 - s * a02;
+ out[6] = a20;
+ out[7] = a21;
+ out[8] = a22;
+ return out;
+}
+/**
+ * Scales the mat3 by the dimensions in the given vec2
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to rotate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat3} out
+ **/
+
+
+function scale(out, a, v) {
+ var x = v[0],
+ y = v[1];
+ out[0] = x * a[0];
+ out[1] = x * a[1];
+ out[2] = x * a[2];
+ out[3] = y * a[3];
+ out[4] = y * a[4];
+ out[5] = y * a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+}
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.translate(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyVec2} v Translation vector
+ * @returns {mat3} out
+ */
+
+
+function fromTranslation(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = v[0];
+ out[7] = v[1];
+ out[8] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.rotate(dest, dest, rad);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+
+
+function fromRotation(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = 0;
+ out[3] = -s;
+ out[4] = c;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.scale(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat3} out
+ */
+
+
+function fromScaling(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = v[1];
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+}
+/**
+ * Copies the values from a mat2d into a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to copy
+ * @returns {mat3} out
+ **/
+
+
+function fromMat2d(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = 0;
+ out[3] = a[2];
+ out[4] = a[3];
+ out[5] = 0;
+ out[6] = a[4];
+ out[7] = a[5];
+ out[8] = 1;
+ return out;
+}
+/**
+ * Calculates a 3x3 matrix from the given quaternion
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyQuat} q Quaternion to create matrix from
+ *
+ * @returns {mat3} out
+ */
+
+
+function fromQuat(out, q) {
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var yx = y * x2;
+ var yy = y * y2;
+ var zx = z * x2;
+ var zy = z * y2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ out[0] = 1 - yy - zz;
+ out[3] = yx - wz;
+ out[6] = zx + wy;
+ out[1] = yx + wz;
+ out[4] = 1 - xx - zz;
+ out[7] = zy - wx;
+ out[2] = zx - wy;
+ out[5] = zy + wx;
+ out[8] = 1 - xx - yy;
+ return out;
+}
+/**
+ * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyMat4} a Mat4 to derive the normal matrix from
+ *
+ * @returns {mat3} out
+ */
+
+
+function normalFromMat4(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ var b00 = a00 * a11 - a01 * a10;
+ var b01 = a00 * a12 - a02 * a10;
+ var b02 = a00 * a13 - a03 * a10;
+ var b03 = a01 * a12 - a02 * a11;
+ var b04 = a01 * a13 - a03 * a11;
+ var b05 = a02 * a13 - a03 * a12;
+ var b06 = a20 * a31 - a21 * a30;
+ var b07 = a20 * a32 - a22 * a30;
+ var b08 = a20 * a33 - a23 * a30;
+ var b09 = a21 * a32 - a22 * a31;
+ var b10 = a21 * a33 - a23 * a31;
+ var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
+
+ var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+ out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+ out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+ return out;
+}
+/**
+ * Generates a 2D projection matrix with the given bounds
+ *
+ * @param {mat3} out mat3 frustum matrix will be written into
+ * @param {number} width Width of your gl context
+ * @param {number} height Height of gl context
+ * @returns {mat3} out
+ */
+
+
+function projection(out, width, height) {
+ out[0] = 2 / width;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = -2 / height;
+ out[5] = 0;
+ out[6] = -1;
+ out[7] = 1;
+ out[8] = 1;
+ return out;
+}
+/**
+ * Returns a string representation of a mat3
+ *
+ * @param {ReadonlyMat3} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+
+function str(a) {
+ return "mat3(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ", " + a[8] + ")";
+}
+/**
+ * Returns Frobenius norm of a mat3
+ *
+ * @param {ReadonlyMat3} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+
+function frob(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
+}
+/**
+ * Adds two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+
+
+function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ out[6] = a[6] + b[6];
+ out[7] = a[7] + b[7];
+ out[8] = a[8] + b[8];
+ return out;
+}
+/**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+
+
+function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ out[4] = a[4] - b[4];
+ out[5] = a[5] - b[5];
+ out[6] = a[6] - b[6];
+ out[7] = a[7] - b[7];
+ out[8] = a[8] - b[8];
+ return out;
+}
+/**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat3} out
+ */
+
+
+function multiplyScalar(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ out[6] = a[6] * b;
+ out[7] = a[7] * b;
+ out[8] = a[8] * b;
+ return out;
+}
+/**
+ * Adds two mat3's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat3} out the receiving vector
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat3} out
+ */
+
+
+function multiplyScalarAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ out[4] = a[4] + b[4] * scale;
+ out[5] = a[5] + b[5] * scale;
+ out[6] = a[6] + b[6] * scale;
+ out[7] = a[7] + b[7] * scale;
+ out[8] = a[8] + b[8] * scale;
+ return out;
+}
+/**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat3} a The first matrix.
+ * @param {ReadonlyMat3} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+
+function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8];
+}
+/**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat3} a The first matrix.
+ * @param {ReadonlyMat3} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+
+function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5],
+ a6 = a[6],
+ a7 = a[7],
+ a8 = a[8];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5],
+ b6 = b[6],
+ b7 = b[7],
+ b8 = b[8];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8));
+}
+/**
+ * Alias for {@link mat3.multiply}
+ * @function
+ */
+
+
+var mul = multiply;
+/**
+ * Alias for {@link mat3.subtract}
+ * @function
+ */
+
+exports.mul = mul;
+var sub = subtract;
+exports.sub = sub;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/cjs/mat4.js b/public/node_modules/gl-matrix/cjs/mat4.js
new file mode 100644
index 0000000..2b536e7
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/mat4.js
@@ -0,0 +1,2023 @@
+"use strict";
+
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.create = create;
+exports.clone = clone;
+exports.copy = copy;
+exports.fromValues = fromValues;
+exports.set = set;
+exports.identity = identity;
+exports.transpose = transpose;
+exports.invert = invert;
+exports.adjoint = adjoint;
+exports.determinant = determinant;
+exports.multiply = multiply;
+exports.translate = translate;
+exports.scale = scale;
+exports.rotate = rotate;
+exports.rotateX = rotateX;
+exports.rotateY = rotateY;
+exports.rotateZ = rotateZ;
+exports.fromTranslation = fromTranslation;
+exports.fromScaling = fromScaling;
+exports.fromRotation = fromRotation;
+exports.fromXRotation = fromXRotation;
+exports.fromYRotation = fromYRotation;
+exports.fromZRotation = fromZRotation;
+exports.fromRotationTranslation = fromRotationTranslation;
+exports.fromQuat2 = fromQuat2;
+exports.getTranslation = getTranslation;
+exports.getScaling = getScaling;
+exports.getRotation = getRotation;
+exports.fromRotationTranslationScale = fromRotationTranslationScale;
+exports.fromRotationTranslationScaleOrigin = fromRotationTranslationScaleOrigin;
+exports.fromQuat = fromQuat;
+exports.frustum = frustum;
+exports.perspectiveNO = perspectiveNO;
+exports.perspectiveZO = perspectiveZO;
+exports.perspectiveFromFieldOfView = perspectiveFromFieldOfView;
+exports.orthoNO = orthoNO;
+exports.orthoZO = orthoZO;
+exports.lookAt = lookAt;
+exports.targetTo = targetTo;
+exports.str = str;
+exports.frob = frob;
+exports.add = add;
+exports.subtract = subtract;
+exports.multiplyScalar = multiplyScalar;
+exports.multiplyScalarAndAdd = multiplyScalarAndAdd;
+exports.exactEquals = exactEquals;
+exports.equals = equals;
+exports.sub = exports.mul = exports.ortho = exports.perspective = void 0;
+
+var glMatrix = _interopRequireWildcard(require("./common.js"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+/**
+ * 4x4 Matrix
Format: column-major, when typed out it looks like row-major
The matrices are being post multiplied.
+ * @module mat4
+ */
+
+/**
+ * Creates a new identity mat4
+ *
+ * @returns {mat4} a new 4x4 matrix
+ */
+function create() {
+ var out = new glMatrix.ARRAY_TYPE(16);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ }
+
+ out[0] = 1;
+ out[5] = 1;
+ out[10] = 1;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a new mat4 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat4} a matrix to clone
+ * @returns {mat4} a new 4x4 matrix
+ */
+
+
+function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(16);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+}
+/**
+ * Copy the values from one mat4 to another
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+
+function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+}
+/**
+ * Create a new mat4 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m03 Component in column 0, row 3 position (index 3)
+ * @param {Number} m10 Component in column 1, row 0 position (index 4)
+ * @param {Number} m11 Component in column 1, row 1 position (index 5)
+ * @param {Number} m12 Component in column 1, row 2 position (index 6)
+ * @param {Number} m13 Component in column 1, row 3 position (index 7)
+ * @param {Number} m20 Component in column 2, row 0 position (index 8)
+ * @param {Number} m21 Component in column 2, row 1 position (index 9)
+ * @param {Number} m22 Component in column 2, row 2 position (index 10)
+ * @param {Number} m23 Component in column 2, row 3 position (index 11)
+ * @param {Number} m30 Component in column 3, row 0 position (index 12)
+ * @param {Number} m31 Component in column 3, row 1 position (index 13)
+ * @param {Number} m32 Component in column 3, row 2 position (index 14)
+ * @param {Number} m33 Component in column 3, row 3 position (index 15)
+ * @returns {mat4} A new mat4
+ */
+
+
+function fromValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
+ var out = new glMatrix.ARRAY_TYPE(16);
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m03;
+ out[4] = m10;
+ out[5] = m11;
+ out[6] = m12;
+ out[7] = m13;
+ out[8] = m20;
+ out[9] = m21;
+ out[10] = m22;
+ out[11] = m23;
+ out[12] = m30;
+ out[13] = m31;
+ out[14] = m32;
+ out[15] = m33;
+ return out;
+}
+/**
+ * Set the components of a mat4 to the given values
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m03 Component in column 0, row 3 position (index 3)
+ * @param {Number} m10 Component in column 1, row 0 position (index 4)
+ * @param {Number} m11 Component in column 1, row 1 position (index 5)
+ * @param {Number} m12 Component in column 1, row 2 position (index 6)
+ * @param {Number} m13 Component in column 1, row 3 position (index 7)
+ * @param {Number} m20 Component in column 2, row 0 position (index 8)
+ * @param {Number} m21 Component in column 2, row 1 position (index 9)
+ * @param {Number} m22 Component in column 2, row 2 position (index 10)
+ * @param {Number} m23 Component in column 2, row 3 position (index 11)
+ * @param {Number} m30 Component in column 3, row 0 position (index 12)
+ * @param {Number} m31 Component in column 3, row 1 position (index 13)
+ * @param {Number} m32 Component in column 3, row 2 position (index 14)
+ * @param {Number} m33 Component in column 3, row 3 position (index 15)
+ * @returns {mat4} out
+ */
+
+
+function set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m03;
+ out[4] = m10;
+ out[5] = m11;
+ out[6] = m12;
+ out[7] = m13;
+ out[8] = m20;
+ out[9] = m21;
+ out[10] = m22;
+ out[11] = m23;
+ out[12] = m30;
+ out[13] = m31;
+ out[14] = m32;
+ out[15] = m33;
+ return out;
+}
+/**
+ * Set a mat4 to the identity matrix
+ *
+ * @param {mat4} out the receiving matrix
+ * @returns {mat4} out
+ */
+
+
+function identity(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Transpose the values of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+
+function transpose(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a12 = a[6],
+ a13 = a[7];
+ var a23 = a[11];
+ out[1] = a[4];
+ out[2] = a[8];
+ out[3] = a[12];
+ out[4] = a01;
+ out[6] = a[9];
+ out[7] = a[13];
+ out[8] = a02;
+ out[9] = a12;
+ out[11] = a[14];
+ out[12] = a03;
+ out[13] = a13;
+ out[14] = a23;
+ } else {
+ out[0] = a[0];
+ out[1] = a[4];
+ out[2] = a[8];
+ out[3] = a[12];
+ out[4] = a[1];
+ out[5] = a[5];
+ out[6] = a[9];
+ out[7] = a[13];
+ out[8] = a[2];
+ out[9] = a[6];
+ out[10] = a[10];
+ out[11] = a[14];
+ out[12] = a[3];
+ out[13] = a[7];
+ out[14] = a[11];
+ out[15] = a[15];
+ }
+
+ return out;
+}
+/**
+ * Inverts a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+
+function invert(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ var b00 = a00 * a11 - a01 * a10;
+ var b01 = a00 * a12 - a02 * a10;
+ var b02 = a00 * a13 - a03 * a10;
+ var b03 = a01 * a12 - a02 * a11;
+ var b04 = a01 * a13 - a03 * a11;
+ var b05 = a02 * a13 - a03 * a12;
+ var b06 = a20 * a31 - a21 * a30;
+ var b07 = a20 * a32 - a22 * a30;
+ var b08 = a20 * a33 - a23 * a30;
+ var b09 = a21 * a32 - a22 * a31;
+ var b10 = a21 * a33 - a23 * a31;
+ var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
+
+ var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
+ out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
+ out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+ out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+ out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+ out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
+ out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
+ out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
+ out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
+ out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
+ return out;
+}
+/**
+ * Calculates the adjugate of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+
+function adjoint(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ out[0] = a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22);
+ out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
+ out[2] = a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12);
+ out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
+ out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
+ out[5] = a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22);
+ out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
+ out[7] = a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12);
+ out[8] = a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21);
+ out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
+ out[10] = a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11);
+ out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
+ out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
+ out[13] = a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21);
+ out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
+ out[15] = a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11);
+ return out;
+}
+/**
+ * Calculates the determinant of a mat4
+ *
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+
+function determinant(a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ var b00 = a00 * a11 - a01 * a10;
+ var b01 = a00 * a12 - a02 * a10;
+ var b02 = a00 * a13 - a03 * a10;
+ var b03 = a01 * a12 - a02 * a11;
+ var b04 = a01 * a13 - a03 * a11;
+ var b05 = a02 * a13 - a03 * a12;
+ var b06 = a20 * a31 - a21 * a30;
+ var b07 = a20 * a32 - a22 * a30;
+ var b08 = a20 * a33 - a23 * a30;
+ var b09 = a21 * a32 - a22 * a31;
+ var b10 = a21 * a33 - a23 * a31;
+ var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
+
+ return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+}
+/**
+ * Multiplies two mat4s
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+
+
+function multiply(out, a, b) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15]; // Cache only the current line of the second matrix
+
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ b0 = b[4];
+ b1 = b[5];
+ b2 = b[6];
+ b3 = b[7];
+ out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ b0 = b[8];
+ b1 = b[9];
+ b2 = b[10];
+ b3 = b[11];
+ out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ b0 = b[12];
+ b1 = b[13];
+ b2 = b[14];
+ b3 = b[15];
+ out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ return out;
+}
+/**
+ * Translate a mat4 by the given vector
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to translate
+ * @param {ReadonlyVec3} v vector to translate by
+ * @returns {mat4} out
+ */
+
+
+function translate(out, a, v) {
+ var x = v[0],
+ y = v[1],
+ z = v[2];
+ var a00, a01, a02, a03;
+ var a10, a11, a12, a13;
+ var a20, a21, a22, a23;
+
+ if (a === out) {
+ out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
+ out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
+ out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
+ out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
+ } else {
+ a00 = a[0];
+ a01 = a[1];
+ a02 = a[2];
+ a03 = a[3];
+ a10 = a[4];
+ a11 = a[5];
+ a12 = a[6];
+ a13 = a[7];
+ a20 = a[8];
+ a21 = a[9];
+ a22 = a[10];
+ a23 = a[11];
+ out[0] = a00;
+ out[1] = a01;
+ out[2] = a02;
+ out[3] = a03;
+ out[4] = a10;
+ out[5] = a11;
+ out[6] = a12;
+ out[7] = a13;
+ out[8] = a20;
+ out[9] = a21;
+ out[10] = a22;
+ out[11] = a23;
+ out[12] = a00 * x + a10 * y + a20 * z + a[12];
+ out[13] = a01 * x + a11 * y + a21 * z + a[13];
+ out[14] = a02 * x + a12 * y + a22 * z + a[14];
+ out[15] = a03 * x + a13 * y + a23 * z + a[15];
+ }
+
+ return out;
+}
+/**
+ * Scales the mat4 by the dimensions in the given vec3 not using vectorization
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to scale
+ * @param {ReadonlyVec3} v the vec3 to scale the matrix by
+ * @returns {mat4} out
+ **/
+
+
+function scale(out, a, v) {
+ var x = v[0],
+ y = v[1],
+ z = v[2];
+ out[0] = a[0] * x;
+ out[1] = a[1] * x;
+ out[2] = a[2] * x;
+ out[3] = a[3] * x;
+ out[4] = a[4] * y;
+ out[5] = a[5] * y;
+ out[6] = a[6] * y;
+ out[7] = a[7] * y;
+ out[8] = a[8] * z;
+ out[9] = a[9] * z;
+ out[10] = a[10] * z;
+ out[11] = a[11] * z;
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+}
+/**
+ * Rotates a mat4 by the given angle around the given axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+
+
+function rotate(out, a, rad, axis) {
+ var x = axis[0],
+ y = axis[1],
+ z = axis[2];
+ var len = Math.hypot(x, y, z);
+ var s, c, t;
+ var a00, a01, a02, a03;
+ var a10, a11, a12, a13;
+ var a20, a21, a22, a23;
+ var b00, b01, b02;
+ var b10, b11, b12;
+ var b20, b21, b22;
+
+ if (len < glMatrix.EPSILON) {
+ return null;
+ }
+
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+ s = Math.sin(rad);
+ c = Math.cos(rad);
+ t = 1 - c;
+ a00 = a[0];
+ a01 = a[1];
+ a02 = a[2];
+ a03 = a[3];
+ a10 = a[4];
+ a11 = a[5];
+ a12 = a[6];
+ a13 = a[7];
+ a20 = a[8];
+ a21 = a[9];
+ a22 = a[10];
+ a23 = a[11]; // Construct the elements of the rotation matrix
+
+ b00 = x * x * t + c;
+ b01 = y * x * t + z * s;
+ b02 = z * x * t - y * s;
+ b10 = x * y * t - z * s;
+ b11 = y * y * t + c;
+ b12 = z * y * t + x * s;
+ b20 = x * z * t + y * s;
+ b21 = y * z * t - x * s;
+ b22 = z * z * t + c; // Perform rotation-specific matrix multiplication
+
+ out[0] = a00 * b00 + a10 * b01 + a20 * b02;
+ out[1] = a01 * b00 + a11 * b01 + a21 * b02;
+ out[2] = a02 * b00 + a12 * b01 + a22 * b02;
+ out[3] = a03 * b00 + a13 * b01 + a23 * b02;
+ out[4] = a00 * b10 + a10 * b11 + a20 * b12;
+ out[5] = a01 * b10 + a11 * b11 + a21 * b12;
+ out[6] = a02 * b10 + a12 * b11 + a22 * b12;
+ out[7] = a03 * b10 + a13 * b11 + a23 * b12;
+ out[8] = a00 * b20 + a10 * b21 + a20 * b22;
+ out[9] = a01 * b20 + a11 * b21 + a21 * b22;
+ out[10] = a02 * b20 + a12 * b21 + a22 * b22;
+ out[11] = a03 * b20 + a13 * b21 + a23 * b22;
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged last row
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+
+ return out;
+}
+/**
+ * Rotates a matrix by the given angle around the X axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+
+function rotateX(out, a, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ var a10 = a[4];
+ var a11 = a[5];
+ var a12 = a[6];
+ var a13 = a[7];
+ var a20 = a[8];
+ var a21 = a[9];
+ var a22 = a[10];
+ var a23 = a[11];
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged rows
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ } // Perform axis-specific matrix multiplication
+
+
+ out[4] = a10 * c + a20 * s;
+ out[5] = a11 * c + a21 * s;
+ out[6] = a12 * c + a22 * s;
+ out[7] = a13 * c + a23 * s;
+ out[8] = a20 * c - a10 * s;
+ out[9] = a21 * c - a11 * s;
+ out[10] = a22 * c - a12 * s;
+ out[11] = a23 * c - a13 * s;
+ return out;
+}
+/**
+ * Rotates a matrix by the given angle around the Y axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+
+function rotateY(out, a, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ var a00 = a[0];
+ var a01 = a[1];
+ var a02 = a[2];
+ var a03 = a[3];
+ var a20 = a[8];
+ var a21 = a[9];
+ var a22 = a[10];
+ var a23 = a[11];
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged rows
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ } // Perform axis-specific matrix multiplication
+
+
+ out[0] = a00 * c - a20 * s;
+ out[1] = a01 * c - a21 * s;
+ out[2] = a02 * c - a22 * s;
+ out[3] = a03 * c - a23 * s;
+ out[8] = a00 * s + a20 * c;
+ out[9] = a01 * s + a21 * c;
+ out[10] = a02 * s + a22 * c;
+ out[11] = a03 * s + a23 * c;
+ return out;
+}
+/**
+ * Rotates a matrix by the given angle around the Z axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+
+function rotateZ(out, a, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ var a00 = a[0];
+ var a01 = a[1];
+ var a02 = a[2];
+ var a03 = a[3];
+ var a10 = a[4];
+ var a11 = a[5];
+ var a12 = a[6];
+ var a13 = a[7];
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged last row
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ } // Perform axis-specific matrix multiplication
+
+
+ out[0] = a00 * c + a10 * s;
+ out[1] = a01 * c + a11 * s;
+ out[2] = a02 * c + a12 * s;
+ out[3] = a03 * c + a13 * s;
+ out[4] = a10 * c - a00 * s;
+ out[5] = a11 * c - a01 * s;
+ out[6] = a12 * c - a02 * s;
+ out[7] = a13 * c - a03 * s;
+ return out;
+}
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyVec3} v Translation vector
+ * @returns {mat4} out
+ */
+
+
+function fromTranslation(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.scale(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyVec3} v Scaling vector
+ * @returns {mat4} out
+ */
+
+
+function fromScaling(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = v[1];
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = v[2];
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a given angle around a given axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotate(dest, dest, rad, axis);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+
+
+function fromRotation(out, rad, axis) {
+ var x = axis[0],
+ y = axis[1],
+ z = axis[2];
+ var len = Math.hypot(x, y, z);
+ var s, c, t;
+
+ if (len < glMatrix.EPSILON) {
+ return null;
+ }
+
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+ s = Math.sin(rad);
+ c = Math.cos(rad);
+ t = 1 - c; // Perform rotation-specific matrix multiplication
+
+ out[0] = x * x * t + c;
+ out[1] = y * x * t + z * s;
+ out[2] = z * x * t - y * s;
+ out[3] = 0;
+ out[4] = x * y * t - z * s;
+ out[5] = y * y * t + c;
+ out[6] = z * y * t + x * s;
+ out[7] = 0;
+ out[8] = x * z * t + y * s;
+ out[9] = y * z * t - x * s;
+ out[10] = z * z * t + c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from the given angle around the X axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateX(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+
+function fromXRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad); // Perform axis-specific matrix multiplication
+
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = c;
+ out[6] = s;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = -s;
+ out[10] = c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from the given angle around the Y axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateY(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+
+function fromYRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad); // Perform axis-specific matrix multiplication
+
+ out[0] = c;
+ out[1] = 0;
+ out[2] = -s;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = s;
+ out[9] = 0;
+ out[10] = c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from the given angle around the Z axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateZ(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+
+function fromZRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad); // Perform axis-specific matrix multiplication
+
+ out[0] = c;
+ out[1] = s;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = -s;
+ out[5] = c;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a quaternion rotation and vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @returns {mat4} out
+ */
+
+
+function fromRotationTranslation(out, q, v) {
+ // Quaternion math
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var xy = x * y2;
+ var xz = x * z2;
+ var yy = y * y2;
+ var yz = y * z2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ out[0] = 1 - (yy + zz);
+ out[1] = xy + wz;
+ out[2] = xz - wy;
+ out[3] = 0;
+ out[4] = xy - wz;
+ out[5] = 1 - (xx + zz);
+ out[6] = yz + wx;
+ out[7] = 0;
+ out[8] = xz + wy;
+ out[9] = yz - wx;
+ out[10] = 1 - (xx + yy);
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a new mat4 from a dual quat.
+ *
+ * @param {mat4} out Matrix
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @returns {mat4} mat4 receiving operation result
+ */
+
+
+function fromQuat2(out, a) {
+ var translation = new glMatrix.ARRAY_TYPE(3);
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7];
+ var magnitude = bx * bx + by * by + bz * bz + bw * bw; //Only scale if it makes sense
+
+ if (magnitude > 0) {
+ translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;
+ translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;
+ translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;
+ } else {
+ translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
+ translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
+ translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
+ }
+
+ fromRotationTranslation(out, a, translation);
+ return out;
+}
+/**
+ * Returns the translation vector component of a transformation
+ * matrix. If a matrix is built with fromRotationTranslation,
+ * the returned vector will be the same as the translation vector
+ * originally supplied.
+ * @param {vec3} out Vector to receive translation component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {vec3} out
+ */
+
+
+function getTranslation(out, mat) {
+ out[0] = mat[12];
+ out[1] = mat[13];
+ out[2] = mat[14];
+ return out;
+}
+/**
+ * Returns the scaling factor component of a transformation
+ * matrix. If a matrix is built with fromRotationTranslationScale
+ * with a normalized Quaternion paramter, the returned vector will be
+ * the same as the scaling vector
+ * originally supplied.
+ * @param {vec3} out Vector to receive scaling factor component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {vec3} out
+ */
+
+
+function getScaling(out, mat) {
+ var m11 = mat[0];
+ var m12 = mat[1];
+ var m13 = mat[2];
+ var m21 = mat[4];
+ var m22 = mat[5];
+ var m23 = mat[6];
+ var m31 = mat[8];
+ var m32 = mat[9];
+ var m33 = mat[10];
+ out[0] = Math.hypot(m11, m12, m13);
+ out[1] = Math.hypot(m21, m22, m23);
+ out[2] = Math.hypot(m31, m32, m33);
+ return out;
+}
+/**
+ * Returns a quaternion representing the rotational component
+ * of a transformation matrix. If a matrix is built with
+ * fromRotationTranslation, the returned quaternion will be the
+ * same as the quaternion originally supplied.
+ * @param {quat} out Quaternion to receive the rotation component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {quat} out
+ */
+
+
+function getRotation(out, mat) {
+ var scaling = new glMatrix.ARRAY_TYPE(3);
+ getScaling(scaling, mat);
+ var is1 = 1 / scaling[0];
+ var is2 = 1 / scaling[1];
+ var is3 = 1 / scaling[2];
+ var sm11 = mat[0] * is1;
+ var sm12 = mat[1] * is2;
+ var sm13 = mat[2] * is3;
+ var sm21 = mat[4] * is1;
+ var sm22 = mat[5] * is2;
+ var sm23 = mat[6] * is3;
+ var sm31 = mat[8] * is1;
+ var sm32 = mat[9] * is2;
+ var sm33 = mat[10] * is3;
+ var trace = sm11 + sm22 + sm33;
+ var S = 0;
+
+ if (trace > 0) {
+ S = Math.sqrt(trace + 1.0) * 2;
+ out[3] = 0.25 * S;
+ out[0] = (sm23 - sm32) / S;
+ out[1] = (sm31 - sm13) / S;
+ out[2] = (sm12 - sm21) / S;
+ } else if (sm11 > sm22 && sm11 > sm33) {
+ S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;
+ out[3] = (sm23 - sm32) / S;
+ out[0] = 0.25 * S;
+ out[1] = (sm12 + sm21) / S;
+ out[2] = (sm31 + sm13) / S;
+ } else if (sm22 > sm33) {
+ S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;
+ out[3] = (sm31 - sm13) / S;
+ out[0] = (sm12 + sm21) / S;
+ out[1] = 0.25 * S;
+ out[2] = (sm23 + sm32) / S;
+ } else {
+ S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;
+ out[3] = (sm12 - sm21) / S;
+ out[0] = (sm31 + sm13) / S;
+ out[1] = (sm23 + sm32) / S;
+ out[2] = 0.25 * S;
+ }
+
+ return out;
+}
+/**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @param {ReadonlyVec3} s Scaling vector
+ * @returns {mat4} out
+ */
+
+
+function fromRotationTranslationScale(out, q, v, s) {
+ // Quaternion math
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var xy = x * y2;
+ var xz = x * z2;
+ var yy = y * y2;
+ var yz = y * z2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ var sx = s[0];
+ var sy = s[1];
+ var sz = s[2];
+ out[0] = (1 - (yy + zz)) * sx;
+ out[1] = (xy + wz) * sx;
+ out[2] = (xz - wy) * sx;
+ out[3] = 0;
+ out[4] = (xy - wz) * sy;
+ out[5] = (1 - (xx + zz)) * sy;
+ out[6] = (yz + wx) * sy;
+ out[7] = 0;
+ out[8] = (xz + wy) * sz;
+ out[9] = (yz - wx) * sz;
+ out[10] = (1 - (xx + yy)) * sz;
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * mat4.translate(dest, origin);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ * mat4.translate(dest, negativeOrigin);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @param {ReadonlyVec3} s Scaling vector
+ * @param {ReadonlyVec3} o The origin vector around which to scale and rotate
+ * @returns {mat4} out
+ */
+
+
+function fromRotationTranslationScaleOrigin(out, q, v, s, o) {
+ // Quaternion math
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var xy = x * y2;
+ var xz = x * z2;
+ var yy = y * y2;
+ var yz = y * z2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ var sx = s[0];
+ var sy = s[1];
+ var sz = s[2];
+ var ox = o[0];
+ var oy = o[1];
+ var oz = o[2];
+ var out0 = (1 - (yy + zz)) * sx;
+ var out1 = (xy + wz) * sx;
+ var out2 = (xz - wy) * sx;
+ var out4 = (xy - wz) * sy;
+ var out5 = (1 - (xx + zz)) * sy;
+ var out6 = (yz + wx) * sy;
+ var out8 = (xz + wy) * sz;
+ var out9 = (yz - wx) * sz;
+ var out10 = (1 - (xx + yy)) * sz;
+ out[0] = out0;
+ out[1] = out1;
+ out[2] = out2;
+ out[3] = 0;
+ out[4] = out4;
+ out[5] = out5;
+ out[6] = out6;
+ out[7] = 0;
+ out[8] = out8;
+ out[9] = out9;
+ out[10] = out10;
+ out[11] = 0;
+ out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);
+ out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);
+ out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);
+ out[15] = 1;
+ return out;
+}
+/**
+ * Calculates a 4x4 matrix from the given quaternion
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyQuat} q Quaternion to create matrix from
+ *
+ * @returns {mat4} out
+ */
+
+
+function fromQuat(out, q) {
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var yx = y * x2;
+ var yy = y * y2;
+ var zx = z * x2;
+ var zy = z * y2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ out[0] = 1 - yy - zz;
+ out[1] = yx + wz;
+ out[2] = zx - wy;
+ out[3] = 0;
+ out[4] = yx - wz;
+ out[5] = 1 - xx - zz;
+ out[6] = zy + wx;
+ out[7] = 0;
+ out[8] = zx + wy;
+ out[9] = zy - wx;
+ out[10] = 1 - xx - yy;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Generates a frustum matrix with the given bounds
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {Number} left Left bound of the frustum
+ * @param {Number} right Right bound of the frustum
+ * @param {Number} bottom Bottom bound of the frustum
+ * @param {Number} top Top bound of the frustum
+ * @param {Number} near Near bound of the frustum
+ * @param {Number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+
+function frustum(out, left, right, bottom, top, near, far) {
+ var rl = 1 / (right - left);
+ var tb = 1 / (top - bottom);
+ var nf = 1 / (near - far);
+ out[0] = near * 2 * rl;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = near * 2 * tb;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = (right + left) * rl;
+ out[9] = (top + bottom) * tb;
+ out[10] = (far + near) * nf;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = far * near * 2 * nf;
+ out[15] = 0;
+ return out;
+}
+/**
+ * Generates a perspective projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
+ * which matches WebGL/OpenGL's clip volume.
+ * Passing null/undefined/no value for far will generate infinite projection matrix.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum, can be null or Infinity
+ * @returns {mat4} out
+ */
+
+
+function perspectiveNO(out, fovy, aspect, near, far) {
+ var f = 1.0 / Math.tan(fovy / 2),
+ nf;
+ out[0] = f / aspect;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = f;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[15] = 0;
+
+ if (far != null && far !== Infinity) {
+ nf = 1 / (near - far);
+ out[10] = (far + near) * nf;
+ out[14] = 2 * far * near * nf;
+ } else {
+ out[10] = -1;
+ out[14] = -2 * near;
+ }
+
+ return out;
+}
+/**
+ * Alias for {@link mat4.perspectiveNO}
+ * @function
+ */
+
+
+var perspective = perspectiveNO;
+/**
+ * Generates a perspective projection matrix suitable for WebGPU with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
+ * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
+ * Passing null/undefined/no value for far will generate infinite projection matrix.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum, can be null or Infinity
+ * @returns {mat4} out
+ */
+
+exports.perspective = perspective;
+
+function perspectiveZO(out, fovy, aspect, near, far) {
+ var f = 1.0 / Math.tan(fovy / 2),
+ nf;
+ out[0] = f / aspect;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = f;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[15] = 0;
+
+ if (far != null && far !== Infinity) {
+ nf = 1 / (near - far);
+ out[10] = far * nf;
+ out[14] = far * near * nf;
+ } else {
+ out[10] = -1;
+ out[14] = -near;
+ }
+
+ return out;
+}
+/**
+ * Generates a perspective projection matrix with the given field of view.
+ * This is primarily useful for generating projection matrices to be used
+ * with the still experiemental WebVR API.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+
+function perspectiveFromFieldOfView(out, fov, near, far) {
+ var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);
+ var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);
+ var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);
+ var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);
+ var xScale = 2.0 / (leftTan + rightTan);
+ var yScale = 2.0 / (upTan + downTan);
+ out[0] = xScale;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ out[3] = 0.0;
+ out[4] = 0.0;
+ out[5] = yScale;
+ out[6] = 0.0;
+ out[7] = 0.0;
+ out[8] = -((leftTan - rightTan) * xScale * 0.5);
+ out[9] = (upTan - downTan) * yScale * 0.5;
+ out[10] = far / (near - far);
+ out[11] = -1.0;
+ out[12] = 0.0;
+ out[13] = 0.0;
+ out[14] = far * near / (near - far);
+ out[15] = 0.0;
+ return out;
+}
+/**
+ * Generates a orthogonal projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
+ * which matches WebGL/OpenGL's clip volume.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+
+function orthoNO(out, left, right, bottom, top, near, far) {
+ var lr = 1 / (left - right);
+ var bt = 1 / (bottom - top);
+ var nf = 1 / (near - far);
+ out[0] = -2 * lr;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = -2 * bt;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 2 * nf;
+ out[11] = 0;
+ out[12] = (left + right) * lr;
+ out[13] = (top + bottom) * bt;
+ out[14] = (far + near) * nf;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Alias for {@link mat4.orthoNO}
+ * @function
+ */
+
+
+var ortho = orthoNO;
+/**
+ * Generates a orthogonal projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
+ * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+exports.ortho = ortho;
+
+function orthoZO(out, left, right, bottom, top, near, far) {
+ var lr = 1 / (left - right);
+ var bt = 1 / (bottom - top);
+ var nf = 1 / (near - far);
+ out[0] = -2 * lr;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = -2 * bt;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = nf;
+ out[11] = 0;
+ out[12] = (left + right) * lr;
+ out[13] = (top + bottom) * bt;
+ out[14] = near * nf;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Generates a look-at matrix with the given eye position, focal point, and up axis.
+ * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {ReadonlyVec3} eye Position of the viewer
+ * @param {ReadonlyVec3} center Point the viewer is looking at
+ * @param {ReadonlyVec3} up vec3 pointing up
+ * @returns {mat4} out
+ */
+
+
+function lookAt(out, eye, center, up) {
+ var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
+ var eyex = eye[0];
+ var eyey = eye[1];
+ var eyez = eye[2];
+ var upx = up[0];
+ var upy = up[1];
+ var upz = up[2];
+ var centerx = center[0];
+ var centery = center[1];
+ var centerz = center[2];
+
+ if (Math.abs(eyex - centerx) < glMatrix.EPSILON && Math.abs(eyey - centery) < glMatrix.EPSILON && Math.abs(eyez - centerz) < glMatrix.EPSILON) {
+ return identity(out);
+ }
+
+ z0 = eyex - centerx;
+ z1 = eyey - centery;
+ z2 = eyez - centerz;
+ len = 1 / Math.hypot(z0, z1, z2);
+ z0 *= len;
+ z1 *= len;
+ z2 *= len;
+ x0 = upy * z2 - upz * z1;
+ x1 = upz * z0 - upx * z2;
+ x2 = upx * z1 - upy * z0;
+ len = Math.hypot(x0, x1, x2);
+
+ if (!len) {
+ x0 = 0;
+ x1 = 0;
+ x2 = 0;
+ } else {
+ len = 1 / len;
+ x0 *= len;
+ x1 *= len;
+ x2 *= len;
+ }
+
+ y0 = z1 * x2 - z2 * x1;
+ y1 = z2 * x0 - z0 * x2;
+ y2 = z0 * x1 - z1 * x0;
+ len = Math.hypot(y0, y1, y2);
+
+ if (!len) {
+ y0 = 0;
+ y1 = 0;
+ y2 = 0;
+ } else {
+ len = 1 / len;
+ y0 *= len;
+ y1 *= len;
+ y2 *= len;
+ }
+
+ out[0] = x0;
+ out[1] = y0;
+ out[2] = z0;
+ out[3] = 0;
+ out[4] = x1;
+ out[5] = y1;
+ out[6] = z1;
+ out[7] = 0;
+ out[8] = x2;
+ out[9] = y2;
+ out[10] = z2;
+ out[11] = 0;
+ out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
+ out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
+ out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
+ out[15] = 1;
+ return out;
+}
+/**
+ * Generates a matrix that makes something look at something else.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {ReadonlyVec3} eye Position of the viewer
+ * @param {ReadonlyVec3} center Point the viewer is looking at
+ * @param {ReadonlyVec3} up vec3 pointing up
+ * @returns {mat4} out
+ */
+
+
+function targetTo(out, eye, target, up) {
+ var eyex = eye[0],
+ eyey = eye[1],
+ eyez = eye[2],
+ upx = up[0],
+ upy = up[1],
+ upz = up[2];
+ var z0 = eyex - target[0],
+ z1 = eyey - target[1],
+ z2 = eyez - target[2];
+ var len = z0 * z0 + z1 * z1 + z2 * z2;
+
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ z0 *= len;
+ z1 *= len;
+ z2 *= len;
+ }
+
+ var x0 = upy * z2 - upz * z1,
+ x1 = upz * z0 - upx * z2,
+ x2 = upx * z1 - upy * z0;
+ len = x0 * x0 + x1 * x1 + x2 * x2;
+
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ x0 *= len;
+ x1 *= len;
+ x2 *= len;
+ }
+
+ out[0] = x0;
+ out[1] = x1;
+ out[2] = x2;
+ out[3] = 0;
+ out[4] = z1 * x2 - z2 * x1;
+ out[5] = z2 * x0 - z0 * x2;
+ out[6] = z0 * x1 - z1 * x0;
+ out[7] = 0;
+ out[8] = z0;
+ out[9] = z1;
+ out[10] = z2;
+ out[11] = 0;
+ out[12] = eyex;
+ out[13] = eyey;
+ out[14] = eyez;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Returns a string representation of a mat4
+ *
+ * @param {ReadonlyMat4} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+
+function str(a) {
+ return "mat4(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ", " + a[8] + ", " + a[9] + ", " + a[10] + ", " + a[11] + ", " + a[12] + ", " + a[13] + ", " + a[14] + ", " + a[15] + ")";
+}
+/**
+ * Returns Frobenius norm of a mat4
+ *
+ * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+
+function frob(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);
+}
+/**
+ * Adds two mat4's
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+
+
+function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ out[6] = a[6] + b[6];
+ out[7] = a[7] + b[7];
+ out[8] = a[8] + b[8];
+ out[9] = a[9] + b[9];
+ out[10] = a[10] + b[10];
+ out[11] = a[11] + b[11];
+ out[12] = a[12] + b[12];
+ out[13] = a[13] + b[13];
+ out[14] = a[14] + b[14];
+ out[15] = a[15] + b[15];
+ return out;
+}
+/**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+
+
+function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ out[4] = a[4] - b[4];
+ out[5] = a[5] - b[5];
+ out[6] = a[6] - b[6];
+ out[7] = a[7] - b[7];
+ out[8] = a[8] - b[8];
+ out[9] = a[9] - b[9];
+ out[10] = a[10] - b[10];
+ out[11] = a[11] - b[11];
+ out[12] = a[12] - b[12];
+ out[13] = a[13] - b[13];
+ out[14] = a[14] - b[14];
+ out[15] = a[15] - b[15];
+ return out;
+}
+/**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat4} out
+ */
+
+
+function multiplyScalar(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ out[6] = a[6] * b;
+ out[7] = a[7] * b;
+ out[8] = a[8] * b;
+ out[9] = a[9] * b;
+ out[10] = a[10] * b;
+ out[11] = a[11] * b;
+ out[12] = a[12] * b;
+ out[13] = a[13] * b;
+ out[14] = a[14] * b;
+ out[15] = a[15] * b;
+ return out;
+}
+/**
+ * Adds two mat4's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat4} out the receiving vector
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat4} out
+ */
+
+
+function multiplyScalarAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ out[4] = a[4] + b[4] * scale;
+ out[5] = a[5] + b[5] * scale;
+ out[6] = a[6] + b[6] * scale;
+ out[7] = a[7] + b[7] * scale;
+ out[8] = a[8] + b[8] * scale;
+ out[9] = a[9] + b[9] * scale;
+ out[10] = a[10] + b[10] * scale;
+ out[11] = a[11] + b[11] * scale;
+ out[12] = a[12] + b[12] * scale;
+ out[13] = a[13] + b[13] * scale;
+ out[14] = a[14] + b[14] * scale;
+ out[15] = a[15] + b[15] * scale;
+ return out;
+}
+/**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat4} a The first matrix.
+ * @param {ReadonlyMat4} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+
+function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];
+}
+/**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat4} a The first matrix.
+ * @param {ReadonlyMat4} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+
+function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var a4 = a[4],
+ a5 = a[5],
+ a6 = a[6],
+ a7 = a[7];
+ var a8 = a[8],
+ a9 = a[9],
+ a10 = a[10],
+ a11 = a[11];
+ var a12 = a[12],
+ a13 = a[13],
+ a14 = a[14],
+ a15 = a[15];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ var b4 = b[4],
+ b5 = b[5],
+ b6 = b[6],
+ b7 = b[7];
+ var b8 = b[8],
+ b9 = b[9],
+ b10 = b[10],
+ b11 = b[11];
+ var b12 = b[12],
+ b13 = b[13],
+ b14 = b[14],
+ b15 = b[15];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));
+}
+/**
+ * Alias for {@link mat4.multiply}
+ * @function
+ */
+
+
+var mul = multiply;
+/**
+ * Alias for {@link mat4.subtract}
+ * @function
+ */
+
+exports.mul = mul;
+var sub = subtract;
+exports.sub = sub;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/cjs/quat.js b/public/node_modules/gl-matrix/cjs/quat.js
new file mode 100644
index 0000000..2c5b17c
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/quat.js
@@ -0,0 +1,791 @@
+"use strict";
+
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.create = create;
+exports.identity = identity;
+exports.setAxisAngle = setAxisAngle;
+exports.getAxisAngle = getAxisAngle;
+exports.getAngle = getAngle;
+exports.multiply = multiply;
+exports.rotateX = rotateX;
+exports.rotateY = rotateY;
+exports.rotateZ = rotateZ;
+exports.calculateW = calculateW;
+exports.exp = exp;
+exports.ln = ln;
+exports.pow = pow;
+exports.slerp = slerp;
+exports.random = random;
+exports.invert = invert;
+exports.conjugate = conjugate;
+exports.fromMat3 = fromMat3;
+exports.fromEuler = fromEuler;
+exports.str = str;
+exports.setAxes = exports.sqlerp = exports.rotationTo = exports.equals = exports.exactEquals = exports.normalize = exports.sqrLen = exports.squaredLength = exports.len = exports.length = exports.lerp = exports.dot = exports.scale = exports.mul = exports.add = exports.set = exports.copy = exports.fromValues = exports.clone = void 0;
+
+var glMatrix = _interopRequireWildcard(require("./common.js"));
+
+var mat3 = _interopRequireWildcard(require("./mat3.js"));
+
+var vec3 = _interopRequireWildcard(require("./vec3.js"));
+
+var vec4 = _interopRequireWildcard(require("./vec4.js"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+/**
+ * Quaternion
+ * @module quat
+ */
+
+/**
+ * Creates a new identity quat
+ *
+ * @returns {quat} a new quaternion
+ */
+function create() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ }
+
+ out[3] = 1;
+ return out;
+}
+/**
+ * Set a quat to the identity quaternion
+ *
+ * @param {quat} out the receiving quaternion
+ * @returns {quat} out
+ */
+
+
+function identity(out) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+}
+/**
+ * Sets a quat from the given angle and rotation axis,
+ * then returns it.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyVec3} axis the axis around which to rotate
+ * @param {Number} rad the angle in radians
+ * @returns {quat} out
+ **/
+
+
+function setAxisAngle(out, axis, rad) {
+ rad = rad * 0.5;
+ var s = Math.sin(rad);
+ out[0] = s * axis[0];
+ out[1] = s * axis[1];
+ out[2] = s * axis[2];
+ out[3] = Math.cos(rad);
+ return out;
+}
+/**
+ * Gets the rotation axis and angle for a given
+ * quaternion. If a quaternion is created with
+ * setAxisAngle, this method will return the same
+ * values as providied in the original parameter list
+ * OR functionally equivalent values.
+ * Example: The quaternion formed by axis [0, 0, 1] and
+ * angle -90 is the same as the quaternion formed by
+ * [0, 0, 1] and 270. This method favors the latter.
+ * @param {vec3} out_axis Vector receiving the axis of rotation
+ * @param {ReadonlyQuat} q Quaternion to be decomposed
+ * @return {Number} Angle, in radians, of the rotation
+ */
+
+
+function getAxisAngle(out_axis, q) {
+ var rad = Math.acos(q[3]) * 2.0;
+ var s = Math.sin(rad / 2.0);
+
+ if (s > glMatrix.EPSILON) {
+ out_axis[0] = q[0] / s;
+ out_axis[1] = q[1] / s;
+ out_axis[2] = q[2] / s;
+ } else {
+ // If s is zero, return any axis (no rotation - axis does not matter)
+ out_axis[0] = 1;
+ out_axis[1] = 0;
+ out_axis[2] = 0;
+ }
+
+ return rad;
+}
+/**
+ * Gets the angular distance between two unit quaternions
+ *
+ * @param {ReadonlyQuat} a Origin unit quaternion
+ * @param {ReadonlyQuat} b Destination unit quaternion
+ * @return {Number} Angle, in radians, between the two quaternions
+ */
+
+
+function getAngle(a, b) {
+ var dotproduct = dot(a, b);
+ return Math.acos(2 * dotproduct * dotproduct - 1);
+}
+/**
+ * Multiplies two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {quat} out
+ */
+
+
+function multiply(out, a, b) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bx = b[0],
+ by = b[1],
+ bz = b[2],
+ bw = b[3];
+ out[0] = ax * bw + aw * bx + ay * bz - az * by;
+ out[1] = ay * bw + aw * by + az * bx - ax * bz;
+ out[2] = az * bw + aw * bz + ax * by - ay * bx;
+ out[3] = aw * bw - ax * bx - ay * by - az * bz;
+ return out;
+}
+/**
+ * Rotates a quaternion by the given angle about the X axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+
+
+function rotateX(out, a, rad) {
+ rad *= 0.5;
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bx = Math.sin(rad),
+ bw = Math.cos(rad);
+ out[0] = ax * bw + aw * bx;
+ out[1] = ay * bw + az * bx;
+ out[2] = az * bw - ay * bx;
+ out[3] = aw * bw - ax * bx;
+ return out;
+}
+/**
+ * Rotates a quaternion by the given angle about the Y axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+
+
+function rotateY(out, a, rad) {
+ rad *= 0.5;
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var by = Math.sin(rad),
+ bw = Math.cos(rad);
+ out[0] = ax * bw - az * by;
+ out[1] = ay * bw + aw * by;
+ out[2] = az * bw + ax * by;
+ out[3] = aw * bw - ay * by;
+ return out;
+}
+/**
+ * Rotates a quaternion by the given angle about the Z axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+
+
+function rotateZ(out, a, rad) {
+ rad *= 0.5;
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bz = Math.sin(rad),
+ bw = Math.cos(rad);
+ out[0] = ax * bw + ay * bz;
+ out[1] = ay * bw - ax * bz;
+ out[2] = az * bw + aw * bz;
+ out[3] = aw * bw - az * bz;
+ return out;
+}
+/**
+ * Calculates the W component of a quat from the X, Y, and Z components.
+ * Assumes that quaternion is 1 unit in length.
+ * Any existing W component will be ignored.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate W component of
+ * @returns {quat} out
+ */
+
+
+function calculateW(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
+ return out;
+}
+/**
+ * Calculate the exponential of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @returns {quat} out
+ */
+
+
+function exp(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ var r = Math.sqrt(x * x + y * y + z * z);
+ var et = Math.exp(w);
+ var s = r > 0 ? et * Math.sin(r) / r : 0;
+ out[0] = x * s;
+ out[1] = y * s;
+ out[2] = z * s;
+ out[3] = et * Math.cos(r);
+ return out;
+}
+/**
+ * Calculate the natural logarithm of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @returns {quat} out
+ */
+
+
+function ln(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ var r = Math.sqrt(x * x + y * y + z * z);
+ var t = r > 0 ? Math.atan2(r, w) / r : 0;
+ out[0] = x * t;
+ out[1] = y * t;
+ out[2] = z * t;
+ out[3] = 0.5 * Math.log(x * x + y * y + z * z + w * w);
+ return out;
+}
+/**
+ * Calculate the scalar power of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @param {Number} b amount to scale the quaternion by
+ * @returns {quat} out
+ */
+
+
+function pow(out, a, b) {
+ ln(out, a);
+ scale(out, out, b);
+ exp(out, out);
+ return out;
+}
+/**
+ * Performs a spherical linear interpolation between two quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ */
+
+
+function slerp(out, a, b, t) {
+ // benchmarks:
+ // http://jsperf.com/quaternion-slerp-implementations
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bx = b[0],
+ by = b[1],
+ bz = b[2],
+ bw = b[3];
+ var omega, cosom, sinom, scale0, scale1; // calc cosine
+
+ cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary)
+
+ if (cosom < 0.0) {
+ cosom = -cosom;
+ bx = -bx;
+ by = -by;
+ bz = -bz;
+ bw = -bw;
+ } // calculate coefficients
+
+
+ if (1.0 - cosom > glMatrix.EPSILON) {
+ // standard case (slerp)
+ omega = Math.acos(cosom);
+ sinom = Math.sin(omega);
+ scale0 = Math.sin((1.0 - t) * omega) / sinom;
+ scale1 = Math.sin(t * omega) / sinom;
+ } else {
+ // "from" and "to" quaternions are very close
+ // ... so we can do a linear interpolation
+ scale0 = 1.0 - t;
+ scale1 = t;
+ } // calculate final values
+
+
+ out[0] = scale0 * ax + scale1 * bx;
+ out[1] = scale0 * ay + scale1 * by;
+ out[2] = scale0 * az + scale1 * bz;
+ out[3] = scale0 * aw + scale1 * bw;
+ return out;
+}
+/**
+ * Generates a random unit quaternion
+ *
+ * @param {quat} out the receiving quaternion
+ * @returns {quat} out
+ */
+
+
+function random(out) {
+ // Implementation of http://planning.cs.uiuc.edu/node198.html
+ // TODO: Calling random 3 times is probably not the fastest solution
+ var u1 = glMatrix.RANDOM();
+ var u2 = glMatrix.RANDOM();
+ var u3 = glMatrix.RANDOM();
+ var sqrt1MinusU1 = Math.sqrt(1 - u1);
+ var sqrtU1 = Math.sqrt(u1);
+ out[0] = sqrt1MinusU1 * Math.sin(2.0 * Math.PI * u2);
+ out[1] = sqrt1MinusU1 * Math.cos(2.0 * Math.PI * u2);
+ out[2] = sqrtU1 * Math.sin(2.0 * Math.PI * u3);
+ out[3] = sqrtU1 * Math.cos(2.0 * Math.PI * u3);
+ return out;
+}
+/**
+ * Calculates the inverse of a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate inverse of
+ * @returns {quat} out
+ */
+
+
+function invert(out, a) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
+ var invDot = dot ? 1.0 / dot : 0; // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
+
+ out[0] = -a0 * invDot;
+ out[1] = -a1 * invDot;
+ out[2] = -a2 * invDot;
+ out[3] = a3 * invDot;
+ return out;
+}
+/**
+ * Calculates the conjugate of a quat
+ * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate conjugate of
+ * @returns {quat} out
+ */
+
+
+function conjugate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Creates a quaternion from the given 3x3 rotation matrix.
+ *
+ * NOTE: The resultant quaternion is not normalized, so you should be sure
+ * to renormalize the quaternion yourself where necessary.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyMat3} m rotation matrix
+ * @returns {quat} out
+ * @function
+ */
+
+
+function fromMat3(out, m) {
+ // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
+ // article "Quaternion Calculus and Fast Animation".
+ var fTrace = m[0] + m[4] + m[8];
+ var fRoot;
+
+ if (fTrace > 0.0) {
+ // |w| > 1/2, may as well choose w > 1/2
+ fRoot = Math.sqrt(fTrace + 1.0); // 2w
+
+ out[3] = 0.5 * fRoot;
+ fRoot = 0.5 / fRoot; // 1/(4w)
+
+ out[0] = (m[5] - m[7]) * fRoot;
+ out[1] = (m[6] - m[2]) * fRoot;
+ out[2] = (m[1] - m[3]) * fRoot;
+ } else {
+ // |w| <= 1/2
+ var i = 0;
+ if (m[4] > m[0]) i = 1;
+ if (m[8] > m[i * 3 + i]) i = 2;
+ var j = (i + 1) % 3;
+ var k = (i + 2) % 3;
+ fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0);
+ out[i] = 0.5 * fRoot;
+ fRoot = 0.5 / fRoot;
+ out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot;
+ out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;
+ out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;
+ }
+
+ return out;
+}
+/**
+ * Creates a quaternion from the given euler angle x, y, z.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {x} Angle to rotate around X axis in degrees.
+ * @param {y} Angle to rotate around Y axis in degrees.
+ * @param {z} Angle to rotate around Z axis in degrees.
+ * @returns {quat} out
+ * @function
+ */
+
+
+function fromEuler(out, x, y, z) {
+ var halfToRad = 0.5 * Math.PI / 180.0;
+ x *= halfToRad;
+ y *= halfToRad;
+ z *= halfToRad;
+ var sx = Math.sin(x);
+ var cx = Math.cos(x);
+ var sy = Math.sin(y);
+ var cy = Math.cos(y);
+ var sz = Math.sin(z);
+ var cz = Math.cos(z);
+ out[0] = sx * cy * cz - cx * sy * sz;
+ out[1] = cx * sy * cz + sx * cy * sz;
+ out[2] = cx * cy * sz - sx * sy * cz;
+ out[3] = cx * cy * cz + sx * sy * sz;
+ return out;
+}
+/**
+ * Returns a string representation of a quatenion
+ *
+ * @param {ReadonlyQuat} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+
+function str(a) {
+ return "quat(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")";
+}
+/**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {ReadonlyQuat} a quaternion to clone
+ * @returns {quat} a new quaternion
+ * @function
+ */
+
+
+var clone = vec4.clone;
+/**
+ * Creates a new quat initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} a new quaternion
+ * @function
+ */
+
+exports.clone = clone;
+var fromValues = vec4.fromValues;
+/**
+ * Copy the values from one quat to another
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the source quaternion
+ * @returns {quat} out
+ * @function
+ */
+
+exports.fromValues = fromValues;
+var copy = vec4.copy;
+/**
+ * Set the components of a quat to the given values
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} out
+ * @function
+ */
+
+exports.copy = copy;
+var set = vec4.set;
+/**
+ * Adds two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {quat} out
+ * @function
+ */
+
+exports.set = set;
+var add = vec4.add;
+/**
+ * Alias for {@link quat.multiply}
+ * @function
+ */
+
+exports.add = add;
+var mul = multiply;
+/**
+ * Scales a quat by a scalar number
+ *
+ * @param {quat} out the receiving vector
+ * @param {ReadonlyQuat} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {quat} out
+ * @function
+ */
+
+exports.mul = mul;
+var scale = vec4.scale;
+/**
+ * Calculates the dot product of two quat's
+ *
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+
+exports.scale = scale;
+var dot = vec4.dot;
+/**
+ * Performs a linear interpolation between two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ * @function
+ */
+
+exports.dot = dot;
+var lerp = vec4.lerp;
+/**
+ * Calculates the length of a quat
+ *
+ * @param {ReadonlyQuat} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+exports.lerp = lerp;
+var length = vec4.length;
+/**
+ * Alias for {@link quat.length}
+ * @function
+ */
+
+exports.length = length;
+var len = length;
+/**
+ * Calculates the squared length of a quat
+ *
+ * @param {ReadonlyQuat} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+
+exports.len = len;
+var squaredLength = vec4.squaredLength;
+/**
+ * Alias for {@link quat.squaredLength}
+ * @function
+ */
+
+exports.squaredLength = squaredLength;
+var sqrLen = squaredLength;
+/**
+ * Normalize a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quaternion to normalize
+ * @returns {quat} out
+ * @function
+ */
+
+exports.sqrLen = sqrLen;
+var normalize = vec4.normalize;
+/**
+ * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyQuat} a The first quaternion.
+ * @param {ReadonlyQuat} b The second quaternion.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+exports.normalize = normalize;
+var exactEquals = vec4.exactEquals;
+/**
+ * Returns whether or not the quaternions have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyQuat} a The first vector.
+ * @param {ReadonlyQuat} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+exports.exactEquals = exactEquals;
+var equals = vec4.equals;
+/**
+ * Sets a quaternion to represent the shortest rotation from one
+ * vector to another.
+ *
+ * Both vectors are assumed to be unit length.
+ *
+ * @param {quat} out the receiving quaternion.
+ * @param {ReadonlyVec3} a the initial vector
+ * @param {ReadonlyVec3} b the destination vector
+ * @returns {quat} out
+ */
+
+exports.equals = equals;
+
+var rotationTo = function () {
+ var tmpvec3 = vec3.create();
+ var xUnitVec3 = vec3.fromValues(1, 0, 0);
+ var yUnitVec3 = vec3.fromValues(0, 1, 0);
+ return function (out, a, b) {
+ var dot = vec3.dot(a, b);
+
+ if (dot < -0.999999) {
+ vec3.cross(tmpvec3, xUnitVec3, a);
+ if (vec3.len(tmpvec3) < 0.000001) vec3.cross(tmpvec3, yUnitVec3, a);
+ vec3.normalize(tmpvec3, tmpvec3);
+ setAxisAngle(out, tmpvec3, Math.PI);
+ return out;
+ } else if (dot > 0.999999) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ } else {
+ vec3.cross(tmpvec3, a, b);
+ out[0] = tmpvec3[0];
+ out[1] = tmpvec3[1];
+ out[2] = tmpvec3[2];
+ out[3] = 1 + dot;
+ return normalize(out, out);
+ }
+ };
+}();
+/**
+ * Performs a spherical linear interpolation with two control points
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {ReadonlyQuat} c the third operand
+ * @param {ReadonlyQuat} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ */
+
+
+exports.rotationTo = rotationTo;
+
+var sqlerp = function () {
+ var temp1 = create();
+ var temp2 = create();
+ return function (out, a, b, c, d, t) {
+ slerp(temp1, a, d, t);
+ slerp(temp2, b, c, t);
+ slerp(out, temp1, temp2, 2 * t * (1 - t));
+ return out;
+ };
+}();
+/**
+ * Sets the specified quaternion with values corresponding to the given
+ * axes. Each axis is a vec3 and is expected to be unit length and
+ * perpendicular to all other specified axes.
+ *
+ * @param {ReadonlyVec3} view the vector representing the viewing direction
+ * @param {ReadonlyVec3} right the vector representing the local "right" direction
+ * @param {ReadonlyVec3} up the vector representing the local "up" direction
+ * @returns {quat} out
+ */
+
+
+exports.sqlerp = sqlerp;
+
+var setAxes = function () {
+ var matr = mat3.create();
+ return function (out, view, right, up) {
+ matr[0] = right[0];
+ matr[3] = right[1];
+ matr[6] = right[2];
+ matr[1] = up[0];
+ matr[4] = up[1];
+ matr[7] = up[2];
+ matr[2] = -view[0];
+ matr[5] = -view[1];
+ matr[8] = -view[2];
+ return normalize(out, fromMat3(out, matr));
+ };
+}();
+
+exports.setAxes = setAxes;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/cjs/quat2.js b/public/node_modules/gl-matrix/cjs/quat2.js
new file mode 100644
index 0000000..fa92010
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/quat2.js
@@ -0,0 +1,924 @@
+"use strict";
+
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.create = create;
+exports.clone = clone;
+exports.fromValues = fromValues;
+exports.fromRotationTranslationValues = fromRotationTranslationValues;
+exports.fromRotationTranslation = fromRotationTranslation;
+exports.fromTranslation = fromTranslation;
+exports.fromRotation = fromRotation;
+exports.fromMat4 = fromMat4;
+exports.copy = copy;
+exports.identity = identity;
+exports.set = set;
+exports.getDual = getDual;
+exports.setDual = setDual;
+exports.getTranslation = getTranslation;
+exports.translate = translate;
+exports.rotateX = rotateX;
+exports.rotateY = rotateY;
+exports.rotateZ = rotateZ;
+exports.rotateByQuatAppend = rotateByQuatAppend;
+exports.rotateByQuatPrepend = rotateByQuatPrepend;
+exports.rotateAroundAxis = rotateAroundAxis;
+exports.add = add;
+exports.multiply = multiply;
+exports.scale = scale;
+exports.lerp = lerp;
+exports.invert = invert;
+exports.conjugate = conjugate;
+exports.normalize = normalize;
+exports.str = str;
+exports.exactEquals = exactEquals;
+exports.equals = equals;
+exports.sqrLen = exports.squaredLength = exports.len = exports.length = exports.dot = exports.mul = exports.setReal = exports.getReal = void 0;
+
+var glMatrix = _interopRequireWildcard(require("./common.js"));
+
+var quat = _interopRequireWildcard(require("./quat.js"));
+
+var mat4 = _interopRequireWildcard(require("./mat4.js"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+/**
+ * Dual Quaternion
+ * Format: [real, dual]
+ * Quaternion format: XYZW
+ * Make sure to have normalized dual quaternions, otherwise the functions may not work as intended.
+ * @module quat2
+ */
+
+/**
+ * Creates a new identity dual quat
+ *
+ * @returns {quat2} a new dual quaternion [real -> rotation, dual -> translation]
+ */
+function create() {
+ var dq = new glMatrix.ARRAY_TYPE(8);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ dq[0] = 0;
+ dq[1] = 0;
+ dq[2] = 0;
+ dq[4] = 0;
+ dq[5] = 0;
+ dq[6] = 0;
+ dq[7] = 0;
+ }
+
+ dq[3] = 1;
+ return dq;
+}
+/**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {ReadonlyQuat2} a dual quaternion to clone
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+
+
+function clone(a) {
+ var dq = new glMatrix.ARRAY_TYPE(8);
+ dq[0] = a[0];
+ dq[1] = a[1];
+ dq[2] = a[2];
+ dq[3] = a[3];
+ dq[4] = a[4];
+ dq[5] = a[5];
+ dq[6] = a[6];
+ dq[7] = a[7];
+ return dq;
+}
+/**
+ * Creates a new dual quat initialized with the given values
+ *
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component
+ * @param {Number} y2 Y component
+ * @param {Number} z2 Z component
+ * @param {Number} w2 W component
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+
+
+function fromValues(x1, y1, z1, w1, x2, y2, z2, w2) {
+ var dq = new glMatrix.ARRAY_TYPE(8);
+ dq[0] = x1;
+ dq[1] = y1;
+ dq[2] = z1;
+ dq[3] = w1;
+ dq[4] = x2;
+ dq[5] = y2;
+ dq[6] = z2;
+ dq[7] = w2;
+ return dq;
+}
+/**
+ * Creates a new dual quat from the given values (quat and translation)
+ *
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component (translation)
+ * @param {Number} y2 Y component (translation)
+ * @param {Number} z2 Z component (translation)
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+
+
+function fromRotationTranslationValues(x1, y1, z1, w1, x2, y2, z2) {
+ var dq = new glMatrix.ARRAY_TYPE(8);
+ dq[0] = x1;
+ dq[1] = y1;
+ dq[2] = z1;
+ dq[3] = w1;
+ var ax = x2 * 0.5,
+ ay = y2 * 0.5,
+ az = z2 * 0.5;
+ dq[4] = ax * w1 + ay * z1 - az * y1;
+ dq[5] = ay * w1 + az * x1 - ax * z1;
+ dq[6] = az * w1 + ax * y1 - ay * x1;
+ dq[7] = -ax * x1 - ay * y1 - az * z1;
+ return dq;
+}
+/**
+ * Creates a dual quat from a quaternion and a translation
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyQuat} q a normalized quaternion
+ * @param {ReadonlyVec3} t tranlation vector
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+
+
+function fromRotationTranslation(out, q, t) {
+ var ax = t[0] * 0.5,
+ ay = t[1] * 0.5,
+ az = t[2] * 0.5,
+ bx = q[0],
+ by = q[1],
+ bz = q[2],
+ bw = q[3];
+ out[0] = bx;
+ out[1] = by;
+ out[2] = bz;
+ out[3] = bw;
+ out[4] = ax * bw + ay * bz - az * by;
+ out[5] = ay * bw + az * bx - ax * bz;
+ out[6] = az * bw + ax * by - ay * bx;
+ out[7] = -ax * bx - ay * by - az * bz;
+ return out;
+}
+/**
+ * Creates a dual quat from a translation
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyVec3} t translation vector
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+
+
+function fromTranslation(out, t) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = t[0] * 0.5;
+ out[5] = t[1] * 0.5;
+ out[6] = t[2] * 0.5;
+ out[7] = 0;
+ return out;
+}
+/**
+ * Creates a dual quat from a quaternion
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyQuat} q the quaternion
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+
+
+function fromRotation(out, q) {
+ out[0] = q[0];
+ out[1] = q[1];
+ out[2] = q[2];
+ out[3] = q[3];
+ out[4] = 0;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ return out;
+}
+/**
+ * Creates a new dual quat from a matrix (4x4)
+ *
+ * @param {quat2} out the dual quaternion
+ * @param {ReadonlyMat4} a the matrix
+ * @returns {quat2} dual quat receiving operation result
+ * @function
+ */
+
+
+function fromMat4(out, a) {
+ //TODO Optimize this
+ var outer = quat.create();
+ mat4.getRotation(outer, a);
+ var t = new glMatrix.ARRAY_TYPE(3);
+ mat4.getTranslation(t, a);
+ fromRotationTranslation(out, outer, t);
+ return out;
+}
+/**
+ * Copy the values from one dual quat to another
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the source dual quaternion
+ * @returns {quat2} out
+ * @function
+ */
+
+
+function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ return out;
+}
+/**
+ * Set a dual quat to the identity dual quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @returns {quat2} out
+ */
+
+
+function identity(out) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = 0;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ return out;
+}
+/**
+ * Set the components of a dual quat to the given values
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component
+ * @param {Number} y2 Y component
+ * @param {Number} z2 Z component
+ * @param {Number} w2 W component
+ * @returns {quat2} out
+ * @function
+ */
+
+
+function set(out, x1, y1, z1, w1, x2, y2, z2, w2) {
+ out[0] = x1;
+ out[1] = y1;
+ out[2] = z1;
+ out[3] = w1;
+ out[4] = x2;
+ out[5] = y2;
+ out[6] = z2;
+ out[7] = w2;
+ return out;
+}
+/**
+ * Gets the real part of a dual quat
+ * @param {quat} out real part
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @return {quat} real part
+ */
+
+
+var getReal = quat.copy;
+/**
+ * Gets the dual part of a dual quat
+ * @param {quat} out dual part
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @return {quat} dual part
+ */
+
+exports.getReal = getReal;
+
+function getDual(out, a) {
+ out[0] = a[4];
+ out[1] = a[5];
+ out[2] = a[6];
+ out[3] = a[7];
+ return out;
+}
+/**
+ * Set the real component of a dual quat to the given quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat} q a quaternion representing the real part
+ * @returns {quat2} out
+ * @function
+ */
+
+
+var setReal = quat.copy;
+/**
+ * Set the dual component of a dual quat to the given quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat} q a quaternion representing the dual part
+ * @returns {quat2} out
+ * @function
+ */
+
+exports.setReal = setReal;
+
+function setDual(out, q) {
+ out[4] = q[0];
+ out[5] = q[1];
+ out[6] = q[2];
+ out[7] = q[3];
+ return out;
+}
+/**
+ * Gets the translation of a normalized dual quat
+ * @param {vec3} out translation
+ * @param {ReadonlyQuat2} a Dual Quaternion to be decomposed
+ * @return {vec3} translation
+ */
+
+
+function getTranslation(out, a) {
+ var ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3];
+ out[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
+ out[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
+ out[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
+ return out;
+}
+/**
+ * Translates a dual quat by the given vector
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to translate
+ * @param {ReadonlyVec3} v vector to translate by
+ * @returns {quat2} out
+ */
+
+
+function translate(out, a, v) {
+ var ax1 = a[0],
+ ay1 = a[1],
+ az1 = a[2],
+ aw1 = a[3],
+ bx1 = v[0] * 0.5,
+ by1 = v[1] * 0.5,
+ bz1 = v[2] * 0.5,
+ ax2 = a[4],
+ ay2 = a[5],
+ az2 = a[6],
+ aw2 = a[7];
+ out[0] = ax1;
+ out[1] = ay1;
+ out[2] = az1;
+ out[3] = aw1;
+ out[4] = aw1 * bx1 + ay1 * bz1 - az1 * by1 + ax2;
+ out[5] = aw1 * by1 + az1 * bx1 - ax1 * bz1 + ay2;
+ out[6] = aw1 * bz1 + ax1 * by1 - ay1 * bx1 + az2;
+ out[7] = -ax1 * bx1 - ay1 * by1 - az1 * bz1 + aw2;
+ return out;
+}
+/**
+ * Rotates a dual quat around the X axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+
+
+function rotateX(out, a, rad) {
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ ax1 = ax * bw + aw * bx + ay * bz - az * by,
+ ay1 = ay * bw + aw * by + az * bx - ax * bz,
+ az1 = az * bw + aw * bz + ax * by - ay * bx,
+ aw1 = aw * bw - ax * bx - ay * by - az * bz;
+ quat.rotateX(out, a, rad);
+ bx = out[0];
+ by = out[1];
+ bz = out[2];
+ bw = out[3];
+ out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ return out;
+}
+/**
+ * Rotates a dual quat around the Y axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+
+
+function rotateY(out, a, rad) {
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ ax1 = ax * bw + aw * bx + ay * bz - az * by,
+ ay1 = ay * bw + aw * by + az * bx - ax * bz,
+ az1 = az * bw + aw * bz + ax * by - ay * bx,
+ aw1 = aw * bw - ax * bx - ay * by - az * bz;
+ quat.rotateY(out, a, rad);
+ bx = out[0];
+ by = out[1];
+ bz = out[2];
+ bw = out[3];
+ out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ return out;
+}
+/**
+ * Rotates a dual quat around the Z axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+
+
+function rotateZ(out, a, rad) {
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ ax1 = ax * bw + aw * bx + ay * bz - az * by,
+ ay1 = ay * bw + aw * by + az * bx - ax * bz,
+ az1 = az * bw + aw * bz + ax * by - ay * bx,
+ aw1 = aw * bw - ax * bx - ay * by - az * bz;
+ quat.rotateZ(out, a, rad);
+ bx = out[0];
+ by = out[1];
+ bz = out[2];
+ bw = out[3];
+ out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ return out;
+}
+/**
+ * Rotates a dual quat by a given quaternion (a * q)
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {ReadonlyQuat} q quaternion to rotate by
+ * @returns {quat2} out
+ */
+
+
+function rotateByQuatAppend(out, a, q) {
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3],
+ ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ out[0] = ax * qw + aw * qx + ay * qz - az * qy;
+ out[1] = ay * qw + aw * qy + az * qx - ax * qz;
+ out[2] = az * qw + aw * qz + ax * qy - ay * qx;
+ out[3] = aw * qw - ax * qx - ay * qy - az * qz;
+ ax = a[4];
+ ay = a[5];
+ az = a[6];
+ aw = a[7];
+ out[4] = ax * qw + aw * qx + ay * qz - az * qy;
+ out[5] = ay * qw + aw * qy + az * qx - ax * qz;
+ out[6] = az * qw + aw * qz + ax * qy - ay * qx;
+ out[7] = aw * qw - ax * qx - ay * qy - az * qz;
+ return out;
+}
+/**
+ * Rotates a dual quat by a given quaternion (q * a)
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat} q quaternion to rotate by
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @returns {quat2} out
+ */
+
+
+function rotateByQuatPrepend(out, q, a) {
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3],
+ bx = a[0],
+ by = a[1],
+ bz = a[2],
+ bw = a[3];
+ out[0] = qx * bw + qw * bx + qy * bz - qz * by;
+ out[1] = qy * bw + qw * by + qz * bx - qx * bz;
+ out[2] = qz * bw + qw * bz + qx * by - qy * bx;
+ out[3] = qw * bw - qx * bx - qy * by - qz * bz;
+ bx = a[4];
+ by = a[5];
+ bz = a[6];
+ bw = a[7];
+ out[4] = qx * bw + qw * bx + qy * bz - qz * by;
+ out[5] = qy * bw + qw * by + qz * bx - qx * bz;
+ out[6] = qz * bw + qw * bz + qx * by - qy * bx;
+ out[7] = qw * bw - qx * bx - qy * by - qz * bz;
+ return out;
+}
+/**
+ * Rotates a dual quat around a given axis. Does the normalisation automatically
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @param {Number} rad how far the rotation should be
+ * @returns {quat2} out
+ */
+
+
+function rotateAroundAxis(out, a, axis, rad) {
+ //Special case for rad = 0
+ if (Math.abs(rad) < glMatrix.EPSILON) {
+ return copy(out, a);
+ }
+
+ var axisLength = Math.hypot(axis[0], axis[1], axis[2]);
+ rad = rad * 0.5;
+ var s = Math.sin(rad);
+ var bx = s * axis[0] / axisLength;
+ var by = s * axis[1] / axisLength;
+ var bz = s * axis[2] / axisLength;
+ var bw = Math.cos(rad);
+ var ax1 = a[0],
+ ay1 = a[1],
+ az1 = a[2],
+ aw1 = a[3];
+ out[0] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[1] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[2] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[3] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ var ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7];
+ out[4] = ax * bw + aw * bx + ay * bz - az * by;
+ out[5] = ay * bw + aw * by + az * bx - ax * bz;
+ out[6] = az * bw + aw * bz + ax * by - ay * bx;
+ out[7] = aw * bw - ax * bx - ay * by - az * bz;
+ return out;
+}
+/**
+ * Adds two dual quat's
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {quat2} out
+ * @function
+ */
+
+
+function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ out[6] = a[6] + b[6];
+ out[7] = a[7] + b[7];
+ return out;
+}
+/**
+ * Multiplies two dual quat's
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {quat2} out
+ */
+
+
+function multiply(out, a, b) {
+ var ax0 = a[0],
+ ay0 = a[1],
+ az0 = a[2],
+ aw0 = a[3],
+ bx1 = b[4],
+ by1 = b[5],
+ bz1 = b[6],
+ bw1 = b[7],
+ ax1 = a[4],
+ ay1 = a[5],
+ az1 = a[6],
+ aw1 = a[7],
+ bx0 = b[0],
+ by0 = b[1],
+ bz0 = b[2],
+ bw0 = b[3];
+ out[0] = ax0 * bw0 + aw0 * bx0 + ay0 * bz0 - az0 * by0;
+ out[1] = ay0 * bw0 + aw0 * by0 + az0 * bx0 - ax0 * bz0;
+ out[2] = az0 * bw0 + aw0 * bz0 + ax0 * by0 - ay0 * bx0;
+ out[3] = aw0 * bw0 - ax0 * bx0 - ay0 * by0 - az0 * bz0;
+ out[4] = ax0 * bw1 + aw0 * bx1 + ay0 * bz1 - az0 * by1 + ax1 * bw0 + aw1 * bx0 + ay1 * bz0 - az1 * by0;
+ out[5] = ay0 * bw1 + aw0 * by1 + az0 * bx1 - ax0 * bz1 + ay1 * bw0 + aw1 * by0 + az1 * bx0 - ax1 * bz0;
+ out[6] = az0 * bw1 + aw0 * bz1 + ax0 * by1 - ay0 * bx1 + az1 * bw0 + aw1 * bz0 + ax1 * by0 - ay1 * bx0;
+ out[7] = aw0 * bw1 - ax0 * bx1 - ay0 * by1 - az0 * bz1 + aw1 * bw0 - ax1 * bx0 - ay1 * by0 - az1 * bz0;
+ return out;
+}
+/**
+ * Alias for {@link quat2.multiply}
+ * @function
+ */
+
+
+var mul = multiply;
+/**
+ * Scales a dual quat by a scalar number
+ *
+ * @param {quat2} out the receiving dual quat
+ * @param {ReadonlyQuat2} a the dual quat to scale
+ * @param {Number} b amount to scale the dual quat by
+ * @returns {quat2} out
+ * @function
+ */
+
+exports.mul = mul;
+
+function scale(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ out[6] = a[6] * b;
+ out[7] = a[7] * b;
+ return out;
+}
+/**
+ * Calculates the dot product of two dual quat's (The dot product of the real parts)
+ *
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+
+
+var dot = quat.dot;
+/**
+ * Performs a linear interpolation between two dual quats's
+ * NOTE: The resulting dual quaternions won't always be normalized (The error is most noticeable when t = 0.5)
+ *
+ * @param {quat2} out the receiving dual quat
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat2} out
+ */
+
+exports.dot = dot;
+
+function lerp(out, a, b, t) {
+ var mt = 1 - t;
+ if (dot(a, b) < 0) t = -t;
+ out[0] = a[0] * mt + b[0] * t;
+ out[1] = a[1] * mt + b[1] * t;
+ out[2] = a[2] * mt + b[2] * t;
+ out[3] = a[3] * mt + b[3] * t;
+ out[4] = a[4] * mt + b[4] * t;
+ out[5] = a[5] * mt + b[5] * t;
+ out[6] = a[6] * mt + b[6] * t;
+ out[7] = a[7] * mt + b[7] * t;
+ return out;
+}
+/**
+ * Calculates the inverse of a dual quat. If they are normalized, conjugate is cheaper
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a dual quat to calculate inverse of
+ * @returns {quat2} out
+ */
+
+
+function invert(out, a) {
+ var sqlen = squaredLength(a);
+ out[0] = -a[0] / sqlen;
+ out[1] = -a[1] / sqlen;
+ out[2] = -a[2] / sqlen;
+ out[3] = a[3] / sqlen;
+ out[4] = -a[4] / sqlen;
+ out[5] = -a[5] / sqlen;
+ out[6] = -a[6] / sqlen;
+ out[7] = a[7] / sqlen;
+ return out;
+}
+/**
+ * Calculates the conjugate of a dual quat
+ * If the dual quaternion is normalized, this function is faster than quat2.inverse and produces the same result.
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat2} a quat to calculate conjugate of
+ * @returns {quat2} out
+ */
+
+
+function conjugate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a[3];
+ out[4] = -a[4];
+ out[5] = -a[5];
+ out[6] = -a[6];
+ out[7] = a[7];
+ return out;
+}
+/**
+ * Calculates the length of a dual quat
+ *
+ * @param {ReadonlyQuat2} a dual quat to calculate length of
+ * @returns {Number} length of a
+ * @function
+ */
+
+
+var length = quat.length;
+/**
+ * Alias for {@link quat2.length}
+ * @function
+ */
+
+exports.length = length;
+var len = length;
+/**
+ * Calculates the squared length of a dual quat
+ *
+ * @param {ReadonlyQuat2} a dual quat to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+
+exports.len = len;
+var squaredLength = quat.squaredLength;
+/**
+ * Alias for {@link quat2.squaredLength}
+ * @function
+ */
+
+exports.squaredLength = squaredLength;
+var sqrLen = squaredLength;
+/**
+ * Normalize a dual quat
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a dual quaternion to normalize
+ * @returns {quat2} out
+ * @function
+ */
+
+exports.sqrLen = sqrLen;
+
+function normalize(out, a) {
+ var magnitude = squaredLength(a);
+
+ if (magnitude > 0) {
+ magnitude = Math.sqrt(magnitude);
+ var a0 = a[0] / magnitude;
+ var a1 = a[1] / magnitude;
+ var a2 = a[2] / magnitude;
+ var a3 = a[3] / magnitude;
+ var b0 = a[4];
+ var b1 = a[5];
+ var b2 = a[6];
+ var b3 = a[7];
+ var a_dot_b = a0 * b0 + a1 * b1 + a2 * b2 + a3 * b3;
+ out[0] = a0;
+ out[1] = a1;
+ out[2] = a2;
+ out[3] = a3;
+ out[4] = (b0 - a0 * a_dot_b) / magnitude;
+ out[5] = (b1 - a1 * a_dot_b) / magnitude;
+ out[6] = (b2 - a2 * a_dot_b) / magnitude;
+ out[7] = (b3 - a3 * a_dot_b) / magnitude;
+ }
+
+ return out;
+}
+/**
+ * Returns a string representation of a dual quatenion
+ *
+ * @param {ReadonlyQuat2} a dual quaternion to represent as a string
+ * @returns {String} string representation of the dual quat
+ */
+
+
+function str(a) {
+ return "quat2(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ")";
+}
+/**
+ * Returns whether or not the dual quaternions have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyQuat2} a the first dual quaternion.
+ * @param {ReadonlyQuat2} b the second dual quaternion.
+ * @returns {Boolean} true if the dual quaternions are equal, false otherwise.
+ */
+
+
+function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7];
+}
+/**
+ * Returns whether or not the dual quaternions have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyQuat2} a the first dual quat.
+ * @param {ReadonlyQuat2} b the second dual quat.
+ * @returns {Boolean} true if the dual quats are equal, false otherwise.
+ */
+
+
+function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5],
+ a6 = a[6],
+ a7 = a[7];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5],
+ b6 = b[6],
+ b7 = b[7];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7));
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/cjs/vec2.js b/public/node_modules/gl-matrix/cjs/vec2.js
new file mode 100644
index 0000000..e97cf05
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/vec2.js
@@ -0,0 +1,721 @@
+"use strict";
+
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.create = create;
+exports.clone = clone;
+exports.fromValues = fromValues;
+exports.copy = copy;
+exports.set = set;
+exports.add = add;
+exports.subtract = subtract;
+exports.multiply = multiply;
+exports.divide = divide;
+exports.ceil = ceil;
+exports.floor = floor;
+exports.min = min;
+exports.max = max;
+exports.round = round;
+exports.scale = scale;
+exports.scaleAndAdd = scaleAndAdd;
+exports.distance = distance;
+exports.squaredDistance = squaredDistance;
+exports.length = length;
+exports.squaredLength = squaredLength;
+exports.negate = negate;
+exports.inverse = inverse;
+exports.normalize = normalize;
+exports.dot = dot;
+exports.cross = cross;
+exports.lerp = lerp;
+exports.random = random;
+exports.transformMat2 = transformMat2;
+exports.transformMat2d = transformMat2d;
+exports.transformMat3 = transformMat3;
+exports.transformMat4 = transformMat4;
+exports.rotate = rotate;
+exports.angle = angle;
+exports.zero = zero;
+exports.str = str;
+exports.exactEquals = exactEquals;
+exports.equals = equals;
+exports.forEach = exports.sqrLen = exports.sqrDist = exports.dist = exports.div = exports.mul = exports.sub = exports.len = void 0;
+
+var glMatrix = _interopRequireWildcard(require("./common.js"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+/**
+ * 2 Dimensional Vector
+ * @module vec2
+ */
+
+/**
+ * Creates a new, empty vec2
+ *
+ * @returns {vec2} a new 2D vector
+ */
+function create() {
+ var out = new glMatrix.ARRAY_TYPE(2);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ }
+
+ return out;
+}
+/**
+ * Creates a new vec2 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec2} a vector to clone
+ * @returns {vec2} a new 2D vector
+ */
+
+
+function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(2);
+ out[0] = a[0];
+ out[1] = a[1];
+ return out;
+}
+/**
+ * Creates a new vec2 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} a new 2D vector
+ */
+
+
+function fromValues(x, y) {
+ var out = new glMatrix.ARRAY_TYPE(2);
+ out[0] = x;
+ out[1] = y;
+ return out;
+}
+/**
+ * Copy the values from one vec2 to another
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the source vector
+ * @returns {vec2} out
+ */
+
+
+function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ return out;
+}
+/**
+ * Set the components of a vec2 to the given values
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} out
+ */
+
+
+function set(out, x, y) {
+ out[0] = x;
+ out[1] = y;
+ return out;
+}
+/**
+ * Adds two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+
+function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ return out;
+}
+/**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+
+function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ return out;
+}
+/**
+ * Multiplies two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+
+function multiply(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ return out;
+}
+/**
+ * Divides two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+
+function divide(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ return out;
+}
+/**
+ * Math.ceil the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to ceil
+ * @returns {vec2} out
+ */
+
+
+function ceil(out, a) {
+ out[0] = Math.ceil(a[0]);
+ out[1] = Math.ceil(a[1]);
+ return out;
+}
+/**
+ * Math.floor the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to floor
+ * @returns {vec2} out
+ */
+
+
+function floor(out, a) {
+ out[0] = Math.floor(a[0]);
+ out[1] = Math.floor(a[1]);
+ return out;
+}
+/**
+ * Returns the minimum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+
+function min(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ return out;
+}
+/**
+ * Returns the maximum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+
+function max(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ return out;
+}
+/**
+ * Math.round the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to round
+ * @returns {vec2} out
+ */
+
+
+function round(out, a) {
+ out[0] = Math.round(a[0]);
+ out[1] = Math.round(a[1]);
+ return out;
+}
+/**
+ * Scales a vec2 by a scalar number
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec2} out
+ */
+
+
+function scale(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ return out;
+}
+/**
+ * Adds two vec2's after scaling the second operand by a scalar value
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec2} out
+ */
+
+
+function scaleAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ return out;
+}
+/**
+ * Calculates the euclidian distance between two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} distance between a and b
+ */
+
+
+function distance(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1];
+ return Math.hypot(x, y);
+}
+/**
+ * Calculates the squared euclidian distance between two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+
+
+function squaredDistance(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1];
+ return x * x + y * y;
+}
+/**
+ * Calculates the length of a vec2
+ *
+ * @param {ReadonlyVec2} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+
+function length(a) {
+ var x = a[0],
+ y = a[1];
+ return Math.hypot(x, y);
+}
+/**
+ * Calculates the squared length of a vec2
+ *
+ * @param {ReadonlyVec2} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+
+
+function squaredLength(a) {
+ var x = a[0],
+ y = a[1];
+ return x * x + y * y;
+}
+/**
+ * Negates the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to negate
+ * @returns {vec2} out
+ */
+
+
+function negate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ return out;
+}
+/**
+ * Returns the inverse of the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to invert
+ * @returns {vec2} out
+ */
+
+
+function inverse(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ return out;
+}
+/**
+ * Normalize a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to normalize
+ * @returns {vec2} out
+ */
+
+
+function normalize(out, a) {
+ var x = a[0],
+ y = a[1];
+ var len = x * x + y * y;
+
+ if (len > 0) {
+ //TODO: evaluate use of glm_invsqrt here?
+ len = 1 / Math.sqrt(len);
+ }
+
+ out[0] = a[0] * len;
+ out[1] = a[1] * len;
+ return out;
+}
+/**
+ * Calculates the dot product of two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+
+
+function dot(a, b) {
+ return a[0] * b[0] + a[1] * b[1];
+}
+/**
+ * Computes the cross product of two vec2's
+ * Note that the cross product must by definition produce a 3D vector
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec3} out
+ */
+
+
+function cross(out, a, b) {
+ var z = a[0] * b[1] - a[1] * b[0];
+ out[0] = out[1] = 0;
+ out[2] = z;
+ return out;
+}
+/**
+ * Performs a linear interpolation between two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec2} out
+ */
+
+
+function lerp(out, a, b, t) {
+ var ax = a[0],
+ ay = a[1];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ return out;
+}
+/**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec2} out
+ */
+
+
+function random(out, scale) {
+ scale = scale || 1.0;
+ var r = glMatrix.RANDOM() * 2.0 * Math.PI;
+ out[0] = Math.cos(r) * scale;
+ out[1] = Math.sin(r) * scale;
+ return out;
+}
+/**
+ * Transforms the vec2 with a mat2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat2} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+
+function transformMat2(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[2] * y;
+ out[1] = m[1] * x + m[3] * y;
+ return out;
+}
+/**
+ * Transforms the vec2 with a mat2d
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat2d} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+
+function transformMat2d(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[2] * y + m[4];
+ out[1] = m[1] * x + m[3] * y + m[5];
+ return out;
+}
+/**
+ * Transforms the vec2 with a mat3
+ * 3rd vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat3} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+
+function transformMat3(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[3] * y + m[6];
+ out[1] = m[1] * x + m[4] * y + m[7];
+ return out;
+}
+/**
+ * Transforms the vec2 with a mat4
+ * 3rd vector component is implicitly '0'
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+
+function transformMat4(out, a, m) {
+ var x = a[0];
+ var y = a[1];
+ out[0] = m[0] * x + m[4] * y + m[12];
+ out[1] = m[1] * x + m[5] * y + m[13];
+ return out;
+}
+/**
+ * Rotate a 2D vector
+ * @param {vec2} out The receiving vec2
+ * @param {ReadonlyVec2} a The vec2 point to rotate
+ * @param {ReadonlyVec2} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec2} out
+ */
+
+
+function rotate(out, a, b, rad) {
+ //Translate point to the origin
+ var p0 = a[0] - b[0],
+ p1 = a[1] - b[1],
+ sinC = Math.sin(rad),
+ cosC = Math.cos(rad); //perform rotation and translate to correct position
+
+ out[0] = p0 * cosC - p1 * sinC + b[0];
+ out[1] = p0 * sinC + p1 * cosC + b[1];
+ return out;
+}
+/**
+ * Get the angle between two 2D vectors
+ * @param {ReadonlyVec2} a The first operand
+ * @param {ReadonlyVec2} b The second operand
+ * @returns {Number} The angle in radians
+ */
+
+
+function angle(a, b) {
+ var x1 = a[0],
+ y1 = a[1],
+ x2 = b[0],
+ y2 = b[1],
+ // mag is the product of the magnitudes of a and b
+ mag = Math.sqrt(x1 * x1 + y1 * y1) * Math.sqrt(x2 * x2 + y2 * y2),
+ // mag &&.. short circuits if mag == 0
+ cosine = mag && (x1 * x2 + y1 * y2) / mag; // Math.min(Math.max(cosine, -1), 1) clamps the cosine between -1 and 1
+
+ return Math.acos(Math.min(Math.max(cosine, -1), 1));
+}
+/**
+ * Set the components of a vec2 to zero
+ *
+ * @param {vec2} out the receiving vector
+ * @returns {vec2} out
+ */
+
+
+function zero(out) {
+ out[0] = 0.0;
+ out[1] = 0.0;
+ return out;
+}
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec2} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+
+function str(a) {
+ return "vec2(" + a[0] + ", " + a[1] + ")";
+}
+/**
+ * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec2} a The first vector.
+ * @param {ReadonlyVec2} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+
+function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1];
+}
+/**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec2} a The first vector.
+ * @param {ReadonlyVec2} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+
+function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1];
+ var b0 = b[0],
+ b1 = b[1];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1));
+}
+/**
+ * Alias for {@link vec2.length}
+ * @function
+ */
+
+
+var len = length;
+/**
+ * Alias for {@link vec2.subtract}
+ * @function
+ */
+
+exports.len = len;
+var sub = subtract;
+/**
+ * Alias for {@link vec2.multiply}
+ * @function
+ */
+
+exports.sub = sub;
+var mul = multiply;
+/**
+ * Alias for {@link vec2.divide}
+ * @function
+ */
+
+exports.mul = mul;
+var div = divide;
+/**
+ * Alias for {@link vec2.distance}
+ * @function
+ */
+
+exports.div = div;
+var dist = distance;
+/**
+ * Alias for {@link vec2.squaredDistance}
+ * @function
+ */
+
+exports.dist = dist;
+var sqrDist = squaredDistance;
+/**
+ * Alias for {@link vec2.squaredLength}
+ * @function
+ */
+
+exports.sqrDist = sqrDist;
+var sqrLen = squaredLength;
+/**
+ * Perform some operation over an array of vec2s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+
+exports.sqrLen = sqrLen;
+
+var forEach = function () {
+ var vec = create();
+ return function (a, stride, offset, count, fn, arg) {
+ var i, l;
+
+ if (!stride) {
+ stride = 2;
+ }
+
+ if (!offset) {
+ offset = 0;
+ }
+
+ if (count) {
+ l = Math.min(count * stride + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for (i = offset; i < l; i += stride) {
+ vec[0] = a[i];
+ vec[1] = a[i + 1];
+ fn(vec, vec, arg);
+ a[i] = vec[0];
+ a[i + 1] = vec[1];
+ }
+
+ return a;
+ };
+}();
+
+exports.forEach = forEach;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/cjs/vec3.js b/public/node_modules/gl-matrix/cjs/vec3.js
new file mode 100644
index 0000000..d734cc9
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/vec3.js
@@ -0,0 +1,890 @@
+"use strict";
+
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.create = create;
+exports.clone = clone;
+exports.length = length;
+exports.fromValues = fromValues;
+exports.copy = copy;
+exports.set = set;
+exports.add = add;
+exports.subtract = subtract;
+exports.multiply = multiply;
+exports.divide = divide;
+exports.ceil = ceil;
+exports.floor = floor;
+exports.min = min;
+exports.max = max;
+exports.round = round;
+exports.scale = scale;
+exports.scaleAndAdd = scaleAndAdd;
+exports.distance = distance;
+exports.squaredDistance = squaredDistance;
+exports.squaredLength = squaredLength;
+exports.negate = negate;
+exports.inverse = inverse;
+exports.normalize = normalize;
+exports.dot = dot;
+exports.cross = cross;
+exports.lerp = lerp;
+exports.hermite = hermite;
+exports.bezier = bezier;
+exports.random = random;
+exports.transformMat4 = transformMat4;
+exports.transformMat3 = transformMat3;
+exports.transformQuat = transformQuat;
+exports.rotateX = rotateX;
+exports.rotateY = rotateY;
+exports.rotateZ = rotateZ;
+exports.angle = angle;
+exports.zero = zero;
+exports.str = str;
+exports.exactEquals = exactEquals;
+exports.equals = equals;
+exports.forEach = exports.sqrLen = exports.len = exports.sqrDist = exports.dist = exports.div = exports.mul = exports.sub = void 0;
+
+var glMatrix = _interopRequireWildcard(require("./common.js"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+/**
+ * 3 Dimensional Vector
+ * @module vec3
+ */
+
+/**
+ * Creates a new, empty vec3
+ *
+ * @returns {vec3} a new 3D vector
+ */
+function create() {
+ var out = new glMatrix.ARRAY_TYPE(3);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ }
+
+ return out;
+}
+/**
+ * Creates a new vec3 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec3} a vector to clone
+ * @returns {vec3} a new 3D vector
+ */
+
+
+function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(3);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ return out;
+}
+/**
+ * Calculates the length of a vec3
+ *
+ * @param {ReadonlyVec3} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+
+function length(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ return Math.hypot(x, y, z);
+}
+/**
+ * Creates a new vec3 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} a new 3D vector
+ */
+
+
+function fromValues(x, y, z) {
+ var out = new glMatrix.ARRAY_TYPE(3);
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ return out;
+}
+/**
+ * Copy the values from one vec3 to another
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the source vector
+ * @returns {vec3} out
+ */
+
+
+function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ return out;
+}
+/**
+ * Set the components of a vec3 to the given values
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} out
+ */
+
+
+function set(out, x, y, z) {
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ return out;
+}
+/**
+ * Adds two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+
+function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ return out;
+}
+/**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+
+function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ return out;
+}
+/**
+ * Multiplies two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+
+function multiply(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ out[2] = a[2] * b[2];
+ return out;
+}
+/**
+ * Divides two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+
+function divide(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ out[2] = a[2] / b[2];
+ return out;
+}
+/**
+ * Math.ceil the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to ceil
+ * @returns {vec3} out
+ */
+
+
+function ceil(out, a) {
+ out[0] = Math.ceil(a[0]);
+ out[1] = Math.ceil(a[1]);
+ out[2] = Math.ceil(a[2]);
+ return out;
+}
+/**
+ * Math.floor the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to floor
+ * @returns {vec3} out
+ */
+
+
+function floor(out, a) {
+ out[0] = Math.floor(a[0]);
+ out[1] = Math.floor(a[1]);
+ out[2] = Math.floor(a[2]);
+ return out;
+}
+/**
+ * Returns the minimum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+
+function min(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ out[2] = Math.min(a[2], b[2]);
+ return out;
+}
+/**
+ * Returns the maximum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+
+function max(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ out[2] = Math.max(a[2], b[2]);
+ return out;
+}
+/**
+ * Math.round the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to round
+ * @returns {vec3} out
+ */
+
+
+function round(out, a) {
+ out[0] = Math.round(a[0]);
+ out[1] = Math.round(a[1]);
+ out[2] = Math.round(a[2]);
+ return out;
+}
+/**
+ * Scales a vec3 by a scalar number
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec3} out
+ */
+
+
+function scale(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ return out;
+}
+/**
+ * Adds two vec3's after scaling the second operand by a scalar value
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec3} out
+ */
+
+
+function scaleAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ return out;
+}
+/**
+ * Calculates the euclidian distance between two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} distance between a and b
+ */
+
+
+function distance(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ return Math.hypot(x, y, z);
+}
+/**
+ * Calculates the squared euclidian distance between two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+
+
+function squaredDistance(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ return x * x + y * y + z * z;
+}
+/**
+ * Calculates the squared length of a vec3
+ *
+ * @param {ReadonlyVec3} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+
+
+function squaredLength(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ return x * x + y * y + z * z;
+}
+/**
+ * Negates the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to negate
+ * @returns {vec3} out
+ */
+
+
+function negate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ return out;
+}
+/**
+ * Returns the inverse of the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to invert
+ * @returns {vec3} out
+ */
+
+
+function inverse(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ out[2] = 1.0 / a[2];
+ return out;
+}
+/**
+ * Normalize a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to normalize
+ * @returns {vec3} out
+ */
+
+
+function normalize(out, a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var len = x * x + y * y + z * z;
+
+ if (len > 0) {
+ //TODO: evaluate use of glm_invsqrt here?
+ len = 1 / Math.sqrt(len);
+ }
+
+ out[0] = a[0] * len;
+ out[1] = a[1] * len;
+ out[2] = a[2] * len;
+ return out;
+}
+/**
+ * Calculates the dot product of two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+
+
+function dot(a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+/**
+ * Computes the cross product of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+
+function cross(out, a, b) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2];
+ var bx = b[0],
+ by = b[1],
+ bz = b[2];
+ out[0] = ay * bz - az * by;
+ out[1] = az * bx - ax * bz;
+ out[2] = ax * by - ay * bx;
+ return out;
+}
+/**
+ * Performs a linear interpolation between two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+
+
+function lerp(out, a, b, t) {
+ var ax = a[0];
+ var ay = a[1];
+ var az = a[2];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ out[2] = az + t * (b[2] - az);
+ return out;
+}
+/**
+ * Performs a hermite interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {ReadonlyVec3} c the third operand
+ * @param {ReadonlyVec3} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+
+
+function hermite(out, a, b, c, d, t) {
+ var factorTimes2 = t * t;
+ var factor1 = factorTimes2 * (2 * t - 3) + 1;
+ var factor2 = factorTimes2 * (t - 2) + t;
+ var factor3 = factorTimes2 * (t - 1);
+ var factor4 = factorTimes2 * (3 - 2 * t);
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+ return out;
+}
+/**
+ * Performs a bezier interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {ReadonlyVec3} c the third operand
+ * @param {ReadonlyVec3} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+
+
+function bezier(out, a, b, c, d, t) {
+ var inverseFactor = 1 - t;
+ var inverseFactorTimesTwo = inverseFactor * inverseFactor;
+ var factorTimes2 = t * t;
+ var factor1 = inverseFactorTimesTwo * inverseFactor;
+ var factor2 = 3 * t * inverseFactorTimesTwo;
+ var factor3 = 3 * factorTimes2 * inverseFactor;
+ var factor4 = factorTimes2 * t;
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+ return out;
+}
+/**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec3} out
+ */
+
+
+function random(out, scale) {
+ scale = scale || 1.0;
+ var r = glMatrix.RANDOM() * 2.0 * Math.PI;
+ var z = glMatrix.RANDOM() * 2.0 - 1.0;
+ var zScale = Math.sqrt(1.0 - z * z) * scale;
+ out[0] = Math.cos(r) * zScale;
+ out[1] = Math.sin(r) * zScale;
+ out[2] = z * scale;
+ return out;
+}
+/**
+ * Transforms the vec3 with a mat4.
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec3} out
+ */
+
+
+function transformMat4(out, a, m) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ var w = m[3] * x + m[7] * y + m[11] * z + m[15];
+ w = w || 1.0;
+ out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
+ out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
+ out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
+ return out;
+}
+/**
+ * Transforms the vec3 with a mat3.
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyMat3} m the 3x3 matrix to transform with
+ * @returns {vec3} out
+ */
+
+
+function transformMat3(out, a, m) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ out[0] = x * m[0] + y * m[3] + z * m[6];
+ out[1] = x * m[1] + y * m[4] + z * m[7];
+ out[2] = x * m[2] + y * m[5] + z * m[8];
+ return out;
+}
+/**
+ * Transforms the vec3 with a quat
+ * Can also be used for dual quaternions. (Multiply it with the real part)
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyQuat} q quaternion to transform with
+ * @returns {vec3} out
+ */
+
+
+function transformQuat(out, a, q) {
+ // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3];
+ var x = a[0],
+ y = a[1],
+ z = a[2]; // var qvec = [qx, qy, qz];
+ // var uv = vec3.cross([], qvec, a);
+
+ var uvx = qy * z - qz * y,
+ uvy = qz * x - qx * z,
+ uvz = qx * y - qy * x; // var uuv = vec3.cross([], qvec, uv);
+
+ var uuvx = qy * uvz - qz * uvy,
+ uuvy = qz * uvx - qx * uvz,
+ uuvz = qx * uvy - qy * uvx; // vec3.scale(uv, uv, 2 * w);
+
+ var w2 = qw * 2;
+ uvx *= w2;
+ uvy *= w2;
+ uvz *= w2; // vec3.scale(uuv, uuv, 2);
+
+ uuvx *= 2;
+ uuvy *= 2;
+ uuvz *= 2; // return vec3.add(out, a, vec3.add(out, uv, uuv));
+
+ out[0] = x + uvx + uuvx;
+ out[1] = y + uvy + uuvy;
+ out[2] = z + uvz + uuvz;
+ return out;
+}
+/**
+ * Rotate a 3D vector around the x-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+
+
+function rotateX(out, a, b, rad) {
+ var p = [],
+ r = []; //Translate point to the origin
+
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2]; //perform rotation
+
+ r[0] = p[0];
+ r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);
+ r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad); //translate to correct position
+
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+ return out;
+}
+/**
+ * Rotate a 3D vector around the y-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+
+
+function rotateY(out, a, b, rad) {
+ var p = [],
+ r = []; //Translate point to the origin
+
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2]; //perform rotation
+
+ r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);
+ r[1] = p[1];
+ r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad); //translate to correct position
+
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+ return out;
+}
+/**
+ * Rotate a 3D vector around the z-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+
+
+function rotateZ(out, a, b, rad) {
+ var p = [],
+ r = []; //Translate point to the origin
+
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2]; //perform rotation
+
+ r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);
+ r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);
+ r[2] = p[2]; //translate to correct position
+
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+ return out;
+}
+/**
+ * Get the angle between two 3D vectors
+ * @param {ReadonlyVec3} a The first operand
+ * @param {ReadonlyVec3} b The second operand
+ * @returns {Number} The angle in radians
+ */
+
+
+function angle(a, b) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ bx = b[0],
+ by = b[1],
+ bz = b[2],
+ mag1 = Math.sqrt(ax * ax + ay * ay + az * az),
+ mag2 = Math.sqrt(bx * bx + by * by + bz * bz),
+ mag = mag1 * mag2,
+ cosine = mag && dot(a, b) / mag;
+ return Math.acos(Math.min(Math.max(cosine, -1), 1));
+}
+/**
+ * Set the components of a vec3 to zero
+ *
+ * @param {vec3} out the receiving vector
+ * @returns {vec3} out
+ */
+
+
+function zero(out) {
+ out[0] = 0.0;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ return out;
+}
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec3} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+
+function str(a) {
+ return "vec3(" + a[0] + ", " + a[1] + ", " + a[2] + ")";
+}
+/**
+ * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec3} a The first vector.
+ * @param {ReadonlyVec3} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+
+function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
+}
+/**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec3} a The first vector.
+ * @param {ReadonlyVec3} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+
+function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2));
+}
+/**
+ * Alias for {@link vec3.subtract}
+ * @function
+ */
+
+
+var sub = subtract;
+/**
+ * Alias for {@link vec3.multiply}
+ * @function
+ */
+
+exports.sub = sub;
+var mul = multiply;
+/**
+ * Alias for {@link vec3.divide}
+ * @function
+ */
+
+exports.mul = mul;
+var div = divide;
+/**
+ * Alias for {@link vec3.distance}
+ * @function
+ */
+
+exports.div = div;
+var dist = distance;
+/**
+ * Alias for {@link vec3.squaredDistance}
+ * @function
+ */
+
+exports.dist = dist;
+var sqrDist = squaredDistance;
+/**
+ * Alias for {@link vec3.length}
+ * @function
+ */
+
+exports.sqrDist = sqrDist;
+var len = length;
+/**
+ * Alias for {@link vec3.squaredLength}
+ * @function
+ */
+
+exports.len = len;
+var sqrLen = squaredLength;
+/**
+ * Perform some operation over an array of vec3s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+
+exports.sqrLen = sqrLen;
+
+var forEach = function () {
+ var vec = create();
+ return function (a, stride, offset, count, fn, arg) {
+ var i, l;
+
+ if (!stride) {
+ stride = 3;
+ }
+
+ if (!offset) {
+ offset = 0;
+ }
+
+ if (count) {
+ l = Math.min(count * stride + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for (i = offset; i < l; i += stride) {
+ vec[0] = a[i];
+ vec[1] = a[i + 1];
+ vec[2] = a[i + 2];
+ fn(vec, vec, arg);
+ a[i] = vec[0];
+ a[i + 1] = vec[1];
+ a[i + 2] = vec[2];
+ }
+
+ return a;
+ };
+}();
+
+exports.forEach = forEach;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/cjs/vec4.js b/public/node_modules/gl-matrix/cjs/vec4.js
new file mode 100644
index 0000000..3a6d821
--- /dev/null
+++ b/public/node_modules/gl-matrix/cjs/vec4.js
@@ -0,0 +1,752 @@
+"use strict";
+
+function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.create = create;
+exports.clone = clone;
+exports.fromValues = fromValues;
+exports.copy = copy;
+exports.set = set;
+exports.add = add;
+exports.subtract = subtract;
+exports.multiply = multiply;
+exports.divide = divide;
+exports.ceil = ceil;
+exports.floor = floor;
+exports.min = min;
+exports.max = max;
+exports.round = round;
+exports.scale = scale;
+exports.scaleAndAdd = scaleAndAdd;
+exports.distance = distance;
+exports.squaredDistance = squaredDistance;
+exports.length = length;
+exports.squaredLength = squaredLength;
+exports.negate = negate;
+exports.inverse = inverse;
+exports.normalize = normalize;
+exports.dot = dot;
+exports.cross = cross;
+exports.lerp = lerp;
+exports.random = random;
+exports.transformMat4 = transformMat4;
+exports.transformQuat = transformQuat;
+exports.zero = zero;
+exports.str = str;
+exports.exactEquals = exactEquals;
+exports.equals = equals;
+exports.forEach = exports.sqrLen = exports.len = exports.sqrDist = exports.dist = exports.div = exports.mul = exports.sub = void 0;
+
+var glMatrix = _interopRequireWildcard(require("./common.js"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+/**
+ * 4 Dimensional Vector
+ * @module vec4
+ */
+
+/**
+ * Creates a new, empty vec4
+ *
+ * @returns {vec4} a new 4D vector
+ */
+function create() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ }
+
+ return out;
+}
+/**
+ * Creates a new vec4 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec4} a vector to clone
+ * @returns {vec4} a new 4D vector
+ */
+
+
+function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Creates a new vec4 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} a new 4D vector
+ */
+
+
+function fromValues(x, y, z, w) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = w;
+ return out;
+}
+/**
+ * Copy the values from one vec4 to another
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the source vector
+ * @returns {vec4} out
+ */
+
+
+function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Set the components of a vec4 to the given values
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} out
+ */
+
+
+function set(out, x, y, z, w) {
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = w;
+ return out;
+}
+/**
+ * Adds two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+
+function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ return out;
+}
+/**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+
+function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ return out;
+}
+/**
+ * Multiplies two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+
+function multiply(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ out[2] = a[2] * b[2];
+ out[3] = a[3] * b[3];
+ return out;
+}
+/**
+ * Divides two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+
+function divide(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ out[2] = a[2] / b[2];
+ out[3] = a[3] / b[3];
+ return out;
+}
+/**
+ * Math.ceil the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to ceil
+ * @returns {vec4} out
+ */
+
+
+function ceil(out, a) {
+ out[0] = Math.ceil(a[0]);
+ out[1] = Math.ceil(a[1]);
+ out[2] = Math.ceil(a[2]);
+ out[3] = Math.ceil(a[3]);
+ return out;
+}
+/**
+ * Math.floor the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to floor
+ * @returns {vec4} out
+ */
+
+
+function floor(out, a) {
+ out[0] = Math.floor(a[0]);
+ out[1] = Math.floor(a[1]);
+ out[2] = Math.floor(a[2]);
+ out[3] = Math.floor(a[3]);
+ return out;
+}
+/**
+ * Returns the minimum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+
+function min(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ out[2] = Math.min(a[2], b[2]);
+ out[3] = Math.min(a[3], b[3]);
+ return out;
+}
+/**
+ * Returns the maximum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+
+function max(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ out[2] = Math.max(a[2], b[2]);
+ out[3] = Math.max(a[3], b[3]);
+ return out;
+}
+/**
+ * Math.round the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to round
+ * @returns {vec4} out
+ */
+
+
+function round(out, a) {
+ out[0] = Math.round(a[0]);
+ out[1] = Math.round(a[1]);
+ out[2] = Math.round(a[2]);
+ out[3] = Math.round(a[3]);
+ return out;
+}
+/**
+ * Scales a vec4 by a scalar number
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec4} out
+ */
+
+
+function scale(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ return out;
+}
+/**
+ * Adds two vec4's after scaling the second operand by a scalar value
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec4} out
+ */
+
+
+function scaleAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ return out;
+}
+/**
+ * Calculates the euclidian distance between two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} distance between a and b
+ */
+
+
+function distance(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ var w = b[3] - a[3];
+ return Math.hypot(x, y, z, w);
+}
+/**
+ * Calculates the squared euclidian distance between two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+
+
+function squaredDistance(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ var w = b[3] - a[3];
+ return x * x + y * y + z * z + w * w;
+}
+/**
+ * Calculates the length of a vec4
+ *
+ * @param {ReadonlyVec4} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+
+function length(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var w = a[3];
+ return Math.hypot(x, y, z, w);
+}
+/**
+ * Calculates the squared length of a vec4
+ *
+ * @param {ReadonlyVec4} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+
+
+function squaredLength(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var w = a[3];
+ return x * x + y * y + z * z + w * w;
+}
+/**
+ * Negates the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to negate
+ * @returns {vec4} out
+ */
+
+
+function negate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = -a[3];
+ return out;
+}
+/**
+ * Returns the inverse of the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to invert
+ * @returns {vec4} out
+ */
+
+
+function inverse(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ out[2] = 1.0 / a[2];
+ out[3] = 1.0 / a[3];
+ return out;
+}
+/**
+ * Normalize a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to normalize
+ * @returns {vec4} out
+ */
+
+
+function normalize(out, a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var w = a[3];
+ var len = x * x + y * y + z * z + w * w;
+
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ }
+
+ out[0] = x * len;
+ out[1] = y * len;
+ out[2] = z * len;
+ out[3] = w * len;
+ return out;
+}
+/**
+ * Calculates the dot product of two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+
+
+function dot(a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+}
+/**
+ * Returns the cross-product of three vectors in a 4-dimensional space
+ *
+ * @param {ReadonlyVec4} result the receiving vector
+ * @param {ReadonlyVec4} U the first vector
+ * @param {ReadonlyVec4} V the second vector
+ * @param {ReadonlyVec4} W the third vector
+ * @returns {vec4} result
+ */
+
+
+function cross(out, u, v, w) {
+ var A = v[0] * w[1] - v[1] * w[0],
+ B = v[0] * w[2] - v[2] * w[0],
+ C = v[0] * w[3] - v[3] * w[0],
+ D = v[1] * w[2] - v[2] * w[1],
+ E = v[1] * w[3] - v[3] * w[1],
+ F = v[2] * w[3] - v[3] * w[2];
+ var G = u[0];
+ var H = u[1];
+ var I = u[2];
+ var J = u[3];
+ out[0] = H * F - I * E + J * D;
+ out[1] = -(G * F) + I * C - J * B;
+ out[2] = G * E - H * C + J * A;
+ out[3] = -(G * D) + H * B - I * A;
+ return out;
+}
+/**
+ * Performs a linear interpolation between two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec4} out
+ */
+
+
+function lerp(out, a, b, t) {
+ var ax = a[0];
+ var ay = a[1];
+ var az = a[2];
+ var aw = a[3];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ out[2] = az + t * (b[2] - az);
+ out[3] = aw + t * (b[3] - aw);
+ return out;
+}
+/**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec4} out
+ */
+
+
+function random(out, scale) {
+ scale = scale || 1.0; // Marsaglia, George. Choosing a Point from the Surface of a
+ // Sphere. Ann. Math. Statist. 43 (1972), no. 2, 645--646.
+ // http://projecteuclid.org/euclid.aoms/1177692644;
+
+ var v1, v2, v3, v4;
+ var s1, s2;
+
+ do {
+ v1 = glMatrix.RANDOM() * 2 - 1;
+ v2 = glMatrix.RANDOM() * 2 - 1;
+ s1 = v1 * v1 + v2 * v2;
+ } while (s1 >= 1);
+
+ do {
+ v3 = glMatrix.RANDOM() * 2 - 1;
+ v4 = glMatrix.RANDOM() * 2 - 1;
+ s2 = v3 * v3 + v4 * v4;
+ } while (s2 >= 1);
+
+ var d = Math.sqrt((1 - s1) / s2);
+ out[0] = scale * v1;
+ out[1] = scale * v2;
+ out[2] = scale * v3 * d;
+ out[3] = scale * v4 * d;
+ return out;
+}
+/**
+ * Transforms the vec4 with a mat4.
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec4} out
+ */
+
+
+function transformMat4(out, a, m) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
+ out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
+ out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
+ out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
+ return out;
+}
+/**
+ * Transforms the vec4 with a quat
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to transform
+ * @param {ReadonlyQuat} q quaternion to transform with
+ * @returns {vec4} out
+ */
+
+
+function transformQuat(out, a, q) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3]; // calculate quat * vec
+
+ var ix = qw * x + qy * z - qz * y;
+ var iy = qw * y + qz * x - qx * z;
+ var iz = qw * z + qx * y - qy * x;
+ var iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat
+
+ out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
+ out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
+ out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Set the components of a vec4 to zero
+ *
+ * @param {vec4} out the receiving vector
+ * @returns {vec4} out
+ */
+
+
+function zero(out) {
+ out[0] = 0.0;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ out[3] = 0.0;
+ return out;
+}
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec4} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+
+function str(a) {
+ return "vec4(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")";
+}
+/**
+ * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec4} a The first vector.
+ * @param {ReadonlyVec4} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+
+function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
+}
+/**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec4} a The first vector.
+ * @param {ReadonlyVec4} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+
+function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3));
+}
+/**
+ * Alias for {@link vec4.subtract}
+ * @function
+ */
+
+
+var sub = subtract;
+/**
+ * Alias for {@link vec4.multiply}
+ * @function
+ */
+
+exports.sub = sub;
+var mul = multiply;
+/**
+ * Alias for {@link vec4.divide}
+ * @function
+ */
+
+exports.mul = mul;
+var div = divide;
+/**
+ * Alias for {@link vec4.distance}
+ * @function
+ */
+
+exports.div = div;
+var dist = distance;
+/**
+ * Alias for {@link vec4.squaredDistance}
+ * @function
+ */
+
+exports.dist = dist;
+var sqrDist = squaredDistance;
+/**
+ * Alias for {@link vec4.length}
+ * @function
+ */
+
+exports.sqrDist = sqrDist;
+var len = length;
+/**
+ * Alias for {@link vec4.squaredLength}
+ * @function
+ */
+
+exports.len = len;
+var sqrLen = squaredLength;
+/**
+ * Perform some operation over an array of vec4s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+
+exports.sqrLen = sqrLen;
+
+var forEach = function () {
+ var vec = create();
+ return function (a, stride, offset, count, fn, arg) {
+ var i, l;
+
+ if (!stride) {
+ stride = 4;
+ }
+
+ if (!offset) {
+ offset = 0;
+ }
+
+ if (count) {
+ l = Math.min(count * stride + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for (i = offset; i < l; i += stride) {
+ vec[0] = a[i];
+ vec[1] = a[i + 1];
+ vec[2] = a[i + 2];
+ vec[3] = a[i + 3];
+ fn(vec, vec, arg);
+ a[i] = vec[0];
+ a[i + 1] = vec[1];
+ a[i + 2] = vec[2];
+ a[i + 3] = vec[3];
+ }
+
+ return a;
+ };
+}();
+
+exports.forEach = forEach;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/common.js b/public/node_modules/gl-matrix/esm/common.js
new file mode 100644
index 0000000..91fed57
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/common.js
@@ -0,0 +1,50 @@
+/**
+ * Common utilities
+ * @module glMatrix
+ */
+// Configuration Constants
+export var EPSILON = 0.000001;
+export var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
+export var RANDOM = Math.random;
+/**
+ * Sets the type of array used when creating new vectors and matrices
+ *
+ * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array
+ */
+
+export function setMatrixArrayType(type) {
+ ARRAY_TYPE = type;
+}
+var degree = Math.PI / 180;
+/**
+ * Convert Degree To Radian
+ *
+ * @param {Number} a Angle in Degrees
+ */
+
+export function toRadian(a) {
+ return a * degree;
+}
+/**
+ * Tests whether or not the arguments have approximately the same value, within an absolute
+ * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less
+ * than or equal to 1.0, and a relative tolerance is used for larger values)
+ *
+ * @param {Number} a The first number to test.
+ * @param {Number} b The second number to test.
+ * @returns {Boolean} True if the numbers are approximately equal, false otherwise.
+ */
+
+export function equals(a, b) {
+ return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));
+}
+if (!Math.hypot) Math.hypot = function () {
+ var y = 0,
+ i = arguments.length;
+
+ while (i--) {
+ y += arguments[i] * arguments[i];
+ }
+
+ return Math.sqrt(y);
+};
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/index.js b/public/node_modules/gl-matrix/esm/index.js
new file mode 100644
index 0000000..e89dffe
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/index.js
@@ -0,0 +1,11 @@
+import * as glMatrix from "./common.js";
+import * as mat2 from "./mat2.js";
+import * as mat2d from "./mat2d.js";
+import * as mat3 from "./mat3.js";
+import * as mat4 from "./mat4.js";
+import * as quat from "./quat.js";
+import * as quat2 from "./quat2.js";
+import * as vec2 from "./vec2.js";
+import * as vec3 from "./vec3.js";
+import * as vec4 from "./vec4.js";
+export { glMatrix, mat2, mat2d, mat3, mat4, quat, quat2, vec2, vec3, vec4 };
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/mat2.js b/public/node_modules/gl-matrix/esm/mat2.js
new file mode 100644
index 0000000..61b6698
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/mat2.js
@@ -0,0 +1,432 @@
+import * as glMatrix from "./common.js";
+/**
+ * 2x2 Matrix
+ * @module mat2
+ */
+
+/**
+ * Creates a new identity mat2
+ *
+ * @returns {mat2} a new 2x2 matrix
+ */
+
+export function create() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ }
+
+ out[0] = 1;
+ out[3] = 1;
+ return out;
+}
+/**
+ * Creates a new mat2 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat2} a matrix to clone
+ * @returns {mat2} a new 2x2 matrix
+ */
+
+export function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Copy the values from one mat2 to another
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+export function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Set a mat2 to the identity matrix
+ *
+ * @param {mat2} out the receiving matrix
+ * @returns {mat2} out
+ */
+
+export function identity(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+}
+/**
+ * Create a new mat2 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m10 Component in column 1, row 0 position (index 2)
+ * @param {Number} m11 Component in column 1, row 1 position (index 3)
+ * @returns {mat2} out A new 2x2 matrix
+ */
+
+export function fromValues(m00, m01, m10, m11) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m10;
+ out[3] = m11;
+ return out;
+}
+/**
+ * Set the components of a mat2 to the given values
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m10 Component in column 1, row 0 position (index 2)
+ * @param {Number} m11 Component in column 1, row 1 position (index 3)
+ * @returns {mat2} out
+ */
+
+export function set(out, m00, m01, m10, m11) {
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m10;
+ out[3] = m11;
+ return out;
+}
+/**
+ * Transpose the values of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+export function transpose(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache
+ // some values
+ if (out === a) {
+ var a1 = a[1];
+ out[1] = a[2];
+ out[2] = a1;
+ } else {
+ out[0] = a[0];
+ out[1] = a[2];
+ out[2] = a[1];
+ out[3] = a[3];
+ }
+
+ return out;
+}
+/**
+ * Inverts a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+export function invert(out, a) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3]; // Calculate the determinant
+
+ var det = a0 * a3 - a2 * a1;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = a3 * det;
+ out[1] = -a1 * det;
+ out[2] = -a2 * det;
+ out[3] = a0 * det;
+ return out;
+}
+/**
+ * Calculates the adjugate of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+export function adjoint(out, a) {
+ // Caching this value is nessecary if out == a
+ var a0 = a[0];
+ out[0] = a[3];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a0;
+ return out;
+}
+/**
+ * Calculates the determinant of a mat2
+ *
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+export function determinant(a) {
+ return a[0] * a[3] - a[2] * a[1];
+}
+/**
+ * Multiplies two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+
+export function multiply(out, a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ out[0] = a0 * b0 + a2 * b1;
+ out[1] = a1 * b0 + a3 * b1;
+ out[2] = a0 * b2 + a2 * b3;
+ out[3] = a1 * b2 + a3 * b3;
+ return out;
+}
+/**
+ * Rotates a mat2 by the given angle
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+
+export function rotate(out, a, rad) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ out[0] = a0 * c + a2 * s;
+ out[1] = a1 * c + a3 * s;
+ out[2] = a0 * -s + a2 * c;
+ out[3] = a1 * -s + a3 * c;
+ return out;
+}
+/**
+ * Scales the mat2 by the dimensions in the given vec2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to rotate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat2} out
+ **/
+
+export function scale(out, a, v) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var v0 = v[0],
+ v1 = v[1];
+ out[0] = a0 * v0;
+ out[1] = a1 * v0;
+ out[2] = a2 * v1;
+ out[3] = a3 * v1;
+ return out;
+}
+/**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.rotate(dest, dest, rad);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+
+export function fromRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = -s;
+ out[3] = c;
+ return out;
+}
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.scale(dest, dest, vec);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat2} out
+ */
+
+export function fromScaling(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = v[1];
+ return out;
+}
+/**
+ * Returns a string representation of a mat2
+ *
+ * @param {ReadonlyMat2} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+export function str(a) {
+ return "mat2(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")";
+}
+/**
+ * Returns Frobenius norm of a mat2
+ *
+ * @param {ReadonlyMat2} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+export function frob(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3]);
+}
+/**
+ * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
+ * @param {ReadonlyMat2} L the lower triangular matrix
+ * @param {ReadonlyMat2} D the diagonal matrix
+ * @param {ReadonlyMat2} U the upper triangular matrix
+ * @param {ReadonlyMat2} a the input matrix to factorize
+ */
+
+export function LDU(L, D, U, a) {
+ L[2] = a[2] / a[0];
+ U[0] = a[0];
+ U[1] = a[1];
+ U[3] = a[3] - L[2] * U[1];
+ return [L, D, U];
+}
+/**
+ * Adds two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+
+export function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ return out;
+}
+/**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+
+export function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ return out;
+}
+/**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat2} a The first matrix.
+ * @param {ReadonlyMat2} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+export function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
+}
+/**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat2} a The first matrix.
+ * @param {ReadonlyMat2} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+export function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3));
+}
+/**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat2} out
+ */
+
+export function multiplyScalar(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ return out;
+}
+/**
+ * Adds two mat2's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat2} out the receiving vector
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat2} out
+ */
+
+export function multiplyScalarAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ return out;
+}
+/**
+ * Alias for {@link mat2.multiply}
+ * @function
+ */
+
+export var mul = multiply;
+/**
+ * Alias for {@link mat2.subtract}
+ * @function
+ */
+
+export var sub = subtract;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/mat2d.js b/public/node_modules/gl-matrix/esm/mat2d.js
new file mode 100644
index 0000000..ce6988c
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/mat2d.js
@@ -0,0 +1,486 @@
+import * as glMatrix from "./common.js";
+/**
+ * 2x3 Matrix
+ * @module mat2d
+ * @description
+ * A mat2d contains six elements defined as:
+ *
+ * [a, b,
+ * c, d,
+ * tx, ty]
+ *
+ * This is a short form for the 3x3 matrix:
+ *
+ * [a, b, 0,
+ * c, d, 0,
+ * tx, ty, 1]
+ *
+ * The last column is ignored so the array is shorter and operations are faster.
+ */
+
+/**
+ * Creates a new identity mat2d
+ *
+ * @returns {mat2d} a new 2x3 matrix
+ */
+
+export function create() {
+ var out = new glMatrix.ARRAY_TYPE(6);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ out[4] = 0;
+ out[5] = 0;
+ }
+
+ out[0] = 1;
+ out[3] = 1;
+ return out;
+}
+/**
+ * Creates a new mat2d initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat2d} a matrix to clone
+ * @returns {mat2d} a new 2x3 matrix
+ */
+
+export function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(6);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ return out;
+}
+/**
+ * Copy the values from one mat2d to another
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+
+export function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ return out;
+}
+/**
+ * Set a mat2d to the identity matrix
+ *
+ * @param {mat2d} out the receiving matrix
+ * @returns {mat2d} out
+ */
+
+export function identity(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+}
+/**
+ * Create a new mat2d with the given values
+ *
+ * @param {Number} a Component A (index 0)
+ * @param {Number} b Component B (index 1)
+ * @param {Number} c Component C (index 2)
+ * @param {Number} d Component D (index 3)
+ * @param {Number} tx Component TX (index 4)
+ * @param {Number} ty Component TY (index 5)
+ * @returns {mat2d} A new mat2d
+ */
+
+export function fromValues(a, b, c, d, tx, ty) {
+ var out = new glMatrix.ARRAY_TYPE(6);
+ out[0] = a;
+ out[1] = b;
+ out[2] = c;
+ out[3] = d;
+ out[4] = tx;
+ out[5] = ty;
+ return out;
+}
+/**
+ * Set the components of a mat2d to the given values
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {Number} a Component A (index 0)
+ * @param {Number} b Component B (index 1)
+ * @param {Number} c Component C (index 2)
+ * @param {Number} d Component D (index 3)
+ * @param {Number} tx Component TX (index 4)
+ * @param {Number} ty Component TY (index 5)
+ * @returns {mat2d} out
+ */
+
+export function set(out, a, b, c, d, tx, ty) {
+ out[0] = a;
+ out[1] = b;
+ out[2] = c;
+ out[3] = d;
+ out[4] = tx;
+ out[5] = ty;
+ return out;
+}
+/**
+ * Inverts a mat2d
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+
+export function invert(out, a) {
+ var aa = a[0],
+ ab = a[1],
+ ac = a[2],
+ ad = a[3];
+ var atx = a[4],
+ aty = a[5];
+ var det = aa * ad - ab * ac;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = ad * det;
+ out[1] = -ab * det;
+ out[2] = -ac * det;
+ out[3] = aa * det;
+ out[4] = (ac * aty - ad * atx) * det;
+ out[5] = (ab * atx - aa * aty) * det;
+ return out;
+}
+/**
+ * Calculates the determinant of a mat2d
+ *
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+export function determinant(a) {
+ return a[0] * a[3] - a[1] * a[2];
+}
+/**
+ * Multiplies two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+
+export function multiply(out, a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5];
+ out[0] = a0 * b0 + a2 * b1;
+ out[1] = a1 * b0 + a3 * b1;
+ out[2] = a0 * b2 + a2 * b3;
+ out[3] = a1 * b2 + a3 * b3;
+ out[4] = a0 * b4 + a2 * b5 + a4;
+ out[5] = a1 * b4 + a3 * b5 + a5;
+ return out;
+}
+/**
+ * Rotates a mat2d by the given angle
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+
+export function rotate(out, a, rad) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ out[0] = a0 * c + a2 * s;
+ out[1] = a1 * c + a3 * s;
+ out[2] = a0 * -s + a2 * c;
+ out[3] = a1 * -s + a3 * c;
+ out[4] = a4;
+ out[5] = a5;
+ return out;
+}
+/**
+ * Scales the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to translate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat2d} out
+ **/
+
+export function scale(out, a, v) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var v0 = v[0],
+ v1 = v[1];
+ out[0] = a0 * v0;
+ out[1] = a1 * v0;
+ out[2] = a2 * v1;
+ out[3] = a3 * v1;
+ out[4] = a4;
+ out[5] = a5;
+ return out;
+}
+/**
+ * Translates the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to translate
+ * @param {ReadonlyVec2} v the vec2 to translate the matrix by
+ * @returns {mat2d} out
+ **/
+
+export function translate(out, a, v) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var v0 = v[0],
+ v1 = v[1];
+ out[0] = a0;
+ out[1] = a1;
+ out[2] = a2;
+ out[3] = a3;
+ out[4] = a0 * v0 + a2 * v1 + a4;
+ out[5] = a1 * v0 + a3 * v1 + a5;
+ return out;
+}
+/**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.rotate(dest, dest, rad);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+
+export function fromRotation(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = -s;
+ out[3] = c;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+}
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.scale(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat2d} out
+ */
+
+export function fromScaling(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = v[1];
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+}
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.translate(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {ReadonlyVec2} v Translation vector
+ * @returns {mat2d} out
+ */
+
+export function fromTranslation(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = v[0];
+ out[5] = v[1];
+ return out;
+}
+/**
+ * Returns a string representation of a mat2d
+ *
+ * @param {ReadonlyMat2d} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+export function str(a) {
+ return "mat2d(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ")";
+}
+/**
+ * Returns Frobenius norm of a mat2d
+ *
+ * @param {ReadonlyMat2d} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+export function frob(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], 1);
+}
+/**
+ * Adds two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+
+export function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ return out;
+}
+/**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+
+export function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ out[4] = a[4] - b[4];
+ out[5] = a[5] - b[5];
+ return out;
+}
+/**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat2d} out
+ */
+
+export function multiplyScalar(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ return out;
+}
+/**
+ * Adds two mat2d's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat2d} out the receiving vector
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat2d} out
+ */
+
+export function multiplyScalarAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ out[4] = a[4] + b[4] * scale;
+ out[5] = a[5] + b[5] * scale;
+ return out;
+}
+/**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat2d} a The first matrix.
+ * @param {ReadonlyMat2d} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+export function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5];
+}
+/**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat2d} a The first matrix.
+ * @param {ReadonlyMat2d} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+export function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5));
+}
+/**
+ * Alias for {@link mat2d.multiply}
+ * @function
+ */
+
+export var mul = multiply;
+/**
+ * Alias for {@link mat2d.subtract}
+ * @function
+ */
+
+export var sub = subtract;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/mat3.js b/public/node_modules/gl-matrix/esm/mat3.js
new file mode 100644
index 0000000..13974ab
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/mat3.js
@@ -0,0 +1,778 @@
+import * as glMatrix from "./common.js";
+/**
+ * 3x3 Matrix
+ * @module mat3
+ */
+
+/**
+ * Creates a new identity mat3
+ *
+ * @returns {mat3} a new 3x3 matrix
+ */
+
+export function create() {
+ var out = new glMatrix.ARRAY_TYPE(9);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ }
+
+ out[0] = 1;
+ out[4] = 1;
+ out[8] = 1;
+ return out;
+}
+/**
+ * Copies the upper-left 3x3 values into the given mat3.
+ *
+ * @param {mat3} out the receiving 3x3 matrix
+ * @param {ReadonlyMat4} a the source 4x4 matrix
+ * @returns {mat3} out
+ */
+
+export function fromMat4(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[4];
+ out[4] = a[5];
+ out[5] = a[6];
+ out[6] = a[8];
+ out[7] = a[9];
+ out[8] = a[10];
+ return out;
+}
+/**
+ * Creates a new mat3 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat3} a matrix to clone
+ * @returns {mat3} a new 3x3 matrix
+ */
+
+export function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(9);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+}
+/**
+ * Copy the values from one mat3 to another
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+export function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+}
+/**
+ * Create a new mat3 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m10 Component in column 1, row 0 position (index 3)
+ * @param {Number} m11 Component in column 1, row 1 position (index 4)
+ * @param {Number} m12 Component in column 1, row 2 position (index 5)
+ * @param {Number} m20 Component in column 2, row 0 position (index 6)
+ * @param {Number} m21 Component in column 2, row 1 position (index 7)
+ * @param {Number} m22 Component in column 2, row 2 position (index 8)
+ * @returns {mat3} A new mat3
+ */
+
+export function fromValues(m00, m01, m02, m10, m11, m12, m20, m21, m22) {
+ var out = new glMatrix.ARRAY_TYPE(9);
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m10;
+ out[4] = m11;
+ out[5] = m12;
+ out[6] = m20;
+ out[7] = m21;
+ out[8] = m22;
+ return out;
+}
+/**
+ * Set the components of a mat3 to the given values
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m10 Component in column 1, row 0 position (index 3)
+ * @param {Number} m11 Component in column 1, row 1 position (index 4)
+ * @param {Number} m12 Component in column 1, row 2 position (index 5)
+ * @param {Number} m20 Component in column 2, row 0 position (index 6)
+ * @param {Number} m21 Component in column 2, row 1 position (index 7)
+ * @param {Number} m22 Component in column 2, row 2 position (index 8)
+ * @returns {mat3} out
+ */
+
+export function set(out, m00, m01, m02, m10, m11, m12, m20, m21, m22) {
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m10;
+ out[4] = m11;
+ out[5] = m12;
+ out[6] = m20;
+ out[7] = m21;
+ out[8] = m22;
+ return out;
+}
+/**
+ * Set a mat3 to the identity matrix
+ *
+ * @param {mat3} out the receiving matrix
+ * @returns {mat3} out
+ */
+
+export function identity(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+}
+/**
+ * Transpose the values of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+export function transpose(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a01 = a[1],
+ a02 = a[2],
+ a12 = a[5];
+ out[1] = a[3];
+ out[2] = a[6];
+ out[3] = a01;
+ out[5] = a[7];
+ out[6] = a02;
+ out[7] = a12;
+ } else {
+ out[0] = a[0];
+ out[1] = a[3];
+ out[2] = a[6];
+ out[3] = a[1];
+ out[4] = a[4];
+ out[5] = a[7];
+ out[6] = a[2];
+ out[7] = a[5];
+ out[8] = a[8];
+ }
+
+ return out;
+}
+/**
+ * Inverts a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+export function invert(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ var b01 = a22 * a11 - a12 * a21;
+ var b11 = -a22 * a10 + a12 * a20;
+ var b21 = a21 * a10 - a11 * a20; // Calculate the determinant
+
+ var det = a00 * b01 + a01 * b11 + a02 * b21;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = b01 * det;
+ out[1] = (-a22 * a01 + a02 * a21) * det;
+ out[2] = (a12 * a01 - a02 * a11) * det;
+ out[3] = b11 * det;
+ out[4] = (a22 * a00 - a02 * a20) * det;
+ out[5] = (-a12 * a00 + a02 * a10) * det;
+ out[6] = b21 * det;
+ out[7] = (-a21 * a00 + a01 * a20) * det;
+ out[8] = (a11 * a00 - a01 * a10) * det;
+ return out;
+}
+/**
+ * Calculates the adjugate of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+export function adjoint(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ out[0] = a11 * a22 - a12 * a21;
+ out[1] = a02 * a21 - a01 * a22;
+ out[2] = a01 * a12 - a02 * a11;
+ out[3] = a12 * a20 - a10 * a22;
+ out[4] = a00 * a22 - a02 * a20;
+ out[5] = a02 * a10 - a00 * a12;
+ out[6] = a10 * a21 - a11 * a20;
+ out[7] = a01 * a20 - a00 * a21;
+ out[8] = a00 * a11 - a01 * a10;
+ return out;
+}
+/**
+ * Calculates the determinant of a mat3
+ *
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+export function determinant(a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
+}
+/**
+ * Multiplies two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+
+export function multiply(out, a, b) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ var b00 = b[0],
+ b01 = b[1],
+ b02 = b[2];
+ var b10 = b[3],
+ b11 = b[4],
+ b12 = b[5];
+ var b20 = b[6],
+ b21 = b[7],
+ b22 = b[8];
+ out[0] = b00 * a00 + b01 * a10 + b02 * a20;
+ out[1] = b00 * a01 + b01 * a11 + b02 * a21;
+ out[2] = b00 * a02 + b01 * a12 + b02 * a22;
+ out[3] = b10 * a00 + b11 * a10 + b12 * a20;
+ out[4] = b10 * a01 + b11 * a11 + b12 * a21;
+ out[5] = b10 * a02 + b11 * a12 + b12 * a22;
+ out[6] = b20 * a00 + b21 * a10 + b22 * a20;
+ out[7] = b20 * a01 + b21 * a11 + b22 * a21;
+ out[8] = b20 * a02 + b21 * a12 + b22 * a22;
+ return out;
+}
+/**
+ * Translate a mat3 by the given vector
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to translate
+ * @param {ReadonlyVec2} v vector to translate by
+ * @returns {mat3} out
+ */
+
+export function translate(out, a, v) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a10 = a[3],
+ a11 = a[4],
+ a12 = a[5],
+ a20 = a[6],
+ a21 = a[7],
+ a22 = a[8],
+ x = v[0],
+ y = v[1];
+ out[0] = a00;
+ out[1] = a01;
+ out[2] = a02;
+ out[3] = a10;
+ out[4] = a11;
+ out[5] = a12;
+ out[6] = x * a00 + y * a10 + a20;
+ out[7] = x * a01 + y * a11 + a21;
+ out[8] = x * a02 + y * a12 + a22;
+ return out;
+}
+/**
+ * Rotates a mat3 by the given angle
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+
+export function rotate(out, a, rad) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a10 = a[3],
+ a11 = a[4],
+ a12 = a[5],
+ a20 = a[6],
+ a21 = a[7],
+ a22 = a[8],
+ s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c * a00 + s * a10;
+ out[1] = c * a01 + s * a11;
+ out[2] = c * a02 + s * a12;
+ out[3] = c * a10 - s * a00;
+ out[4] = c * a11 - s * a01;
+ out[5] = c * a12 - s * a02;
+ out[6] = a20;
+ out[7] = a21;
+ out[8] = a22;
+ return out;
+}
+/**
+ * Scales the mat3 by the dimensions in the given vec2
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to rotate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat3} out
+ **/
+
+export function scale(out, a, v) {
+ var x = v[0],
+ y = v[1];
+ out[0] = x * a[0];
+ out[1] = x * a[1];
+ out[2] = x * a[2];
+ out[3] = y * a[3];
+ out[4] = y * a[4];
+ out[5] = y * a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+}
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.translate(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyVec2} v Translation vector
+ * @returns {mat3} out
+ */
+
+export function fromTranslation(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = v[0];
+ out[7] = v[1];
+ out[8] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.rotate(dest, dest, rad);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+
+export function fromRotation(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = 0;
+ out[3] = -s;
+ out[4] = c;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.scale(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat3} out
+ */
+
+export function fromScaling(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = v[1];
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+}
+/**
+ * Copies the values from a mat2d into a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to copy
+ * @returns {mat3} out
+ **/
+
+export function fromMat2d(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = 0;
+ out[3] = a[2];
+ out[4] = a[3];
+ out[5] = 0;
+ out[6] = a[4];
+ out[7] = a[5];
+ out[8] = 1;
+ return out;
+}
+/**
+ * Calculates a 3x3 matrix from the given quaternion
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyQuat} q Quaternion to create matrix from
+ *
+ * @returns {mat3} out
+ */
+
+export function fromQuat(out, q) {
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var yx = y * x2;
+ var yy = y * y2;
+ var zx = z * x2;
+ var zy = z * y2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ out[0] = 1 - yy - zz;
+ out[3] = yx - wz;
+ out[6] = zx + wy;
+ out[1] = yx + wz;
+ out[4] = 1 - xx - zz;
+ out[7] = zy - wx;
+ out[2] = zx - wy;
+ out[5] = zy + wx;
+ out[8] = 1 - xx - yy;
+ return out;
+}
+/**
+ * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyMat4} a Mat4 to derive the normal matrix from
+ *
+ * @returns {mat3} out
+ */
+
+export function normalFromMat4(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ var b00 = a00 * a11 - a01 * a10;
+ var b01 = a00 * a12 - a02 * a10;
+ var b02 = a00 * a13 - a03 * a10;
+ var b03 = a01 * a12 - a02 * a11;
+ var b04 = a01 * a13 - a03 * a11;
+ var b05 = a02 * a13 - a03 * a12;
+ var b06 = a20 * a31 - a21 * a30;
+ var b07 = a20 * a32 - a22 * a30;
+ var b08 = a20 * a33 - a23 * a30;
+ var b09 = a21 * a32 - a22 * a31;
+ var b10 = a21 * a33 - a23 * a31;
+ var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
+
+ var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+ out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+ out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+ return out;
+}
+/**
+ * Generates a 2D projection matrix with the given bounds
+ *
+ * @param {mat3} out mat3 frustum matrix will be written into
+ * @param {number} width Width of your gl context
+ * @param {number} height Height of gl context
+ * @returns {mat3} out
+ */
+
+export function projection(out, width, height) {
+ out[0] = 2 / width;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = -2 / height;
+ out[5] = 0;
+ out[6] = -1;
+ out[7] = 1;
+ out[8] = 1;
+ return out;
+}
+/**
+ * Returns a string representation of a mat3
+ *
+ * @param {ReadonlyMat3} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+export function str(a) {
+ return "mat3(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ", " + a[8] + ")";
+}
+/**
+ * Returns Frobenius norm of a mat3
+ *
+ * @param {ReadonlyMat3} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+export function frob(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
+}
+/**
+ * Adds two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+
+export function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ out[6] = a[6] + b[6];
+ out[7] = a[7] + b[7];
+ out[8] = a[8] + b[8];
+ return out;
+}
+/**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+
+export function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ out[4] = a[4] - b[4];
+ out[5] = a[5] - b[5];
+ out[6] = a[6] - b[6];
+ out[7] = a[7] - b[7];
+ out[8] = a[8] - b[8];
+ return out;
+}
+/**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat3} out
+ */
+
+export function multiplyScalar(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ out[6] = a[6] * b;
+ out[7] = a[7] * b;
+ out[8] = a[8] * b;
+ return out;
+}
+/**
+ * Adds two mat3's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat3} out the receiving vector
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat3} out
+ */
+
+export function multiplyScalarAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ out[4] = a[4] + b[4] * scale;
+ out[5] = a[5] + b[5] * scale;
+ out[6] = a[6] + b[6] * scale;
+ out[7] = a[7] + b[7] * scale;
+ out[8] = a[8] + b[8] * scale;
+ return out;
+}
+/**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat3} a The first matrix.
+ * @param {ReadonlyMat3} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+export function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8];
+}
+/**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat3} a The first matrix.
+ * @param {ReadonlyMat3} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+export function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5],
+ a6 = a[6],
+ a7 = a[7],
+ a8 = a[8];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5],
+ b6 = b[6],
+ b7 = b[7],
+ b8 = b[8];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8));
+}
+/**
+ * Alias for {@link mat3.multiply}
+ * @function
+ */
+
+export var mul = multiply;
+/**
+ * Alias for {@link mat3.subtract}
+ * @function
+ */
+
+export var sub = subtract;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/mat4.js b/public/node_modules/gl-matrix/esm/mat4.js
new file mode 100644
index 0000000..edb7b76
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/mat4.js
@@ -0,0 +1,1910 @@
+import * as glMatrix from "./common.js";
+/**
+ * 4x4 Matrix
Format: column-major, when typed out it looks like row-major
The matrices are being post multiplied.
+ * @module mat4
+ */
+
+/**
+ * Creates a new identity mat4
+ *
+ * @returns {mat4} a new 4x4 matrix
+ */
+
+export function create() {
+ var out = new glMatrix.ARRAY_TYPE(16);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ }
+
+ out[0] = 1;
+ out[5] = 1;
+ out[10] = 1;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a new mat4 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat4} a matrix to clone
+ * @returns {mat4} a new 4x4 matrix
+ */
+
+export function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(16);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+}
+/**
+ * Copy the values from one mat4 to another
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+export function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+}
+/**
+ * Create a new mat4 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m03 Component in column 0, row 3 position (index 3)
+ * @param {Number} m10 Component in column 1, row 0 position (index 4)
+ * @param {Number} m11 Component in column 1, row 1 position (index 5)
+ * @param {Number} m12 Component in column 1, row 2 position (index 6)
+ * @param {Number} m13 Component in column 1, row 3 position (index 7)
+ * @param {Number} m20 Component in column 2, row 0 position (index 8)
+ * @param {Number} m21 Component in column 2, row 1 position (index 9)
+ * @param {Number} m22 Component in column 2, row 2 position (index 10)
+ * @param {Number} m23 Component in column 2, row 3 position (index 11)
+ * @param {Number} m30 Component in column 3, row 0 position (index 12)
+ * @param {Number} m31 Component in column 3, row 1 position (index 13)
+ * @param {Number} m32 Component in column 3, row 2 position (index 14)
+ * @param {Number} m33 Component in column 3, row 3 position (index 15)
+ * @returns {mat4} A new mat4
+ */
+
+export function fromValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
+ var out = new glMatrix.ARRAY_TYPE(16);
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m03;
+ out[4] = m10;
+ out[5] = m11;
+ out[6] = m12;
+ out[7] = m13;
+ out[8] = m20;
+ out[9] = m21;
+ out[10] = m22;
+ out[11] = m23;
+ out[12] = m30;
+ out[13] = m31;
+ out[14] = m32;
+ out[15] = m33;
+ return out;
+}
+/**
+ * Set the components of a mat4 to the given values
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m03 Component in column 0, row 3 position (index 3)
+ * @param {Number} m10 Component in column 1, row 0 position (index 4)
+ * @param {Number} m11 Component in column 1, row 1 position (index 5)
+ * @param {Number} m12 Component in column 1, row 2 position (index 6)
+ * @param {Number} m13 Component in column 1, row 3 position (index 7)
+ * @param {Number} m20 Component in column 2, row 0 position (index 8)
+ * @param {Number} m21 Component in column 2, row 1 position (index 9)
+ * @param {Number} m22 Component in column 2, row 2 position (index 10)
+ * @param {Number} m23 Component in column 2, row 3 position (index 11)
+ * @param {Number} m30 Component in column 3, row 0 position (index 12)
+ * @param {Number} m31 Component in column 3, row 1 position (index 13)
+ * @param {Number} m32 Component in column 3, row 2 position (index 14)
+ * @param {Number} m33 Component in column 3, row 3 position (index 15)
+ * @returns {mat4} out
+ */
+
+export function set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m03;
+ out[4] = m10;
+ out[5] = m11;
+ out[6] = m12;
+ out[7] = m13;
+ out[8] = m20;
+ out[9] = m21;
+ out[10] = m22;
+ out[11] = m23;
+ out[12] = m30;
+ out[13] = m31;
+ out[14] = m32;
+ out[15] = m33;
+ return out;
+}
+/**
+ * Set a mat4 to the identity matrix
+ *
+ * @param {mat4} out the receiving matrix
+ * @returns {mat4} out
+ */
+
+export function identity(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Transpose the values of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+export function transpose(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a12 = a[6],
+ a13 = a[7];
+ var a23 = a[11];
+ out[1] = a[4];
+ out[2] = a[8];
+ out[3] = a[12];
+ out[4] = a01;
+ out[6] = a[9];
+ out[7] = a[13];
+ out[8] = a02;
+ out[9] = a12;
+ out[11] = a[14];
+ out[12] = a03;
+ out[13] = a13;
+ out[14] = a23;
+ } else {
+ out[0] = a[0];
+ out[1] = a[4];
+ out[2] = a[8];
+ out[3] = a[12];
+ out[4] = a[1];
+ out[5] = a[5];
+ out[6] = a[9];
+ out[7] = a[13];
+ out[8] = a[2];
+ out[9] = a[6];
+ out[10] = a[10];
+ out[11] = a[14];
+ out[12] = a[3];
+ out[13] = a[7];
+ out[14] = a[11];
+ out[15] = a[15];
+ }
+
+ return out;
+}
+/**
+ * Inverts a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+export function invert(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ var b00 = a00 * a11 - a01 * a10;
+ var b01 = a00 * a12 - a02 * a10;
+ var b02 = a00 * a13 - a03 * a10;
+ var b03 = a01 * a12 - a02 * a11;
+ var b04 = a01 * a13 - a03 * a11;
+ var b05 = a02 * a13 - a03 * a12;
+ var b06 = a20 * a31 - a21 * a30;
+ var b07 = a20 * a32 - a22 * a30;
+ var b08 = a20 * a33 - a23 * a30;
+ var b09 = a21 * a32 - a22 * a31;
+ var b10 = a21 * a33 - a23 * a31;
+ var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
+
+ var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
+ out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
+ out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+ out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+ out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+ out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
+ out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
+ out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
+ out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
+ out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
+ return out;
+}
+/**
+ * Calculates the adjugate of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+export function adjoint(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ out[0] = a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22);
+ out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
+ out[2] = a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12);
+ out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
+ out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
+ out[5] = a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22);
+ out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
+ out[7] = a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12);
+ out[8] = a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21);
+ out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
+ out[10] = a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11);
+ out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
+ out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
+ out[13] = a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21);
+ out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
+ out[15] = a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11);
+ return out;
+}
+/**
+ * Calculates the determinant of a mat4
+ *
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+export function determinant(a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ var b00 = a00 * a11 - a01 * a10;
+ var b01 = a00 * a12 - a02 * a10;
+ var b02 = a00 * a13 - a03 * a10;
+ var b03 = a01 * a12 - a02 * a11;
+ var b04 = a01 * a13 - a03 * a11;
+ var b05 = a02 * a13 - a03 * a12;
+ var b06 = a20 * a31 - a21 * a30;
+ var b07 = a20 * a32 - a22 * a30;
+ var b08 = a20 * a33 - a23 * a30;
+ var b09 = a21 * a32 - a22 * a31;
+ var b10 = a21 * a33 - a23 * a31;
+ var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
+
+ return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+}
+/**
+ * Multiplies two mat4s
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+
+export function multiply(out, a, b) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15]; // Cache only the current line of the second matrix
+
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ b0 = b[4];
+ b1 = b[5];
+ b2 = b[6];
+ b3 = b[7];
+ out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ b0 = b[8];
+ b1 = b[9];
+ b2 = b[10];
+ b3 = b[11];
+ out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ b0 = b[12];
+ b1 = b[13];
+ b2 = b[14];
+ b3 = b[15];
+ out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ return out;
+}
+/**
+ * Translate a mat4 by the given vector
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to translate
+ * @param {ReadonlyVec3} v vector to translate by
+ * @returns {mat4} out
+ */
+
+export function translate(out, a, v) {
+ var x = v[0],
+ y = v[1],
+ z = v[2];
+ var a00, a01, a02, a03;
+ var a10, a11, a12, a13;
+ var a20, a21, a22, a23;
+
+ if (a === out) {
+ out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
+ out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
+ out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
+ out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
+ } else {
+ a00 = a[0];
+ a01 = a[1];
+ a02 = a[2];
+ a03 = a[3];
+ a10 = a[4];
+ a11 = a[5];
+ a12 = a[6];
+ a13 = a[7];
+ a20 = a[8];
+ a21 = a[9];
+ a22 = a[10];
+ a23 = a[11];
+ out[0] = a00;
+ out[1] = a01;
+ out[2] = a02;
+ out[3] = a03;
+ out[4] = a10;
+ out[5] = a11;
+ out[6] = a12;
+ out[7] = a13;
+ out[8] = a20;
+ out[9] = a21;
+ out[10] = a22;
+ out[11] = a23;
+ out[12] = a00 * x + a10 * y + a20 * z + a[12];
+ out[13] = a01 * x + a11 * y + a21 * z + a[13];
+ out[14] = a02 * x + a12 * y + a22 * z + a[14];
+ out[15] = a03 * x + a13 * y + a23 * z + a[15];
+ }
+
+ return out;
+}
+/**
+ * Scales the mat4 by the dimensions in the given vec3 not using vectorization
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to scale
+ * @param {ReadonlyVec3} v the vec3 to scale the matrix by
+ * @returns {mat4} out
+ **/
+
+export function scale(out, a, v) {
+ var x = v[0],
+ y = v[1],
+ z = v[2];
+ out[0] = a[0] * x;
+ out[1] = a[1] * x;
+ out[2] = a[2] * x;
+ out[3] = a[3] * x;
+ out[4] = a[4] * y;
+ out[5] = a[5] * y;
+ out[6] = a[6] * y;
+ out[7] = a[7] * y;
+ out[8] = a[8] * z;
+ out[9] = a[9] * z;
+ out[10] = a[10] * z;
+ out[11] = a[11] * z;
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+}
+/**
+ * Rotates a mat4 by the given angle around the given axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+
+export function rotate(out, a, rad, axis) {
+ var x = axis[0],
+ y = axis[1],
+ z = axis[2];
+ var len = Math.hypot(x, y, z);
+ var s, c, t;
+ var a00, a01, a02, a03;
+ var a10, a11, a12, a13;
+ var a20, a21, a22, a23;
+ var b00, b01, b02;
+ var b10, b11, b12;
+ var b20, b21, b22;
+
+ if (len < glMatrix.EPSILON) {
+ return null;
+ }
+
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+ s = Math.sin(rad);
+ c = Math.cos(rad);
+ t = 1 - c;
+ a00 = a[0];
+ a01 = a[1];
+ a02 = a[2];
+ a03 = a[3];
+ a10 = a[4];
+ a11 = a[5];
+ a12 = a[6];
+ a13 = a[7];
+ a20 = a[8];
+ a21 = a[9];
+ a22 = a[10];
+ a23 = a[11]; // Construct the elements of the rotation matrix
+
+ b00 = x * x * t + c;
+ b01 = y * x * t + z * s;
+ b02 = z * x * t - y * s;
+ b10 = x * y * t - z * s;
+ b11 = y * y * t + c;
+ b12 = z * y * t + x * s;
+ b20 = x * z * t + y * s;
+ b21 = y * z * t - x * s;
+ b22 = z * z * t + c; // Perform rotation-specific matrix multiplication
+
+ out[0] = a00 * b00 + a10 * b01 + a20 * b02;
+ out[1] = a01 * b00 + a11 * b01 + a21 * b02;
+ out[2] = a02 * b00 + a12 * b01 + a22 * b02;
+ out[3] = a03 * b00 + a13 * b01 + a23 * b02;
+ out[4] = a00 * b10 + a10 * b11 + a20 * b12;
+ out[5] = a01 * b10 + a11 * b11 + a21 * b12;
+ out[6] = a02 * b10 + a12 * b11 + a22 * b12;
+ out[7] = a03 * b10 + a13 * b11 + a23 * b12;
+ out[8] = a00 * b20 + a10 * b21 + a20 * b22;
+ out[9] = a01 * b20 + a11 * b21 + a21 * b22;
+ out[10] = a02 * b20 + a12 * b21 + a22 * b22;
+ out[11] = a03 * b20 + a13 * b21 + a23 * b22;
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged last row
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+
+ return out;
+}
+/**
+ * Rotates a matrix by the given angle around the X axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+export function rotateX(out, a, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ var a10 = a[4];
+ var a11 = a[5];
+ var a12 = a[6];
+ var a13 = a[7];
+ var a20 = a[8];
+ var a21 = a[9];
+ var a22 = a[10];
+ var a23 = a[11];
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged rows
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ } // Perform axis-specific matrix multiplication
+
+
+ out[4] = a10 * c + a20 * s;
+ out[5] = a11 * c + a21 * s;
+ out[6] = a12 * c + a22 * s;
+ out[7] = a13 * c + a23 * s;
+ out[8] = a20 * c - a10 * s;
+ out[9] = a21 * c - a11 * s;
+ out[10] = a22 * c - a12 * s;
+ out[11] = a23 * c - a13 * s;
+ return out;
+}
+/**
+ * Rotates a matrix by the given angle around the Y axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+export function rotateY(out, a, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ var a00 = a[0];
+ var a01 = a[1];
+ var a02 = a[2];
+ var a03 = a[3];
+ var a20 = a[8];
+ var a21 = a[9];
+ var a22 = a[10];
+ var a23 = a[11];
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged rows
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ } // Perform axis-specific matrix multiplication
+
+
+ out[0] = a00 * c - a20 * s;
+ out[1] = a01 * c - a21 * s;
+ out[2] = a02 * c - a22 * s;
+ out[3] = a03 * c - a23 * s;
+ out[8] = a00 * s + a20 * c;
+ out[9] = a01 * s + a21 * c;
+ out[10] = a02 * s + a22 * c;
+ out[11] = a03 * s + a23 * c;
+ return out;
+}
+/**
+ * Rotates a matrix by the given angle around the Z axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+export function rotateZ(out, a, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ var a00 = a[0];
+ var a01 = a[1];
+ var a02 = a[2];
+ var a03 = a[3];
+ var a10 = a[4];
+ var a11 = a[5];
+ var a12 = a[6];
+ var a13 = a[7];
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged last row
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ } // Perform axis-specific matrix multiplication
+
+
+ out[0] = a00 * c + a10 * s;
+ out[1] = a01 * c + a11 * s;
+ out[2] = a02 * c + a12 * s;
+ out[3] = a03 * c + a13 * s;
+ out[4] = a10 * c - a00 * s;
+ out[5] = a11 * c - a01 * s;
+ out[6] = a12 * c - a02 * s;
+ out[7] = a13 * c - a03 * s;
+ return out;
+}
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyVec3} v Translation vector
+ * @returns {mat4} out
+ */
+
+export function fromTranslation(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.scale(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyVec3} v Scaling vector
+ * @returns {mat4} out
+ */
+
+export function fromScaling(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = v[1];
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = v[2];
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a given angle around a given axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotate(dest, dest, rad, axis);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+
+export function fromRotation(out, rad, axis) {
+ var x = axis[0],
+ y = axis[1],
+ z = axis[2];
+ var len = Math.hypot(x, y, z);
+ var s, c, t;
+
+ if (len < glMatrix.EPSILON) {
+ return null;
+ }
+
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+ s = Math.sin(rad);
+ c = Math.cos(rad);
+ t = 1 - c; // Perform rotation-specific matrix multiplication
+
+ out[0] = x * x * t + c;
+ out[1] = y * x * t + z * s;
+ out[2] = z * x * t - y * s;
+ out[3] = 0;
+ out[4] = x * y * t - z * s;
+ out[5] = y * y * t + c;
+ out[6] = z * y * t + x * s;
+ out[7] = 0;
+ out[8] = x * z * t + y * s;
+ out[9] = y * z * t - x * s;
+ out[10] = z * z * t + c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from the given angle around the X axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateX(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+export function fromXRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad); // Perform axis-specific matrix multiplication
+
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = c;
+ out[6] = s;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = -s;
+ out[10] = c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from the given angle around the Y axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateY(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+export function fromYRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad); // Perform axis-specific matrix multiplication
+
+ out[0] = c;
+ out[1] = 0;
+ out[2] = -s;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = s;
+ out[9] = 0;
+ out[10] = c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from the given angle around the Z axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateZ(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+export function fromZRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad); // Perform axis-specific matrix multiplication
+
+ out[0] = c;
+ out[1] = s;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = -s;
+ out[5] = c;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a quaternion rotation and vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @returns {mat4} out
+ */
+
+export function fromRotationTranslation(out, q, v) {
+ // Quaternion math
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var xy = x * y2;
+ var xz = x * z2;
+ var yy = y * y2;
+ var yz = y * z2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ out[0] = 1 - (yy + zz);
+ out[1] = xy + wz;
+ out[2] = xz - wy;
+ out[3] = 0;
+ out[4] = xy - wz;
+ out[5] = 1 - (xx + zz);
+ out[6] = yz + wx;
+ out[7] = 0;
+ out[8] = xz + wy;
+ out[9] = yz - wx;
+ out[10] = 1 - (xx + yy);
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a new mat4 from a dual quat.
+ *
+ * @param {mat4} out Matrix
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @returns {mat4} mat4 receiving operation result
+ */
+
+export function fromQuat2(out, a) {
+ var translation = new glMatrix.ARRAY_TYPE(3);
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7];
+ var magnitude = bx * bx + by * by + bz * bz + bw * bw; //Only scale if it makes sense
+
+ if (magnitude > 0) {
+ translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;
+ translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;
+ translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;
+ } else {
+ translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
+ translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
+ translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
+ }
+
+ fromRotationTranslation(out, a, translation);
+ return out;
+}
+/**
+ * Returns the translation vector component of a transformation
+ * matrix. If a matrix is built with fromRotationTranslation,
+ * the returned vector will be the same as the translation vector
+ * originally supplied.
+ * @param {vec3} out Vector to receive translation component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {vec3} out
+ */
+
+export function getTranslation(out, mat) {
+ out[0] = mat[12];
+ out[1] = mat[13];
+ out[2] = mat[14];
+ return out;
+}
+/**
+ * Returns the scaling factor component of a transformation
+ * matrix. If a matrix is built with fromRotationTranslationScale
+ * with a normalized Quaternion paramter, the returned vector will be
+ * the same as the scaling vector
+ * originally supplied.
+ * @param {vec3} out Vector to receive scaling factor component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {vec3} out
+ */
+
+export function getScaling(out, mat) {
+ var m11 = mat[0];
+ var m12 = mat[1];
+ var m13 = mat[2];
+ var m21 = mat[4];
+ var m22 = mat[5];
+ var m23 = mat[6];
+ var m31 = mat[8];
+ var m32 = mat[9];
+ var m33 = mat[10];
+ out[0] = Math.hypot(m11, m12, m13);
+ out[1] = Math.hypot(m21, m22, m23);
+ out[2] = Math.hypot(m31, m32, m33);
+ return out;
+}
+/**
+ * Returns a quaternion representing the rotational component
+ * of a transformation matrix. If a matrix is built with
+ * fromRotationTranslation, the returned quaternion will be the
+ * same as the quaternion originally supplied.
+ * @param {quat} out Quaternion to receive the rotation component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {quat} out
+ */
+
+export function getRotation(out, mat) {
+ var scaling = new glMatrix.ARRAY_TYPE(3);
+ getScaling(scaling, mat);
+ var is1 = 1 / scaling[0];
+ var is2 = 1 / scaling[1];
+ var is3 = 1 / scaling[2];
+ var sm11 = mat[0] * is1;
+ var sm12 = mat[1] * is2;
+ var sm13 = mat[2] * is3;
+ var sm21 = mat[4] * is1;
+ var sm22 = mat[5] * is2;
+ var sm23 = mat[6] * is3;
+ var sm31 = mat[8] * is1;
+ var sm32 = mat[9] * is2;
+ var sm33 = mat[10] * is3;
+ var trace = sm11 + sm22 + sm33;
+ var S = 0;
+
+ if (trace > 0) {
+ S = Math.sqrt(trace + 1.0) * 2;
+ out[3] = 0.25 * S;
+ out[0] = (sm23 - sm32) / S;
+ out[1] = (sm31 - sm13) / S;
+ out[2] = (sm12 - sm21) / S;
+ } else if (sm11 > sm22 && sm11 > sm33) {
+ S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;
+ out[3] = (sm23 - sm32) / S;
+ out[0] = 0.25 * S;
+ out[1] = (sm12 + sm21) / S;
+ out[2] = (sm31 + sm13) / S;
+ } else if (sm22 > sm33) {
+ S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;
+ out[3] = (sm31 - sm13) / S;
+ out[0] = (sm12 + sm21) / S;
+ out[1] = 0.25 * S;
+ out[2] = (sm23 + sm32) / S;
+ } else {
+ S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;
+ out[3] = (sm12 - sm21) / S;
+ out[0] = (sm31 + sm13) / S;
+ out[1] = (sm23 + sm32) / S;
+ out[2] = 0.25 * S;
+ }
+
+ return out;
+}
+/**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @param {ReadonlyVec3} s Scaling vector
+ * @returns {mat4} out
+ */
+
+export function fromRotationTranslationScale(out, q, v, s) {
+ // Quaternion math
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var xy = x * y2;
+ var xz = x * z2;
+ var yy = y * y2;
+ var yz = y * z2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ var sx = s[0];
+ var sy = s[1];
+ var sz = s[2];
+ out[0] = (1 - (yy + zz)) * sx;
+ out[1] = (xy + wz) * sx;
+ out[2] = (xz - wy) * sx;
+ out[3] = 0;
+ out[4] = (xy - wz) * sy;
+ out[5] = (1 - (xx + zz)) * sy;
+ out[6] = (yz + wx) * sy;
+ out[7] = 0;
+ out[8] = (xz + wy) * sz;
+ out[9] = (yz - wx) * sz;
+ out[10] = (1 - (xx + yy)) * sz;
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+}
+/**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * mat4.translate(dest, origin);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ * mat4.translate(dest, negativeOrigin);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @param {ReadonlyVec3} s Scaling vector
+ * @param {ReadonlyVec3} o The origin vector around which to scale and rotate
+ * @returns {mat4} out
+ */
+
+export function fromRotationTranslationScaleOrigin(out, q, v, s, o) {
+ // Quaternion math
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var xy = x * y2;
+ var xz = x * z2;
+ var yy = y * y2;
+ var yz = y * z2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ var sx = s[0];
+ var sy = s[1];
+ var sz = s[2];
+ var ox = o[0];
+ var oy = o[1];
+ var oz = o[2];
+ var out0 = (1 - (yy + zz)) * sx;
+ var out1 = (xy + wz) * sx;
+ var out2 = (xz - wy) * sx;
+ var out4 = (xy - wz) * sy;
+ var out5 = (1 - (xx + zz)) * sy;
+ var out6 = (yz + wx) * sy;
+ var out8 = (xz + wy) * sz;
+ var out9 = (yz - wx) * sz;
+ var out10 = (1 - (xx + yy)) * sz;
+ out[0] = out0;
+ out[1] = out1;
+ out[2] = out2;
+ out[3] = 0;
+ out[4] = out4;
+ out[5] = out5;
+ out[6] = out6;
+ out[7] = 0;
+ out[8] = out8;
+ out[9] = out9;
+ out[10] = out10;
+ out[11] = 0;
+ out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);
+ out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);
+ out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);
+ out[15] = 1;
+ return out;
+}
+/**
+ * Calculates a 4x4 matrix from the given quaternion
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyQuat} q Quaternion to create matrix from
+ *
+ * @returns {mat4} out
+ */
+
+export function fromQuat(out, q) {
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var yx = y * x2;
+ var yy = y * y2;
+ var zx = z * x2;
+ var zy = z * y2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ out[0] = 1 - yy - zz;
+ out[1] = yx + wz;
+ out[2] = zx - wy;
+ out[3] = 0;
+ out[4] = yx - wz;
+ out[5] = 1 - xx - zz;
+ out[6] = zy + wx;
+ out[7] = 0;
+ out[8] = zx + wy;
+ out[9] = zy - wx;
+ out[10] = 1 - xx - yy;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Generates a frustum matrix with the given bounds
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {Number} left Left bound of the frustum
+ * @param {Number} right Right bound of the frustum
+ * @param {Number} bottom Bottom bound of the frustum
+ * @param {Number} top Top bound of the frustum
+ * @param {Number} near Near bound of the frustum
+ * @param {Number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+export function frustum(out, left, right, bottom, top, near, far) {
+ var rl = 1 / (right - left);
+ var tb = 1 / (top - bottom);
+ var nf = 1 / (near - far);
+ out[0] = near * 2 * rl;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = near * 2 * tb;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = (right + left) * rl;
+ out[9] = (top + bottom) * tb;
+ out[10] = (far + near) * nf;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = far * near * 2 * nf;
+ out[15] = 0;
+ return out;
+}
+/**
+ * Generates a perspective projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
+ * which matches WebGL/OpenGL's clip volume.
+ * Passing null/undefined/no value for far will generate infinite projection matrix.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum, can be null or Infinity
+ * @returns {mat4} out
+ */
+
+export function perspectiveNO(out, fovy, aspect, near, far) {
+ var f = 1.0 / Math.tan(fovy / 2),
+ nf;
+ out[0] = f / aspect;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = f;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[15] = 0;
+
+ if (far != null && far !== Infinity) {
+ nf = 1 / (near - far);
+ out[10] = (far + near) * nf;
+ out[14] = 2 * far * near * nf;
+ } else {
+ out[10] = -1;
+ out[14] = -2 * near;
+ }
+
+ return out;
+}
+/**
+ * Alias for {@link mat4.perspectiveNO}
+ * @function
+ */
+
+export var perspective = perspectiveNO;
+/**
+ * Generates a perspective projection matrix suitable for WebGPU with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
+ * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
+ * Passing null/undefined/no value for far will generate infinite projection matrix.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum, can be null or Infinity
+ * @returns {mat4} out
+ */
+
+export function perspectiveZO(out, fovy, aspect, near, far) {
+ var f = 1.0 / Math.tan(fovy / 2),
+ nf;
+ out[0] = f / aspect;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = f;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[15] = 0;
+
+ if (far != null && far !== Infinity) {
+ nf = 1 / (near - far);
+ out[10] = far * nf;
+ out[14] = far * near * nf;
+ } else {
+ out[10] = -1;
+ out[14] = -near;
+ }
+
+ return out;
+}
+/**
+ * Generates a perspective projection matrix with the given field of view.
+ * This is primarily useful for generating projection matrices to be used
+ * with the still experiemental WebVR API.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+export function perspectiveFromFieldOfView(out, fov, near, far) {
+ var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);
+ var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);
+ var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);
+ var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);
+ var xScale = 2.0 / (leftTan + rightTan);
+ var yScale = 2.0 / (upTan + downTan);
+ out[0] = xScale;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ out[3] = 0.0;
+ out[4] = 0.0;
+ out[5] = yScale;
+ out[6] = 0.0;
+ out[7] = 0.0;
+ out[8] = -((leftTan - rightTan) * xScale * 0.5);
+ out[9] = (upTan - downTan) * yScale * 0.5;
+ out[10] = far / (near - far);
+ out[11] = -1.0;
+ out[12] = 0.0;
+ out[13] = 0.0;
+ out[14] = far * near / (near - far);
+ out[15] = 0.0;
+ return out;
+}
+/**
+ * Generates a orthogonal projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
+ * which matches WebGL/OpenGL's clip volume.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+export function orthoNO(out, left, right, bottom, top, near, far) {
+ var lr = 1 / (left - right);
+ var bt = 1 / (bottom - top);
+ var nf = 1 / (near - far);
+ out[0] = -2 * lr;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = -2 * bt;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 2 * nf;
+ out[11] = 0;
+ out[12] = (left + right) * lr;
+ out[13] = (top + bottom) * bt;
+ out[14] = (far + near) * nf;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Alias for {@link mat4.orthoNO}
+ * @function
+ */
+
+export var ortho = orthoNO;
+/**
+ * Generates a orthogonal projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
+ * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+export function orthoZO(out, left, right, bottom, top, near, far) {
+ var lr = 1 / (left - right);
+ var bt = 1 / (bottom - top);
+ var nf = 1 / (near - far);
+ out[0] = -2 * lr;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = -2 * bt;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = nf;
+ out[11] = 0;
+ out[12] = (left + right) * lr;
+ out[13] = (top + bottom) * bt;
+ out[14] = near * nf;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Generates a look-at matrix with the given eye position, focal point, and up axis.
+ * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {ReadonlyVec3} eye Position of the viewer
+ * @param {ReadonlyVec3} center Point the viewer is looking at
+ * @param {ReadonlyVec3} up vec3 pointing up
+ * @returns {mat4} out
+ */
+
+export function lookAt(out, eye, center, up) {
+ var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
+ var eyex = eye[0];
+ var eyey = eye[1];
+ var eyez = eye[2];
+ var upx = up[0];
+ var upy = up[1];
+ var upz = up[2];
+ var centerx = center[0];
+ var centery = center[1];
+ var centerz = center[2];
+
+ if (Math.abs(eyex - centerx) < glMatrix.EPSILON && Math.abs(eyey - centery) < glMatrix.EPSILON && Math.abs(eyez - centerz) < glMatrix.EPSILON) {
+ return identity(out);
+ }
+
+ z0 = eyex - centerx;
+ z1 = eyey - centery;
+ z2 = eyez - centerz;
+ len = 1 / Math.hypot(z0, z1, z2);
+ z0 *= len;
+ z1 *= len;
+ z2 *= len;
+ x0 = upy * z2 - upz * z1;
+ x1 = upz * z0 - upx * z2;
+ x2 = upx * z1 - upy * z0;
+ len = Math.hypot(x0, x1, x2);
+
+ if (!len) {
+ x0 = 0;
+ x1 = 0;
+ x2 = 0;
+ } else {
+ len = 1 / len;
+ x0 *= len;
+ x1 *= len;
+ x2 *= len;
+ }
+
+ y0 = z1 * x2 - z2 * x1;
+ y1 = z2 * x0 - z0 * x2;
+ y2 = z0 * x1 - z1 * x0;
+ len = Math.hypot(y0, y1, y2);
+
+ if (!len) {
+ y0 = 0;
+ y1 = 0;
+ y2 = 0;
+ } else {
+ len = 1 / len;
+ y0 *= len;
+ y1 *= len;
+ y2 *= len;
+ }
+
+ out[0] = x0;
+ out[1] = y0;
+ out[2] = z0;
+ out[3] = 0;
+ out[4] = x1;
+ out[5] = y1;
+ out[6] = z1;
+ out[7] = 0;
+ out[8] = x2;
+ out[9] = y2;
+ out[10] = z2;
+ out[11] = 0;
+ out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
+ out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
+ out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
+ out[15] = 1;
+ return out;
+}
+/**
+ * Generates a matrix that makes something look at something else.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {ReadonlyVec3} eye Position of the viewer
+ * @param {ReadonlyVec3} center Point the viewer is looking at
+ * @param {ReadonlyVec3} up vec3 pointing up
+ * @returns {mat4} out
+ */
+
+export function targetTo(out, eye, target, up) {
+ var eyex = eye[0],
+ eyey = eye[1],
+ eyez = eye[2],
+ upx = up[0],
+ upy = up[1],
+ upz = up[2];
+ var z0 = eyex - target[0],
+ z1 = eyey - target[1],
+ z2 = eyez - target[2];
+ var len = z0 * z0 + z1 * z1 + z2 * z2;
+
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ z0 *= len;
+ z1 *= len;
+ z2 *= len;
+ }
+
+ var x0 = upy * z2 - upz * z1,
+ x1 = upz * z0 - upx * z2,
+ x2 = upx * z1 - upy * z0;
+ len = x0 * x0 + x1 * x1 + x2 * x2;
+
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ x0 *= len;
+ x1 *= len;
+ x2 *= len;
+ }
+
+ out[0] = x0;
+ out[1] = x1;
+ out[2] = x2;
+ out[3] = 0;
+ out[4] = z1 * x2 - z2 * x1;
+ out[5] = z2 * x0 - z0 * x2;
+ out[6] = z0 * x1 - z1 * x0;
+ out[7] = 0;
+ out[8] = z0;
+ out[9] = z1;
+ out[10] = z2;
+ out[11] = 0;
+ out[12] = eyex;
+ out[13] = eyey;
+ out[14] = eyez;
+ out[15] = 1;
+ return out;
+}
+/**
+ * Returns a string representation of a mat4
+ *
+ * @param {ReadonlyMat4} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+export function str(a) {
+ return "mat4(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ", " + a[8] + ", " + a[9] + ", " + a[10] + ", " + a[11] + ", " + a[12] + ", " + a[13] + ", " + a[14] + ", " + a[15] + ")";
+}
+/**
+ * Returns Frobenius norm of a mat4
+ *
+ * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+export function frob(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);
+}
+/**
+ * Adds two mat4's
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+
+export function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ out[6] = a[6] + b[6];
+ out[7] = a[7] + b[7];
+ out[8] = a[8] + b[8];
+ out[9] = a[9] + b[9];
+ out[10] = a[10] + b[10];
+ out[11] = a[11] + b[11];
+ out[12] = a[12] + b[12];
+ out[13] = a[13] + b[13];
+ out[14] = a[14] + b[14];
+ out[15] = a[15] + b[15];
+ return out;
+}
+/**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+
+export function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ out[4] = a[4] - b[4];
+ out[5] = a[5] - b[5];
+ out[6] = a[6] - b[6];
+ out[7] = a[7] - b[7];
+ out[8] = a[8] - b[8];
+ out[9] = a[9] - b[9];
+ out[10] = a[10] - b[10];
+ out[11] = a[11] - b[11];
+ out[12] = a[12] - b[12];
+ out[13] = a[13] - b[13];
+ out[14] = a[14] - b[14];
+ out[15] = a[15] - b[15];
+ return out;
+}
+/**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat4} out
+ */
+
+export function multiplyScalar(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ out[6] = a[6] * b;
+ out[7] = a[7] * b;
+ out[8] = a[8] * b;
+ out[9] = a[9] * b;
+ out[10] = a[10] * b;
+ out[11] = a[11] * b;
+ out[12] = a[12] * b;
+ out[13] = a[13] * b;
+ out[14] = a[14] * b;
+ out[15] = a[15] * b;
+ return out;
+}
+/**
+ * Adds two mat4's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat4} out the receiving vector
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat4} out
+ */
+
+export function multiplyScalarAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ out[4] = a[4] + b[4] * scale;
+ out[5] = a[5] + b[5] * scale;
+ out[6] = a[6] + b[6] * scale;
+ out[7] = a[7] + b[7] * scale;
+ out[8] = a[8] + b[8] * scale;
+ out[9] = a[9] + b[9] * scale;
+ out[10] = a[10] + b[10] * scale;
+ out[11] = a[11] + b[11] * scale;
+ out[12] = a[12] + b[12] * scale;
+ out[13] = a[13] + b[13] * scale;
+ out[14] = a[14] + b[14] * scale;
+ out[15] = a[15] + b[15] * scale;
+ return out;
+}
+/**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat4} a The first matrix.
+ * @param {ReadonlyMat4} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+export function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];
+}
+/**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat4} a The first matrix.
+ * @param {ReadonlyMat4} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+export function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var a4 = a[4],
+ a5 = a[5],
+ a6 = a[6],
+ a7 = a[7];
+ var a8 = a[8],
+ a9 = a[9],
+ a10 = a[10],
+ a11 = a[11];
+ var a12 = a[12],
+ a13 = a[13],
+ a14 = a[14],
+ a15 = a[15];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ var b4 = b[4],
+ b5 = b[5],
+ b6 = b[6],
+ b7 = b[7];
+ var b8 = b[8],
+ b9 = b[9],
+ b10 = b[10],
+ b11 = b[11];
+ var b12 = b[12],
+ b13 = b[13],
+ b14 = b[14],
+ b15 = b[15];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));
+}
+/**
+ * Alias for {@link mat4.multiply}
+ * @function
+ */
+
+export var mul = multiply;
+/**
+ * Alias for {@link mat4.subtract}
+ * @function
+ */
+
+export var sub = subtract;
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/quat.js b/public/node_modules/gl-matrix/esm/quat.js
new file mode 100644
index 0000000..9c13f1a
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/quat.js
@@ -0,0 +1,710 @@
+import * as glMatrix from "./common.js";
+import * as mat3 from "./mat3.js";
+import * as vec3 from "./vec3.js";
+import * as vec4 from "./vec4.js";
+/**
+ * Quaternion
+ * @module quat
+ */
+
+/**
+ * Creates a new identity quat
+ *
+ * @returns {quat} a new quaternion
+ */
+
+export function create() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ }
+
+ out[3] = 1;
+ return out;
+}
+/**
+ * Set a quat to the identity quaternion
+ *
+ * @param {quat} out the receiving quaternion
+ * @returns {quat} out
+ */
+
+export function identity(out) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+}
+/**
+ * Sets a quat from the given angle and rotation axis,
+ * then returns it.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyVec3} axis the axis around which to rotate
+ * @param {Number} rad the angle in radians
+ * @returns {quat} out
+ **/
+
+export function setAxisAngle(out, axis, rad) {
+ rad = rad * 0.5;
+ var s = Math.sin(rad);
+ out[0] = s * axis[0];
+ out[1] = s * axis[1];
+ out[2] = s * axis[2];
+ out[3] = Math.cos(rad);
+ return out;
+}
+/**
+ * Gets the rotation axis and angle for a given
+ * quaternion. If a quaternion is created with
+ * setAxisAngle, this method will return the same
+ * values as providied in the original parameter list
+ * OR functionally equivalent values.
+ * Example: The quaternion formed by axis [0, 0, 1] and
+ * angle -90 is the same as the quaternion formed by
+ * [0, 0, 1] and 270. This method favors the latter.
+ * @param {vec3} out_axis Vector receiving the axis of rotation
+ * @param {ReadonlyQuat} q Quaternion to be decomposed
+ * @return {Number} Angle, in radians, of the rotation
+ */
+
+export function getAxisAngle(out_axis, q) {
+ var rad = Math.acos(q[3]) * 2.0;
+ var s = Math.sin(rad / 2.0);
+
+ if (s > glMatrix.EPSILON) {
+ out_axis[0] = q[0] / s;
+ out_axis[1] = q[1] / s;
+ out_axis[2] = q[2] / s;
+ } else {
+ // If s is zero, return any axis (no rotation - axis does not matter)
+ out_axis[0] = 1;
+ out_axis[1] = 0;
+ out_axis[2] = 0;
+ }
+
+ return rad;
+}
+/**
+ * Gets the angular distance between two unit quaternions
+ *
+ * @param {ReadonlyQuat} a Origin unit quaternion
+ * @param {ReadonlyQuat} b Destination unit quaternion
+ * @return {Number} Angle, in radians, between the two quaternions
+ */
+
+export function getAngle(a, b) {
+ var dotproduct = dot(a, b);
+ return Math.acos(2 * dotproduct * dotproduct - 1);
+}
+/**
+ * Multiplies two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {quat} out
+ */
+
+export function multiply(out, a, b) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bx = b[0],
+ by = b[1],
+ bz = b[2],
+ bw = b[3];
+ out[0] = ax * bw + aw * bx + ay * bz - az * by;
+ out[1] = ay * bw + aw * by + az * bx - ax * bz;
+ out[2] = az * bw + aw * bz + ax * by - ay * bx;
+ out[3] = aw * bw - ax * bx - ay * by - az * bz;
+ return out;
+}
+/**
+ * Rotates a quaternion by the given angle about the X axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+
+export function rotateX(out, a, rad) {
+ rad *= 0.5;
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bx = Math.sin(rad),
+ bw = Math.cos(rad);
+ out[0] = ax * bw + aw * bx;
+ out[1] = ay * bw + az * bx;
+ out[2] = az * bw - ay * bx;
+ out[3] = aw * bw - ax * bx;
+ return out;
+}
+/**
+ * Rotates a quaternion by the given angle about the Y axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+
+export function rotateY(out, a, rad) {
+ rad *= 0.5;
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var by = Math.sin(rad),
+ bw = Math.cos(rad);
+ out[0] = ax * bw - az * by;
+ out[1] = ay * bw + aw * by;
+ out[2] = az * bw + ax * by;
+ out[3] = aw * bw - ay * by;
+ return out;
+}
+/**
+ * Rotates a quaternion by the given angle about the Z axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+
+export function rotateZ(out, a, rad) {
+ rad *= 0.5;
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bz = Math.sin(rad),
+ bw = Math.cos(rad);
+ out[0] = ax * bw + ay * bz;
+ out[1] = ay * bw - ax * bz;
+ out[2] = az * bw + aw * bz;
+ out[3] = aw * bw - az * bz;
+ return out;
+}
+/**
+ * Calculates the W component of a quat from the X, Y, and Z components.
+ * Assumes that quaternion is 1 unit in length.
+ * Any existing W component will be ignored.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate W component of
+ * @returns {quat} out
+ */
+
+export function calculateW(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
+ return out;
+}
+/**
+ * Calculate the exponential of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @returns {quat} out
+ */
+
+export function exp(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ var r = Math.sqrt(x * x + y * y + z * z);
+ var et = Math.exp(w);
+ var s = r > 0 ? et * Math.sin(r) / r : 0;
+ out[0] = x * s;
+ out[1] = y * s;
+ out[2] = z * s;
+ out[3] = et * Math.cos(r);
+ return out;
+}
+/**
+ * Calculate the natural logarithm of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @returns {quat} out
+ */
+
+export function ln(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ var r = Math.sqrt(x * x + y * y + z * z);
+ var t = r > 0 ? Math.atan2(r, w) / r : 0;
+ out[0] = x * t;
+ out[1] = y * t;
+ out[2] = z * t;
+ out[3] = 0.5 * Math.log(x * x + y * y + z * z + w * w);
+ return out;
+}
+/**
+ * Calculate the scalar power of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @param {Number} b amount to scale the quaternion by
+ * @returns {quat} out
+ */
+
+export function pow(out, a, b) {
+ ln(out, a);
+ scale(out, out, b);
+ exp(out, out);
+ return out;
+}
+/**
+ * Performs a spherical linear interpolation between two quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ */
+
+export function slerp(out, a, b, t) {
+ // benchmarks:
+ // http://jsperf.com/quaternion-slerp-implementations
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bx = b[0],
+ by = b[1],
+ bz = b[2],
+ bw = b[3];
+ var omega, cosom, sinom, scale0, scale1; // calc cosine
+
+ cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary)
+
+ if (cosom < 0.0) {
+ cosom = -cosom;
+ bx = -bx;
+ by = -by;
+ bz = -bz;
+ bw = -bw;
+ } // calculate coefficients
+
+
+ if (1.0 - cosom > glMatrix.EPSILON) {
+ // standard case (slerp)
+ omega = Math.acos(cosom);
+ sinom = Math.sin(omega);
+ scale0 = Math.sin((1.0 - t) * omega) / sinom;
+ scale1 = Math.sin(t * omega) / sinom;
+ } else {
+ // "from" and "to" quaternions are very close
+ // ... so we can do a linear interpolation
+ scale0 = 1.0 - t;
+ scale1 = t;
+ } // calculate final values
+
+
+ out[0] = scale0 * ax + scale1 * bx;
+ out[1] = scale0 * ay + scale1 * by;
+ out[2] = scale0 * az + scale1 * bz;
+ out[3] = scale0 * aw + scale1 * bw;
+ return out;
+}
+/**
+ * Generates a random unit quaternion
+ *
+ * @param {quat} out the receiving quaternion
+ * @returns {quat} out
+ */
+
+export function random(out) {
+ // Implementation of http://planning.cs.uiuc.edu/node198.html
+ // TODO: Calling random 3 times is probably not the fastest solution
+ var u1 = glMatrix.RANDOM();
+ var u2 = glMatrix.RANDOM();
+ var u3 = glMatrix.RANDOM();
+ var sqrt1MinusU1 = Math.sqrt(1 - u1);
+ var sqrtU1 = Math.sqrt(u1);
+ out[0] = sqrt1MinusU1 * Math.sin(2.0 * Math.PI * u2);
+ out[1] = sqrt1MinusU1 * Math.cos(2.0 * Math.PI * u2);
+ out[2] = sqrtU1 * Math.sin(2.0 * Math.PI * u3);
+ out[3] = sqrtU1 * Math.cos(2.0 * Math.PI * u3);
+ return out;
+}
+/**
+ * Calculates the inverse of a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate inverse of
+ * @returns {quat} out
+ */
+
+export function invert(out, a) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
+ var invDot = dot ? 1.0 / dot : 0; // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
+
+ out[0] = -a0 * invDot;
+ out[1] = -a1 * invDot;
+ out[2] = -a2 * invDot;
+ out[3] = a3 * invDot;
+ return out;
+}
+/**
+ * Calculates the conjugate of a quat
+ * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate conjugate of
+ * @returns {quat} out
+ */
+
+export function conjugate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Creates a quaternion from the given 3x3 rotation matrix.
+ *
+ * NOTE: The resultant quaternion is not normalized, so you should be sure
+ * to renormalize the quaternion yourself where necessary.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyMat3} m rotation matrix
+ * @returns {quat} out
+ * @function
+ */
+
+export function fromMat3(out, m) {
+ // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
+ // article "Quaternion Calculus and Fast Animation".
+ var fTrace = m[0] + m[4] + m[8];
+ var fRoot;
+
+ if (fTrace > 0.0) {
+ // |w| > 1/2, may as well choose w > 1/2
+ fRoot = Math.sqrt(fTrace + 1.0); // 2w
+
+ out[3] = 0.5 * fRoot;
+ fRoot = 0.5 / fRoot; // 1/(4w)
+
+ out[0] = (m[5] - m[7]) * fRoot;
+ out[1] = (m[6] - m[2]) * fRoot;
+ out[2] = (m[1] - m[3]) * fRoot;
+ } else {
+ // |w| <= 1/2
+ var i = 0;
+ if (m[4] > m[0]) i = 1;
+ if (m[8] > m[i * 3 + i]) i = 2;
+ var j = (i + 1) % 3;
+ var k = (i + 2) % 3;
+ fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0);
+ out[i] = 0.5 * fRoot;
+ fRoot = 0.5 / fRoot;
+ out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot;
+ out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;
+ out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;
+ }
+
+ return out;
+}
+/**
+ * Creates a quaternion from the given euler angle x, y, z.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {x} Angle to rotate around X axis in degrees.
+ * @param {y} Angle to rotate around Y axis in degrees.
+ * @param {z} Angle to rotate around Z axis in degrees.
+ * @returns {quat} out
+ * @function
+ */
+
+export function fromEuler(out, x, y, z) {
+ var halfToRad = 0.5 * Math.PI / 180.0;
+ x *= halfToRad;
+ y *= halfToRad;
+ z *= halfToRad;
+ var sx = Math.sin(x);
+ var cx = Math.cos(x);
+ var sy = Math.sin(y);
+ var cy = Math.cos(y);
+ var sz = Math.sin(z);
+ var cz = Math.cos(z);
+ out[0] = sx * cy * cz - cx * sy * sz;
+ out[1] = cx * sy * cz + sx * cy * sz;
+ out[2] = cx * cy * sz - sx * sy * cz;
+ out[3] = cx * cy * cz + sx * sy * sz;
+ return out;
+}
+/**
+ * Returns a string representation of a quatenion
+ *
+ * @param {ReadonlyQuat} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+export function str(a) {
+ return "quat(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")";
+}
+/**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {ReadonlyQuat} a quaternion to clone
+ * @returns {quat} a new quaternion
+ * @function
+ */
+
+export var clone = vec4.clone;
+/**
+ * Creates a new quat initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} a new quaternion
+ * @function
+ */
+
+export var fromValues = vec4.fromValues;
+/**
+ * Copy the values from one quat to another
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the source quaternion
+ * @returns {quat} out
+ * @function
+ */
+
+export var copy = vec4.copy;
+/**
+ * Set the components of a quat to the given values
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} out
+ * @function
+ */
+
+export var set = vec4.set;
+/**
+ * Adds two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {quat} out
+ * @function
+ */
+
+export var add = vec4.add;
+/**
+ * Alias for {@link quat.multiply}
+ * @function
+ */
+
+export var mul = multiply;
+/**
+ * Scales a quat by a scalar number
+ *
+ * @param {quat} out the receiving vector
+ * @param {ReadonlyQuat} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {quat} out
+ * @function
+ */
+
+export var scale = vec4.scale;
+/**
+ * Calculates the dot product of two quat's
+ *
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+
+export var dot = vec4.dot;
+/**
+ * Performs a linear interpolation between two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ * @function
+ */
+
+export var lerp = vec4.lerp;
+/**
+ * Calculates the length of a quat
+ *
+ * @param {ReadonlyQuat} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+export var length = vec4.length;
+/**
+ * Alias for {@link quat.length}
+ * @function
+ */
+
+export var len = length;
+/**
+ * Calculates the squared length of a quat
+ *
+ * @param {ReadonlyQuat} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+
+export var squaredLength = vec4.squaredLength;
+/**
+ * Alias for {@link quat.squaredLength}
+ * @function
+ */
+
+export var sqrLen = squaredLength;
+/**
+ * Normalize a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quaternion to normalize
+ * @returns {quat} out
+ * @function
+ */
+
+export var normalize = vec4.normalize;
+/**
+ * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyQuat} a The first quaternion.
+ * @param {ReadonlyQuat} b The second quaternion.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+export var exactEquals = vec4.exactEquals;
+/**
+ * Returns whether or not the quaternions have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyQuat} a The first vector.
+ * @param {ReadonlyQuat} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+export var equals = vec4.equals;
+/**
+ * Sets a quaternion to represent the shortest rotation from one
+ * vector to another.
+ *
+ * Both vectors are assumed to be unit length.
+ *
+ * @param {quat} out the receiving quaternion.
+ * @param {ReadonlyVec3} a the initial vector
+ * @param {ReadonlyVec3} b the destination vector
+ * @returns {quat} out
+ */
+
+export var rotationTo = function () {
+ var tmpvec3 = vec3.create();
+ var xUnitVec3 = vec3.fromValues(1, 0, 0);
+ var yUnitVec3 = vec3.fromValues(0, 1, 0);
+ return function (out, a, b) {
+ var dot = vec3.dot(a, b);
+
+ if (dot < -0.999999) {
+ vec3.cross(tmpvec3, xUnitVec3, a);
+ if (vec3.len(tmpvec3) < 0.000001) vec3.cross(tmpvec3, yUnitVec3, a);
+ vec3.normalize(tmpvec3, tmpvec3);
+ setAxisAngle(out, tmpvec3, Math.PI);
+ return out;
+ } else if (dot > 0.999999) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ } else {
+ vec3.cross(tmpvec3, a, b);
+ out[0] = tmpvec3[0];
+ out[1] = tmpvec3[1];
+ out[2] = tmpvec3[2];
+ out[3] = 1 + dot;
+ return normalize(out, out);
+ }
+ };
+}();
+/**
+ * Performs a spherical linear interpolation with two control points
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {ReadonlyQuat} c the third operand
+ * @param {ReadonlyQuat} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ */
+
+export var sqlerp = function () {
+ var temp1 = create();
+ var temp2 = create();
+ return function (out, a, b, c, d, t) {
+ slerp(temp1, a, d, t);
+ slerp(temp2, b, c, t);
+ slerp(out, temp1, temp2, 2 * t * (1 - t));
+ return out;
+ };
+}();
+/**
+ * Sets the specified quaternion with values corresponding to the given
+ * axes. Each axis is a vec3 and is expected to be unit length and
+ * perpendicular to all other specified axes.
+ *
+ * @param {ReadonlyVec3} view the vector representing the viewing direction
+ * @param {ReadonlyVec3} right the vector representing the local "right" direction
+ * @param {ReadonlyVec3} up the vector representing the local "up" direction
+ * @returns {quat} out
+ */
+
+export var setAxes = function () {
+ var matr = mat3.create();
+ return function (out, view, right, up) {
+ matr[0] = right[0];
+ matr[3] = right[1];
+ matr[6] = right[2];
+ matr[1] = up[0];
+ matr[4] = up[1];
+ matr[7] = up[2];
+ matr[2] = -view[0];
+ matr[5] = -view[1];
+ matr[8] = -view[2];
+ return normalize(out, fromMat3(out, matr));
+ };
+}();
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/quat2.js b/public/node_modules/gl-matrix/esm/quat2.js
new file mode 100644
index 0000000..ff732d0
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/quat2.js
@@ -0,0 +1,835 @@
+import * as glMatrix from "./common.js";
+import * as quat from "./quat.js";
+import * as mat4 from "./mat4.js";
+/**
+ * Dual Quaternion
+ * Format: [real, dual]
+ * Quaternion format: XYZW
+ * Make sure to have normalized dual quaternions, otherwise the functions may not work as intended.
+ * @module quat2
+ */
+
+/**
+ * Creates a new identity dual quat
+ *
+ * @returns {quat2} a new dual quaternion [real -> rotation, dual -> translation]
+ */
+
+export function create() {
+ var dq = new glMatrix.ARRAY_TYPE(8);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ dq[0] = 0;
+ dq[1] = 0;
+ dq[2] = 0;
+ dq[4] = 0;
+ dq[5] = 0;
+ dq[6] = 0;
+ dq[7] = 0;
+ }
+
+ dq[3] = 1;
+ return dq;
+}
+/**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {ReadonlyQuat2} a dual quaternion to clone
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+
+export function clone(a) {
+ var dq = new glMatrix.ARRAY_TYPE(8);
+ dq[0] = a[0];
+ dq[1] = a[1];
+ dq[2] = a[2];
+ dq[3] = a[3];
+ dq[4] = a[4];
+ dq[5] = a[5];
+ dq[6] = a[6];
+ dq[7] = a[7];
+ return dq;
+}
+/**
+ * Creates a new dual quat initialized with the given values
+ *
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component
+ * @param {Number} y2 Y component
+ * @param {Number} z2 Z component
+ * @param {Number} w2 W component
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+
+export function fromValues(x1, y1, z1, w1, x2, y2, z2, w2) {
+ var dq = new glMatrix.ARRAY_TYPE(8);
+ dq[0] = x1;
+ dq[1] = y1;
+ dq[2] = z1;
+ dq[3] = w1;
+ dq[4] = x2;
+ dq[5] = y2;
+ dq[6] = z2;
+ dq[7] = w2;
+ return dq;
+}
+/**
+ * Creates a new dual quat from the given values (quat and translation)
+ *
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component (translation)
+ * @param {Number} y2 Y component (translation)
+ * @param {Number} z2 Z component (translation)
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+
+export function fromRotationTranslationValues(x1, y1, z1, w1, x2, y2, z2) {
+ var dq = new glMatrix.ARRAY_TYPE(8);
+ dq[0] = x1;
+ dq[1] = y1;
+ dq[2] = z1;
+ dq[3] = w1;
+ var ax = x2 * 0.5,
+ ay = y2 * 0.5,
+ az = z2 * 0.5;
+ dq[4] = ax * w1 + ay * z1 - az * y1;
+ dq[5] = ay * w1 + az * x1 - ax * z1;
+ dq[6] = az * w1 + ax * y1 - ay * x1;
+ dq[7] = -ax * x1 - ay * y1 - az * z1;
+ return dq;
+}
+/**
+ * Creates a dual quat from a quaternion and a translation
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyQuat} q a normalized quaternion
+ * @param {ReadonlyVec3} t tranlation vector
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+
+export function fromRotationTranslation(out, q, t) {
+ var ax = t[0] * 0.5,
+ ay = t[1] * 0.5,
+ az = t[2] * 0.5,
+ bx = q[0],
+ by = q[1],
+ bz = q[2],
+ bw = q[3];
+ out[0] = bx;
+ out[1] = by;
+ out[2] = bz;
+ out[3] = bw;
+ out[4] = ax * bw + ay * bz - az * by;
+ out[5] = ay * bw + az * bx - ax * bz;
+ out[6] = az * bw + ax * by - ay * bx;
+ out[7] = -ax * bx - ay * by - az * bz;
+ return out;
+}
+/**
+ * Creates a dual quat from a translation
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyVec3} t translation vector
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+
+export function fromTranslation(out, t) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = t[0] * 0.5;
+ out[5] = t[1] * 0.5;
+ out[6] = t[2] * 0.5;
+ out[7] = 0;
+ return out;
+}
+/**
+ * Creates a dual quat from a quaternion
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyQuat} q the quaternion
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+
+export function fromRotation(out, q) {
+ out[0] = q[0];
+ out[1] = q[1];
+ out[2] = q[2];
+ out[3] = q[3];
+ out[4] = 0;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ return out;
+}
+/**
+ * Creates a new dual quat from a matrix (4x4)
+ *
+ * @param {quat2} out the dual quaternion
+ * @param {ReadonlyMat4} a the matrix
+ * @returns {quat2} dual quat receiving operation result
+ * @function
+ */
+
+export function fromMat4(out, a) {
+ //TODO Optimize this
+ var outer = quat.create();
+ mat4.getRotation(outer, a);
+ var t = new glMatrix.ARRAY_TYPE(3);
+ mat4.getTranslation(t, a);
+ fromRotationTranslation(out, outer, t);
+ return out;
+}
+/**
+ * Copy the values from one dual quat to another
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the source dual quaternion
+ * @returns {quat2} out
+ * @function
+ */
+
+export function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ return out;
+}
+/**
+ * Set a dual quat to the identity dual quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @returns {quat2} out
+ */
+
+export function identity(out) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = 0;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ return out;
+}
+/**
+ * Set the components of a dual quat to the given values
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component
+ * @param {Number} y2 Y component
+ * @param {Number} z2 Z component
+ * @param {Number} w2 W component
+ * @returns {quat2} out
+ * @function
+ */
+
+export function set(out, x1, y1, z1, w1, x2, y2, z2, w2) {
+ out[0] = x1;
+ out[1] = y1;
+ out[2] = z1;
+ out[3] = w1;
+ out[4] = x2;
+ out[5] = y2;
+ out[6] = z2;
+ out[7] = w2;
+ return out;
+}
+/**
+ * Gets the real part of a dual quat
+ * @param {quat} out real part
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @return {quat} real part
+ */
+
+export var getReal = quat.copy;
+/**
+ * Gets the dual part of a dual quat
+ * @param {quat} out dual part
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @return {quat} dual part
+ */
+
+export function getDual(out, a) {
+ out[0] = a[4];
+ out[1] = a[5];
+ out[2] = a[6];
+ out[3] = a[7];
+ return out;
+}
+/**
+ * Set the real component of a dual quat to the given quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat} q a quaternion representing the real part
+ * @returns {quat2} out
+ * @function
+ */
+
+export var setReal = quat.copy;
+/**
+ * Set the dual component of a dual quat to the given quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat} q a quaternion representing the dual part
+ * @returns {quat2} out
+ * @function
+ */
+
+export function setDual(out, q) {
+ out[4] = q[0];
+ out[5] = q[1];
+ out[6] = q[2];
+ out[7] = q[3];
+ return out;
+}
+/**
+ * Gets the translation of a normalized dual quat
+ * @param {vec3} out translation
+ * @param {ReadonlyQuat2} a Dual Quaternion to be decomposed
+ * @return {vec3} translation
+ */
+
+export function getTranslation(out, a) {
+ var ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3];
+ out[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
+ out[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
+ out[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
+ return out;
+}
+/**
+ * Translates a dual quat by the given vector
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to translate
+ * @param {ReadonlyVec3} v vector to translate by
+ * @returns {quat2} out
+ */
+
+export function translate(out, a, v) {
+ var ax1 = a[0],
+ ay1 = a[1],
+ az1 = a[2],
+ aw1 = a[3],
+ bx1 = v[0] * 0.5,
+ by1 = v[1] * 0.5,
+ bz1 = v[2] * 0.5,
+ ax2 = a[4],
+ ay2 = a[5],
+ az2 = a[6],
+ aw2 = a[7];
+ out[0] = ax1;
+ out[1] = ay1;
+ out[2] = az1;
+ out[3] = aw1;
+ out[4] = aw1 * bx1 + ay1 * bz1 - az1 * by1 + ax2;
+ out[5] = aw1 * by1 + az1 * bx1 - ax1 * bz1 + ay2;
+ out[6] = aw1 * bz1 + ax1 * by1 - ay1 * bx1 + az2;
+ out[7] = -ax1 * bx1 - ay1 * by1 - az1 * bz1 + aw2;
+ return out;
+}
+/**
+ * Rotates a dual quat around the X axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+
+export function rotateX(out, a, rad) {
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ ax1 = ax * bw + aw * bx + ay * bz - az * by,
+ ay1 = ay * bw + aw * by + az * bx - ax * bz,
+ az1 = az * bw + aw * bz + ax * by - ay * bx,
+ aw1 = aw * bw - ax * bx - ay * by - az * bz;
+ quat.rotateX(out, a, rad);
+ bx = out[0];
+ by = out[1];
+ bz = out[2];
+ bw = out[3];
+ out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ return out;
+}
+/**
+ * Rotates a dual quat around the Y axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+
+export function rotateY(out, a, rad) {
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ ax1 = ax * bw + aw * bx + ay * bz - az * by,
+ ay1 = ay * bw + aw * by + az * bx - ax * bz,
+ az1 = az * bw + aw * bz + ax * by - ay * bx,
+ aw1 = aw * bw - ax * bx - ay * by - az * bz;
+ quat.rotateY(out, a, rad);
+ bx = out[0];
+ by = out[1];
+ bz = out[2];
+ bw = out[3];
+ out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ return out;
+}
+/**
+ * Rotates a dual quat around the Z axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+
+export function rotateZ(out, a, rad) {
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ ax1 = ax * bw + aw * bx + ay * bz - az * by,
+ ay1 = ay * bw + aw * by + az * bx - ax * bz,
+ az1 = az * bw + aw * bz + ax * by - ay * bx,
+ aw1 = aw * bw - ax * bx - ay * by - az * bz;
+ quat.rotateZ(out, a, rad);
+ bx = out[0];
+ by = out[1];
+ bz = out[2];
+ bw = out[3];
+ out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ return out;
+}
+/**
+ * Rotates a dual quat by a given quaternion (a * q)
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {ReadonlyQuat} q quaternion to rotate by
+ * @returns {quat2} out
+ */
+
+export function rotateByQuatAppend(out, a, q) {
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3],
+ ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ out[0] = ax * qw + aw * qx + ay * qz - az * qy;
+ out[1] = ay * qw + aw * qy + az * qx - ax * qz;
+ out[2] = az * qw + aw * qz + ax * qy - ay * qx;
+ out[3] = aw * qw - ax * qx - ay * qy - az * qz;
+ ax = a[4];
+ ay = a[5];
+ az = a[6];
+ aw = a[7];
+ out[4] = ax * qw + aw * qx + ay * qz - az * qy;
+ out[5] = ay * qw + aw * qy + az * qx - ax * qz;
+ out[6] = az * qw + aw * qz + ax * qy - ay * qx;
+ out[7] = aw * qw - ax * qx - ay * qy - az * qz;
+ return out;
+}
+/**
+ * Rotates a dual quat by a given quaternion (q * a)
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat} q quaternion to rotate by
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @returns {quat2} out
+ */
+
+export function rotateByQuatPrepend(out, q, a) {
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3],
+ bx = a[0],
+ by = a[1],
+ bz = a[2],
+ bw = a[3];
+ out[0] = qx * bw + qw * bx + qy * bz - qz * by;
+ out[1] = qy * bw + qw * by + qz * bx - qx * bz;
+ out[2] = qz * bw + qw * bz + qx * by - qy * bx;
+ out[3] = qw * bw - qx * bx - qy * by - qz * bz;
+ bx = a[4];
+ by = a[5];
+ bz = a[6];
+ bw = a[7];
+ out[4] = qx * bw + qw * bx + qy * bz - qz * by;
+ out[5] = qy * bw + qw * by + qz * bx - qx * bz;
+ out[6] = qz * bw + qw * bz + qx * by - qy * bx;
+ out[7] = qw * bw - qx * bx - qy * by - qz * bz;
+ return out;
+}
+/**
+ * Rotates a dual quat around a given axis. Does the normalisation automatically
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @param {Number} rad how far the rotation should be
+ * @returns {quat2} out
+ */
+
+export function rotateAroundAxis(out, a, axis, rad) {
+ //Special case for rad = 0
+ if (Math.abs(rad) < glMatrix.EPSILON) {
+ return copy(out, a);
+ }
+
+ var axisLength = Math.hypot(axis[0], axis[1], axis[2]);
+ rad = rad * 0.5;
+ var s = Math.sin(rad);
+ var bx = s * axis[0] / axisLength;
+ var by = s * axis[1] / axisLength;
+ var bz = s * axis[2] / axisLength;
+ var bw = Math.cos(rad);
+ var ax1 = a[0],
+ ay1 = a[1],
+ az1 = a[2],
+ aw1 = a[3];
+ out[0] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[1] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[2] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[3] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ var ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7];
+ out[4] = ax * bw + aw * bx + ay * bz - az * by;
+ out[5] = ay * bw + aw * by + az * bx - ax * bz;
+ out[6] = az * bw + aw * bz + ax * by - ay * bx;
+ out[7] = aw * bw - ax * bx - ay * by - az * bz;
+ return out;
+}
+/**
+ * Adds two dual quat's
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {quat2} out
+ * @function
+ */
+
+export function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ out[6] = a[6] + b[6];
+ out[7] = a[7] + b[7];
+ return out;
+}
+/**
+ * Multiplies two dual quat's
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {quat2} out
+ */
+
+export function multiply(out, a, b) {
+ var ax0 = a[0],
+ ay0 = a[1],
+ az0 = a[2],
+ aw0 = a[3],
+ bx1 = b[4],
+ by1 = b[5],
+ bz1 = b[6],
+ bw1 = b[7],
+ ax1 = a[4],
+ ay1 = a[5],
+ az1 = a[6],
+ aw1 = a[7],
+ bx0 = b[0],
+ by0 = b[1],
+ bz0 = b[2],
+ bw0 = b[3];
+ out[0] = ax0 * bw0 + aw0 * bx0 + ay0 * bz0 - az0 * by0;
+ out[1] = ay0 * bw0 + aw0 * by0 + az0 * bx0 - ax0 * bz0;
+ out[2] = az0 * bw0 + aw0 * bz0 + ax0 * by0 - ay0 * bx0;
+ out[3] = aw0 * bw0 - ax0 * bx0 - ay0 * by0 - az0 * bz0;
+ out[4] = ax0 * bw1 + aw0 * bx1 + ay0 * bz1 - az0 * by1 + ax1 * bw0 + aw1 * bx0 + ay1 * bz0 - az1 * by0;
+ out[5] = ay0 * bw1 + aw0 * by1 + az0 * bx1 - ax0 * bz1 + ay1 * bw0 + aw1 * by0 + az1 * bx0 - ax1 * bz0;
+ out[6] = az0 * bw1 + aw0 * bz1 + ax0 * by1 - ay0 * bx1 + az1 * bw0 + aw1 * bz0 + ax1 * by0 - ay1 * bx0;
+ out[7] = aw0 * bw1 - ax0 * bx1 - ay0 * by1 - az0 * bz1 + aw1 * bw0 - ax1 * bx0 - ay1 * by0 - az1 * bz0;
+ return out;
+}
+/**
+ * Alias for {@link quat2.multiply}
+ * @function
+ */
+
+export var mul = multiply;
+/**
+ * Scales a dual quat by a scalar number
+ *
+ * @param {quat2} out the receiving dual quat
+ * @param {ReadonlyQuat2} a the dual quat to scale
+ * @param {Number} b amount to scale the dual quat by
+ * @returns {quat2} out
+ * @function
+ */
+
+export function scale(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ out[6] = a[6] * b;
+ out[7] = a[7] * b;
+ return out;
+}
+/**
+ * Calculates the dot product of two dual quat's (The dot product of the real parts)
+ *
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+
+export var dot = quat.dot;
+/**
+ * Performs a linear interpolation between two dual quats's
+ * NOTE: The resulting dual quaternions won't always be normalized (The error is most noticeable when t = 0.5)
+ *
+ * @param {quat2} out the receiving dual quat
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat2} out
+ */
+
+export function lerp(out, a, b, t) {
+ var mt = 1 - t;
+ if (dot(a, b) < 0) t = -t;
+ out[0] = a[0] * mt + b[0] * t;
+ out[1] = a[1] * mt + b[1] * t;
+ out[2] = a[2] * mt + b[2] * t;
+ out[3] = a[3] * mt + b[3] * t;
+ out[4] = a[4] * mt + b[4] * t;
+ out[5] = a[5] * mt + b[5] * t;
+ out[6] = a[6] * mt + b[6] * t;
+ out[7] = a[7] * mt + b[7] * t;
+ return out;
+}
+/**
+ * Calculates the inverse of a dual quat. If they are normalized, conjugate is cheaper
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a dual quat to calculate inverse of
+ * @returns {quat2} out
+ */
+
+export function invert(out, a) {
+ var sqlen = squaredLength(a);
+ out[0] = -a[0] / sqlen;
+ out[1] = -a[1] / sqlen;
+ out[2] = -a[2] / sqlen;
+ out[3] = a[3] / sqlen;
+ out[4] = -a[4] / sqlen;
+ out[5] = -a[5] / sqlen;
+ out[6] = -a[6] / sqlen;
+ out[7] = a[7] / sqlen;
+ return out;
+}
+/**
+ * Calculates the conjugate of a dual quat
+ * If the dual quaternion is normalized, this function is faster than quat2.inverse and produces the same result.
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat2} a quat to calculate conjugate of
+ * @returns {quat2} out
+ */
+
+export function conjugate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a[3];
+ out[4] = -a[4];
+ out[5] = -a[5];
+ out[6] = -a[6];
+ out[7] = a[7];
+ return out;
+}
+/**
+ * Calculates the length of a dual quat
+ *
+ * @param {ReadonlyQuat2} a dual quat to calculate length of
+ * @returns {Number} length of a
+ * @function
+ */
+
+export var length = quat.length;
+/**
+ * Alias for {@link quat2.length}
+ * @function
+ */
+
+export var len = length;
+/**
+ * Calculates the squared length of a dual quat
+ *
+ * @param {ReadonlyQuat2} a dual quat to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+
+export var squaredLength = quat.squaredLength;
+/**
+ * Alias for {@link quat2.squaredLength}
+ * @function
+ */
+
+export var sqrLen = squaredLength;
+/**
+ * Normalize a dual quat
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a dual quaternion to normalize
+ * @returns {quat2} out
+ * @function
+ */
+
+export function normalize(out, a) {
+ var magnitude = squaredLength(a);
+
+ if (magnitude > 0) {
+ magnitude = Math.sqrt(magnitude);
+ var a0 = a[0] / magnitude;
+ var a1 = a[1] / magnitude;
+ var a2 = a[2] / magnitude;
+ var a3 = a[3] / magnitude;
+ var b0 = a[4];
+ var b1 = a[5];
+ var b2 = a[6];
+ var b3 = a[7];
+ var a_dot_b = a0 * b0 + a1 * b1 + a2 * b2 + a3 * b3;
+ out[0] = a0;
+ out[1] = a1;
+ out[2] = a2;
+ out[3] = a3;
+ out[4] = (b0 - a0 * a_dot_b) / magnitude;
+ out[5] = (b1 - a1 * a_dot_b) / magnitude;
+ out[6] = (b2 - a2 * a_dot_b) / magnitude;
+ out[7] = (b3 - a3 * a_dot_b) / magnitude;
+ }
+
+ return out;
+}
+/**
+ * Returns a string representation of a dual quatenion
+ *
+ * @param {ReadonlyQuat2} a dual quaternion to represent as a string
+ * @returns {String} string representation of the dual quat
+ */
+
+export function str(a) {
+ return "quat2(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ")";
+}
+/**
+ * Returns whether or not the dual quaternions have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyQuat2} a the first dual quaternion.
+ * @param {ReadonlyQuat2} b the second dual quaternion.
+ * @returns {Boolean} true if the dual quaternions are equal, false otherwise.
+ */
+
+export function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7];
+}
+/**
+ * Returns whether or not the dual quaternions have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyQuat2} a the first dual quat.
+ * @param {ReadonlyQuat2} b the second dual quat.
+ * @returns {Boolean} true if the dual quats are equal, false otherwise.
+ */
+
+export function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5],
+ a6 = a[6],
+ a7 = a[7];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5],
+ b6 = b[6],
+ b7 = b[7];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7));
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/vec2.js b/public/node_modules/gl-matrix/esm/vec2.js
new file mode 100644
index 0000000..eca4b07
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/vec2.js
@@ -0,0 +1,624 @@
+import * as glMatrix from "./common.js";
+/**
+ * 2 Dimensional Vector
+ * @module vec2
+ */
+
+/**
+ * Creates a new, empty vec2
+ *
+ * @returns {vec2} a new 2D vector
+ */
+
+export function create() {
+ var out = new glMatrix.ARRAY_TYPE(2);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ }
+
+ return out;
+}
+/**
+ * Creates a new vec2 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec2} a vector to clone
+ * @returns {vec2} a new 2D vector
+ */
+
+export function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(2);
+ out[0] = a[0];
+ out[1] = a[1];
+ return out;
+}
+/**
+ * Creates a new vec2 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} a new 2D vector
+ */
+
+export function fromValues(x, y) {
+ var out = new glMatrix.ARRAY_TYPE(2);
+ out[0] = x;
+ out[1] = y;
+ return out;
+}
+/**
+ * Copy the values from one vec2 to another
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the source vector
+ * @returns {vec2} out
+ */
+
+export function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ return out;
+}
+/**
+ * Set the components of a vec2 to the given values
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} out
+ */
+
+export function set(out, x, y) {
+ out[0] = x;
+ out[1] = y;
+ return out;
+}
+/**
+ * Adds two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+export function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ return out;
+}
+/**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+export function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ return out;
+}
+/**
+ * Multiplies two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+export function multiply(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ return out;
+}
+/**
+ * Divides two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+export function divide(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ return out;
+}
+/**
+ * Math.ceil the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to ceil
+ * @returns {vec2} out
+ */
+
+export function ceil(out, a) {
+ out[0] = Math.ceil(a[0]);
+ out[1] = Math.ceil(a[1]);
+ return out;
+}
+/**
+ * Math.floor the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to floor
+ * @returns {vec2} out
+ */
+
+export function floor(out, a) {
+ out[0] = Math.floor(a[0]);
+ out[1] = Math.floor(a[1]);
+ return out;
+}
+/**
+ * Returns the minimum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+export function min(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ return out;
+}
+/**
+ * Returns the maximum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+export function max(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ return out;
+}
+/**
+ * Math.round the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to round
+ * @returns {vec2} out
+ */
+
+export function round(out, a) {
+ out[0] = Math.round(a[0]);
+ out[1] = Math.round(a[1]);
+ return out;
+}
+/**
+ * Scales a vec2 by a scalar number
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec2} out
+ */
+
+export function scale(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ return out;
+}
+/**
+ * Adds two vec2's after scaling the second operand by a scalar value
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec2} out
+ */
+
+export function scaleAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ return out;
+}
+/**
+ * Calculates the euclidian distance between two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} distance between a and b
+ */
+
+export function distance(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1];
+ return Math.hypot(x, y);
+}
+/**
+ * Calculates the squared euclidian distance between two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+
+export function squaredDistance(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1];
+ return x * x + y * y;
+}
+/**
+ * Calculates the length of a vec2
+ *
+ * @param {ReadonlyVec2} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+export function length(a) {
+ var x = a[0],
+ y = a[1];
+ return Math.hypot(x, y);
+}
+/**
+ * Calculates the squared length of a vec2
+ *
+ * @param {ReadonlyVec2} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+
+export function squaredLength(a) {
+ var x = a[0],
+ y = a[1];
+ return x * x + y * y;
+}
+/**
+ * Negates the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to negate
+ * @returns {vec2} out
+ */
+
+export function negate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ return out;
+}
+/**
+ * Returns the inverse of the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to invert
+ * @returns {vec2} out
+ */
+
+export function inverse(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ return out;
+}
+/**
+ * Normalize a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to normalize
+ * @returns {vec2} out
+ */
+
+export function normalize(out, a) {
+ var x = a[0],
+ y = a[1];
+ var len = x * x + y * y;
+
+ if (len > 0) {
+ //TODO: evaluate use of glm_invsqrt here?
+ len = 1 / Math.sqrt(len);
+ }
+
+ out[0] = a[0] * len;
+ out[1] = a[1] * len;
+ return out;
+}
+/**
+ * Calculates the dot product of two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+
+export function dot(a, b) {
+ return a[0] * b[0] + a[1] * b[1];
+}
+/**
+ * Computes the cross product of two vec2's
+ * Note that the cross product must by definition produce a 3D vector
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec3} out
+ */
+
+export function cross(out, a, b) {
+ var z = a[0] * b[1] - a[1] * b[0];
+ out[0] = out[1] = 0;
+ out[2] = z;
+ return out;
+}
+/**
+ * Performs a linear interpolation between two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec2} out
+ */
+
+export function lerp(out, a, b, t) {
+ var ax = a[0],
+ ay = a[1];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ return out;
+}
+/**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec2} out
+ */
+
+export function random(out, scale) {
+ scale = scale || 1.0;
+ var r = glMatrix.RANDOM() * 2.0 * Math.PI;
+ out[0] = Math.cos(r) * scale;
+ out[1] = Math.sin(r) * scale;
+ return out;
+}
+/**
+ * Transforms the vec2 with a mat2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat2} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+export function transformMat2(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[2] * y;
+ out[1] = m[1] * x + m[3] * y;
+ return out;
+}
+/**
+ * Transforms the vec2 with a mat2d
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat2d} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+export function transformMat2d(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[2] * y + m[4];
+ out[1] = m[1] * x + m[3] * y + m[5];
+ return out;
+}
+/**
+ * Transforms the vec2 with a mat3
+ * 3rd vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat3} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+export function transformMat3(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[3] * y + m[6];
+ out[1] = m[1] * x + m[4] * y + m[7];
+ return out;
+}
+/**
+ * Transforms the vec2 with a mat4
+ * 3rd vector component is implicitly '0'
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+export function transformMat4(out, a, m) {
+ var x = a[0];
+ var y = a[1];
+ out[0] = m[0] * x + m[4] * y + m[12];
+ out[1] = m[1] * x + m[5] * y + m[13];
+ return out;
+}
+/**
+ * Rotate a 2D vector
+ * @param {vec2} out The receiving vec2
+ * @param {ReadonlyVec2} a The vec2 point to rotate
+ * @param {ReadonlyVec2} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec2} out
+ */
+
+export function rotate(out, a, b, rad) {
+ //Translate point to the origin
+ var p0 = a[0] - b[0],
+ p1 = a[1] - b[1],
+ sinC = Math.sin(rad),
+ cosC = Math.cos(rad); //perform rotation and translate to correct position
+
+ out[0] = p0 * cosC - p1 * sinC + b[0];
+ out[1] = p0 * sinC + p1 * cosC + b[1];
+ return out;
+}
+/**
+ * Get the angle between two 2D vectors
+ * @param {ReadonlyVec2} a The first operand
+ * @param {ReadonlyVec2} b The second operand
+ * @returns {Number} The angle in radians
+ */
+
+export function angle(a, b) {
+ var x1 = a[0],
+ y1 = a[1],
+ x2 = b[0],
+ y2 = b[1],
+ // mag is the product of the magnitudes of a and b
+ mag = Math.sqrt(x1 * x1 + y1 * y1) * Math.sqrt(x2 * x2 + y2 * y2),
+ // mag &&.. short circuits if mag == 0
+ cosine = mag && (x1 * x2 + y1 * y2) / mag; // Math.min(Math.max(cosine, -1), 1) clamps the cosine between -1 and 1
+
+ return Math.acos(Math.min(Math.max(cosine, -1), 1));
+}
+/**
+ * Set the components of a vec2 to zero
+ *
+ * @param {vec2} out the receiving vector
+ * @returns {vec2} out
+ */
+
+export function zero(out) {
+ out[0] = 0.0;
+ out[1] = 0.0;
+ return out;
+}
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec2} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+export function str(a) {
+ return "vec2(" + a[0] + ", " + a[1] + ")";
+}
+/**
+ * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec2} a The first vector.
+ * @param {ReadonlyVec2} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+export function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1];
+}
+/**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec2} a The first vector.
+ * @param {ReadonlyVec2} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+export function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1];
+ var b0 = b[0],
+ b1 = b[1];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1));
+}
+/**
+ * Alias for {@link vec2.length}
+ * @function
+ */
+
+export var len = length;
+/**
+ * Alias for {@link vec2.subtract}
+ * @function
+ */
+
+export var sub = subtract;
+/**
+ * Alias for {@link vec2.multiply}
+ * @function
+ */
+
+export var mul = multiply;
+/**
+ * Alias for {@link vec2.divide}
+ * @function
+ */
+
+export var div = divide;
+/**
+ * Alias for {@link vec2.distance}
+ * @function
+ */
+
+export var dist = distance;
+/**
+ * Alias for {@link vec2.squaredDistance}
+ * @function
+ */
+
+export var sqrDist = squaredDistance;
+/**
+ * Alias for {@link vec2.squaredLength}
+ * @function
+ */
+
+export var sqrLen = squaredLength;
+/**
+ * Perform some operation over an array of vec2s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+
+export var forEach = function () {
+ var vec = create();
+ return function (a, stride, offset, count, fn, arg) {
+ var i, l;
+
+ if (!stride) {
+ stride = 2;
+ }
+
+ if (!offset) {
+ offset = 0;
+ }
+
+ if (count) {
+ l = Math.min(count * stride + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for (i = offset; i < l; i += stride) {
+ vec[0] = a[i];
+ vec[1] = a[i + 1];
+ fn(vec, vec, arg);
+ a[i] = vec[0];
+ a[i + 1] = vec[1];
+ }
+
+ return a;
+ };
+}();
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/vec3.js b/public/node_modules/gl-matrix/esm/vec3.js
new file mode 100644
index 0000000..f5fc096
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/vec3.js
@@ -0,0 +1,787 @@
+import * as glMatrix from "./common.js";
+/**
+ * 3 Dimensional Vector
+ * @module vec3
+ */
+
+/**
+ * Creates a new, empty vec3
+ *
+ * @returns {vec3} a new 3D vector
+ */
+
+export function create() {
+ var out = new glMatrix.ARRAY_TYPE(3);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ }
+
+ return out;
+}
+/**
+ * Creates a new vec3 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec3} a vector to clone
+ * @returns {vec3} a new 3D vector
+ */
+
+export function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(3);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ return out;
+}
+/**
+ * Calculates the length of a vec3
+ *
+ * @param {ReadonlyVec3} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+export function length(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ return Math.hypot(x, y, z);
+}
+/**
+ * Creates a new vec3 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} a new 3D vector
+ */
+
+export function fromValues(x, y, z) {
+ var out = new glMatrix.ARRAY_TYPE(3);
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ return out;
+}
+/**
+ * Copy the values from one vec3 to another
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the source vector
+ * @returns {vec3} out
+ */
+
+export function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ return out;
+}
+/**
+ * Set the components of a vec3 to the given values
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} out
+ */
+
+export function set(out, x, y, z) {
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ return out;
+}
+/**
+ * Adds two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+export function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ return out;
+}
+/**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+export function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ return out;
+}
+/**
+ * Multiplies two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+export function multiply(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ out[2] = a[2] * b[2];
+ return out;
+}
+/**
+ * Divides two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+export function divide(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ out[2] = a[2] / b[2];
+ return out;
+}
+/**
+ * Math.ceil the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to ceil
+ * @returns {vec3} out
+ */
+
+export function ceil(out, a) {
+ out[0] = Math.ceil(a[0]);
+ out[1] = Math.ceil(a[1]);
+ out[2] = Math.ceil(a[2]);
+ return out;
+}
+/**
+ * Math.floor the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to floor
+ * @returns {vec3} out
+ */
+
+export function floor(out, a) {
+ out[0] = Math.floor(a[0]);
+ out[1] = Math.floor(a[1]);
+ out[2] = Math.floor(a[2]);
+ return out;
+}
+/**
+ * Returns the minimum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+export function min(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ out[2] = Math.min(a[2], b[2]);
+ return out;
+}
+/**
+ * Returns the maximum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+export function max(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ out[2] = Math.max(a[2], b[2]);
+ return out;
+}
+/**
+ * Math.round the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to round
+ * @returns {vec3} out
+ */
+
+export function round(out, a) {
+ out[0] = Math.round(a[0]);
+ out[1] = Math.round(a[1]);
+ out[2] = Math.round(a[2]);
+ return out;
+}
+/**
+ * Scales a vec3 by a scalar number
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec3} out
+ */
+
+export function scale(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ return out;
+}
+/**
+ * Adds two vec3's after scaling the second operand by a scalar value
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec3} out
+ */
+
+export function scaleAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ return out;
+}
+/**
+ * Calculates the euclidian distance between two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} distance between a and b
+ */
+
+export function distance(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ return Math.hypot(x, y, z);
+}
+/**
+ * Calculates the squared euclidian distance between two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+
+export function squaredDistance(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ return x * x + y * y + z * z;
+}
+/**
+ * Calculates the squared length of a vec3
+ *
+ * @param {ReadonlyVec3} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+
+export function squaredLength(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ return x * x + y * y + z * z;
+}
+/**
+ * Negates the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to negate
+ * @returns {vec3} out
+ */
+
+export function negate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ return out;
+}
+/**
+ * Returns the inverse of the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to invert
+ * @returns {vec3} out
+ */
+
+export function inverse(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ out[2] = 1.0 / a[2];
+ return out;
+}
+/**
+ * Normalize a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to normalize
+ * @returns {vec3} out
+ */
+
+export function normalize(out, a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var len = x * x + y * y + z * z;
+
+ if (len > 0) {
+ //TODO: evaluate use of glm_invsqrt here?
+ len = 1 / Math.sqrt(len);
+ }
+
+ out[0] = a[0] * len;
+ out[1] = a[1] * len;
+ out[2] = a[2] * len;
+ return out;
+}
+/**
+ * Calculates the dot product of two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+
+export function dot(a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+/**
+ * Computes the cross product of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+export function cross(out, a, b) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2];
+ var bx = b[0],
+ by = b[1],
+ bz = b[2];
+ out[0] = ay * bz - az * by;
+ out[1] = az * bx - ax * bz;
+ out[2] = ax * by - ay * bx;
+ return out;
+}
+/**
+ * Performs a linear interpolation between two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+
+export function lerp(out, a, b, t) {
+ var ax = a[0];
+ var ay = a[1];
+ var az = a[2];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ out[2] = az + t * (b[2] - az);
+ return out;
+}
+/**
+ * Performs a hermite interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {ReadonlyVec3} c the third operand
+ * @param {ReadonlyVec3} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+
+export function hermite(out, a, b, c, d, t) {
+ var factorTimes2 = t * t;
+ var factor1 = factorTimes2 * (2 * t - 3) + 1;
+ var factor2 = factorTimes2 * (t - 2) + t;
+ var factor3 = factorTimes2 * (t - 1);
+ var factor4 = factorTimes2 * (3 - 2 * t);
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+ return out;
+}
+/**
+ * Performs a bezier interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {ReadonlyVec3} c the third operand
+ * @param {ReadonlyVec3} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+
+export function bezier(out, a, b, c, d, t) {
+ var inverseFactor = 1 - t;
+ var inverseFactorTimesTwo = inverseFactor * inverseFactor;
+ var factorTimes2 = t * t;
+ var factor1 = inverseFactorTimesTwo * inverseFactor;
+ var factor2 = 3 * t * inverseFactorTimesTwo;
+ var factor3 = 3 * factorTimes2 * inverseFactor;
+ var factor4 = factorTimes2 * t;
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+ return out;
+}
+/**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec3} out
+ */
+
+export function random(out, scale) {
+ scale = scale || 1.0;
+ var r = glMatrix.RANDOM() * 2.0 * Math.PI;
+ var z = glMatrix.RANDOM() * 2.0 - 1.0;
+ var zScale = Math.sqrt(1.0 - z * z) * scale;
+ out[0] = Math.cos(r) * zScale;
+ out[1] = Math.sin(r) * zScale;
+ out[2] = z * scale;
+ return out;
+}
+/**
+ * Transforms the vec3 with a mat4.
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec3} out
+ */
+
+export function transformMat4(out, a, m) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ var w = m[3] * x + m[7] * y + m[11] * z + m[15];
+ w = w || 1.0;
+ out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
+ out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
+ out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
+ return out;
+}
+/**
+ * Transforms the vec3 with a mat3.
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyMat3} m the 3x3 matrix to transform with
+ * @returns {vec3} out
+ */
+
+export function transformMat3(out, a, m) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ out[0] = x * m[0] + y * m[3] + z * m[6];
+ out[1] = x * m[1] + y * m[4] + z * m[7];
+ out[2] = x * m[2] + y * m[5] + z * m[8];
+ return out;
+}
+/**
+ * Transforms the vec3 with a quat
+ * Can also be used for dual quaternions. (Multiply it with the real part)
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyQuat} q quaternion to transform with
+ * @returns {vec3} out
+ */
+
+export function transformQuat(out, a, q) {
+ // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3];
+ var x = a[0],
+ y = a[1],
+ z = a[2]; // var qvec = [qx, qy, qz];
+ // var uv = vec3.cross([], qvec, a);
+
+ var uvx = qy * z - qz * y,
+ uvy = qz * x - qx * z,
+ uvz = qx * y - qy * x; // var uuv = vec3.cross([], qvec, uv);
+
+ var uuvx = qy * uvz - qz * uvy,
+ uuvy = qz * uvx - qx * uvz,
+ uuvz = qx * uvy - qy * uvx; // vec3.scale(uv, uv, 2 * w);
+
+ var w2 = qw * 2;
+ uvx *= w2;
+ uvy *= w2;
+ uvz *= w2; // vec3.scale(uuv, uuv, 2);
+
+ uuvx *= 2;
+ uuvy *= 2;
+ uuvz *= 2; // return vec3.add(out, a, vec3.add(out, uv, uuv));
+
+ out[0] = x + uvx + uuvx;
+ out[1] = y + uvy + uuvy;
+ out[2] = z + uvz + uuvz;
+ return out;
+}
+/**
+ * Rotate a 3D vector around the x-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+
+export function rotateX(out, a, b, rad) {
+ var p = [],
+ r = []; //Translate point to the origin
+
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2]; //perform rotation
+
+ r[0] = p[0];
+ r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);
+ r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad); //translate to correct position
+
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+ return out;
+}
+/**
+ * Rotate a 3D vector around the y-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+
+export function rotateY(out, a, b, rad) {
+ var p = [],
+ r = []; //Translate point to the origin
+
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2]; //perform rotation
+
+ r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);
+ r[1] = p[1];
+ r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad); //translate to correct position
+
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+ return out;
+}
+/**
+ * Rotate a 3D vector around the z-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+
+export function rotateZ(out, a, b, rad) {
+ var p = [],
+ r = []; //Translate point to the origin
+
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2]; //perform rotation
+
+ r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);
+ r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);
+ r[2] = p[2]; //translate to correct position
+
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+ return out;
+}
+/**
+ * Get the angle between two 3D vectors
+ * @param {ReadonlyVec3} a The first operand
+ * @param {ReadonlyVec3} b The second operand
+ * @returns {Number} The angle in radians
+ */
+
+export function angle(a, b) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ bx = b[0],
+ by = b[1],
+ bz = b[2],
+ mag1 = Math.sqrt(ax * ax + ay * ay + az * az),
+ mag2 = Math.sqrt(bx * bx + by * by + bz * bz),
+ mag = mag1 * mag2,
+ cosine = mag && dot(a, b) / mag;
+ return Math.acos(Math.min(Math.max(cosine, -1), 1));
+}
+/**
+ * Set the components of a vec3 to zero
+ *
+ * @param {vec3} out the receiving vector
+ * @returns {vec3} out
+ */
+
+export function zero(out) {
+ out[0] = 0.0;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ return out;
+}
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec3} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+export function str(a) {
+ return "vec3(" + a[0] + ", " + a[1] + ", " + a[2] + ")";
+}
+/**
+ * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec3} a The first vector.
+ * @param {ReadonlyVec3} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+export function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
+}
+/**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec3} a The first vector.
+ * @param {ReadonlyVec3} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+export function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2));
+}
+/**
+ * Alias for {@link vec3.subtract}
+ * @function
+ */
+
+export var sub = subtract;
+/**
+ * Alias for {@link vec3.multiply}
+ * @function
+ */
+
+export var mul = multiply;
+/**
+ * Alias for {@link vec3.divide}
+ * @function
+ */
+
+export var div = divide;
+/**
+ * Alias for {@link vec3.distance}
+ * @function
+ */
+
+export var dist = distance;
+/**
+ * Alias for {@link vec3.squaredDistance}
+ * @function
+ */
+
+export var sqrDist = squaredDistance;
+/**
+ * Alias for {@link vec3.length}
+ * @function
+ */
+
+export var len = length;
+/**
+ * Alias for {@link vec3.squaredLength}
+ * @function
+ */
+
+export var sqrLen = squaredLength;
+/**
+ * Perform some operation over an array of vec3s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+
+export var forEach = function () {
+ var vec = create();
+ return function (a, stride, offset, count, fn, arg) {
+ var i, l;
+
+ if (!stride) {
+ stride = 3;
+ }
+
+ if (!offset) {
+ offset = 0;
+ }
+
+ if (count) {
+ l = Math.min(count * stride + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for (i = offset; i < l; i += stride) {
+ vec[0] = a[i];
+ vec[1] = a[i + 1];
+ vec[2] = a[i + 2];
+ fn(vec, vec, arg);
+ a[i] = vec[0];
+ a[i + 1] = vec[1];
+ a[i + 2] = vec[2];
+ }
+
+ return a;
+ };
+}();
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/esm/vec4.js b/public/node_modules/gl-matrix/esm/vec4.js
new file mode 100644
index 0000000..e0f206f
--- /dev/null
+++ b/public/node_modules/gl-matrix/esm/vec4.js
@@ -0,0 +1,663 @@
+import * as glMatrix from "./common.js";
+/**
+ * 4 Dimensional Vector
+ * @module vec4
+ */
+
+/**
+ * Creates a new, empty vec4
+ *
+ * @returns {vec4} a new 4D vector
+ */
+
+export function create() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+
+ if (glMatrix.ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ }
+
+ return out;
+}
+/**
+ * Creates a new vec4 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec4} a vector to clone
+ * @returns {vec4} a new 4D vector
+ */
+
+export function clone(a) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Creates a new vec4 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} a new 4D vector
+ */
+
+export function fromValues(x, y, z, w) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = w;
+ return out;
+}
+/**
+ * Copy the values from one vec4 to another
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the source vector
+ * @returns {vec4} out
+ */
+
+export function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Set the components of a vec4 to the given values
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} out
+ */
+
+export function set(out, x, y, z, w) {
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = w;
+ return out;
+}
+/**
+ * Adds two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+export function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ return out;
+}
+/**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+export function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ return out;
+}
+/**
+ * Multiplies two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+export function multiply(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ out[2] = a[2] * b[2];
+ out[3] = a[3] * b[3];
+ return out;
+}
+/**
+ * Divides two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+export function divide(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ out[2] = a[2] / b[2];
+ out[3] = a[3] / b[3];
+ return out;
+}
+/**
+ * Math.ceil the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to ceil
+ * @returns {vec4} out
+ */
+
+export function ceil(out, a) {
+ out[0] = Math.ceil(a[0]);
+ out[1] = Math.ceil(a[1]);
+ out[2] = Math.ceil(a[2]);
+ out[3] = Math.ceil(a[3]);
+ return out;
+}
+/**
+ * Math.floor the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to floor
+ * @returns {vec4} out
+ */
+
+export function floor(out, a) {
+ out[0] = Math.floor(a[0]);
+ out[1] = Math.floor(a[1]);
+ out[2] = Math.floor(a[2]);
+ out[3] = Math.floor(a[3]);
+ return out;
+}
+/**
+ * Returns the minimum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+export function min(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ out[2] = Math.min(a[2], b[2]);
+ out[3] = Math.min(a[3], b[3]);
+ return out;
+}
+/**
+ * Returns the maximum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+export function max(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ out[2] = Math.max(a[2], b[2]);
+ out[3] = Math.max(a[3], b[3]);
+ return out;
+}
+/**
+ * Math.round the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to round
+ * @returns {vec4} out
+ */
+
+export function round(out, a) {
+ out[0] = Math.round(a[0]);
+ out[1] = Math.round(a[1]);
+ out[2] = Math.round(a[2]);
+ out[3] = Math.round(a[3]);
+ return out;
+}
+/**
+ * Scales a vec4 by a scalar number
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec4} out
+ */
+
+export function scale(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ return out;
+}
+/**
+ * Adds two vec4's after scaling the second operand by a scalar value
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec4} out
+ */
+
+export function scaleAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ return out;
+}
+/**
+ * Calculates the euclidian distance between two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} distance between a and b
+ */
+
+export function distance(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ var w = b[3] - a[3];
+ return Math.hypot(x, y, z, w);
+}
+/**
+ * Calculates the squared euclidian distance between two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+
+export function squaredDistance(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ var w = b[3] - a[3];
+ return x * x + y * y + z * z + w * w;
+}
+/**
+ * Calculates the length of a vec4
+ *
+ * @param {ReadonlyVec4} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+export function length(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var w = a[3];
+ return Math.hypot(x, y, z, w);
+}
+/**
+ * Calculates the squared length of a vec4
+ *
+ * @param {ReadonlyVec4} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+
+export function squaredLength(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var w = a[3];
+ return x * x + y * y + z * z + w * w;
+}
+/**
+ * Negates the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to negate
+ * @returns {vec4} out
+ */
+
+export function negate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = -a[3];
+ return out;
+}
+/**
+ * Returns the inverse of the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to invert
+ * @returns {vec4} out
+ */
+
+export function inverse(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ out[2] = 1.0 / a[2];
+ out[3] = 1.0 / a[3];
+ return out;
+}
+/**
+ * Normalize a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to normalize
+ * @returns {vec4} out
+ */
+
+export function normalize(out, a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var w = a[3];
+ var len = x * x + y * y + z * z + w * w;
+
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ }
+
+ out[0] = x * len;
+ out[1] = y * len;
+ out[2] = z * len;
+ out[3] = w * len;
+ return out;
+}
+/**
+ * Calculates the dot product of two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+
+export function dot(a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+}
+/**
+ * Returns the cross-product of three vectors in a 4-dimensional space
+ *
+ * @param {ReadonlyVec4} result the receiving vector
+ * @param {ReadonlyVec4} U the first vector
+ * @param {ReadonlyVec4} V the second vector
+ * @param {ReadonlyVec4} W the third vector
+ * @returns {vec4} result
+ */
+
+export function cross(out, u, v, w) {
+ var A = v[0] * w[1] - v[1] * w[0],
+ B = v[0] * w[2] - v[2] * w[0],
+ C = v[0] * w[3] - v[3] * w[0],
+ D = v[1] * w[2] - v[2] * w[1],
+ E = v[1] * w[3] - v[3] * w[1],
+ F = v[2] * w[3] - v[3] * w[2];
+ var G = u[0];
+ var H = u[1];
+ var I = u[2];
+ var J = u[3];
+ out[0] = H * F - I * E + J * D;
+ out[1] = -(G * F) + I * C - J * B;
+ out[2] = G * E - H * C + J * A;
+ out[3] = -(G * D) + H * B - I * A;
+ return out;
+}
+/**
+ * Performs a linear interpolation between two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec4} out
+ */
+
+export function lerp(out, a, b, t) {
+ var ax = a[0];
+ var ay = a[1];
+ var az = a[2];
+ var aw = a[3];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ out[2] = az + t * (b[2] - az);
+ out[3] = aw + t * (b[3] - aw);
+ return out;
+}
+/**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec4} out
+ */
+
+export function random(out, scale) {
+ scale = scale || 1.0; // Marsaglia, George. Choosing a Point from the Surface of a
+ // Sphere. Ann. Math. Statist. 43 (1972), no. 2, 645--646.
+ // http://projecteuclid.org/euclid.aoms/1177692644;
+
+ var v1, v2, v3, v4;
+ var s1, s2;
+
+ do {
+ v1 = glMatrix.RANDOM() * 2 - 1;
+ v2 = glMatrix.RANDOM() * 2 - 1;
+ s1 = v1 * v1 + v2 * v2;
+ } while (s1 >= 1);
+
+ do {
+ v3 = glMatrix.RANDOM() * 2 - 1;
+ v4 = glMatrix.RANDOM() * 2 - 1;
+ s2 = v3 * v3 + v4 * v4;
+ } while (s2 >= 1);
+
+ var d = Math.sqrt((1 - s1) / s2);
+ out[0] = scale * v1;
+ out[1] = scale * v2;
+ out[2] = scale * v3 * d;
+ out[3] = scale * v4 * d;
+ return out;
+}
+/**
+ * Transforms the vec4 with a mat4.
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec4} out
+ */
+
+export function transformMat4(out, a, m) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
+ out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
+ out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
+ out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
+ return out;
+}
+/**
+ * Transforms the vec4 with a quat
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to transform
+ * @param {ReadonlyQuat} q quaternion to transform with
+ * @returns {vec4} out
+ */
+
+export function transformQuat(out, a, q) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3]; // calculate quat * vec
+
+ var ix = qw * x + qy * z - qz * y;
+ var iy = qw * y + qz * x - qx * z;
+ var iz = qw * z + qx * y - qy * x;
+ var iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat
+
+ out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
+ out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
+ out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
+ out[3] = a[3];
+ return out;
+}
+/**
+ * Set the components of a vec4 to zero
+ *
+ * @param {vec4} out the receiving vector
+ * @returns {vec4} out
+ */
+
+export function zero(out) {
+ out[0] = 0.0;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ out[3] = 0.0;
+ return out;
+}
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec4} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+export function str(a) {
+ return "vec4(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")";
+}
+/**
+ * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec4} a The first vector.
+ * @param {ReadonlyVec4} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+export function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
+}
+/**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec4} a The first vector.
+ * @param {ReadonlyVec4} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+export function equals(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3));
+}
+/**
+ * Alias for {@link vec4.subtract}
+ * @function
+ */
+
+export var sub = subtract;
+/**
+ * Alias for {@link vec4.multiply}
+ * @function
+ */
+
+export var mul = multiply;
+/**
+ * Alias for {@link vec4.divide}
+ * @function
+ */
+
+export var div = divide;
+/**
+ * Alias for {@link vec4.distance}
+ * @function
+ */
+
+export var dist = distance;
+/**
+ * Alias for {@link vec4.squaredDistance}
+ * @function
+ */
+
+export var sqrDist = squaredDistance;
+/**
+ * Alias for {@link vec4.length}
+ * @function
+ */
+
+export var len = length;
+/**
+ * Alias for {@link vec4.squaredLength}
+ * @function
+ */
+
+export var sqrLen = squaredLength;
+/**
+ * Perform some operation over an array of vec4s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+
+export var forEach = function () {
+ var vec = create();
+ return function (a, stride, offset, count, fn, arg) {
+ var i, l;
+
+ if (!stride) {
+ stride = 4;
+ }
+
+ if (!offset) {
+ offset = 0;
+ }
+
+ if (count) {
+ l = Math.min(count * stride + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for (i = offset; i < l; i += stride) {
+ vec[0] = a[i];
+ vec[1] = a[i + 1];
+ vec[2] = a[i + 2];
+ vec[3] = a[i + 3];
+ fn(vec, vec, arg);
+ a[i] = vec[0];
+ a[i + 1] = vec[1];
+ a[i + 2] = vec[2];
+ a[i + 3] = vec[3];
+ }
+
+ return a;
+ };
+}();
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/gl-matrix-min.js b/public/node_modules/gl-matrix/gl-matrix-min.js
new file mode 100644
index 0000000..d2dd80a
--- /dev/null
+++ b/public/node_modules/gl-matrix/gl-matrix-min.js
@@ -0,0 +1,28 @@
+/*!
+@fileoverview gl-matrix - High performance matrix and vector operations
+@author Brandon Jones
+@author Colin MacKenzie IV
+@version 3.4.3
+
+Copyright (c) 2015-2021, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+*/
+!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t=t||self).glMatrix={})}(this,(function(t){"use strict";var n=1e-6,a="undefined"!=typeof Float32Array?Float32Array:Array,r=Math.random;var u=Math.PI/180;Math.hypot||(Math.hypot=function(){for(var t=0,n=arguments.length;n--;)t+=arguments[n]*arguments[n];return Math.sqrt(t)});var e=Object.freeze({__proto__:null,EPSILON:n,get ARRAY_TYPE(){return a},RANDOM:r,setMatrixArrayType:function(t){a=t},toRadian:function(t){return t*u},equals:function(t,a){return Math.abs(t-a)<=n*Math.max(1,Math.abs(t),Math.abs(a))}});function o(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1],c=a[2],s=a[3];return t[0]=r*i+e*h,t[1]=u*i+o*h,t[2]=r*c+e*s,t[3]=u*c+o*s,t}function i(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t}var h=o,c=i,s=Object.freeze({__proto__:null,create:function(){var t=new a(4);return a!=Float32Array&&(t[1]=0,t[2]=0),t[0]=1,t[3]=1,t},clone:function(t){var n=new a(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},fromValues:function(t,n,r,u){var e=new a(4);return e[0]=t,e[1]=n,e[2]=r,e[3]=u,e},set:function(t,n,a,r,u){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t},transpose:function(t,n){if(t===n){var a=n[1];t[1]=n[2],t[2]=a}else t[0]=n[0],t[1]=n[2],t[2]=n[1],t[3]=n[3];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*e-u*r;return o?(o=1/o,t[0]=e*o,t[1]=-r*o,t[2]=-u*o,t[3]=a*o,t):null},adjoint:function(t,n){var a=n[0];return t[0]=n[3],t[1]=-n[1],t[2]=-n[2],t[3]=a,t},determinant:function(t){return t[0]*t[3]-t[2]*t[1]},multiply:o,rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h+e*i,t[1]=u*h+o*i,t[2]=r*-i+e*h,t[3]=u*-i+o*h,t},scale:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1];return t[0]=r*i,t[1]=u*i,t[2]=e*h,t[3]=o*h,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=-a,t[3]=r,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t},str:function(t){return"mat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3])},LDU:function(t,n,a,r){return t[2]=r[2]/r[0],a[0]=r[0],a[1]=r[1],a[3]=r[3]-t[2]*a[1],[t,n,a]},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t},subtract:i,exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=a[0],h=a[1],c=a[2],s=a[3];return Math.abs(r-i)<=n*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(u-h)<=n*Math.max(1,Math.abs(u),Math.abs(h))&&Math.abs(e-c)<=n*Math.max(1,Math.abs(e),Math.abs(c))&&Math.abs(o-s)<=n*Math.max(1,Math.abs(o),Math.abs(s))},multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t},mul:h,sub:c});function M(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=a[0],s=a[1],M=a[2],f=a[3],l=a[4],v=a[5];return t[0]=r*c+e*s,t[1]=u*c+o*s,t[2]=r*M+e*f,t[3]=u*M+o*f,t[4]=r*l+e*v+i,t[5]=u*l+o*v+h,t}function f(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t}var l=M,v=f,b=Object.freeze({__proto__:null,create:function(){var t=new a(6);return a!=Float32Array&&(t[1]=0,t[2]=0,t[4]=0,t[5]=0),t[0]=1,t[3]=1,t},clone:function(t){var n=new a(6);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},fromValues:function(t,n,r,u,e,o){var i=new a(6);return i[0]=t,i[1]=n,i[2]=r,i[3]=u,i[4]=e,i[5]=o,i},set:function(t,n,a,r,u,e,o){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=a*e-r*u;return h?(h=1/h,t[0]=e*h,t[1]=-r*h,t[2]=-u*h,t[3]=a*h,t[4]=(u*i-e*o)*h,t[5]=(r*o-a*i)*h,t):null},determinant:function(t){return t[0]*t[3]-t[1]*t[2]},multiply:M,rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=Math.sin(a),s=Math.cos(a);return t[0]=r*s+e*c,t[1]=u*s+o*c,t[2]=r*-c+e*s,t[3]=u*-c+o*s,t[4]=i,t[5]=h,t},scale:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=a[0],s=a[1];return t[0]=r*c,t[1]=u*c,t[2]=e*s,t[3]=o*s,t[4]=i,t[5]=h,t},translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=a[0],s=a[1];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=r*c+e*s+i,t[5]=u*c+o*s+h,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=-a,t[3]=r,t[4]=0,t[5]=0,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t[4]=0,t[5]=0,t},fromTranslation:function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=n[0],t[5]=n[1],t},str:function(t){return"mat2d("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],1)},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t},subtract:f,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],h=t[5],c=a[0],s=a[1],M=a[2],f=a[3],l=a[4],v=a[5];return Math.abs(r-c)<=n*Math.max(1,Math.abs(r),Math.abs(c))&&Math.abs(u-s)<=n*Math.max(1,Math.abs(u),Math.abs(s))&&Math.abs(e-M)<=n*Math.max(1,Math.abs(e),Math.abs(M))&&Math.abs(o-f)<=n*Math.max(1,Math.abs(o),Math.abs(f))&&Math.abs(i-l)<=n*Math.max(1,Math.abs(i),Math.abs(l))&&Math.abs(h-v)<=n*Math.max(1,Math.abs(h),Math.abs(v))},mul:l,sub:v});function m(){var t=new a(9);return a!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[5]=0,t[6]=0,t[7]=0),t[0]=1,t[4]=1,t[8]=1,t}function d(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=a[0],l=a[1],v=a[2],b=a[3],m=a[4],d=a[5],p=a[6],x=a[7],y=a[8];return t[0]=f*r+l*o+v*c,t[1]=f*u+l*i+v*s,t[2]=f*e+l*h+v*M,t[3]=b*r+m*o+d*c,t[4]=b*u+m*i+d*s,t[5]=b*e+m*h+d*M,t[6]=p*r+x*o+y*c,t[7]=p*u+x*i+y*s,t[8]=p*e+x*h+y*M,t}function p(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t[6]=n[6]-a[6],t[7]=n[7]-a[7],t[8]=n[8]-a[8],t}var x=d,y=p,q=Object.freeze({__proto__:null,create:m,fromMat4:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t},clone:function(t){var n=new a(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},fromValues:function(t,n,r,u,e,o,i,h,c){var s=new a(9);return s[0]=t,s[1]=n,s[2]=r,s[3]=u,s[4]=e,s[5]=o,s[6]=i,s[7]=h,s[8]=c,s},set:function(t,n,a,r,u,e,o,i,h,c){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=h,t[8]=c,t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},transpose:function(t,n){if(t===n){var a=n[1],r=n[2],u=n[5];t[1]=n[3],t[2]=n[6],t[3]=a,t[5]=n[7],t[6]=r,t[7]=u}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=s*o-i*c,f=-s*e+i*h,l=c*e-o*h,v=a*M+r*f+u*l;return v?(v=1/v,t[0]=M*v,t[1]=(-s*r+u*c)*v,t[2]=(i*r-u*o)*v,t[3]=f*v,t[4]=(s*a-u*h)*v,t[5]=(-i*a+u*e)*v,t[6]=l*v,t[7]=(-c*a+r*h)*v,t[8]=(o*a-r*e)*v,t):null},adjoint:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8];return t[0]=o*s-i*c,t[1]=u*c-r*s,t[2]=r*i-u*o,t[3]=i*h-e*s,t[4]=a*s-u*h,t[5]=u*e-a*i,t[6]=e*c-o*h,t[7]=r*h-a*c,t[8]=a*o-r*e,t},determinant:function(t){var n=t[0],a=t[1],r=t[2],u=t[3],e=t[4],o=t[5],i=t[6],h=t[7],c=t[8];return n*(c*e-o*h)+a*(-c*u+o*i)+r*(h*u-e*i)},multiply:d,translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=a[0],l=a[1];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=i,t[5]=h,t[6]=f*r+l*o+c,t[7]=f*u+l*i+s,t[8]=f*e+l*h+M,t},rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=Math.sin(a),l=Math.cos(a);return t[0]=l*r+f*o,t[1]=l*u+f*i,t[2]=l*e+f*h,t[3]=l*o-f*r,t[4]=l*i-f*u,t[5]=l*h-f*e,t[6]=c,t[7]=s,t[8]=M,t},scale:function(t,n,a){var r=a[0],u=a[1];return t[0]=r*n[0],t[1]=r*n[1],t[2]=r*n[2],t[3]=u*n[3],t[4]=u*n[4],t[5]=u*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},fromTranslation:function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=0,t[3]=-a,t[4]=r,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},fromMat2d:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t},fromQuat:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a+a,i=r+r,h=u+u,c=a*o,s=r*o,M=r*i,f=u*o,l=u*i,v=u*h,b=e*o,m=e*i,d=e*h;return t[0]=1-M-v,t[3]=s-d,t[6]=f+m,t[1]=s+d,t[4]=1-c-v,t[7]=l-b,t[2]=f-m,t[5]=l+b,t[8]=1-c-M,t},normalFromMat4:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],p=a*i-r*o,x=a*h-u*o,y=a*c-e*o,q=r*h-u*i,g=r*c-e*i,_=u*c-e*h,A=s*b-M*v,w=s*m-f*v,R=s*d-l*v,z=M*m-f*b,O=M*d-l*b,j=f*d-l*m,P=p*j-x*O+y*z+q*R-g*w+_*A;return P?(P=1/P,t[0]=(i*j-h*O+c*z)*P,t[1]=(h*R-o*j-c*w)*P,t[2]=(o*O-i*R+c*A)*P,t[3]=(u*O-r*j-e*z)*P,t[4]=(a*j-u*R+e*w)*P,t[5]=(r*R-a*O-e*A)*P,t[6]=(b*_-m*g+d*q)*P,t[7]=(m*y-v*_-d*x)*P,t[8]=(v*g-b*y+d*p)*P,t):null},projection:function(t,n,a){return t[0]=2/n,t[1]=0,t[2]=0,t[3]=0,t[4]=-2/a,t[5]=0,t[6]=-1,t[7]=1,t[8]=1,t},str:function(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8])},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t[8]=n[8]+a[8],t},subtract:p,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t[8]=n[8]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t[6]=n[6]+a[6]*r,t[7]=n[7]+a[7]*r,t[8]=n[8]+a[8]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],h=t[5],c=t[6],s=t[7],M=t[8],f=a[0],l=a[1],v=a[2],b=a[3],m=a[4],d=a[5],p=a[6],x=a[7],y=a[8];return Math.abs(r-f)<=n*Math.max(1,Math.abs(r),Math.abs(f))&&Math.abs(u-l)<=n*Math.max(1,Math.abs(u),Math.abs(l))&&Math.abs(e-v)<=n*Math.max(1,Math.abs(e),Math.abs(v))&&Math.abs(o-b)<=n*Math.max(1,Math.abs(o),Math.abs(b))&&Math.abs(i-m)<=n*Math.max(1,Math.abs(i),Math.abs(m))&&Math.abs(h-d)<=n*Math.max(1,Math.abs(h),Math.abs(d))&&Math.abs(c-p)<=n*Math.max(1,Math.abs(c),Math.abs(p))&&Math.abs(s-x)<=n*Math.max(1,Math.abs(s),Math.abs(x))&&Math.abs(M-y)<=n*Math.max(1,Math.abs(M),Math.abs(y))},mul:x,sub:y});function g(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function _(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=n[9],l=n[10],v=n[11],b=n[12],m=n[13],d=n[14],p=n[15],x=a[0],y=a[1],q=a[2],g=a[3];return t[0]=x*r+y*i+q*M+g*b,t[1]=x*u+y*h+q*f+g*m,t[2]=x*e+y*c+q*l+g*d,t[3]=x*o+y*s+q*v+g*p,x=a[4],y=a[5],q=a[6],g=a[7],t[4]=x*r+y*i+q*M+g*b,t[5]=x*u+y*h+q*f+g*m,t[6]=x*e+y*c+q*l+g*d,t[7]=x*o+y*s+q*v+g*p,x=a[8],y=a[9],q=a[10],g=a[11],t[8]=x*r+y*i+q*M+g*b,t[9]=x*u+y*h+q*f+g*m,t[10]=x*e+y*c+q*l+g*d,t[11]=x*o+y*s+q*v+g*p,x=a[12],y=a[13],q=a[14],g=a[15],t[12]=x*r+y*i+q*M+g*b,t[13]=x*u+y*h+q*f+g*m,t[14]=x*e+y*c+q*l+g*d,t[15]=x*o+y*s+q*v+g*p,t}function A(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=r+r,h=u+u,c=e+e,s=r*i,M=r*h,f=r*c,l=u*h,v=u*c,b=e*c,m=o*i,d=o*h,p=o*c;return t[0]=1-(l+b),t[1]=M+p,t[2]=f-d,t[3]=0,t[4]=M-p,t[5]=1-(s+b),t[6]=v+m,t[7]=0,t[8]=f+d,t[9]=v-m,t[10]=1-(s+l),t[11]=0,t[12]=a[0],t[13]=a[1],t[14]=a[2],t[15]=1,t}function w(t,n){return t[0]=n[12],t[1]=n[13],t[2]=n[14],t}function R(t,n){var a=n[0],r=n[1],u=n[2],e=n[4],o=n[5],i=n[6],h=n[8],c=n[9],s=n[10];return t[0]=Math.hypot(a,r,u),t[1]=Math.hypot(e,o,i),t[2]=Math.hypot(h,c,s),t}function z(t,n){var r=new a(3);R(r,n);var u=1/r[0],e=1/r[1],o=1/r[2],i=n[0]*u,h=n[1]*e,c=n[2]*o,s=n[4]*u,M=n[5]*e,f=n[6]*o,l=n[8]*u,v=n[9]*e,b=n[10]*o,m=i+M+b,d=0;return m>0?(d=2*Math.sqrt(m+1),t[3]=.25*d,t[0]=(f-v)/d,t[1]=(l-c)/d,t[2]=(h-s)/d):i>M&&i>b?(d=2*Math.sqrt(1+i-M-b),t[3]=(f-v)/d,t[0]=.25*d,t[1]=(h+s)/d,t[2]=(l+c)/d):M>b?(d=2*Math.sqrt(1+M-i-b),t[3]=(l-c)/d,t[0]=(h+s)/d,t[1]=.25*d,t[2]=(f+v)/d):(d=2*Math.sqrt(1+b-i-M),t[3]=(h-s)/d,t[0]=(l+c)/d,t[1]=(f+v)/d,t[2]=.25*d),t}function O(t,n,a,r,u){var e,o=1/Math.tan(n/2);return t[0]=o/a,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=o,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=u&&u!==1/0?(e=1/(r-u),t[10]=(u+r)*e,t[14]=2*u*r*e):(t[10]=-1,t[14]=-2*r),t}var j=O;function P(t,n,a,r,u,e,o){var i=1/(n-a),h=1/(r-u),c=1/(e-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*h,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*c,t[11]=0,t[12]=(n+a)*i,t[13]=(u+r)*h,t[14]=(o+e)*c,t[15]=1,t}var S=P;function E(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t[6]=n[6]-a[6],t[7]=n[7]-a[7],t[8]=n[8]-a[8],t[9]=n[9]-a[9],t[10]=n[10]-a[10],t[11]=n[11]-a[11],t[12]=n[12]-a[12],t[13]=n[13]-a[13],t[14]=n[14]-a[14],t[15]=n[15]-a[15],t}var T=_,D=E,F=Object.freeze({__proto__:null,create:function(){var t=new a(16);return a!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0),t[0]=1,t[5]=1,t[10]=1,t[15]=1,t},clone:function(t){var n=new a(16);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n[9]=t[9],n[10]=t[10],n[11]=t[11],n[12]=t[12],n[13]=t[13],n[14]=t[14],n[15]=t[15],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},fromValues:function(t,n,r,u,e,o,i,h,c,s,M,f,l,v,b,m){var d=new a(16);return d[0]=t,d[1]=n,d[2]=r,d[3]=u,d[4]=e,d[5]=o,d[6]=i,d[7]=h,d[8]=c,d[9]=s,d[10]=M,d[11]=f,d[12]=l,d[13]=v,d[14]=b,d[15]=m,d},set:function(t,n,a,r,u,e,o,i,h,c,s,M,f,l,v,b,m){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=h,t[8]=c,t[9]=s,t[10]=M,t[11]=f,t[12]=l,t[13]=v,t[14]=b,t[15]=m,t},identity:g,transpose:function(t,n){if(t===n){var a=n[1],r=n[2],u=n[3],e=n[6],o=n[7],i=n[11];t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=a,t[6]=n[9],t[7]=n[13],t[8]=r,t[9]=e,t[11]=n[14],t[12]=u,t[13]=o,t[14]=i}else t[0]=n[0],t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=n[1],t[5]=n[5],t[6]=n[9],t[7]=n[13],t[8]=n[2],t[9]=n[6],t[10]=n[10],t[11]=n[14],t[12]=n[3],t[13]=n[7],t[14]=n[11],t[15]=n[15];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],p=a*i-r*o,x=a*h-u*o,y=a*c-e*o,q=r*h-u*i,g=r*c-e*i,_=u*c-e*h,A=s*b-M*v,w=s*m-f*v,R=s*d-l*v,z=M*m-f*b,O=M*d-l*b,j=f*d-l*m,P=p*j-x*O+y*z+q*R-g*w+_*A;return P?(P=1/P,t[0]=(i*j-h*O+c*z)*P,t[1]=(u*O-r*j-e*z)*P,t[2]=(b*_-m*g+d*q)*P,t[3]=(f*g-M*_-l*q)*P,t[4]=(h*R-o*j-c*w)*P,t[5]=(a*j-u*R+e*w)*P,t[6]=(m*y-v*_-d*x)*P,t[7]=(s*_-f*y+l*x)*P,t[8]=(o*O-i*R+c*A)*P,t[9]=(r*R-a*O-e*A)*P,t[10]=(v*g-b*y+d*p)*P,t[11]=(M*y-s*g-l*p)*P,t[12]=(i*w-o*z-h*A)*P,t[13]=(a*z-r*w+u*A)*P,t[14]=(b*x-v*q-m*p)*P,t[15]=(s*q-M*x+f*p)*P,t):null},adjoint:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15];return t[0]=i*(f*d-l*m)-M*(h*d-c*m)+b*(h*l-c*f),t[1]=-(r*(f*d-l*m)-M*(u*d-e*m)+b*(u*l-e*f)),t[2]=r*(h*d-c*m)-i*(u*d-e*m)+b*(u*c-e*h),t[3]=-(r*(h*l-c*f)-i*(u*l-e*f)+M*(u*c-e*h)),t[4]=-(o*(f*d-l*m)-s*(h*d-c*m)+v*(h*l-c*f)),t[5]=a*(f*d-l*m)-s*(u*d-e*m)+v*(u*l-e*f),t[6]=-(a*(h*d-c*m)-o*(u*d-e*m)+v*(u*c-e*h)),t[7]=a*(h*l-c*f)-o*(u*l-e*f)+s*(u*c-e*h),t[8]=o*(M*d-l*b)-s*(i*d-c*b)+v*(i*l-c*M),t[9]=-(a*(M*d-l*b)-s*(r*d-e*b)+v*(r*l-e*M)),t[10]=a*(i*d-c*b)-o*(r*d-e*b)+v*(r*c-e*i),t[11]=-(a*(i*l-c*M)-o*(r*l-e*M)+s*(r*c-e*i)),t[12]=-(o*(M*m-f*b)-s*(i*m-h*b)+v*(i*f-h*M)),t[13]=a*(M*m-f*b)-s*(r*m-u*b)+v*(r*f-u*M),t[14]=-(a*(i*m-h*b)-o*(r*m-u*b)+v*(r*h-u*i)),t[15]=a*(i*f-h*M)-o*(r*f-u*M)+s*(r*h-u*i),t},determinant:function(t){var n=t[0],a=t[1],r=t[2],u=t[3],e=t[4],o=t[5],i=t[6],h=t[7],c=t[8],s=t[9],M=t[10],f=t[11],l=t[12],v=t[13],b=t[14],m=t[15];return(n*o-a*e)*(M*m-f*b)-(n*i-r*e)*(s*m-f*v)+(n*h-u*e)*(s*b-M*v)+(a*i-r*o)*(c*m-f*l)-(a*h-u*o)*(c*b-M*l)+(r*h-u*i)*(c*v-s*l)},multiply:_,translate:function(t,n,a){var r,u,e,o,i,h,c,s,M,f,l,v,b=a[0],m=a[1],d=a[2];return n===t?(t[12]=n[0]*b+n[4]*m+n[8]*d+n[12],t[13]=n[1]*b+n[5]*m+n[9]*d+n[13],t[14]=n[2]*b+n[6]*m+n[10]*d+n[14],t[15]=n[3]*b+n[7]*m+n[11]*d+n[15]):(r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=n[9],l=n[10],v=n[11],t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=i,t[5]=h,t[6]=c,t[7]=s,t[8]=M,t[9]=f,t[10]=l,t[11]=v,t[12]=r*b+i*m+M*d+n[12],t[13]=u*b+h*m+f*d+n[13],t[14]=e*b+c*m+l*d+n[14],t[15]=o*b+s*m+v*d+n[15]),t},scale:function(t,n,a){var r=a[0],u=a[1],e=a[2];return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*u,t[5]=n[5]*u,t[6]=n[6]*u,t[7]=n[7]*u,t[8]=n[8]*e,t[9]=n[9]*e,t[10]=n[10]*e,t[11]=n[11]*e,t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},rotate:function(t,a,r,u){var e,o,i,h,c,s,M,f,l,v,b,m,d,p,x,y,q,g,_,A,w,R,z,O,j=u[0],P=u[1],S=u[2],E=Math.hypot(j,P,S);return E0?(r[0]=2*(h*i+M*u+c*o-s*e)/f,r[1]=2*(c*i+M*e+s*u-h*o)/f,r[2]=2*(s*i+M*o+h*e-c*u)/f):(r[0]=2*(h*i+M*u+c*o-s*e),r[1]=2*(c*i+M*e+s*u-h*o),r[2]=2*(s*i+M*o+h*e-c*u)),A(t,n,r),t},getTranslation:w,getScaling:R,getRotation:z,fromRotationTranslationScale:function(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=n[3],h=u+u,c=e+e,s=o+o,M=u*h,f=u*c,l=u*s,v=e*c,b=e*s,m=o*s,d=i*h,p=i*c,x=i*s,y=r[0],q=r[1],g=r[2];return t[0]=(1-(v+m))*y,t[1]=(f+x)*y,t[2]=(l-p)*y,t[3]=0,t[4]=(f-x)*q,t[5]=(1-(M+m))*q,t[6]=(b+d)*q,t[7]=0,t[8]=(l+p)*g,t[9]=(b-d)*g,t[10]=(1-(M+v))*g,t[11]=0,t[12]=a[0],t[13]=a[1],t[14]=a[2],t[15]=1,t},fromRotationTranslationScaleOrigin:function(t,n,a,r,u){var e=n[0],o=n[1],i=n[2],h=n[3],c=e+e,s=o+o,M=i+i,f=e*c,l=e*s,v=e*M,b=o*s,m=o*M,d=i*M,p=h*c,x=h*s,y=h*M,q=r[0],g=r[1],_=r[2],A=u[0],w=u[1],R=u[2],z=(1-(b+d))*q,O=(l+y)*q,j=(v-x)*q,P=(l-y)*g,S=(1-(f+d))*g,E=(m+p)*g,T=(v+x)*_,D=(m-p)*_,F=(1-(f+b))*_;return t[0]=z,t[1]=O,t[2]=j,t[3]=0,t[4]=P,t[5]=S,t[6]=E,t[7]=0,t[8]=T,t[9]=D,t[10]=F,t[11]=0,t[12]=a[0]+A-(z*A+P*w+T*R),t[13]=a[1]+w-(O*A+S*w+D*R),t[14]=a[2]+R-(j*A+E*w+F*R),t[15]=1,t},fromQuat:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a+a,i=r+r,h=u+u,c=a*o,s=r*o,M=r*i,f=u*o,l=u*i,v=u*h,b=e*o,m=e*i,d=e*h;return t[0]=1-M-v,t[1]=s+d,t[2]=f-m,t[3]=0,t[4]=s-d,t[5]=1-c-v,t[6]=l+b,t[7]=0,t[8]=f+m,t[9]=l-b,t[10]=1-c-M,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},frustum:function(t,n,a,r,u,e,o){var i=1/(a-n),h=1/(u-r),c=1/(e-o);return t[0]=2*e*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*e*h,t[6]=0,t[7]=0,t[8]=(a+n)*i,t[9]=(u+r)*h,t[10]=(o+e)*c,t[11]=-1,t[12]=0,t[13]=0,t[14]=o*e*2*c,t[15]=0,t},perspectiveNO:O,perspective:j,perspectiveZO:function(t,n,a,r,u){var e,o=1/Math.tan(n/2);return t[0]=o/a,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=o,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=u&&u!==1/0?(e=1/(r-u),t[10]=u*e,t[14]=u*r*e):(t[10]=-1,t[14]=-r),t},perspectiveFromFieldOfView:function(t,n,a,r){var u=Math.tan(n.upDegrees*Math.PI/180),e=Math.tan(n.downDegrees*Math.PI/180),o=Math.tan(n.leftDegrees*Math.PI/180),i=Math.tan(n.rightDegrees*Math.PI/180),h=2/(o+i),c=2/(u+e);return t[0]=h,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=c,t[6]=0,t[7]=0,t[8]=-(o-i)*h*.5,t[9]=(u-e)*c*.5,t[10]=r/(a-r),t[11]=-1,t[12]=0,t[13]=0,t[14]=r*a/(a-r),t[15]=0,t},orthoNO:P,ortho:S,orthoZO:function(t,n,a,r,u,e,o){var i=1/(n-a),h=1/(r-u),c=1/(e-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*h,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=c,t[11]=0,t[12]=(n+a)*i,t[13]=(u+r)*h,t[14]=e*c,t[15]=1,t},lookAt:function(t,a,r,u){var e,o,i,h,c,s,M,f,l,v,b=a[0],m=a[1],d=a[2],p=u[0],x=u[1],y=u[2],q=r[0],_=r[1],A=r[2];return Math.abs(b-q)0&&(s*=l=1/Math.sqrt(l),M*=l,f*=l);var v=h*f-c*M,b=c*s-i*f,m=i*M-h*s;return(l=v*v+b*b+m*m)>0&&(v*=l=1/Math.sqrt(l),b*=l,m*=l),t[0]=v,t[1]=b,t[2]=m,t[3]=0,t[4]=M*m-f*b,t[5]=f*v-s*m,t[6]=s*b-M*v,t[7]=0,t[8]=s,t[9]=M,t[10]=f,t[11]=0,t[12]=u,t[13]=e,t[14]=o,t[15]=1,t},str:function(t){return"mat4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+", "+t[9]+", "+t[10]+", "+t[11]+", "+t[12]+", "+t[13]+", "+t[14]+", "+t[15]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t[8]=n[8]+a[8],t[9]=n[9]+a[9],t[10]=n[10]+a[10],t[11]=n[11]+a[11],t[12]=n[12]+a[12],t[13]=n[13]+a[13],t[14]=n[14]+a[14],t[15]=n[15]+a[15],t},subtract:E,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=n[11]*a,t[12]=n[12]*a,t[13]=n[13]*a,t[14]=n[14]*a,t[15]=n[15]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t[6]=n[6]+a[6]*r,t[7]=n[7]+a[7]*r,t[8]=n[8]+a[8]*r,t[9]=n[9]+a[9]*r,t[10]=n[10]+a[10]*r,t[11]=n[11]+a[11]*r,t[12]=n[12]+a[12]*r,t[13]=n[13]+a[13]*r,t[14]=n[14]+a[14]*r,t[15]=n[15]+a[15]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]&&t[9]===n[9]&&t[10]===n[10]&&t[11]===n[11]&&t[12]===n[12]&&t[13]===n[13]&&t[14]===n[14]&&t[15]===n[15]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],h=t[5],c=t[6],s=t[7],M=t[8],f=t[9],l=t[10],v=t[11],b=t[12],m=t[13],d=t[14],p=t[15],x=a[0],y=a[1],q=a[2],g=a[3],_=a[4],A=a[5],w=a[6],R=a[7],z=a[8],O=a[9],j=a[10],P=a[11],S=a[12],E=a[13],T=a[14],D=a[15];return Math.abs(r-x)<=n*Math.max(1,Math.abs(r),Math.abs(x))&&Math.abs(u-y)<=n*Math.max(1,Math.abs(u),Math.abs(y))&&Math.abs(e-q)<=n*Math.max(1,Math.abs(e),Math.abs(q))&&Math.abs(o-g)<=n*Math.max(1,Math.abs(o),Math.abs(g))&&Math.abs(i-_)<=n*Math.max(1,Math.abs(i),Math.abs(_))&&Math.abs(h-A)<=n*Math.max(1,Math.abs(h),Math.abs(A))&&Math.abs(c-w)<=n*Math.max(1,Math.abs(c),Math.abs(w))&&Math.abs(s-R)<=n*Math.max(1,Math.abs(s),Math.abs(R))&&Math.abs(M-z)<=n*Math.max(1,Math.abs(M),Math.abs(z))&&Math.abs(f-O)<=n*Math.max(1,Math.abs(f),Math.abs(O))&&Math.abs(l-j)<=n*Math.max(1,Math.abs(l),Math.abs(j))&&Math.abs(v-P)<=n*Math.max(1,Math.abs(v),Math.abs(P))&&Math.abs(b-S)<=n*Math.max(1,Math.abs(b),Math.abs(S))&&Math.abs(m-E)<=n*Math.max(1,Math.abs(m),Math.abs(E))&&Math.abs(d-T)<=n*Math.max(1,Math.abs(d),Math.abs(T))&&Math.abs(p-D)<=n*Math.max(1,Math.abs(p),Math.abs(D))},mul:T,sub:D});function I(){var t=new a(3);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t}function L(t){var n=t[0],a=t[1],r=t[2];return Math.hypot(n,a,r)}function V(t,n,r){var u=new a(3);return u[0]=t,u[1]=n,u[2]=r,u}function Q(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t}function Y(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t[2]=n[2]*a[2],t}function Z(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t[2]=n[2]/a[2],t}function X(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2];return Math.hypot(a,r,u)}function N(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2];return a*a+r*r+u*u}function B(t){var n=t[0],a=t[1],r=t[2];return n*n+a*a+r*r}function k(t,n){var a=n[0],r=n[1],u=n[2],e=a*a+r*r+u*u;return e>0&&(e=1/Math.sqrt(e)),t[0]=n[0]*e,t[1]=n[1]*e,t[2]=n[2]*e,t}function U(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function W(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[0],i=a[1],h=a[2];return t[0]=u*h-e*i,t[1]=e*o-r*h,t[2]=r*i-u*o,t}var C,G=Q,H=Y,J=Z,K=X,$=N,tt=L,nt=B,at=(C=I(),function(t,n,a,r,u,e){var o,i;for(n||(n=3),a||(a=0),i=r?Math.min(r*n+a,t.length):t.length,o=a;o0&&(o=1/Math.sqrt(o)),t[0]=a*o,t[1]=r*o,t[2]=u*o,t[3]=e*o,t}function xt(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]}function yt(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=n[3];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t[2]=o+r*(a[2]-o),t[3]=i+r*(a[3]-i),t}function qt(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]}function gt(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=a[0],h=a[1],c=a[2],s=a[3];return Math.abs(r-i)<=n*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(u-h)<=n*Math.max(1,Math.abs(u),Math.abs(h))&&Math.abs(e-c)<=n*Math.max(1,Math.abs(e),Math.abs(c))&&Math.abs(o-s)<=n*Math.max(1,Math.abs(o),Math.abs(s))}var _t=st,At=Mt,wt=ft,Rt=vt,zt=bt,Ot=mt,jt=dt,Pt=function(){var t=ut();return function(n,a,r,u,e,o){var i,h;for(a||(a=4),r||(r=0),h=u?Math.min(u*a+r,n.length):n.length,i=r;i=1);do{h=(e=2*r()-1)*e+(o=2*r()-1)*o}while(h>=1);var c=Math.sqrt((1-i)/h);return t[0]=n*a,t[1]=n*u,t[2]=n*e*c,t[3]=n*o*c,t},transformMat4:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3];return t[0]=a[0]*r+a[4]*u+a[8]*e+a[12]*o,t[1]=a[1]*r+a[5]*u+a[9]*e+a[13]*o,t[2]=a[2]*r+a[6]*u+a[10]*e+a[14]*o,t[3]=a[3]*r+a[7]*u+a[11]*e+a[15]*o,t},transformQuat:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[0],i=a[1],h=a[2],c=a[3],s=c*r+i*e-h*u,M=c*u+h*r-o*e,f=c*e+o*u-i*r,l=-o*r-i*u-h*e;return t[0]=s*c+l*-o+M*-h-f*-i,t[1]=M*c+l*-i+f*-o-s*-h,t[2]=f*c+l*-h+s*-i-M*-o,t[3]=n[3],t},zero:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t},str:function(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},exactEquals:qt,equals:gt,sub:_t,mul:At,div:wt,dist:Rt,sqrDist:zt,len:Ot,sqrLen:jt,forEach:Pt});function Et(){var t=new a(4);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t[3]=1,t}function Tt(t,n,a){a*=.5;var r=Math.sin(a);return t[0]=r*n[0],t[1]=r*n[1],t[2]=r*n[2],t[3]=Math.cos(a),t}function Dt(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1],c=a[2],s=a[3];return t[0]=r*s+o*i+u*c-e*h,t[1]=u*s+o*h+e*i-r*c,t[2]=e*s+o*c+r*h-u*i,t[3]=o*s-r*i-u*h-e*c,t}function Ft(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h+o*i,t[1]=u*h+e*i,t[2]=e*h-u*i,t[3]=o*h-r*i,t}function It(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h-e*i,t[1]=u*h+o*i,t[2]=e*h+r*i,t[3]=o*h-u*i,t}function Lt(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h+u*i,t[1]=u*h-r*i,t[2]=e*h+o*i,t[3]=o*h-e*i,t}function Vt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=Math.sqrt(a*a+r*r+u*u),i=Math.exp(e),h=o>0?i*Math.sin(o)/o:0;return t[0]=a*h,t[1]=r*h,t[2]=u*h,t[3]=i*Math.cos(o),t}function Qt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=Math.sqrt(a*a+r*r+u*u),i=o>0?Math.atan2(o,e)/o:0;return t[0]=a*i,t[1]=r*i,t[2]=u*i,t[3]=.5*Math.log(a*a+r*r+u*u+e*e),t}function Yt(t,a,r,u){var e,o,i,h,c,s=a[0],M=a[1],f=a[2],l=a[3],v=r[0],b=r[1],m=r[2],d=r[3];return(o=s*v+M*b+f*m+l*d)<0&&(o=-o,v=-v,b=-b,m=-m,d=-d),1-o>n?(e=Math.acos(o),i=Math.sin(e),h=Math.sin((1-u)*e)/i,c=Math.sin(u*e)/i):(h=1-u,c=u),t[0]=h*s+c*v,t[1]=h*M+c*b,t[2]=h*f+c*m,t[3]=h*l+c*d,t}function Zt(t,n){var a,r=n[0]+n[4]+n[8];if(r>0)a=Math.sqrt(r+1),t[3]=.5*a,a=.5/a,t[0]=(n[5]-n[7])*a,t[1]=(n[6]-n[2])*a,t[2]=(n[1]-n[3])*a;else{var u=0;n[4]>n[0]&&(u=1),n[8]>n[3*u+u]&&(u=2);var e=(u+1)%3,o=(u+2)%3;a=Math.sqrt(n[3*u+u]-n[3*e+e]-n[3*o+o]+1),t[u]=.5*a,a=.5/a,t[3]=(n[3*e+o]-n[3*o+e])*a,t[e]=(n[3*e+u]+n[3*u+e])*a,t[o]=(n[3*o+u]+n[3*u+o])*a}return t}var Xt,Nt,Bt,kt,Ut,Wt,Ct=et,Gt=ot,Ht=it,Jt=ht,Kt=ct,$t=Dt,tn=lt,nn=xt,an=yt,rn=mt,un=rn,en=dt,on=en,hn=pt,cn=qt,sn=gt,Mn=(Xt=I(),Nt=V(1,0,0),Bt=V(0,1,0),function(t,n,a){var r=U(n,a);return r<-.999999?(W(Xt,Nt,n),tt(Xt)<1e-6&&W(Xt,Bt,n),k(Xt,Xt),Tt(t,Xt,Math.PI),t):r>.999999?(t[0]=0,t[1]=0,t[2]=0,t[3]=1,t):(W(Xt,n,a),t[0]=Xt[0],t[1]=Xt[1],t[2]=Xt[2],t[3]=1+r,hn(t,t))}),fn=(kt=Et(),Ut=Et(),function(t,n,a,r,u,e){return Yt(kt,n,u,e),Yt(Ut,a,r,e),Yt(t,kt,Ut,2*e*(1-e)),t}),ln=(Wt=m(),function(t,n,a,r){return Wt[0]=a[0],Wt[3]=a[1],Wt[6]=a[2],Wt[1]=r[0],Wt[4]=r[1],Wt[7]=r[2],Wt[2]=-n[0],Wt[5]=-n[1],Wt[8]=-n[2],hn(t,Zt(t,Wt))}),vn=Object.freeze({__proto__:null,create:Et,identity:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t},setAxisAngle:Tt,getAxisAngle:function(t,a){var r=2*Math.acos(a[3]),u=Math.sin(r/2);return u>n?(t[0]=a[0]/u,t[1]=a[1]/u,t[2]=a[2]/u):(t[0]=1,t[1]=0,t[2]=0),r},getAngle:function(t,n){var a=nn(t,n);return Math.acos(2*a*a-1)},multiply:Dt,rotateX:Ft,rotateY:It,rotateZ:Lt,calculateW:function(t,n){var a=n[0],r=n[1],u=n[2];return t[0]=a,t[1]=r,t[2]=u,t[3]=Math.sqrt(Math.abs(1-a*a-r*r-u*u)),t},exp:Vt,ln:Qt,pow:function(t,n,a){return Qt(t,n),tn(t,t,a),Vt(t,t),t},slerp:Yt,random:function(t){var n=r(),a=r(),u=r(),e=Math.sqrt(1-n),o=Math.sqrt(n);return t[0]=e*Math.sin(2*Math.PI*a),t[1]=e*Math.cos(2*Math.PI*a),t[2]=o*Math.sin(2*Math.PI*u),t[3]=o*Math.cos(2*Math.PI*u),t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*a+r*r+u*u+e*e,i=o?1/o:0;return t[0]=-a*i,t[1]=-r*i,t[2]=-u*i,t[3]=e*i,t},conjugate:function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t},fromMat3:Zt,fromEuler:function(t,n,a,r){var u=.5*Math.PI/180;n*=u,a*=u,r*=u;var e=Math.sin(n),o=Math.cos(n),i=Math.sin(a),h=Math.cos(a),c=Math.sin(r),s=Math.cos(r);return t[0]=e*h*s-o*i*c,t[1]=o*i*s+e*h*c,t[2]=o*h*c-e*i*s,t[3]=o*h*s+e*i*c,t},str:function(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},clone:Ct,fromValues:Gt,copy:Ht,set:Jt,add:Kt,mul:$t,scale:tn,dot:nn,lerp:an,length:rn,len:un,squaredLength:en,sqrLen:on,normalize:hn,exactEquals:cn,equals:sn,rotationTo:Mn,sqlerp:fn,setAxes:ln});function bn(t,n,a){var r=.5*a[0],u=.5*a[1],e=.5*a[2],o=n[0],i=n[1],h=n[2],c=n[3];return t[0]=o,t[1]=i,t[2]=h,t[3]=c,t[4]=r*c+u*h-e*i,t[5]=u*c+e*o-r*h,t[6]=e*c+r*i-u*o,t[7]=-r*o-u*i-e*h,t}function mn(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t}var dn=Ht;var pn=Ht;function xn(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[4],h=a[5],c=a[6],s=a[7],M=n[4],f=n[5],l=n[6],v=n[7],b=a[0],m=a[1],d=a[2],p=a[3];return t[0]=r*p+o*b+u*d-e*m,t[1]=u*p+o*m+e*b-r*d,t[2]=e*p+o*d+r*m-u*b,t[3]=o*p-r*b-u*m-e*d,t[4]=r*s+o*i+u*c-e*h+M*p+v*b+f*d-l*m,t[5]=u*s+o*h+e*i-r*c+f*p+v*m+l*b-M*d,t[6]=e*s+o*c+r*h-u*i+l*p+v*d+M*m-f*b,t[7]=o*s-r*i-u*h-e*c+v*p-M*b-f*m-l*d,t}var yn=xn;var qn=nn;var gn=rn,_n=gn,An=en,wn=An;var Rn=Object.freeze({__proto__:null,create:function(){var t=new a(8);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[4]=0,t[5]=0,t[6]=0,t[7]=0),t[3]=1,t},clone:function(t){var n=new a(8);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n},fromValues:function(t,n,r,u,e,o,i,h){var c=new a(8);return c[0]=t,c[1]=n,c[2]=r,c[3]=u,c[4]=e,c[5]=o,c[6]=i,c[7]=h,c},fromRotationTranslationValues:function(t,n,r,u,e,o,i){var h=new a(8);h[0]=t,h[1]=n,h[2]=r,h[3]=u;var c=.5*e,s=.5*o,M=.5*i;return h[4]=c*u+s*r-M*n,h[5]=s*u+M*t-c*r,h[6]=M*u+c*n-s*t,h[7]=-c*t-s*n-M*r,h},fromRotationTranslation:bn,fromTranslation:function(t,n){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t[4]=.5*n[0],t[5]=.5*n[1],t[6]=.5*n[2],t[7]=0,t},fromRotation:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=0,t[5]=0,t[6]=0,t[7]=0,t},fromMat4:function(t,n){var r=Et();z(r,n);var u=new a(3);return w(u,n),bn(t,r,u),t},copy:mn,identity:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t[6]=0,t[7]=0,t},set:function(t,n,a,r,u,e,o,i,h){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=h,t},getReal:dn,getDual:function(t,n){return t[0]=n[4],t[1]=n[5],t[2]=n[6],t[3]=n[7],t},setReal:pn,setDual:function(t,n){return t[4]=n[0],t[5]=n[1],t[6]=n[2],t[7]=n[3],t},getTranslation:function(t,n){var a=n[4],r=n[5],u=n[6],e=n[7],o=-n[0],i=-n[1],h=-n[2],c=n[3];return t[0]=2*(a*c+e*o+r*h-u*i),t[1]=2*(r*c+e*i+u*o-a*h),t[2]=2*(u*c+e*h+a*i-r*o),t},translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=.5*a[0],h=.5*a[1],c=.5*a[2],s=n[4],M=n[5],f=n[6],l=n[7];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=o*i+u*c-e*h+s,t[5]=o*h+e*i-r*c+M,t[6]=o*c+r*h-u*i+f,t[7]=-r*i-u*h-e*c+l,t},rotateX:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=i*o+s*r+h*e-c*u,f=h*o+s*u+c*r-i*e,l=c*o+s*e+i*u-h*r,v=s*o-i*r-h*u-c*e;return Ft(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateY:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=i*o+s*r+h*e-c*u,f=h*o+s*u+c*r-i*e,l=c*o+s*e+i*u-h*r,v=s*o-i*r-h*u-c*e;return It(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateZ:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=i*o+s*r+h*e-c*u,f=h*o+s*u+c*r-i*e,l=c*o+s*e+i*u-h*r,v=s*o-i*r-h*u-c*e;return Lt(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateByQuatAppend:function(t,n,a){var r=a[0],u=a[1],e=a[2],o=a[3],i=n[0],h=n[1],c=n[2],s=n[3];return t[0]=i*o+s*r+h*e-c*u,t[1]=h*o+s*u+c*r-i*e,t[2]=c*o+s*e+i*u-h*r,t[3]=s*o-i*r-h*u-c*e,i=n[4],h=n[5],c=n[6],s=n[7],t[4]=i*o+s*r+h*e-c*u,t[5]=h*o+s*u+c*r-i*e,t[6]=c*o+s*e+i*u-h*r,t[7]=s*o-i*r-h*u-c*e,t},rotateByQuatPrepend:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1],c=a[2],s=a[3];return t[0]=r*s+o*i+u*c-e*h,t[1]=u*s+o*h+e*i-r*c,t[2]=e*s+o*c+r*h-u*i,t[3]=o*s-r*i-u*h-e*c,i=a[4],h=a[5],c=a[6],s=a[7],t[4]=r*s+o*i+u*c-e*h,t[5]=u*s+o*h+e*i-r*c,t[6]=e*s+o*c+r*h-u*i,t[7]=o*s-r*i-u*h-e*c,t},rotateAroundAxis:function(t,a,r,u){if(Math.abs(u)0){a=Math.sqrt(a);var r=n[0]/a,u=n[1]/a,e=n[2]/a,o=n[3]/a,i=n[4],h=n[5],c=n[6],s=n[7],M=r*i+u*h+e*c+o*s;t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=(i-r*M)/a,t[5]=(h-u*M)/a,t[6]=(c-e*M)/a,t[7]=(s-o*M)/a}return t},str:function(t){return"quat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+")"},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],h=t[5],c=t[6],s=t[7],M=a[0],f=a[1],l=a[2],v=a[3],b=a[4],m=a[5],d=a[6],p=a[7];return Math.abs(r-M)<=n*Math.max(1,Math.abs(r),Math.abs(M))&&Math.abs(u-f)<=n*Math.max(1,Math.abs(u),Math.abs(f))&&Math.abs(e-l)<=n*Math.max(1,Math.abs(e),Math.abs(l))&&Math.abs(o-v)<=n*Math.max(1,Math.abs(o),Math.abs(v))&&Math.abs(i-b)<=n*Math.max(1,Math.abs(i),Math.abs(b))&&Math.abs(h-m)<=n*Math.max(1,Math.abs(h),Math.abs(m))&&Math.abs(c-d)<=n*Math.max(1,Math.abs(c),Math.abs(d))&&Math.abs(s-p)<=n*Math.max(1,Math.abs(s),Math.abs(p))}});function zn(){var t=new a(2);return a!=Float32Array&&(t[0]=0,t[1]=0),t}function On(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t}function jn(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t}function Pn(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t}function Sn(t,n){var a=n[0]-t[0],r=n[1]-t[1];return Math.hypot(a,r)}function En(t,n){var a=n[0]-t[0],r=n[1]-t[1];return a*a+r*r}function Tn(t){var n=t[0],a=t[1];return Math.hypot(n,a)}function Dn(t){var n=t[0],a=t[1];return n*n+a*a}var Fn=Tn,In=On,Ln=jn,Vn=Pn,Qn=Sn,Yn=En,Zn=Dn,Xn=function(){var t=zn();return function(n,a,r,u,e,o){var i,h;for(a||(a=2),r||(r=0),h=u?Math.min(u*a+r,n.length):n.length,i=r;i0&&(u=1/Math.sqrt(u)),t[0]=n[0]*u,t[1]=n[1]*u,t},dot:function(t,n){return t[0]*n[0]+t[1]*n[1]},cross:function(t,n,a){var r=n[0]*a[1]-n[1]*a[0];return t[0]=t[1]=0,t[2]=r,t},lerp:function(t,n,a,r){var u=n[0],e=n[1];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t},random:function(t,n){n=n||1;var a=2*r()*Math.PI;return t[0]=Math.cos(a)*n,t[1]=Math.sin(a)*n,t},transformMat2:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[2]*u,t[1]=a[1]*r+a[3]*u,t},transformMat2d:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[2]*u+a[4],t[1]=a[1]*r+a[3]*u+a[5],t},transformMat3:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[3]*u+a[6],t[1]=a[1]*r+a[4]*u+a[7],t},transformMat4:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[4]*u+a[12],t[1]=a[1]*r+a[5]*u+a[13],t},rotate:function(t,n,a,r){var u=n[0]-a[0],e=n[1]-a[1],o=Math.sin(r),i=Math.cos(r);return t[0]=u*i-e*o+a[0],t[1]=u*o+e*i+a[1],t},angle:function(t,n){var a=t[0],r=t[1],u=n[0],e=n[1],o=Math.sqrt(a*a+r*r)*Math.sqrt(u*u+e*e),i=o&&(a*u+r*e)/o;return Math.acos(Math.min(Math.max(i,-1),1))},zero:function(t){return t[0]=0,t[1]=0,t},str:function(t){return"vec2("+t[0]+", "+t[1]+")"},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]},equals:function(t,a){var r=t[0],u=t[1],e=a[0],o=a[1];return Math.abs(r-e)<=n*Math.max(1,Math.abs(r),Math.abs(e))&&Math.abs(u-o)<=n*Math.max(1,Math.abs(u),Math.abs(o))},len:Fn,sub:In,mul:Ln,div:Vn,dist:Qn,sqrDist:Yn,sqrLen:Zn,forEach:Xn});t.glMatrix=e,t.mat2=s,t.mat2d=b,t.mat3=q,t.mat4=F,t.quat=vn,t.quat2=Rn,t.vec2=Nn,t.vec3=rt,t.vec4=St,Object.defineProperty(t,"__esModule",{value:!0})}));
diff --git a/public/node_modules/gl-matrix/gl-matrix.js b/public/node_modules/gl-matrix/gl-matrix.js
new file mode 100644
index 0000000..b360046
--- /dev/null
+++ b/public/node_modules/gl-matrix/gl-matrix.js
@@ -0,0 +1,7711 @@
+
+/*!
+@fileoverview gl-matrix - High performance matrix and vector operations
+@author Brandon Jones
+@author Colin MacKenzie IV
+@version 3.4.3
+
+Copyright (c) 2015-2021, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+*/
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
+ (global = global || self, factory(global.glMatrix = {}));
+}(this, (function (exports) { 'use strict';
+
+ /**
+ * Common utilities
+ * @module glMatrix
+ */
+ // Configuration Constants
+ var EPSILON = 0.000001;
+ var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
+ var RANDOM = Math.random;
+ /**
+ * Sets the type of array used when creating new vectors and matrices
+ *
+ * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array
+ */
+
+ function setMatrixArrayType(type) {
+ ARRAY_TYPE = type;
+ }
+ var degree = Math.PI / 180;
+ /**
+ * Convert Degree To Radian
+ *
+ * @param {Number} a Angle in Degrees
+ */
+
+ function toRadian(a) {
+ return a * degree;
+ }
+ /**
+ * Tests whether or not the arguments have approximately the same value, within an absolute
+ * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less
+ * than or equal to 1.0, and a relative tolerance is used for larger values)
+ *
+ * @param {Number} a The first number to test.
+ * @param {Number} b The second number to test.
+ * @returns {Boolean} True if the numbers are approximately equal, false otherwise.
+ */
+
+ function equals(a, b) {
+ return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));
+ }
+ if (!Math.hypot) Math.hypot = function () {
+ var y = 0,
+ i = arguments.length;
+
+ while (i--) {
+ y += arguments[i] * arguments[i];
+ }
+
+ return Math.sqrt(y);
+ };
+
+ var common = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ EPSILON: EPSILON,
+ get ARRAY_TYPE () { return ARRAY_TYPE; },
+ RANDOM: RANDOM,
+ setMatrixArrayType: setMatrixArrayType,
+ toRadian: toRadian,
+ equals: equals
+ });
+
+ /**
+ * 2x2 Matrix
+ * @module mat2
+ */
+
+ /**
+ * Creates a new identity mat2
+ *
+ * @returns {mat2} a new 2x2 matrix
+ */
+
+ function create() {
+ var out = new ARRAY_TYPE(4);
+
+ if (ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ }
+
+ out[0] = 1;
+ out[3] = 1;
+ return out;
+ }
+ /**
+ * Creates a new mat2 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat2} a matrix to clone
+ * @returns {mat2} a new 2x2 matrix
+ */
+
+ function clone(a) {
+ var out = new ARRAY_TYPE(4);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+ }
+ /**
+ * Copy the values from one mat2 to another
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+ function copy(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+ }
+ /**
+ * Set a mat2 to the identity matrix
+ *
+ * @param {mat2} out the receiving matrix
+ * @returns {mat2} out
+ */
+
+ function identity(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ }
+ /**
+ * Create a new mat2 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m10 Component in column 1, row 0 position (index 2)
+ * @param {Number} m11 Component in column 1, row 1 position (index 3)
+ * @returns {mat2} out A new 2x2 matrix
+ */
+
+ function fromValues(m00, m01, m10, m11) {
+ var out = new ARRAY_TYPE(4);
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m10;
+ out[3] = m11;
+ return out;
+ }
+ /**
+ * Set the components of a mat2 to the given values
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m10 Component in column 1, row 0 position (index 2)
+ * @param {Number} m11 Component in column 1, row 1 position (index 3)
+ * @returns {mat2} out
+ */
+
+ function set(out, m00, m01, m10, m11) {
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m10;
+ out[3] = m11;
+ return out;
+ }
+ /**
+ * Transpose the values of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+ function transpose(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache
+ // some values
+ if (out === a) {
+ var a1 = a[1];
+ out[1] = a[2];
+ out[2] = a1;
+ } else {
+ out[0] = a[0];
+ out[1] = a[2];
+ out[2] = a[1];
+ out[3] = a[3];
+ }
+
+ return out;
+ }
+ /**
+ * Inverts a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+ function invert(out, a) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3]; // Calculate the determinant
+
+ var det = a0 * a3 - a2 * a1;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = a3 * det;
+ out[1] = -a1 * det;
+ out[2] = -a2 * det;
+ out[3] = a0 * det;
+ return out;
+ }
+ /**
+ * Calculates the adjugate of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+
+ function adjoint(out, a) {
+ // Caching this value is nessecary if out == a
+ var a0 = a[0];
+ out[0] = a[3];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a0;
+ return out;
+ }
+ /**
+ * Calculates the determinant of a mat2
+ *
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+ function determinant(a) {
+ return a[0] * a[3] - a[2] * a[1];
+ }
+ /**
+ * Multiplies two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+
+ function multiply(out, a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ out[0] = a0 * b0 + a2 * b1;
+ out[1] = a1 * b0 + a3 * b1;
+ out[2] = a0 * b2 + a2 * b3;
+ out[3] = a1 * b2 + a3 * b3;
+ return out;
+ }
+ /**
+ * Rotates a mat2 by the given angle
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+
+ function rotate(out, a, rad) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ out[0] = a0 * c + a2 * s;
+ out[1] = a1 * c + a3 * s;
+ out[2] = a0 * -s + a2 * c;
+ out[3] = a1 * -s + a3 * c;
+ return out;
+ }
+ /**
+ * Scales the mat2 by the dimensions in the given vec2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to rotate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat2} out
+ **/
+
+ function scale(out, a, v) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var v0 = v[0],
+ v1 = v[1];
+ out[0] = a0 * v0;
+ out[1] = a1 * v0;
+ out[2] = a2 * v1;
+ out[3] = a3 * v1;
+ return out;
+ }
+ /**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.rotate(dest, dest, rad);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+
+ function fromRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = -s;
+ out[3] = c;
+ return out;
+ }
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.scale(dest, dest, vec);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat2} out
+ */
+
+ function fromScaling(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = v[1];
+ return out;
+ }
+ /**
+ * Returns a string representation of a mat2
+ *
+ * @param {ReadonlyMat2} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+ function str(a) {
+ return "mat2(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")";
+ }
+ /**
+ * Returns Frobenius norm of a mat2
+ *
+ * @param {ReadonlyMat2} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+ function frob(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3]);
+ }
+ /**
+ * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
+ * @param {ReadonlyMat2} L the lower triangular matrix
+ * @param {ReadonlyMat2} D the diagonal matrix
+ * @param {ReadonlyMat2} U the upper triangular matrix
+ * @param {ReadonlyMat2} a the input matrix to factorize
+ */
+
+ function LDU(L, D, U, a) {
+ L[2] = a[2] / a[0];
+ U[0] = a[0];
+ U[1] = a[1];
+ U[3] = a[3] - L[2] * U[1];
+ return [L, D, U];
+ }
+ /**
+ * Adds two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+
+ function add(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ return out;
+ }
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+
+ function subtract(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ return out;
+ }
+ /**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat2} a The first matrix.
+ * @param {ReadonlyMat2} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+ function exactEquals(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
+ }
+ /**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat2} a The first matrix.
+ * @param {ReadonlyMat2} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+ function equals$1(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3));
+ }
+ /**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat2} out
+ */
+
+ function multiplyScalar(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ return out;
+ }
+ /**
+ * Adds two mat2's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat2} out the receiving vector
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat2} out
+ */
+
+ function multiplyScalarAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ return out;
+ }
+ /**
+ * Alias for {@link mat2.multiply}
+ * @function
+ */
+
+ var mul = multiply;
+ /**
+ * Alias for {@link mat2.subtract}
+ * @function
+ */
+
+ var sub = subtract;
+
+ var mat2 = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ create: create,
+ clone: clone,
+ copy: copy,
+ identity: identity,
+ fromValues: fromValues,
+ set: set,
+ transpose: transpose,
+ invert: invert,
+ adjoint: adjoint,
+ determinant: determinant,
+ multiply: multiply,
+ rotate: rotate,
+ scale: scale,
+ fromRotation: fromRotation,
+ fromScaling: fromScaling,
+ str: str,
+ frob: frob,
+ LDU: LDU,
+ add: add,
+ subtract: subtract,
+ exactEquals: exactEquals,
+ equals: equals$1,
+ multiplyScalar: multiplyScalar,
+ multiplyScalarAndAdd: multiplyScalarAndAdd,
+ mul: mul,
+ sub: sub
+ });
+
+ /**
+ * 2x3 Matrix
+ * @module mat2d
+ * @description
+ * A mat2d contains six elements defined as:
+ *
+ * [a, b,
+ * c, d,
+ * tx, ty]
+ *
+ * This is a short form for the 3x3 matrix:
+ *
+ * [a, b, 0,
+ * c, d, 0,
+ * tx, ty, 1]
+ *
+ * The last column is ignored so the array is shorter and operations are faster.
+ */
+
+ /**
+ * Creates a new identity mat2d
+ *
+ * @returns {mat2d} a new 2x3 matrix
+ */
+
+ function create$1() {
+ var out = new ARRAY_TYPE(6);
+
+ if (ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ out[4] = 0;
+ out[5] = 0;
+ }
+
+ out[0] = 1;
+ out[3] = 1;
+ return out;
+ }
+ /**
+ * Creates a new mat2d initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat2d} a matrix to clone
+ * @returns {mat2d} a new 2x3 matrix
+ */
+
+ function clone$1(a) {
+ var out = new ARRAY_TYPE(6);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ return out;
+ }
+ /**
+ * Copy the values from one mat2d to another
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+
+ function copy$1(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ return out;
+ }
+ /**
+ * Set a mat2d to the identity matrix
+ *
+ * @param {mat2d} out the receiving matrix
+ * @returns {mat2d} out
+ */
+
+ function identity$1(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+ }
+ /**
+ * Create a new mat2d with the given values
+ *
+ * @param {Number} a Component A (index 0)
+ * @param {Number} b Component B (index 1)
+ * @param {Number} c Component C (index 2)
+ * @param {Number} d Component D (index 3)
+ * @param {Number} tx Component TX (index 4)
+ * @param {Number} ty Component TY (index 5)
+ * @returns {mat2d} A new mat2d
+ */
+
+ function fromValues$1(a, b, c, d, tx, ty) {
+ var out = new ARRAY_TYPE(6);
+ out[0] = a;
+ out[1] = b;
+ out[2] = c;
+ out[3] = d;
+ out[4] = tx;
+ out[5] = ty;
+ return out;
+ }
+ /**
+ * Set the components of a mat2d to the given values
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {Number} a Component A (index 0)
+ * @param {Number} b Component B (index 1)
+ * @param {Number} c Component C (index 2)
+ * @param {Number} d Component D (index 3)
+ * @param {Number} tx Component TX (index 4)
+ * @param {Number} ty Component TY (index 5)
+ * @returns {mat2d} out
+ */
+
+ function set$1(out, a, b, c, d, tx, ty) {
+ out[0] = a;
+ out[1] = b;
+ out[2] = c;
+ out[3] = d;
+ out[4] = tx;
+ out[5] = ty;
+ return out;
+ }
+ /**
+ * Inverts a mat2d
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+
+ function invert$1(out, a) {
+ var aa = a[0],
+ ab = a[1],
+ ac = a[2],
+ ad = a[3];
+ var atx = a[4],
+ aty = a[5];
+ var det = aa * ad - ab * ac;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = ad * det;
+ out[1] = -ab * det;
+ out[2] = -ac * det;
+ out[3] = aa * det;
+ out[4] = (ac * aty - ad * atx) * det;
+ out[5] = (ab * atx - aa * aty) * det;
+ return out;
+ }
+ /**
+ * Calculates the determinant of a mat2d
+ *
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+ function determinant$1(a) {
+ return a[0] * a[3] - a[1] * a[2];
+ }
+ /**
+ * Multiplies two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+
+ function multiply$1(out, a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5];
+ out[0] = a0 * b0 + a2 * b1;
+ out[1] = a1 * b0 + a3 * b1;
+ out[2] = a0 * b2 + a2 * b3;
+ out[3] = a1 * b2 + a3 * b3;
+ out[4] = a0 * b4 + a2 * b5 + a4;
+ out[5] = a1 * b4 + a3 * b5 + a5;
+ return out;
+ }
+ /**
+ * Rotates a mat2d by the given angle
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+
+ function rotate$1(out, a, rad) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ out[0] = a0 * c + a2 * s;
+ out[1] = a1 * c + a3 * s;
+ out[2] = a0 * -s + a2 * c;
+ out[3] = a1 * -s + a3 * c;
+ out[4] = a4;
+ out[5] = a5;
+ return out;
+ }
+ /**
+ * Scales the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to translate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat2d} out
+ **/
+
+ function scale$1(out, a, v) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var v0 = v[0],
+ v1 = v[1];
+ out[0] = a0 * v0;
+ out[1] = a1 * v0;
+ out[2] = a2 * v1;
+ out[3] = a3 * v1;
+ out[4] = a4;
+ out[5] = a5;
+ return out;
+ }
+ /**
+ * Translates the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to translate
+ * @param {ReadonlyVec2} v the vec2 to translate the matrix by
+ * @returns {mat2d} out
+ **/
+
+ function translate(out, a, v) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var v0 = v[0],
+ v1 = v[1];
+ out[0] = a0;
+ out[1] = a1;
+ out[2] = a2;
+ out[3] = a3;
+ out[4] = a0 * v0 + a2 * v1 + a4;
+ out[5] = a1 * v0 + a3 * v1 + a5;
+ return out;
+ }
+ /**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.rotate(dest, dest, rad);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+
+ function fromRotation$1(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = -s;
+ out[3] = c;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+ }
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.scale(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat2d} out
+ */
+
+ function fromScaling$1(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = v[1];
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+ }
+ /**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.translate(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {ReadonlyVec2} v Translation vector
+ * @returns {mat2d} out
+ */
+
+ function fromTranslation(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = v[0];
+ out[5] = v[1];
+ return out;
+ }
+ /**
+ * Returns a string representation of a mat2d
+ *
+ * @param {ReadonlyMat2d} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+ function str$1(a) {
+ return "mat2d(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ")";
+ }
+ /**
+ * Returns Frobenius norm of a mat2d
+ *
+ * @param {ReadonlyMat2d} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+ function frob$1(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], 1);
+ }
+ /**
+ * Adds two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+
+ function add$1(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ return out;
+ }
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+
+ function subtract$1(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ out[4] = a[4] - b[4];
+ out[5] = a[5] - b[5];
+ return out;
+ }
+ /**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat2d} out
+ */
+
+ function multiplyScalar$1(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ return out;
+ }
+ /**
+ * Adds two mat2d's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat2d} out the receiving vector
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat2d} out
+ */
+
+ function multiplyScalarAndAdd$1(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ out[4] = a[4] + b[4] * scale;
+ out[5] = a[5] + b[5] * scale;
+ return out;
+ }
+ /**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat2d} a The first matrix.
+ * @param {ReadonlyMat2d} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+ function exactEquals$1(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5];
+ }
+ /**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat2d} a The first matrix.
+ * @param {ReadonlyMat2d} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+ function equals$2(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5];
+ return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5));
+ }
+ /**
+ * Alias for {@link mat2d.multiply}
+ * @function
+ */
+
+ var mul$1 = multiply$1;
+ /**
+ * Alias for {@link mat2d.subtract}
+ * @function
+ */
+
+ var sub$1 = subtract$1;
+
+ var mat2d = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ create: create$1,
+ clone: clone$1,
+ copy: copy$1,
+ identity: identity$1,
+ fromValues: fromValues$1,
+ set: set$1,
+ invert: invert$1,
+ determinant: determinant$1,
+ multiply: multiply$1,
+ rotate: rotate$1,
+ scale: scale$1,
+ translate: translate,
+ fromRotation: fromRotation$1,
+ fromScaling: fromScaling$1,
+ fromTranslation: fromTranslation,
+ str: str$1,
+ frob: frob$1,
+ add: add$1,
+ subtract: subtract$1,
+ multiplyScalar: multiplyScalar$1,
+ multiplyScalarAndAdd: multiplyScalarAndAdd$1,
+ exactEquals: exactEquals$1,
+ equals: equals$2,
+ mul: mul$1,
+ sub: sub$1
+ });
+
+ /**
+ * 3x3 Matrix
+ * @module mat3
+ */
+
+ /**
+ * Creates a new identity mat3
+ *
+ * @returns {mat3} a new 3x3 matrix
+ */
+
+ function create$2() {
+ var out = new ARRAY_TYPE(9);
+
+ if (ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ }
+
+ out[0] = 1;
+ out[4] = 1;
+ out[8] = 1;
+ return out;
+ }
+ /**
+ * Copies the upper-left 3x3 values into the given mat3.
+ *
+ * @param {mat3} out the receiving 3x3 matrix
+ * @param {ReadonlyMat4} a the source 4x4 matrix
+ * @returns {mat3} out
+ */
+
+ function fromMat4(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[4];
+ out[4] = a[5];
+ out[5] = a[6];
+ out[6] = a[8];
+ out[7] = a[9];
+ out[8] = a[10];
+ return out;
+ }
+ /**
+ * Creates a new mat3 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat3} a matrix to clone
+ * @returns {mat3} a new 3x3 matrix
+ */
+
+ function clone$2(a) {
+ var out = new ARRAY_TYPE(9);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+ }
+ /**
+ * Copy the values from one mat3 to another
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+ function copy$2(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+ }
+ /**
+ * Create a new mat3 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m10 Component in column 1, row 0 position (index 3)
+ * @param {Number} m11 Component in column 1, row 1 position (index 4)
+ * @param {Number} m12 Component in column 1, row 2 position (index 5)
+ * @param {Number} m20 Component in column 2, row 0 position (index 6)
+ * @param {Number} m21 Component in column 2, row 1 position (index 7)
+ * @param {Number} m22 Component in column 2, row 2 position (index 8)
+ * @returns {mat3} A new mat3
+ */
+
+ function fromValues$2(m00, m01, m02, m10, m11, m12, m20, m21, m22) {
+ var out = new ARRAY_TYPE(9);
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m10;
+ out[4] = m11;
+ out[5] = m12;
+ out[6] = m20;
+ out[7] = m21;
+ out[8] = m22;
+ return out;
+ }
+ /**
+ * Set the components of a mat3 to the given values
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m10 Component in column 1, row 0 position (index 3)
+ * @param {Number} m11 Component in column 1, row 1 position (index 4)
+ * @param {Number} m12 Component in column 1, row 2 position (index 5)
+ * @param {Number} m20 Component in column 2, row 0 position (index 6)
+ * @param {Number} m21 Component in column 2, row 1 position (index 7)
+ * @param {Number} m22 Component in column 2, row 2 position (index 8)
+ * @returns {mat3} out
+ */
+
+ function set$2(out, m00, m01, m02, m10, m11, m12, m20, m21, m22) {
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m10;
+ out[4] = m11;
+ out[5] = m12;
+ out[6] = m20;
+ out[7] = m21;
+ out[8] = m22;
+ return out;
+ }
+ /**
+ * Set a mat3 to the identity matrix
+ *
+ * @param {mat3} out the receiving matrix
+ * @returns {mat3} out
+ */
+
+ function identity$2(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+ }
+ /**
+ * Transpose the values of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+ function transpose$1(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a01 = a[1],
+ a02 = a[2],
+ a12 = a[5];
+ out[1] = a[3];
+ out[2] = a[6];
+ out[3] = a01;
+ out[5] = a[7];
+ out[6] = a02;
+ out[7] = a12;
+ } else {
+ out[0] = a[0];
+ out[1] = a[3];
+ out[2] = a[6];
+ out[3] = a[1];
+ out[4] = a[4];
+ out[5] = a[7];
+ out[6] = a[2];
+ out[7] = a[5];
+ out[8] = a[8];
+ }
+
+ return out;
+ }
+ /**
+ * Inverts a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+ function invert$2(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ var b01 = a22 * a11 - a12 * a21;
+ var b11 = -a22 * a10 + a12 * a20;
+ var b21 = a21 * a10 - a11 * a20; // Calculate the determinant
+
+ var det = a00 * b01 + a01 * b11 + a02 * b21;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = b01 * det;
+ out[1] = (-a22 * a01 + a02 * a21) * det;
+ out[2] = (a12 * a01 - a02 * a11) * det;
+ out[3] = b11 * det;
+ out[4] = (a22 * a00 - a02 * a20) * det;
+ out[5] = (-a12 * a00 + a02 * a10) * det;
+ out[6] = b21 * det;
+ out[7] = (-a21 * a00 + a01 * a20) * det;
+ out[8] = (a11 * a00 - a01 * a10) * det;
+ return out;
+ }
+ /**
+ * Calculates the adjugate of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+
+ function adjoint$1(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ out[0] = a11 * a22 - a12 * a21;
+ out[1] = a02 * a21 - a01 * a22;
+ out[2] = a01 * a12 - a02 * a11;
+ out[3] = a12 * a20 - a10 * a22;
+ out[4] = a00 * a22 - a02 * a20;
+ out[5] = a02 * a10 - a00 * a12;
+ out[6] = a10 * a21 - a11 * a20;
+ out[7] = a01 * a20 - a00 * a21;
+ out[8] = a00 * a11 - a01 * a10;
+ return out;
+ }
+ /**
+ * Calculates the determinant of a mat3
+ *
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+ function determinant$2(a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
+ }
+ /**
+ * Multiplies two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+
+ function multiply$2(out, a, b) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2];
+ var a10 = a[3],
+ a11 = a[4],
+ a12 = a[5];
+ var a20 = a[6],
+ a21 = a[7],
+ a22 = a[8];
+ var b00 = b[0],
+ b01 = b[1],
+ b02 = b[2];
+ var b10 = b[3],
+ b11 = b[4],
+ b12 = b[5];
+ var b20 = b[6],
+ b21 = b[7],
+ b22 = b[8];
+ out[0] = b00 * a00 + b01 * a10 + b02 * a20;
+ out[1] = b00 * a01 + b01 * a11 + b02 * a21;
+ out[2] = b00 * a02 + b01 * a12 + b02 * a22;
+ out[3] = b10 * a00 + b11 * a10 + b12 * a20;
+ out[4] = b10 * a01 + b11 * a11 + b12 * a21;
+ out[5] = b10 * a02 + b11 * a12 + b12 * a22;
+ out[6] = b20 * a00 + b21 * a10 + b22 * a20;
+ out[7] = b20 * a01 + b21 * a11 + b22 * a21;
+ out[8] = b20 * a02 + b21 * a12 + b22 * a22;
+ return out;
+ }
+ /**
+ * Translate a mat3 by the given vector
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to translate
+ * @param {ReadonlyVec2} v vector to translate by
+ * @returns {mat3} out
+ */
+
+ function translate$1(out, a, v) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a10 = a[3],
+ a11 = a[4],
+ a12 = a[5],
+ a20 = a[6],
+ a21 = a[7],
+ a22 = a[8],
+ x = v[0],
+ y = v[1];
+ out[0] = a00;
+ out[1] = a01;
+ out[2] = a02;
+ out[3] = a10;
+ out[4] = a11;
+ out[5] = a12;
+ out[6] = x * a00 + y * a10 + a20;
+ out[7] = x * a01 + y * a11 + a21;
+ out[8] = x * a02 + y * a12 + a22;
+ return out;
+ }
+ /**
+ * Rotates a mat3 by the given angle
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+
+ function rotate$2(out, a, rad) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a10 = a[3],
+ a11 = a[4],
+ a12 = a[5],
+ a20 = a[6],
+ a21 = a[7],
+ a22 = a[8],
+ s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c * a00 + s * a10;
+ out[1] = c * a01 + s * a11;
+ out[2] = c * a02 + s * a12;
+ out[3] = c * a10 - s * a00;
+ out[4] = c * a11 - s * a01;
+ out[5] = c * a12 - s * a02;
+ out[6] = a20;
+ out[7] = a21;
+ out[8] = a22;
+ return out;
+ }
+ /**
+ * Scales the mat3 by the dimensions in the given vec2
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to rotate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat3} out
+ **/
+
+ function scale$2(out, a, v) {
+ var x = v[0],
+ y = v[1];
+ out[0] = x * a[0];
+ out[1] = x * a[1];
+ out[2] = x * a[2];
+ out[3] = y * a[3];
+ out[4] = y * a[4];
+ out[5] = y * a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+ }
+ /**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.translate(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyVec2} v Translation vector
+ * @returns {mat3} out
+ */
+
+ function fromTranslation$1(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = v[0];
+ out[7] = v[1];
+ out[8] = 1;
+ return out;
+ }
+ /**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.rotate(dest, dest, rad);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+
+ function fromRotation$2(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = 0;
+ out[3] = -s;
+ out[4] = c;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+ }
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.scale(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat3} out
+ */
+
+ function fromScaling$2(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = v[1];
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+ }
+ /**
+ * Copies the values from a mat2d into a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to copy
+ * @returns {mat3} out
+ **/
+
+ function fromMat2d(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = 0;
+ out[3] = a[2];
+ out[4] = a[3];
+ out[5] = 0;
+ out[6] = a[4];
+ out[7] = a[5];
+ out[8] = 1;
+ return out;
+ }
+ /**
+ * Calculates a 3x3 matrix from the given quaternion
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyQuat} q Quaternion to create matrix from
+ *
+ * @returns {mat3} out
+ */
+
+ function fromQuat(out, q) {
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var yx = y * x2;
+ var yy = y * y2;
+ var zx = z * x2;
+ var zy = z * y2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ out[0] = 1 - yy - zz;
+ out[3] = yx - wz;
+ out[6] = zx + wy;
+ out[1] = yx + wz;
+ out[4] = 1 - xx - zz;
+ out[7] = zy - wx;
+ out[2] = zx - wy;
+ out[5] = zy + wx;
+ out[8] = 1 - xx - yy;
+ return out;
+ }
+ /**
+ * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyMat4} a Mat4 to derive the normal matrix from
+ *
+ * @returns {mat3} out
+ */
+
+ function normalFromMat4(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ var b00 = a00 * a11 - a01 * a10;
+ var b01 = a00 * a12 - a02 * a10;
+ var b02 = a00 * a13 - a03 * a10;
+ var b03 = a01 * a12 - a02 * a11;
+ var b04 = a01 * a13 - a03 * a11;
+ var b05 = a02 * a13 - a03 * a12;
+ var b06 = a20 * a31 - a21 * a30;
+ var b07 = a20 * a32 - a22 * a30;
+ var b08 = a20 * a33 - a23 * a30;
+ var b09 = a21 * a32 - a22 * a31;
+ var b10 = a21 * a33 - a23 * a31;
+ var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
+
+ var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+ out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+ out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+ return out;
+ }
+ /**
+ * Generates a 2D projection matrix with the given bounds
+ *
+ * @param {mat3} out mat3 frustum matrix will be written into
+ * @param {number} width Width of your gl context
+ * @param {number} height Height of gl context
+ * @returns {mat3} out
+ */
+
+ function projection(out, width, height) {
+ out[0] = 2 / width;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = -2 / height;
+ out[5] = 0;
+ out[6] = -1;
+ out[7] = 1;
+ out[8] = 1;
+ return out;
+ }
+ /**
+ * Returns a string representation of a mat3
+ *
+ * @param {ReadonlyMat3} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+ function str$2(a) {
+ return "mat3(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ", " + a[8] + ")";
+ }
+ /**
+ * Returns Frobenius norm of a mat3
+ *
+ * @param {ReadonlyMat3} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+ function frob$2(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
+ }
+ /**
+ * Adds two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+
+ function add$2(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ out[6] = a[6] + b[6];
+ out[7] = a[7] + b[7];
+ out[8] = a[8] + b[8];
+ return out;
+ }
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+
+ function subtract$2(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ out[4] = a[4] - b[4];
+ out[5] = a[5] - b[5];
+ out[6] = a[6] - b[6];
+ out[7] = a[7] - b[7];
+ out[8] = a[8] - b[8];
+ return out;
+ }
+ /**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat3} out
+ */
+
+ function multiplyScalar$2(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ out[6] = a[6] * b;
+ out[7] = a[7] * b;
+ out[8] = a[8] * b;
+ return out;
+ }
+ /**
+ * Adds two mat3's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat3} out the receiving vector
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat3} out
+ */
+
+ function multiplyScalarAndAdd$2(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ out[4] = a[4] + b[4] * scale;
+ out[5] = a[5] + b[5] * scale;
+ out[6] = a[6] + b[6] * scale;
+ out[7] = a[7] + b[7] * scale;
+ out[8] = a[8] + b[8] * scale;
+ return out;
+ }
+ /**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat3} a The first matrix.
+ * @param {ReadonlyMat3} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+ function exactEquals$2(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8];
+ }
+ /**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat3} a The first matrix.
+ * @param {ReadonlyMat3} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+ function equals$3(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5],
+ a6 = a[6],
+ a7 = a[7],
+ a8 = a[8];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5],
+ b6 = b[6],
+ b7 = b[7],
+ b8 = b[8];
+ return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8));
+ }
+ /**
+ * Alias for {@link mat3.multiply}
+ * @function
+ */
+
+ var mul$2 = multiply$2;
+ /**
+ * Alias for {@link mat3.subtract}
+ * @function
+ */
+
+ var sub$2 = subtract$2;
+
+ var mat3 = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ create: create$2,
+ fromMat4: fromMat4,
+ clone: clone$2,
+ copy: copy$2,
+ fromValues: fromValues$2,
+ set: set$2,
+ identity: identity$2,
+ transpose: transpose$1,
+ invert: invert$2,
+ adjoint: adjoint$1,
+ determinant: determinant$2,
+ multiply: multiply$2,
+ translate: translate$1,
+ rotate: rotate$2,
+ scale: scale$2,
+ fromTranslation: fromTranslation$1,
+ fromRotation: fromRotation$2,
+ fromScaling: fromScaling$2,
+ fromMat2d: fromMat2d,
+ fromQuat: fromQuat,
+ normalFromMat4: normalFromMat4,
+ projection: projection,
+ str: str$2,
+ frob: frob$2,
+ add: add$2,
+ subtract: subtract$2,
+ multiplyScalar: multiplyScalar$2,
+ multiplyScalarAndAdd: multiplyScalarAndAdd$2,
+ exactEquals: exactEquals$2,
+ equals: equals$3,
+ mul: mul$2,
+ sub: sub$2
+ });
+
+ /**
+ * 4x4 Matrix
Format: column-major, when typed out it looks like row-major
The matrices are being post multiplied.
+ * @module mat4
+ */
+
+ /**
+ * Creates a new identity mat4
+ *
+ * @returns {mat4} a new 4x4 matrix
+ */
+
+ function create$3() {
+ var out = new ARRAY_TYPE(16);
+
+ if (ARRAY_TYPE != Float32Array) {
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ }
+
+ out[0] = 1;
+ out[5] = 1;
+ out[10] = 1;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Creates a new mat4 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat4} a matrix to clone
+ * @returns {mat4} a new 4x4 matrix
+ */
+
+ function clone$3(a) {
+ var out = new ARRAY_TYPE(16);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+ }
+ /**
+ * Copy the values from one mat4 to another
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+ function copy$3(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+ }
+ /**
+ * Create a new mat4 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m03 Component in column 0, row 3 position (index 3)
+ * @param {Number} m10 Component in column 1, row 0 position (index 4)
+ * @param {Number} m11 Component in column 1, row 1 position (index 5)
+ * @param {Number} m12 Component in column 1, row 2 position (index 6)
+ * @param {Number} m13 Component in column 1, row 3 position (index 7)
+ * @param {Number} m20 Component in column 2, row 0 position (index 8)
+ * @param {Number} m21 Component in column 2, row 1 position (index 9)
+ * @param {Number} m22 Component in column 2, row 2 position (index 10)
+ * @param {Number} m23 Component in column 2, row 3 position (index 11)
+ * @param {Number} m30 Component in column 3, row 0 position (index 12)
+ * @param {Number} m31 Component in column 3, row 1 position (index 13)
+ * @param {Number} m32 Component in column 3, row 2 position (index 14)
+ * @param {Number} m33 Component in column 3, row 3 position (index 15)
+ * @returns {mat4} A new mat4
+ */
+
+ function fromValues$3(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
+ var out = new ARRAY_TYPE(16);
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m03;
+ out[4] = m10;
+ out[5] = m11;
+ out[6] = m12;
+ out[7] = m13;
+ out[8] = m20;
+ out[9] = m21;
+ out[10] = m22;
+ out[11] = m23;
+ out[12] = m30;
+ out[13] = m31;
+ out[14] = m32;
+ out[15] = m33;
+ return out;
+ }
+ /**
+ * Set the components of a mat4 to the given values
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m03 Component in column 0, row 3 position (index 3)
+ * @param {Number} m10 Component in column 1, row 0 position (index 4)
+ * @param {Number} m11 Component in column 1, row 1 position (index 5)
+ * @param {Number} m12 Component in column 1, row 2 position (index 6)
+ * @param {Number} m13 Component in column 1, row 3 position (index 7)
+ * @param {Number} m20 Component in column 2, row 0 position (index 8)
+ * @param {Number} m21 Component in column 2, row 1 position (index 9)
+ * @param {Number} m22 Component in column 2, row 2 position (index 10)
+ * @param {Number} m23 Component in column 2, row 3 position (index 11)
+ * @param {Number} m30 Component in column 3, row 0 position (index 12)
+ * @param {Number} m31 Component in column 3, row 1 position (index 13)
+ * @param {Number} m32 Component in column 3, row 2 position (index 14)
+ * @param {Number} m33 Component in column 3, row 3 position (index 15)
+ * @returns {mat4} out
+ */
+
+ function set$3(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
+ out[0] = m00;
+ out[1] = m01;
+ out[2] = m02;
+ out[3] = m03;
+ out[4] = m10;
+ out[5] = m11;
+ out[6] = m12;
+ out[7] = m13;
+ out[8] = m20;
+ out[9] = m21;
+ out[10] = m22;
+ out[11] = m23;
+ out[12] = m30;
+ out[13] = m31;
+ out[14] = m32;
+ out[15] = m33;
+ return out;
+ }
+ /**
+ * Set a mat4 to the identity matrix
+ *
+ * @param {mat4} out the receiving matrix
+ * @returns {mat4} out
+ */
+
+ function identity$3(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Transpose the values of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+ function transpose$2(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a12 = a[6],
+ a13 = a[7];
+ var a23 = a[11];
+ out[1] = a[4];
+ out[2] = a[8];
+ out[3] = a[12];
+ out[4] = a01;
+ out[6] = a[9];
+ out[7] = a[13];
+ out[8] = a02;
+ out[9] = a12;
+ out[11] = a[14];
+ out[12] = a03;
+ out[13] = a13;
+ out[14] = a23;
+ } else {
+ out[0] = a[0];
+ out[1] = a[4];
+ out[2] = a[8];
+ out[3] = a[12];
+ out[4] = a[1];
+ out[5] = a[5];
+ out[6] = a[9];
+ out[7] = a[13];
+ out[8] = a[2];
+ out[9] = a[6];
+ out[10] = a[10];
+ out[11] = a[14];
+ out[12] = a[3];
+ out[13] = a[7];
+ out[14] = a[11];
+ out[15] = a[15];
+ }
+
+ return out;
+ }
+ /**
+ * Inverts a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+ function invert$3(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ var b00 = a00 * a11 - a01 * a10;
+ var b01 = a00 * a12 - a02 * a10;
+ var b02 = a00 * a13 - a03 * a10;
+ var b03 = a01 * a12 - a02 * a11;
+ var b04 = a01 * a13 - a03 * a11;
+ var b05 = a02 * a13 - a03 * a12;
+ var b06 = a20 * a31 - a21 * a30;
+ var b07 = a20 * a32 - a22 * a30;
+ var b08 = a20 * a33 - a23 * a30;
+ var b09 = a21 * a32 - a22 * a31;
+ var b10 = a21 * a33 - a23 * a31;
+ var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
+
+ var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
+ out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
+ out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+ out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+ out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+ out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
+ out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
+ out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
+ out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
+ out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
+ return out;
+ }
+ /**
+ * Calculates the adjugate of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+
+ function adjoint$2(out, a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ out[0] = a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22);
+ out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
+ out[2] = a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12);
+ out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
+ out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
+ out[5] = a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22);
+ out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
+ out[7] = a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12);
+ out[8] = a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21);
+ out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
+ out[10] = a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11);
+ out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
+ out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
+ out[13] = a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21);
+ out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
+ out[15] = a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11);
+ return out;
+ }
+ /**
+ * Calculates the determinant of a mat4
+ *
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {Number} determinant of a
+ */
+
+ function determinant$3(a) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15];
+ var b00 = a00 * a11 - a01 * a10;
+ var b01 = a00 * a12 - a02 * a10;
+ var b02 = a00 * a13 - a03 * a10;
+ var b03 = a01 * a12 - a02 * a11;
+ var b04 = a01 * a13 - a03 * a11;
+ var b05 = a02 * a13 - a03 * a12;
+ var b06 = a20 * a31 - a21 * a30;
+ var b07 = a20 * a32 - a22 * a30;
+ var b08 = a20 * a33 - a23 * a30;
+ var b09 = a21 * a32 - a22 * a31;
+ var b10 = a21 * a33 - a23 * a31;
+ var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
+
+ return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+ }
+ /**
+ * Multiplies two mat4s
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+
+ function multiply$3(out, a, b) {
+ var a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3];
+ var a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+ var a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+ var a30 = a[12],
+ a31 = a[13],
+ a32 = a[14],
+ a33 = a[15]; // Cache only the current line of the second matrix
+
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ b0 = b[4];
+ b1 = b[5];
+ b2 = b[6];
+ b3 = b[7];
+ out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ b0 = b[8];
+ b1 = b[9];
+ b2 = b[10];
+ b3 = b[11];
+ out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ b0 = b[12];
+ b1 = b[13];
+ b2 = b[14];
+ b3 = b[15];
+ out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
+ out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
+ out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
+ out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
+ return out;
+ }
+ /**
+ * Translate a mat4 by the given vector
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to translate
+ * @param {ReadonlyVec3} v vector to translate by
+ * @returns {mat4} out
+ */
+
+ function translate$2(out, a, v) {
+ var x = v[0],
+ y = v[1],
+ z = v[2];
+ var a00, a01, a02, a03;
+ var a10, a11, a12, a13;
+ var a20, a21, a22, a23;
+
+ if (a === out) {
+ out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
+ out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
+ out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
+ out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
+ } else {
+ a00 = a[0];
+ a01 = a[1];
+ a02 = a[2];
+ a03 = a[3];
+ a10 = a[4];
+ a11 = a[5];
+ a12 = a[6];
+ a13 = a[7];
+ a20 = a[8];
+ a21 = a[9];
+ a22 = a[10];
+ a23 = a[11];
+ out[0] = a00;
+ out[1] = a01;
+ out[2] = a02;
+ out[3] = a03;
+ out[4] = a10;
+ out[5] = a11;
+ out[6] = a12;
+ out[7] = a13;
+ out[8] = a20;
+ out[9] = a21;
+ out[10] = a22;
+ out[11] = a23;
+ out[12] = a00 * x + a10 * y + a20 * z + a[12];
+ out[13] = a01 * x + a11 * y + a21 * z + a[13];
+ out[14] = a02 * x + a12 * y + a22 * z + a[14];
+ out[15] = a03 * x + a13 * y + a23 * z + a[15];
+ }
+
+ return out;
+ }
+ /**
+ * Scales the mat4 by the dimensions in the given vec3 not using vectorization
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to scale
+ * @param {ReadonlyVec3} v the vec3 to scale the matrix by
+ * @returns {mat4} out
+ **/
+
+ function scale$3(out, a, v) {
+ var x = v[0],
+ y = v[1],
+ z = v[2];
+ out[0] = a[0] * x;
+ out[1] = a[1] * x;
+ out[2] = a[2] * x;
+ out[3] = a[3] * x;
+ out[4] = a[4] * y;
+ out[5] = a[5] * y;
+ out[6] = a[6] * y;
+ out[7] = a[7] * y;
+ out[8] = a[8] * z;
+ out[9] = a[9] * z;
+ out[10] = a[10] * z;
+ out[11] = a[11] * z;
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+ }
+ /**
+ * Rotates a mat4 by the given angle around the given axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+
+ function rotate$3(out, a, rad, axis) {
+ var x = axis[0],
+ y = axis[1],
+ z = axis[2];
+ var len = Math.hypot(x, y, z);
+ var s, c, t;
+ var a00, a01, a02, a03;
+ var a10, a11, a12, a13;
+ var a20, a21, a22, a23;
+ var b00, b01, b02;
+ var b10, b11, b12;
+ var b20, b21, b22;
+
+ if (len < EPSILON) {
+ return null;
+ }
+
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+ s = Math.sin(rad);
+ c = Math.cos(rad);
+ t = 1 - c;
+ a00 = a[0];
+ a01 = a[1];
+ a02 = a[2];
+ a03 = a[3];
+ a10 = a[4];
+ a11 = a[5];
+ a12 = a[6];
+ a13 = a[7];
+ a20 = a[8];
+ a21 = a[9];
+ a22 = a[10];
+ a23 = a[11]; // Construct the elements of the rotation matrix
+
+ b00 = x * x * t + c;
+ b01 = y * x * t + z * s;
+ b02 = z * x * t - y * s;
+ b10 = x * y * t - z * s;
+ b11 = y * y * t + c;
+ b12 = z * y * t + x * s;
+ b20 = x * z * t + y * s;
+ b21 = y * z * t - x * s;
+ b22 = z * z * t + c; // Perform rotation-specific matrix multiplication
+
+ out[0] = a00 * b00 + a10 * b01 + a20 * b02;
+ out[1] = a01 * b00 + a11 * b01 + a21 * b02;
+ out[2] = a02 * b00 + a12 * b01 + a22 * b02;
+ out[3] = a03 * b00 + a13 * b01 + a23 * b02;
+ out[4] = a00 * b10 + a10 * b11 + a20 * b12;
+ out[5] = a01 * b10 + a11 * b11 + a21 * b12;
+ out[6] = a02 * b10 + a12 * b11 + a22 * b12;
+ out[7] = a03 * b10 + a13 * b11 + a23 * b12;
+ out[8] = a00 * b20 + a10 * b21 + a20 * b22;
+ out[9] = a01 * b20 + a11 * b21 + a21 * b22;
+ out[10] = a02 * b20 + a12 * b21 + a22 * b22;
+ out[11] = a03 * b20 + a13 * b21 + a23 * b22;
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged last row
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+
+ return out;
+ }
+ /**
+ * Rotates a matrix by the given angle around the X axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+ function rotateX(out, a, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ var a10 = a[4];
+ var a11 = a[5];
+ var a12 = a[6];
+ var a13 = a[7];
+ var a20 = a[8];
+ var a21 = a[9];
+ var a22 = a[10];
+ var a23 = a[11];
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged rows
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ } // Perform axis-specific matrix multiplication
+
+
+ out[4] = a10 * c + a20 * s;
+ out[5] = a11 * c + a21 * s;
+ out[6] = a12 * c + a22 * s;
+ out[7] = a13 * c + a23 * s;
+ out[8] = a20 * c - a10 * s;
+ out[9] = a21 * c - a11 * s;
+ out[10] = a22 * c - a12 * s;
+ out[11] = a23 * c - a13 * s;
+ return out;
+ }
+ /**
+ * Rotates a matrix by the given angle around the Y axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+ function rotateY(out, a, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ var a00 = a[0];
+ var a01 = a[1];
+ var a02 = a[2];
+ var a03 = a[3];
+ var a20 = a[8];
+ var a21 = a[9];
+ var a22 = a[10];
+ var a23 = a[11];
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged rows
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ } // Perform axis-specific matrix multiplication
+
+
+ out[0] = a00 * c - a20 * s;
+ out[1] = a01 * c - a21 * s;
+ out[2] = a02 * c - a22 * s;
+ out[3] = a03 * c - a23 * s;
+ out[8] = a00 * s + a20 * c;
+ out[9] = a01 * s + a21 * c;
+ out[10] = a02 * s + a22 * c;
+ out[11] = a03 * s + a23 * c;
+ return out;
+ }
+ /**
+ * Rotates a matrix by the given angle around the Z axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+ function rotateZ(out, a, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad);
+ var a00 = a[0];
+ var a01 = a[1];
+ var a02 = a[2];
+ var a03 = a[3];
+ var a10 = a[4];
+ var a11 = a[5];
+ var a12 = a[6];
+ var a13 = a[7];
+
+ if (a !== out) {
+ // If the source and destination differ, copy the unchanged last row
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ } // Perform axis-specific matrix multiplication
+
+
+ out[0] = a00 * c + a10 * s;
+ out[1] = a01 * c + a11 * s;
+ out[2] = a02 * c + a12 * s;
+ out[3] = a03 * c + a13 * s;
+ out[4] = a10 * c - a00 * s;
+ out[5] = a11 * c - a01 * s;
+ out[6] = a12 * c - a02 * s;
+ out[7] = a13 * c - a03 * s;
+ return out;
+ }
+ /**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyVec3} v Translation vector
+ * @returns {mat4} out
+ */
+
+ function fromTranslation$2(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.scale(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyVec3} v Scaling vector
+ * @returns {mat4} out
+ */
+
+ function fromScaling$3(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = v[1];
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = v[2];
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Creates a matrix from a given angle around a given axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotate(dest, dest, rad, axis);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+
+ function fromRotation$3(out, rad, axis) {
+ var x = axis[0],
+ y = axis[1],
+ z = axis[2];
+ var len = Math.hypot(x, y, z);
+ var s, c, t;
+
+ if (len < EPSILON) {
+ return null;
+ }
+
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+ s = Math.sin(rad);
+ c = Math.cos(rad);
+ t = 1 - c; // Perform rotation-specific matrix multiplication
+
+ out[0] = x * x * t + c;
+ out[1] = y * x * t + z * s;
+ out[2] = z * x * t - y * s;
+ out[3] = 0;
+ out[4] = x * y * t - z * s;
+ out[5] = y * y * t + c;
+ out[6] = z * y * t + x * s;
+ out[7] = 0;
+ out[8] = x * z * t + y * s;
+ out[9] = y * z * t - x * s;
+ out[10] = z * z * t + c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Creates a matrix from the given angle around the X axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateX(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+ function fromXRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad); // Perform axis-specific matrix multiplication
+
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = c;
+ out[6] = s;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = -s;
+ out[10] = c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Creates a matrix from the given angle around the Y axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateY(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+ function fromYRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad); // Perform axis-specific matrix multiplication
+
+ out[0] = c;
+ out[1] = 0;
+ out[2] = -s;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = s;
+ out[9] = 0;
+ out[10] = c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Creates a matrix from the given angle around the Z axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateZ(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+
+ function fromZRotation(out, rad) {
+ var s = Math.sin(rad);
+ var c = Math.cos(rad); // Perform axis-specific matrix multiplication
+
+ out[0] = c;
+ out[1] = s;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = -s;
+ out[5] = c;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Creates a matrix from a quaternion rotation and vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @returns {mat4} out
+ */
+
+ function fromRotationTranslation(out, q, v) {
+ // Quaternion math
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var xy = x * y2;
+ var xz = x * z2;
+ var yy = y * y2;
+ var yz = y * z2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ out[0] = 1 - (yy + zz);
+ out[1] = xy + wz;
+ out[2] = xz - wy;
+ out[3] = 0;
+ out[4] = xy - wz;
+ out[5] = 1 - (xx + zz);
+ out[6] = yz + wx;
+ out[7] = 0;
+ out[8] = xz + wy;
+ out[9] = yz - wx;
+ out[10] = 1 - (xx + yy);
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Creates a new mat4 from a dual quat.
+ *
+ * @param {mat4} out Matrix
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @returns {mat4} mat4 receiving operation result
+ */
+
+ function fromQuat2(out, a) {
+ var translation = new ARRAY_TYPE(3);
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7];
+ var magnitude = bx * bx + by * by + bz * bz + bw * bw; //Only scale if it makes sense
+
+ if (magnitude > 0) {
+ translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;
+ translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;
+ translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;
+ } else {
+ translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
+ translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
+ translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
+ }
+
+ fromRotationTranslation(out, a, translation);
+ return out;
+ }
+ /**
+ * Returns the translation vector component of a transformation
+ * matrix. If a matrix is built with fromRotationTranslation,
+ * the returned vector will be the same as the translation vector
+ * originally supplied.
+ * @param {vec3} out Vector to receive translation component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {vec3} out
+ */
+
+ function getTranslation(out, mat) {
+ out[0] = mat[12];
+ out[1] = mat[13];
+ out[2] = mat[14];
+ return out;
+ }
+ /**
+ * Returns the scaling factor component of a transformation
+ * matrix. If a matrix is built with fromRotationTranslationScale
+ * with a normalized Quaternion paramter, the returned vector will be
+ * the same as the scaling vector
+ * originally supplied.
+ * @param {vec3} out Vector to receive scaling factor component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {vec3} out
+ */
+
+ function getScaling(out, mat) {
+ var m11 = mat[0];
+ var m12 = mat[1];
+ var m13 = mat[2];
+ var m21 = mat[4];
+ var m22 = mat[5];
+ var m23 = mat[6];
+ var m31 = mat[8];
+ var m32 = mat[9];
+ var m33 = mat[10];
+ out[0] = Math.hypot(m11, m12, m13);
+ out[1] = Math.hypot(m21, m22, m23);
+ out[2] = Math.hypot(m31, m32, m33);
+ return out;
+ }
+ /**
+ * Returns a quaternion representing the rotational component
+ * of a transformation matrix. If a matrix is built with
+ * fromRotationTranslation, the returned quaternion will be the
+ * same as the quaternion originally supplied.
+ * @param {quat} out Quaternion to receive the rotation component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {quat} out
+ */
+
+ function getRotation(out, mat) {
+ var scaling = new ARRAY_TYPE(3);
+ getScaling(scaling, mat);
+ var is1 = 1 / scaling[0];
+ var is2 = 1 / scaling[1];
+ var is3 = 1 / scaling[2];
+ var sm11 = mat[0] * is1;
+ var sm12 = mat[1] * is2;
+ var sm13 = mat[2] * is3;
+ var sm21 = mat[4] * is1;
+ var sm22 = mat[5] * is2;
+ var sm23 = mat[6] * is3;
+ var sm31 = mat[8] * is1;
+ var sm32 = mat[9] * is2;
+ var sm33 = mat[10] * is3;
+ var trace = sm11 + sm22 + sm33;
+ var S = 0;
+
+ if (trace > 0) {
+ S = Math.sqrt(trace + 1.0) * 2;
+ out[3] = 0.25 * S;
+ out[0] = (sm23 - sm32) / S;
+ out[1] = (sm31 - sm13) / S;
+ out[2] = (sm12 - sm21) / S;
+ } else if (sm11 > sm22 && sm11 > sm33) {
+ S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;
+ out[3] = (sm23 - sm32) / S;
+ out[0] = 0.25 * S;
+ out[1] = (sm12 + sm21) / S;
+ out[2] = (sm31 + sm13) / S;
+ } else if (sm22 > sm33) {
+ S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;
+ out[3] = (sm31 - sm13) / S;
+ out[0] = (sm12 + sm21) / S;
+ out[1] = 0.25 * S;
+ out[2] = (sm23 + sm32) / S;
+ } else {
+ S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;
+ out[3] = (sm12 - sm21) / S;
+ out[0] = (sm31 + sm13) / S;
+ out[1] = (sm23 + sm32) / S;
+ out[2] = 0.25 * S;
+ }
+
+ return out;
+ }
+ /**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @param {ReadonlyVec3} s Scaling vector
+ * @returns {mat4} out
+ */
+
+ function fromRotationTranslationScale(out, q, v, s) {
+ // Quaternion math
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var xy = x * y2;
+ var xz = x * z2;
+ var yy = y * y2;
+ var yz = y * z2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ var sx = s[0];
+ var sy = s[1];
+ var sz = s[2];
+ out[0] = (1 - (yy + zz)) * sx;
+ out[1] = (xy + wz) * sx;
+ out[2] = (xz - wy) * sx;
+ out[3] = 0;
+ out[4] = (xy - wz) * sy;
+ out[5] = (1 - (xx + zz)) * sy;
+ out[6] = (yz + wx) * sy;
+ out[7] = 0;
+ out[8] = (xz + wy) * sz;
+ out[9] = (yz - wx) * sz;
+ out[10] = (1 - (xx + yy)) * sz;
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * mat4.translate(dest, origin);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ * mat4.translate(dest, negativeOrigin);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @param {ReadonlyVec3} s Scaling vector
+ * @param {ReadonlyVec3} o The origin vector around which to scale and rotate
+ * @returns {mat4} out
+ */
+
+ function fromRotationTranslationScaleOrigin(out, q, v, s, o) {
+ // Quaternion math
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var xy = x * y2;
+ var xz = x * z2;
+ var yy = y * y2;
+ var yz = y * z2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ var sx = s[0];
+ var sy = s[1];
+ var sz = s[2];
+ var ox = o[0];
+ var oy = o[1];
+ var oz = o[2];
+ var out0 = (1 - (yy + zz)) * sx;
+ var out1 = (xy + wz) * sx;
+ var out2 = (xz - wy) * sx;
+ var out4 = (xy - wz) * sy;
+ var out5 = (1 - (xx + zz)) * sy;
+ var out6 = (yz + wx) * sy;
+ var out8 = (xz + wy) * sz;
+ var out9 = (yz - wx) * sz;
+ var out10 = (1 - (xx + yy)) * sz;
+ out[0] = out0;
+ out[1] = out1;
+ out[2] = out2;
+ out[3] = 0;
+ out[4] = out4;
+ out[5] = out5;
+ out[6] = out6;
+ out[7] = 0;
+ out[8] = out8;
+ out[9] = out9;
+ out[10] = out10;
+ out[11] = 0;
+ out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);
+ out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);
+ out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Calculates a 4x4 matrix from the given quaternion
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyQuat} q Quaternion to create matrix from
+ *
+ * @returns {mat4} out
+ */
+
+ function fromQuat$1(out, q) {
+ var x = q[0],
+ y = q[1],
+ z = q[2],
+ w = q[3];
+ var x2 = x + x;
+ var y2 = y + y;
+ var z2 = z + z;
+ var xx = x * x2;
+ var yx = y * x2;
+ var yy = y * y2;
+ var zx = z * x2;
+ var zy = z * y2;
+ var zz = z * z2;
+ var wx = w * x2;
+ var wy = w * y2;
+ var wz = w * z2;
+ out[0] = 1 - yy - zz;
+ out[1] = yx + wz;
+ out[2] = zx - wy;
+ out[3] = 0;
+ out[4] = yx - wz;
+ out[5] = 1 - xx - zz;
+ out[6] = zy + wx;
+ out[7] = 0;
+ out[8] = zx + wy;
+ out[9] = zy - wx;
+ out[10] = 1 - xx - yy;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Generates a frustum matrix with the given bounds
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {Number} left Left bound of the frustum
+ * @param {Number} right Right bound of the frustum
+ * @param {Number} bottom Bottom bound of the frustum
+ * @param {Number} top Top bound of the frustum
+ * @param {Number} near Near bound of the frustum
+ * @param {Number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+ function frustum(out, left, right, bottom, top, near, far) {
+ var rl = 1 / (right - left);
+ var tb = 1 / (top - bottom);
+ var nf = 1 / (near - far);
+ out[0] = near * 2 * rl;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = near * 2 * tb;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = (right + left) * rl;
+ out[9] = (top + bottom) * tb;
+ out[10] = (far + near) * nf;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = far * near * 2 * nf;
+ out[15] = 0;
+ return out;
+ }
+ /**
+ * Generates a perspective projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
+ * which matches WebGL/OpenGL's clip volume.
+ * Passing null/undefined/no value for far will generate infinite projection matrix.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum, can be null or Infinity
+ * @returns {mat4} out
+ */
+
+ function perspectiveNO(out, fovy, aspect, near, far) {
+ var f = 1.0 / Math.tan(fovy / 2),
+ nf;
+ out[0] = f / aspect;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = f;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[15] = 0;
+
+ if (far != null && far !== Infinity) {
+ nf = 1 / (near - far);
+ out[10] = (far + near) * nf;
+ out[14] = 2 * far * near * nf;
+ } else {
+ out[10] = -1;
+ out[14] = -2 * near;
+ }
+
+ return out;
+ }
+ /**
+ * Alias for {@link mat4.perspectiveNO}
+ * @function
+ */
+
+ var perspective = perspectiveNO;
+ /**
+ * Generates a perspective projection matrix suitable for WebGPU with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
+ * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
+ * Passing null/undefined/no value for far will generate infinite projection matrix.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum, can be null or Infinity
+ * @returns {mat4} out
+ */
+
+ function perspectiveZO(out, fovy, aspect, near, far) {
+ var f = 1.0 / Math.tan(fovy / 2),
+ nf;
+ out[0] = f / aspect;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = f;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[15] = 0;
+
+ if (far != null && far !== Infinity) {
+ nf = 1 / (near - far);
+ out[10] = far * nf;
+ out[14] = far * near * nf;
+ } else {
+ out[10] = -1;
+ out[14] = -near;
+ }
+
+ return out;
+ }
+ /**
+ * Generates a perspective projection matrix with the given field of view.
+ * This is primarily useful for generating projection matrices to be used
+ * with the still experiemental WebVR API.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+ function perspectiveFromFieldOfView(out, fov, near, far) {
+ var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);
+ var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);
+ var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);
+ var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);
+ var xScale = 2.0 / (leftTan + rightTan);
+ var yScale = 2.0 / (upTan + downTan);
+ out[0] = xScale;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ out[3] = 0.0;
+ out[4] = 0.0;
+ out[5] = yScale;
+ out[6] = 0.0;
+ out[7] = 0.0;
+ out[8] = -((leftTan - rightTan) * xScale * 0.5);
+ out[9] = (upTan - downTan) * yScale * 0.5;
+ out[10] = far / (near - far);
+ out[11] = -1.0;
+ out[12] = 0.0;
+ out[13] = 0.0;
+ out[14] = far * near / (near - far);
+ out[15] = 0.0;
+ return out;
+ }
+ /**
+ * Generates a orthogonal projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
+ * which matches WebGL/OpenGL's clip volume.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+ function orthoNO(out, left, right, bottom, top, near, far) {
+ var lr = 1 / (left - right);
+ var bt = 1 / (bottom - top);
+ var nf = 1 / (near - far);
+ out[0] = -2 * lr;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = -2 * bt;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 2 * nf;
+ out[11] = 0;
+ out[12] = (left + right) * lr;
+ out[13] = (top + bottom) * bt;
+ out[14] = (far + near) * nf;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Alias for {@link mat4.orthoNO}
+ * @function
+ */
+
+ var ortho = orthoNO;
+ /**
+ * Generates a orthogonal projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
+ * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+
+ function orthoZO(out, left, right, bottom, top, near, far) {
+ var lr = 1 / (left - right);
+ var bt = 1 / (bottom - top);
+ var nf = 1 / (near - far);
+ out[0] = -2 * lr;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = -2 * bt;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = nf;
+ out[11] = 0;
+ out[12] = (left + right) * lr;
+ out[13] = (top + bottom) * bt;
+ out[14] = near * nf;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Generates a look-at matrix with the given eye position, focal point, and up axis.
+ * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {ReadonlyVec3} eye Position of the viewer
+ * @param {ReadonlyVec3} center Point the viewer is looking at
+ * @param {ReadonlyVec3} up vec3 pointing up
+ * @returns {mat4} out
+ */
+
+ function lookAt(out, eye, center, up) {
+ var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
+ var eyex = eye[0];
+ var eyey = eye[1];
+ var eyez = eye[2];
+ var upx = up[0];
+ var upy = up[1];
+ var upz = up[2];
+ var centerx = center[0];
+ var centery = center[1];
+ var centerz = center[2];
+
+ if (Math.abs(eyex - centerx) < EPSILON && Math.abs(eyey - centery) < EPSILON && Math.abs(eyez - centerz) < EPSILON) {
+ return identity$3(out);
+ }
+
+ z0 = eyex - centerx;
+ z1 = eyey - centery;
+ z2 = eyez - centerz;
+ len = 1 / Math.hypot(z0, z1, z2);
+ z0 *= len;
+ z1 *= len;
+ z2 *= len;
+ x0 = upy * z2 - upz * z1;
+ x1 = upz * z0 - upx * z2;
+ x2 = upx * z1 - upy * z0;
+ len = Math.hypot(x0, x1, x2);
+
+ if (!len) {
+ x0 = 0;
+ x1 = 0;
+ x2 = 0;
+ } else {
+ len = 1 / len;
+ x0 *= len;
+ x1 *= len;
+ x2 *= len;
+ }
+
+ y0 = z1 * x2 - z2 * x1;
+ y1 = z2 * x0 - z0 * x2;
+ y2 = z0 * x1 - z1 * x0;
+ len = Math.hypot(y0, y1, y2);
+
+ if (!len) {
+ y0 = 0;
+ y1 = 0;
+ y2 = 0;
+ } else {
+ len = 1 / len;
+ y0 *= len;
+ y1 *= len;
+ y2 *= len;
+ }
+
+ out[0] = x0;
+ out[1] = y0;
+ out[2] = z0;
+ out[3] = 0;
+ out[4] = x1;
+ out[5] = y1;
+ out[6] = z1;
+ out[7] = 0;
+ out[8] = x2;
+ out[9] = y2;
+ out[10] = z2;
+ out[11] = 0;
+ out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
+ out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
+ out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Generates a matrix that makes something look at something else.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {ReadonlyVec3} eye Position of the viewer
+ * @param {ReadonlyVec3} center Point the viewer is looking at
+ * @param {ReadonlyVec3} up vec3 pointing up
+ * @returns {mat4} out
+ */
+
+ function targetTo(out, eye, target, up) {
+ var eyex = eye[0],
+ eyey = eye[1],
+ eyez = eye[2],
+ upx = up[0],
+ upy = up[1],
+ upz = up[2];
+ var z0 = eyex - target[0],
+ z1 = eyey - target[1],
+ z2 = eyez - target[2];
+ var len = z0 * z0 + z1 * z1 + z2 * z2;
+
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ z0 *= len;
+ z1 *= len;
+ z2 *= len;
+ }
+
+ var x0 = upy * z2 - upz * z1,
+ x1 = upz * z0 - upx * z2,
+ x2 = upx * z1 - upy * z0;
+ len = x0 * x0 + x1 * x1 + x2 * x2;
+
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ x0 *= len;
+ x1 *= len;
+ x2 *= len;
+ }
+
+ out[0] = x0;
+ out[1] = x1;
+ out[2] = x2;
+ out[3] = 0;
+ out[4] = z1 * x2 - z2 * x1;
+ out[5] = z2 * x0 - z0 * x2;
+ out[6] = z0 * x1 - z1 * x0;
+ out[7] = 0;
+ out[8] = z0;
+ out[9] = z1;
+ out[10] = z2;
+ out[11] = 0;
+ out[12] = eyex;
+ out[13] = eyey;
+ out[14] = eyez;
+ out[15] = 1;
+ return out;
+ }
+ /**
+ * Returns a string representation of a mat4
+ *
+ * @param {ReadonlyMat4} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+
+ function str$3(a) {
+ return "mat4(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ", " + a[8] + ", " + a[9] + ", " + a[10] + ", " + a[11] + ", " + a[12] + ", " + a[13] + ", " + a[14] + ", " + a[15] + ")";
+ }
+ /**
+ * Returns Frobenius norm of a mat4
+ *
+ * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+
+ function frob$3(a) {
+ return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);
+ }
+ /**
+ * Adds two mat4's
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+
+ function add$3(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ out[6] = a[6] + b[6];
+ out[7] = a[7] + b[7];
+ out[8] = a[8] + b[8];
+ out[9] = a[9] + b[9];
+ out[10] = a[10] + b[10];
+ out[11] = a[11] + b[11];
+ out[12] = a[12] + b[12];
+ out[13] = a[13] + b[13];
+ out[14] = a[14] + b[14];
+ out[15] = a[15] + b[15];
+ return out;
+ }
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+
+ function subtract$3(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ out[4] = a[4] - b[4];
+ out[5] = a[5] - b[5];
+ out[6] = a[6] - b[6];
+ out[7] = a[7] - b[7];
+ out[8] = a[8] - b[8];
+ out[9] = a[9] - b[9];
+ out[10] = a[10] - b[10];
+ out[11] = a[11] - b[11];
+ out[12] = a[12] - b[12];
+ out[13] = a[13] - b[13];
+ out[14] = a[14] - b[14];
+ out[15] = a[15] - b[15];
+ return out;
+ }
+ /**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat4} out
+ */
+
+ function multiplyScalar$3(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ out[6] = a[6] * b;
+ out[7] = a[7] * b;
+ out[8] = a[8] * b;
+ out[9] = a[9] * b;
+ out[10] = a[10] * b;
+ out[11] = a[11] * b;
+ out[12] = a[12] * b;
+ out[13] = a[13] * b;
+ out[14] = a[14] * b;
+ out[15] = a[15] * b;
+ return out;
+ }
+ /**
+ * Adds two mat4's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat4} out the receiving vector
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat4} out
+ */
+
+ function multiplyScalarAndAdd$3(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ out[4] = a[4] + b[4] * scale;
+ out[5] = a[5] + b[5] * scale;
+ out[6] = a[6] + b[6] * scale;
+ out[7] = a[7] + b[7] * scale;
+ out[8] = a[8] + b[8] * scale;
+ out[9] = a[9] + b[9] * scale;
+ out[10] = a[10] + b[10] * scale;
+ out[11] = a[11] + b[11] * scale;
+ out[12] = a[12] + b[12] * scale;
+ out[13] = a[13] + b[13] * scale;
+ out[14] = a[14] + b[14] * scale;
+ out[15] = a[15] + b[15] * scale;
+ return out;
+ }
+ /**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat4} a The first matrix.
+ * @param {ReadonlyMat4} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+ function exactEquals$3(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];
+ }
+ /**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat4} a The first matrix.
+ * @param {ReadonlyMat4} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+
+ function equals$4(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var a4 = a[4],
+ a5 = a[5],
+ a6 = a[6],
+ a7 = a[7];
+ var a8 = a[8],
+ a9 = a[9],
+ a10 = a[10],
+ a11 = a[11];
+ var a12 = a[12],
+ a13 = a[13],
+ a14 = a[14],
+ a15 = a[15];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ var b4 = b[4],
+ b5 = b[5],
+ b6 = b[6],
+ b7 = b[7];
+ var b8 = b[8],
+ b9 = b[9],
+ b10 = b[10],
+ b11 = b[11];
+ var b12 = b[12],
+ b13 = b[13],
+ b14 = b[14],
+ b15 = b[15];
+ return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));
+ }
+ /**
+ * Alias for {@link mat4.multiply}
+ * @function
+ */
+
+ var mul$3 = multiply$3;
+ /**
+ * Alias for {@link mat4.subtract}
+ * @function
+ */
+
+ var sub$3 = subtract$3;
+
+ var mat4 = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ create: create$3,
+ clone: clone$3,
+ copy: copy$3,
+ fromValues: fromValues$3,
+ set: set$3,
+ identity: identity$3,
+ transpose: transpose$2,
+ invert: invert$3,
+ adjoint: adjoint$2,
+ determinant: determinant$3,
+ multiply: multiply$3,
+ translate: translate$2,
+ scale: scale$3,
+ rotate: rotate$3,
+ rotateX: rotateX,
+ rotateY: rotateY,
+ rotateZ: rotateZ,
+ fromTranslation: fromTranslation$2,
+ fromScaling: fromScaling$3,
+ fromRotation: fromRotation$3,
+ fromXRotation: fromXRotation,
+ fromYRotation: fromYRotation,
+ fromZRotation: fromZRotation,
+ fromRotationTranslation: fromRotationTranslation,
+ fromQuat2: fromQuat2,
+ getTranslation: getTranslation,
+ getScaling: getScaling,
+ getRotation: getRotation,
+ fromRotationTranslationScale: fromRotationTranslationScale,
+ fromRotationTranslationScaleOrigin: fromRotationTranslationScaleOrigin,
+ fromQuat: fromQuat$1,
+ frustum: frustum,
+ perspectiveNO: perspectiveNO,
+ perspective: perspective,
+ perspectiveZO: perspectiveZO,
+ perspectiveFromFieldOfView: perspectiveFromFieldOfView,
+ orthoNO: orthoNO,
+ ortho: ortho,
+ orthoZO: orthoZO,
+ lookAt: lookAt,
+ targetTo: targetTo,
+ str: str$3,
+ frob: frob$3,
+ add: add$3,
+ subtract: subtract$3,
+ multiplyScalar: multiplyScalar$3,
+ multiplyScalarAndAdd: multiplyScalarAndAdd$3,
+ exactEquals: exactEquals$3,
+ equals: equals$4,
+ mul: mul$3,
+ sub: sub$3
+ });
+
+ /**
+ * 3 Dimensional Vector
+ * @module vec3
+ */
+
+ /**
+ * Creates a new, empty vec3
+ *
+ * @returns {vec3} a new 3D vector
+ */
+
+ function create$4() {
+ var out = new ARRAY_TYPE(3);
+
+ if (ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ }
+
+ return out;
+ }
+ /**
+ * Creates a new vec3 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec3} a vector to clone
+ * @returns {vec3} a new 3D vector
+ */
+
+ function clone$4(a) {
+ var out = new ARRAY_TYPE(3);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ return out;
+ }
+ /**
+ * Calculates the length of a vec3
+ *
+ * @param {ReadonlyVec3} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+ function length(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ return Math.hypot(x, y, z);
+ }
+ /**
+ * Creates a new vec3 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} a new 3D vector
+ */
+
+ function fromValues$4(x, y, z) {
+ var out = new ARRAY_TYPE(3);
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ return out;
+ }
+ /**
+ * Copy the values from one vec3 to another
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the source vector
+ * @returns {vec3} out
+ */
+
+ function copy$4(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ return out;
+ }
+ /**
+ * Set the components of a vec3 to the given values
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} out
+ */
+
+ function set$4(out, x, y, z) {
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ return out;
+ }
+ /**
+ * Adds two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+ function add$4(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ return out;
+ }
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+ function subtract$4(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ return out;
+ }
+ /**
+ * Multiplies two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+ function multiply$4(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ out[2] = a[2] * b[2];
+ return out;
+ }
+ /**
+ * Divides two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+ function divide(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ out[2] = a[2] / b[2];
+ return out;
+ }
+ /**
+ * Math.ceil the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to ceil
+ * @returns {vec3} out
+ */
+
+ function ceil(out, a) {
+ out[0] = Math.ceil(a[0]);
+ out[1] = Math.ceil(a[1]);
+ out[2] = Math.ceil(a[2]);
+ return out;
+ }
+ /**
+ * Math.floor the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to floor
+ * @returns {vec3} out
+ */
+
+ function floor(out, a) {
+ out[0] = Math.floor(a[0]);
+ out[1] = Math.floor(a[1]);
+ out[2] = Math.floor(a[2]);
+ return out;
+ }
+ /**
+ * Returns the minimum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+ function min(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ out[2] = Math.min(a[2], b[2]);
+ return out;
+ }
+ /**
+ * Returns the maximum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+ function max(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ out[2] = Math.max(a[2], b[2]);
+ return out;
+ }
+ /**
+ * Math.round the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to round
+ * @returns {vec3} out
+ */
+
+ function round(out, a) {
+ out[0] = Math.round(a[0]);
+ out[1] = Math.round(a[1]);
+ out[2] = Math.round(a[2]);
+ return out;
+ }
+ /**
+ * Scales a vec3 by a scalar number
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec3} out
+ */
+
+ function scale$4(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ return out;
+ }
+ /**
+ * Adds two vec3's after scaling the second operand by a scalar value
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec3} out
+ */
+
+ function scaleAndAdd(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ return out;
+ }
+ /**
+ * Calculates the euclidian distance between two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} distance between a and b
+ */
+
+ function distance(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ return Math.hypot(x, y, z);
+ }
+ /**
+ * Calculates the squared euclidian distance between two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+
+ function squaredDistance(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ return x * x + y * y + z * z;
+ }
+ /**
+ * Calculates the squared length of a vec3
+ *
+ * @param {ReadonlyVec3} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+
+ function squaredLength(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ return x * x + y * y + z * z;
+ }
+ /**
+ * Negates the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to negate
+ * @returns {vec3} out
+ */
+
+ function negate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ return out;
+ }
+ /**
+ * Returns the inverse of the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to invert
+ * @returns {vec3} out
+ */
+
+ function inverse(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ out[2] = 1.0 / a[2];
+ return out;
+ }
+ /**
+ * Normalize a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to normalize
+ * @returns {vec3} out
+ */
+
+ function normalize(out, a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var len = x * x + y * y + z * z;
+
+ if (len > 0) {
+ //TODO: evaluate use of glm_invsqrt here?
+ len = 1 / Math.sqrt(len);
+ }
+
+ out[0] = a[0] * len;
+ out[1] = a[1] * len;
+ out[2] = a[2] * len;
+ return out;
+ }
+ /**
+ * Calculates the dot product of two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+
+ function dot(a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ }
+ /**
+ * Computes the cross product of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+
+ function cross(out, a, b) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2];
+ var bx = b[0],
+ by = b[1],
+ bz = b[2];
+ out[0] = ay * bz - az * by;
+ out[1] = az * bx - ax * bz;
+ out[2] = ax * by - ay * bx;
+ return out;
+ }
+ /**
+ * Performs a linear interpolation between two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+
+ function lerp(out, a, b, t) {
+ var ax = a[0];
+ var ay = a[1];
+ var az = a[2];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ out[2] = az + t * (b[2] - az);
+ return out;
+ }
+ /**
+ * Performs a hermite interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {ReadonlyVec3} c the third operand
+ * @param {ReadonlyVec3} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+
+ function hermite(out, a, b, c, d, t) {
+ var factorTimes2 = t * t;
+ var factor1 = factorTimes2 * (2 * t - 3) + 1;
+ var factor2 = factorTimes2 * (t - 2) + t;
+ var factor3 = factorTimes2 * (t - 1);
+ var factor4 = factorTimes2 * (3 - 2 * t);
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+ return out;
+ }
+ /**
+ * Performs a bezier interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {ReadonlyVec3} c the third operand
+ * @param {ReadonlyVec3} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+
+ function bezier(out, a, b, c, d, t) {
+ var inverseFactor = 1 - t;
+ var inverseFactorTimesTwo = inverseFactor * inverseFactor;
+ var factorTimes2 = t * t;
+ var factor1 = inverseFactorTimesTwo * inverseFactor;
+ var factor2 = 3 * t * inverseFactorTimesTwo;
+ var factor3 = 3 * factorTimes2 * inverseFactor;
+ var factor4 = factorTimes2 * t;
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+ return out;
+ }
+ /**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec3} out
+ */
+
+ function random(out, scale) {
+ scale = scale || 1.0;
+ var r = RANDOM() * 2.0 * Math.PI;
+ var z = RANDOM() * 2.0 - 1.0;
+ var zScale = Math.sqrt(1.0 - z * z) * scale;
+ out[0] = Math.cos(r) * zScale;
+ out[1] = Math.sin(r) * zScale;
+ out[2] = z * scale;
+ return out;
+ }
+ /**
+ * Transforms the vec3 with a mat4.
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec3} out
+ */
+
+ function transformMat4(out, a, m) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ var w = m[3] * x + m[7] * y + m[11] * z + m[15];
+ w = w || 1.0;
+ out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
+ out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
+ out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
+ return out;
+ }
+ /**
+ * Transforms the vec3 with a mat3.
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyMat3} m the 3x3 matrix to transform with
+ * @returns {vec3} out
+ */
+
+ function transformMat3(out, a, m) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ out[0] = x * m[0] + y * m[3] + z * m[6];
+ out[1] = x * m[1] + y * m[4] + z * m[7];
+ out[2] = x * m[2] + y * m[5] + z * m[8];
+ return out;
+ }
+ /**
+ * Transforms the vec3 with a quat
+ * Can also be used for dual quaternions. (Multiply it with the real part)
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyQuat} q quaternion to transform with
+ * @returns {vec3} out
+ */
+
+ function transformQuat(out, a, q) {
+ // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3];
+ var x = a[0],
+ y = a[1],
+ z = a[2]; // var qvec = [qx, qy, qz];
+ // var uv = vec3.cross([], qvec, a);
+
+ var uvx = qy * z - qz * y,
+ uvy = qz * x - qx * z,
+ uvz = qx * y - qy * x; // var uuv = vec3.cross([], qvec, uv);
+
+ var uuvx = qy * uvz - qz * uvy,
+ uuvy = qz * uvx - qx * uvz,
+ uuvz = qx * uvy - qy * uvx; // vec3.scale(uv, uv, 2 * w);
+
+ var w2 = qw * 2;
+ uvx *= w2;
+ uvy *= w2;
+ uvz *= w2; // vec3.scale(uuv, uuv, 2);
+
+ uuvx *= 2;
+ uuvy *= 2;
+ uuvz *= 2; // return vec3.add(out, a, vec3.add(out, uv, uuv));
+
+ out[0] = x + uvx + uuvx;
+ out[1] = y + uvy + uuvy;
+ out[2] = z + uvz + uuvz;
+ return out;
+ }
+ /**
+ * Rotate a 3D vector around the x-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+
+ function rotateX$1(out, a, b, rad) {
+ var p = [],
+ r = []; //Translate point to the origin
+
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2]; //perform rotation
+
+ r[0] = p[0];
+ r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);
+ r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad); //translate to correct position
+
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+ return out;
+ }
+ /**
+ * Rotate a 3D vector around the y-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+
+ function rotateY$1(out, a, b, rad) {
+ var p = [],
+ r = []; //Translate point to the origin
+
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2]; //perform rotation
+
+ r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);
+ r[1] = p[1];
+ r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad); //translate to correct position
+
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+ return out;
+ }
+ /**
+ * Rotate a 3D vector around the z-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+
+ function rotateZ$1(out, a, b, rad) {
+ var p = [],
+ r = []; //Translate point to the origin
+
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2]; //perform rotation
+
+ r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);
+ r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);
+ r[2] = p[2]; //translate to correct position
+
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+ return out;
+ }
+ /**
+ * Get the angle between two 3D vectors
+ * @param {ReadonlyVec3} a The first operand
+ * @param {ReadonlyVec3} b The second operand
+ * @returns {Number} The angle in radians
+ */
+
+ function angle(a, b) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ bx = b[0],
+ by = b[1],
+ bz = b[2],
+ mag1 = Math.sqrt(ax * ax + ay * ay + az * az),
+ mag2 = Math.sqrt(bx * bx + by * by + bz * bz),
+ mag = mag1 * mag2,
+ cosine = mag && dot(a, b) / mag;
+ return Math.acos(Math.min(Math.max(cosine, -1), 1));
+ }
+ /**
+ * Set the components of a vec3 to zero
+ *
+ * @param {vec3} out the receiving vector
+ * @returns {vec3} out
+ */
+
+ function zero(out) {
+ out[0] = 0.0;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ return out;
+ }
+ /**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec3} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+ function str$4(a) {
+ return "vec3(" + a[0] + ", " + a[1] + ", " + a[2] + ")";
+ }
+ /**
+ * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec3} a The first vector.
+ * @param {ReadonlyVec3} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+ function exactEquals$4(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
+ }
+ /**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec3} a The first vector.
+ * @param {ReadonlyVec3} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+ function equals$5(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2];
+ return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2));
+ }
+ /**
+ * Alias for {@link vec3.subtract}
+ * @function
+ */
+
+ var sub$4 = subtract$4;
+ /**
+ * Alias for {@link vec3.multiply}
+ * @function
+ */
+
+ var mul$4 = multiply$4;
+ /**
+ * Alias for {@link vec3.divide}
+ * @function
+ */
+
+ var div = divide;
+ /**
+ * Alias for {@link vec3.distance}
+ * @function
+ */
+
+ var dist = distance;
+ /**
+ * Alias for {@link vec3.squaredDistance}
+ * @function
+ */
+
+ var sqrDist = squaredDistance;
+ /**
+ * Alias for {@link vec3.length}
+ * @function
+ */
+
+ var len = length;
+ /**
+ * Alias for {@link vec3.squaredLength}
+ * @function
+ */
+
+ var sqrLen = squaredLength;
+ /**
+ * Perform some operation over an array of vec3s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+
+ var forEach = function () {
+ var vec = create$4();
+ return function (a, stride, offset, count, fn, arg) {
+ var i, l;
+
+ if (!stride) {
+ stride = 3;
+ }
+
+ if (!offset) {
+ offset = 0;
+ }
+
+ if (count) {
+ l = Math.min(count * stride + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for (i = offset; i < l; i += stride) {
+ vec[0] = a[i];
+ vec[1] = a[i + 1];
+ vec[2] = a[i + 2];
+ fn(vec, vec, arg);
+ a[i] = vec[0];
+ a[i + 1] = vec[1];
+ a[i + 2] = vec[2];
+ }
+
+ return a;
+ };
+ }();
+
+ var vec3 = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ create: create$4,
+ clone: clone$4,
+ length: length,
+ fromValues: fromValues$4,
+ copy: copy$4,
+ set: set$4,
+ add: add$4,
+ subtract: subtract$4,
+ multiply: multiply$4,
+ divide: divide,
+ ceil: ceil,
+ floor: floor,
+ min: min,
+ max: max,
+ round: round,
+ scale: scale$4,
+ scaleAndAdd: scaleAndAdd,
+ distance: distance,
+ squaredDistance: squaredDistance,
+ squaredLength: squaredLength,
+ negate: negate,
+ inverse: inverse,
+ normalize: normalize,
+ dot: dot,
+ cross: cross,
+ lerp: lerp,
+ hermite: hermite,
+ bezier: bezier,
+ random: random,
+ transformMat4: transformMat4,
+ transformMat3: transformMat3,
+ transformQuat: transformQuat,
+ rotateX: rotateX$1,
+ rotateY: rotateY$1,
+ rotateZ: rotateZ$1,
+ angle: angle,
+ zero: zero,
+ str: str$4,
+ exactEquals: exactEquals$4,
+ equals: equals$5,
+ sub: sub$4,
+ mul: mul$4,
+ div: div,
+ dist: dist,
+ sqrDist: sqrDist,
+ len: len,
+ sqrLen: sqrLen,
+ forEach: forEach
+ });
+
+ /**
+ * 4 Dimensional Vector
+ * @module vec4
+ */
+
+ /**
+ * Creates a new, empty vec4
+ *
+ * @returns {vec4} a new 4D vector
+ */
+
+ function create$5() {
+ var out = new ARRAY_TYPE(4);
+
+ if (ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ }
+
+ return out;
+ }
+ /**
+ * Creates a new vec4 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec4} a vector to clone
+ * @returns {vec4} a new 4D vector
+ */
+
+ function clone$5(a) {
+ var out = new ARRAY_TYPE(4);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+ }
+ /**
+ * Creates a new vec4 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} a new 4D vector
+ */
+
+ function fromValues$5(x, y, z, w) {
+ var out = new ARRAY_TYPE(4);
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = w;
+ return out;
+ }
+ /**
+ * Copy the values from one vec4 to another
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the source vector
+ * @returns {vec4} out
+ */
+
+ function copy$5(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+ }
+ /**
+ * Set the components of a vec4 to the given values
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} out
+ */
+
+ function set$5(out, x, y, z, w) {
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = w;
+ return out;
+ }
+ /**
+ * Adds two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+ function add$5(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ return out;
+ }
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+ function subtract$5(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ return out;
+ }
+ /**
+ * Multiplies two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+ function multiply$5(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ out[2] = a[2] * b[2];
+ out[3] = a[3] * b[3];
+ return out;
+ }
+ /**
+ * Divides two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+ function divide$1(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ out[2] = a[2] / b[2];
+ out[3] = a[3] / b[3];
+ return out;
+ }
+ /**
+ * Math.ceil the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to ceil
+ * @returns {vec4} out
+ */
+
+ function ceil$1(out, a) {
+ out[0] = Math.ceil(a[0]);
+ out[1] = Math.ceil(a[1]);
+ out[2] = Math.ceil(a[2]);
+ out[3] = Math.ceil(a[3]);
+ return out;
+ }
+ /**
+ * Math.floor the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to floor
+ * @returns {vec4} out
+ */
+
+ function floor$1(out, a) {
+ out[0] = Math.floor(a[0]);
+ out[1] = Math.floor(a[1]);
+ out[2] = Math.floor(a[2]);
+ out[3] = Math.floor(a[3]);
+ return out;
+ }
+ /**
+ * Returns the minimum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+ function min$1(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ out[2] = Math.min(a[2], b[2]);
+ out[3] = Math.min(a[3], b[3]);
+ return out;
+ }
+ /**
+ * Returns the maximum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+
+ function max$1(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ out[2] = Math.max(a[2], b[2]);
+ out[3] = Math.max(a[3], b[3]);
+ return out;
+ }
+ /**
+ * Math.round the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to round
+ * @returns {vec4} out
+ */
+
+ function round$1(out, a) {
+ out[0] = Math.round(a[0]);
+ out[1] = Math.round(a[1]);
+ out[2] = Math.round(a[2]);
+ out[3] = Math.round(a[3]);
+ return out;
+ }
+ /**
+ * Scales a vec4 by a scalar number
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec4} out
+ */
+
+ function scale$5(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ return out;
+ }
+ /**
+ * Adds two vec4's after scaling the second operand by a scalar value
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec4} out
+ */
+
+ function scaleAndAdd$1(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ out[2] = a[2] + b[2] * scale;
+ out[3] = a[3] + b[3] * scale;
+ return out;
+ }
+ /**
+ * Calculates the euclidian distance between two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} distance between a and b
+ */
+
+ function distance$1(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ var w = b[3] - a[3];
+ return Math.hypot(x, y, z, w);
+ }
+ /**
+ * Calculates the squared euclidian distance between two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+
+ function squaredDistance$1(a, b) {
+ var x = b[0] - a[0];
+ var y = b[1] - a[1];
+ var z = b[2] - a[2];
+ var w = b[3] - a[3];
+ return x * x + y * y + z * z + w * w;
+ }
+ /**
+ * Calculates the length of a vec4
+ *
+ * @param {ReadonlyVec4} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+ function length$1(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var w = a[3];
+ return Math.hypot(x, y, z, w);
+ }
+ /**
+ * Calculates the squared length of a vec4
+ *
+ * @param {ReadonlyVec4} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+
+ function squaredLength$1(a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var w = a[3];
+ return x * x + y * y + z * z + w * w;
+ }
+ /**
+ * Negates the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to negate
+ * @returns {vec4} out
+ */
+
+ function negate$1(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = -a[3];
+ return out;
+ }
+ /**
+ * Returns the inverse of the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to invert
+ * @returns {vec4} out
+ */
+
+ function inverse$1(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ out[2] = 1.0 / a[2];
+ out[3] = 1.0 / a[3];
+ return out;
+ }
+ /**
+ * Normalize a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to normalize
+ * @returns {vec4} out
+ */
+
+ function normalize$1(out, a) {
+ var x = a[0];
+ var y = a[1];
+ var z = a[2];
+ var w = a[3];
+ var len = x * x + y * y + z * z + w * w;
+
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ }
+
+ out[0] = x * len;
+ out[1] = y * len;
+ out[2] = z * len;
+ out[3] = w * len;
+ return out;
+ }
+ /**
+ * Calculates the dot product of two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+
+ function dot$1(a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+ }
+ /**
+ * Returns the cross-product of three vectors in a 4-dimensional space
+ *
+ * @param {ReadonlyVec4} result the receiving vector
+ * @param {ReadonlyVec4} U the first vector
+ * @param {ReadonlyVec4} V the second vector
+ * @param {ReadonlyVec4} W the third vector
+ * @returns {vec4} result
+ */
+
+ function cross$1(out, u, v, w) {
+ var A = v[0] * w[1] - v[1] * w[0],
+ B = v[0] * w[2] - v[2] * w[0],
+ C = v[0] * w[3] - v[3] * w[0],
+ D = v[1] * w[2] - v[2] * w[1],
+ E = v[1] * w[3] - v[3] * w[1],
+ F = v[2] * w[3] - v[3] * w[2];
+ var G = u[0];
+ var H = u[1];
+ var I = u[2];
+ var J = u[3];
+ out[0] = H * F - I * E + J * D;
+ out[1] = -(G * F) + I * C - J * B;
+ out[2] = G * E - H * C + J * A;
+ out[3] = -(G * D) + H * B - I * A;
+ return out;
+ }
+ /**
+ * Performs a linear interpolation between two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec4} out
+ */
+
+ function lerp$1(out, a, b, t) {
+ var ax = a[0];
+ var ay = a[1];
+ var az = a[2];
+ var aw = a[3];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ out[2] = az + t * (b[2] - az);
+ out[3] = aw + t * (b[3] - aw);
+ return out;
+ }
+ /**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec4} out
+ */
+
+ function random$1(out, scale) {
+ scale = scale || 1.0; // Marsaglia, George. Choosing a Point from the Surface of a
+ // Sphere. Ann. Math. Statist. 43 (1972), no. 2, 645--646.
+ // http://projecteuclid.org/euclid.aoms/1177692644;
+
+ var v1, v2, v3, v4;
+ var s1, s2;
+
+ do {
+ v1 = RANDOM() * 2 - 1;
+ v2 = RANDOM() * 2 - 1;
+ s1 = v1 * v1 + v2 * v2;
+ } while (s1 >= 1);
+
+ do {
+ v3 = RANDOM() * 2 - 1;
+ v4 = RANDOM() * 2 - 1;
+ s2 = v3 * v3 + v4 * v4;
+ } while (s2 >= 1);
+
+ var d = Math.sqrt((1 - s1) / s2);
+ out[0] = scale * v1;
+ out[1] = scale * v2;
+ out[2] = scale * v3 * d;
+ out[3] = scale * v4 * d;
+ return out;
+ }
+ /**
+ * Transforms the vec4 with a mat4.
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec4} out
+ */
+
+ function transformMat4$1(out, a, m) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
+ out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
+ out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
+ out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
+ return out;
+ }
+ /**
+ * Transforms the vec4 with a quat
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to transform
+ * @param {ReadonlyQuat} q quaternion to transform with
+ * @returns {vec4} out
+ */
+
+ function transformQuat$1(out, a, q) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3]; // calculate quat * vec
+
+ var ix = qw * x + qy * z - qz * y;
+ var iy = qw * y + qz * x - qx * z;
+ var iz = qw * z + qx * y - qy * x;
+ var iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat
+
+ out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
+ out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
+ out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
+ out[3] = a[3];
+ return out;
+ }
+ /**
+ * Set the components of a vec4 to zero
+ *
+ * @param {vec4} out the receiving vector
+ * @returns {vec4} out
+ */
+
+ function zero$1(out) {
+ out[0] = 0.0;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ out[3] = 0.0;
+ return out;
+ }
+ /**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec4} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+ function str$5(a) {
+ return "vec4(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")";
+ }
+ /**
+ * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec4} a The first vector.
+ * @param {ReadonlyVec4} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+ function exactEquals$5(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];
+ }
+ /**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec4} a The first vector.
+ * @param {ReadonlyVec4} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+ function equals$6(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3];
+ return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3));
+ }
+ /**
+ * Alias for {@link vec4.subtract}
+ * @function
+ */
+
+ var sub$5 = subtract$5;
+ /**
+ * Alias for {@link vec4.multiply}
+ * @function
+ */
+
+ var mul$5 = multiply$5;
+ /**
+ * Alias for {@link vec4.divide}
+ * @function
+ */
+
+ var div$1 = divide$1;
+ /**
+ * Alias for {@link vec4.distance}
+ * @function
+ */
+
+ var dist$1 = distance$1;
+ /**
+ * Alias for {@link vec4.squaredDistance}
+ * @function
+ */
+
+ var sqrDist$1 = squaredDistance$1;
+ /**
+ * Alias for {@link vec4.length}
+ * @function
+ */
+
+ var len$1 = length$1;
+ /**
+ * Alias for {@link vec4.squaredLength}
+ * @function
+ */
+
+ var sqrLen$1 = squaredLength$1;
+ /**
+ * Perform some operation over an array of vec4s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+
+ var forEach$1 = function () {
+ var vec = create$5();
+ return function (a, stride, offset, count, fn, arg) {
+ var i, l;
+
+ if (!stride) {
+ stride = 4;
+ }
+
+ if (!offset) {
+ offset = 0;
+ }
+
+ if (count) {
+ l = Math.min(count * stride + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for (i = offset; i < l; i += stride) {
+ vec[0] = a[i];
+ vec[1] = a[i + 1];
+ vec[2] = a[i + 2];
+ vec[3] = a[i + 3];
+ fn(vec, vec, arg);
+ a[i] = vec[0];
+ a[i + 1] = vec[1];
+ a[i + 2] = vec[2];
+ a[i + 3] = vec[3];
+ }
+
+ return a;
+ };
+ }();
+
+ var vec4 = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ create: create$5,
+ clone: clone$5,
+ fromValues: fromValues$5,
+ copy: copy$5,
+ set: set$5,
+ add: add$5,
+ subtract: subtract$5,
+ multiply: multiply$5,
+ divide: divide$1,
+ ceil: ceil$1,
+ floor: floor$1,
+ min: min$1,
+ max: max$1,
+ round: round$1,
+ scale: scale$5,
+ scaleAndAdd: scaleAndAdd$1,
+ distance: distance$1,
+ squaredDistance: squaredDistance$1,
+ length: length$1,
+ squaredLength: squaredLength$1,
+ negate: negate$1,
+ inverse: inverse$1,
+ normalize: normalize$1,
+ dot: dot$1,
+ cross: cross$1,
+ lerp: lerp$1,
+ random: random$1,
+ transformMat4: transformMat4$1,
+ transformQuat: transformQuat$1,
+ zero: zero$1,
+ str: str$5,
+ exactEquals: exactEquals$5,
+ equals: equals$6,
+ sub: sub$5,
+ mul: mul$5,
+ div: div$1,
+ dist: dist$1,
+ sqrDist: sqrDist$1,
+ len: len$1,
+ sqrLen: sqrLen$1,
+ forEach: forEach$1
+ });
+
+ /**
+ * Quaternion
+ * @module quat
+ */
+
+ /**
+ * Creates a new identity quat
+ *
+ * @returns {quat} a new quaternion
+ */
+
+ function create$6() {
+ var out = new ARRAY_TYPE(4);
+
+ if (ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ }
+
+ out[3] = 1;
+ return out;
+ }
+ /**
+ * Set a quat to the identity quaternion
+ *
+ * @param {quat} out the receiving quaternion
+ * @returns {quat} out
+ */
+
+ function identity$4(out) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ }
+ /**
+ * Sets a quat from the given angle and rotation axis,
+ * then returns it.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyVec3} axis the axis around which to rotate
+ * @param {Number} rad the angle in radians
+ * @returns {quat} out
+ **/
+
+ function setAxisAngle(out, axis, rad) {
+ rad = rad * 0.5;
+ var s = Math.sin(rad);
+ out[0] = s * axis[0];
+ out[1] = s * axis[1];
+ out[2] = s * axis[2];
+ out[3] = Math.cos(rad);
+ return out;
+ }
+ /**
+ * Gets the rotation axis and angle for a given
+ * quaternion. If a quaternion is created with
+ * setAxisAngle, this method will return the same
+ * values as providied in the original parameter list
+ * OR functionally equivalent values.
+ * Example: The quaternion formed by axis [0, 0, 1] and
+ * angle -90 is the same as the quaternion formed by
+ * [0, 0, 1] and 270. This method favors the latter.
+ * @param {vec3} out_axis Vector receiving the axis of rotation
+ * @param {ReadonlyQuat} q Quaternion to be decomposed
+ * @return {Number} Angle, in radians, of the rotation
+ */
+
+ function getAxisAngle(out_axis, q) {
+ var rad = Math.acos(q[3]) * 2.0;
+ var s = Math.sin(rad / 2.0);
+
+ if (s > EPSILON) {
+ out_axis[0] = q[0] / s;
+ out_axis[1] = q[1] / s;
+ out_axis[2] = q[2] / s;
+ } else {
+ // If s is zero, return any axis (no rotation - axis does not matter)
+ out_axis[0] = 1;
+ out_axis[1] = 0;
+ out_axis[2] = 0;
+ }
+
+ return rad;
+ }
+ /**
+ * Gets the angular distance between two unit quaternions
+ *
+ * @param {ReadonlyQuat} a Origin unit quaternion
+ * @param {ReadonlyQuat} b Destination unit quaternion
+ * @return {Number} Angle, in radians, between the two quaternions
+ */
+
+ function getAngle(a, b) {
+ var dotproduct = dot$2(a, b);
+ return Math.acos(2 * dotproduct * dotproduct - 1);
+ }
+ /**
+ * Multiplies two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {quat} out
+ */
+
+ function multiply$6(out, a, b) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bx = b[0],
+ by = b[1],
+ bz = b[2],
+ bw = b[3];
+ out[0] = ax * bw + aw * bx + ay * bz - az * by;
+ out[1] = ay * bw + aw * by + az * bx - ax * bz;
+ out[2] = az * bw + aw * bz + ax * by - ay * bx;
+ out[3] = aw * bw - ax * bx - ay * by - az * bz;
+ return out;
+ }
+ /**
+ * Rotates a quaternion by the given angle about the X axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+
+ function rotateX$2(out, a, rad) {
+ rad *= 0.5;
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bx = Math.sin(rad),
+ bw = Math.cos(rad);
+ out[0] = ax * bw + aw * bx;
+ out[1] = ay * bw + az * bx;
+ out[2] = az * bw - ay * bx;
+ out[3] = aw * bw - ax * bx;
+ return out;
+ }
+ /**
+ * Rotates a quaternion by the given angle about the Y axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+
+ function rotateY$2(out, a, rad) {
+ rad *= 0.5;
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var by = Math.sin(rad),
+ bw = Math.cos(rad);
+ out[0] = ax * bw - az * by;
+ out[1] = ay * bw + aw * by;
+ out[2] = az * bw + ax * by;
+ out[3] = aw * bw - ay * by;
+ return out;
+ }
+ /**
+ * Rotates a quaternion by the given angle about the Z axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+
+ function rotateZ$2(out, a, rad) {
+ rad *= 0.5;
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bz = Math.sin(rad),
+ bw = Math.cos(rad);
+ out[0] = ax * bw + ay * bz;
+ out[1] = ay * bw - ax * bz;
+ out[2] = az * bw + aw * bz;
+ out[3] = aw * bw - az * bz;
+ return out;
+ }
+ /**
+ * Calculates the W component of a quat from the X, Y, and Z components.
+ * Assumes that quaternion is 1 unit in length.
+ * Any existing W component will be ignored.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate W component of
+ * @returns {quat} out
+ */
+
+ function calculateW(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
+ return out;
+ }
+ /**
+ * Calculate the exponential of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @returns {quat} out
+ */
+
+ function exp(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ var r = Math.sqrt(x * x + y * y + z * z);
+ var et = Math.exp(w);
+ var s = r > 0 ? et * Math.sin(r) / r : 0;
+ out[0] = x * s;
+ out[1] = y * s;
+ out[2] = z * s;
+ out[3] = et * Math.cos(r);
+ return out;
+ }
+ /**
+ * Calculate the natural logarithm of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @returns {quat} out
+ */
+
+ function ln(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ var r = Math.sqrt(x * x + y * y + z * z);
+ var t = r > 0 ? Math.atan2(r, w) / r : 0;
+ out[0] = x * t;
+ out[1] = y * t;
+ out[2] = z * t;
+ out[3] = 0.5 * Math.log(x * x + y * y + z * z + w * w);
+ return out;
+ }
+ /**
+ * Calculate the scalar power of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @param {Number} b amount to scale the quaternion by
+ * @returns {quat} out
+ */
+
+ function pow(out, a, b) {
+ ln(out, a);
+ scale$6(out, out, b);
+ exp(out, out);
+ return out;
+ }
+ /**
+ * Performs a spherical linear interpolation between two quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ */
+
+ function slerp(out, a, b, t) {
+ // benchmarks:
+ // http://jsperf.com/quaternion-slerp-implementations
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ var bx = b[0],
+ by = b[1],
+ bz = b[2],
+ bw = b[3];
+ var omega, cosom, sinom, scale0, scale1; // calc cosine
+
+ cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary)
+
+ if (cosom < 0.0) {
+ cosom = -cosom;
+ bx = -bx;
+ by = -by;
+ bz = -bz;
+ bw = -bw;
+ } // calculate coefficients
+
+
+ if (1.0 - cosom > EPSILON) {
+ // standard case (slerp)
+ omega = Math.acos(cosom);
+ sinom = Math.sin(omega);
+ scale0 = Math.sin((1.0 - t) * omega) / sinom;
+ scale1 = Math.sin(t * omega) / sinom;
+ } else {
+ // "from" and "to" quaternions are very close
+ // ... so we can do a linear interpolation
+ scale0 = 1.0 - t;
+ scale1 = t;
+ } // calculate final values
+
+
+ out[0] = scale0 * ax + scale1 * bx;
+ out[1] = scale0 * ay + scale1 * by;
+ out[2] = scale0 * az + scale1 * bz;
+ out[3] = scale0 * aw + scale1 * bw;
+ return out;
+ }
+ /**
+ * Generates a random unit quaternion
+ *
+ * @param {quat} out the receiving quaternion
+ * @returns {quat} out
+ */
+
+ function random$2(out) {
+ // Implementation of http://planning.cs.uiuc.edu/node198.html
+ // TODO: Calling random 3 times is probably not the fastest solution
+ var u1 = RANDOM();
+ var u2 = RANDOM();
+ var u3 = RANDOM();
+ var sqrt1MinusU1 = Math.sqrt(1 - u1);
+ var sqrtU1 = Math.sqrt(u1);
+ out[0] = sqrt1MinusU1 * Math.sin(2.0 * Math.PI * u2);
+ out[1] = sqrt1MinusU1 * Math.cos(2.0 * Math.PI * u2);
+ out[2] = sqrtU1 * Math.sin(2.0 * Math.PI * u3);
+ out[3] = sqrtU1 * Math.cos(2.0 * Math.PI * u3);
+ return out;
+ }
+ /**
+ * Calculates the inverse of a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate inverse of
+ * @returns {quat} out
+ */
+
+ function invert$4(out, a) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3];
+ var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
+ var invDot = dot ? 1.0 / dot : 0; // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
+
+ out[0] = -a0 * invDot;
+ out[1] = -a1 * invDot;
+ out[2] = -a2 * invDot;
+ out[3] = a3 * invDot;
+ return out;
+ }
+ /**
+ * Calculates the conjugate of a quat
+ * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate conjugate of
+ * @returns {quat} out
+ */
+
+ function conjugate(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a[3];
+ return out;
+ }
+ /**
+ * Creates a quaternion from the given 3x3 rotation matrix.
+ *
+ * NOTE: The resultant quaternion is not normalized, so you should be sure
+ * to renormalize the quaternion yourself where necessary.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyMat3} m rotation matrix
+ * @returns {quat} out
+ * @function
+ */
+
+ function fromMat3(out, m) {
+ // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
+ // article "Quaternion Calculus and Fast Animation".
+ var fTrace = m[0] + m[4] + m[8];
+ var fRoot;
+
+ if (fTrace > 0.0) {
+ // |w| > 1/2, may as well choose w > 1/2
+ fRoot = Math.sqrt(fTrace + 1.0); // 2w
+
+ out[3] = 0.5 * fRoot;
+ fRoot = 0.5 / fRoot; // 1/(4w)
+
+ out[0] = (m[5] - m[7]) * fRoot;
+ out[1] = (m[6] - m[2]) * fRoot;
+ out[2] = (m[1] - m[3]) * fRoot;
+ } else {
+ // |w| <= 1/2
+ var i = 0;
+ if (m[4] > m[0]) i = 1;
+ if (m[8] > m[i * 3 + i]) i = 2;
+ var j = (i + 1) % 3;
+ var k = (i + 2) % 3;
+ fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0);
+ out[i] = 0.5 * fRoot;
+ fRoot = 0.5 / fRoot;
+ out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot;
+ out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;
+ out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;
+ }
+
+ return out;
+ }
+ /**
+ * Creates a quaternion from the given euler angle x, y, z.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {x} Angle to rotate around X axis in degrees.
+ * @param {y} Angle to rotate around Y axis in degrees.
+ * @param {z} Angle to rotate around Z axis in degrees.
+ * @returns {quat} out
+ * @function
+ */
+
+ function fromEuler(out, x, y, z) {
+ var halfToRad = 0.5 * Math.PI / 180.0;
+ x *= halfToRad;
+ y *= halfToRad;
+ z *= halfToRad;
+ var sx = Math.sin(x);
+ var cx = Math.cos(x);
+ var sy = Math.sin(y);
+ var cy = Math.cos(y);
+ var sz = Math.sin(z);
+ var cz = Math.cos(z);
+ out[0] = sx * cy * cz - cx * sy * sz;
+ out[1] = cx * sy * cz + sx * cy * sz;
+ out[2] = cx * cy * sz - sx * sy * cz;
+ out[3] = cx * cy * cz + sx * sy * sz;
+ return out;
+ }
+ /**
+ * Returns a string representation of a quatenion
+ *
+ * @param {ReadonlyQuat} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+ function str$6(a) {
+ return "quat(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")";
+ }
+ /**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {ReadonlyQuat} a quaternion to clone
+ * @returns {quat} a new quaternion
+ * @function
+ */
+
+ var clone$6 = clone$5;
+ /**
+ * Creates a new quat initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} a new quaternion
+ * @function
+ */
+
+ var fromValues$6 = fromValues$5;
+ /**
+ * Copy the values from one quat to another
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the source quaternion
+ * @returns {quat} out
+ * @function
+ */
+
+ var copy$6 = copy$5;
+ /**
+ * Set the components of a quat to the given values
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} out
+ * @function
+ */
+
+ var set$6 = set$5;
+ /**
+ * Adds two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {quat} out
+ * @function
+ */
+
+ var add$6 = add$5;
+ /**
+ * Alias for {@link quat.multiply}
+ * @function
+ */
+
+ var mul$6 = multiply$6;
+ /**
+ * Scales a quat by a scalar number
+ *
+ * @param {quat} out the receiving vector
+ * @param {ReadonlyQuat} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {quat} out
+ * @function
+ */
+
+ var scale$6 = scale$5;
+ /**
+ * Calculates the dot product of two quat's
+ *
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+
+ var dot$2 = dot$1;
+ /**
+ * Performs a linear interpolation between two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ * @function
+ */
+
+ var lerp$2 = lerp$1;
+ /**
+ * Calculates the length of a quat
+ *
+ * @param {ReadonlyQuat} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+ var length$2 = length$1;
+ /**
+ * Alias for {@link quat.length}
+ * @function
+ */
+
+ var len$2 = length$2;
+ /**
+ * Calculates the squared length of a quat
+ *
+ * @param {ReadonlyQuat} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+
+ var squaredLength$2 = squaredLength$1;
+ /**
+ * Alias for {@link quat.squaredLength}
+ * @function
+ */
+
+ var sqrLen$2 = squaredLength$2;
+ /**
+ * Normalize a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quaternion to normalize
+ * @returns {quat} out
+ * @function
+ */
+
+ var normalize$2 = normalize$1;
+ /**
+ * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyQuat} a The first quaternion.
+ * @param {ReadonlyQuat} b The second quaternion.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+ var exactEquals$6 = exactEquals$5;
+ /**
+ * Returns whether or not the quaternions have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyQuat} a The first vector.
+ * @param {ReadonlyQuat} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+ var equals$7 = equals$6;
+ /**
+ * Sets a quaternion to represent the shortest rotation from one
+ * vector to another.
+ *
+ * Both vectors are assumed to be unit length.
+ *
+ * @param {quat} out the receiving quaternion.
+ * @param {ReadonlyVec3} a the initial vector
+ * @param {ReadonlyVec3} b the destination vector
+ * @returns {quat} out
+ */
+
+ var rotationTo = function () {
+ var tmpvec3 = create$4();
+ var xUnitVec3 = fromValues$4(1, 0, 0);
+ var yUnitVec3 = fromValues$4(0, 1, 0);
+ return function (out, a, b) {
+ var dot$1 = dot(a, b);
+
+ if (dot$1 < -0.999999) {
+ cross(tmpvec3, xUnitVec3, a);
+ if (len(tmpvec3) < 0.000001) cross(tmpvec3, yUnitVec3, a);
+ normalize(tmpvec3, tmpvec3);
+ setAxisAngle(out, tmpvec3, Math.PI);
+ return out;
+ } else if (dot$1 > 0.999999) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ } else {
+ cross(tmpvec3, a, b);
+ out[0] = tmpvec3[0];
+ out[1] = tmpvec3[1];
+ out[2] = tmpvec3[2];
+ out[3] = 1 + dot$1;
+ return normalize$2(out, out);
+ }
+ };
+ }();
+ /**
+ * Performs a spherical linear interpolation with two control points
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {ReadonlyQuat} c the third operand
+ * @param {ReadonlyQuat} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ */
+
+ var sqlerp = function () {
+ var temp1 = create$6();
+ var temp2 = create$6();
+ return function (out, a, b, c, d, t) {
+ slerp(temp1, a, d, t);
+ slerp(temp2, b, c, t);
+ slerp(out, temp1, temp2, 2 * t * (1 - t));
+ return out;
+ };
+ }();
+ /**
+ * Sets the specified quaternion with values corresponding to the given
+ * axes. Each axis is a vec3 and is expected to be unit length and
+ * perpendicular to all other specified axes.
+ *
+ * @param {ReadonlyVec3} view the vector representing the viewing direction
+ * @param {ReadonlyVec3} right the vector representing the local "right" direction
+ * @param {ReadonlyVec3} up the vector representing the local "up" direction
+ * @returns {quat} out
+ */
+
+ var setAxes = function () {
+ var matr = create$2();
+ return function (out, view, right, up) {
+ matr[0] = right[0];
+ matr[3] = right[1];
+ matr[6] = right[2];
+ matr[1] = up[0];
+ matr[4] = up[1];
+ matr[7] = up[2];
+ matr[2] = -view[0];
+ matr[5] = -view[1];
+ matr[8] = -view[2];
+ return normalize$2(out, fromMat3(out, matr));
+ };
+ }();
+
+ var quat = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ create: create$6,
+ identity: identity$4,
+ setAxisAngle: setAxisAngle,
+ getAxisAngle: getAxisAngle,
+ getAngle: getAngle,
+ multiply: multiply$6,
+ rotateX: rotateX$2,
+ rotateY: rotateY$2,
+ rotateZ: rotateZ$2,
+ calculateW: calculateW,
+ exp: exp,
+ ln: ln,
+ pow: pow,
+ slerp: slerp,
+ random: random$2,
+ invert: invert$4,
+ conjugate: conjugate,
+ fromMat3: fromMat3,
+ fromEuler: fromEuler,
+ str: str$6,
+ clone: clone$6,
+ fromValues: fromValues$6,
+ copy: copy$6,
+ set: set$6,
+ add: add$6,
+ mul: mul$6,
+ scale: scale$6,
+ dot: dot$2,
+ lerp: lerp$2,
+ length: length$2,
+ len: len$2,
+ squaredLength: squaredLength$2,
+ sqrLen: sqrLen$2,
+ normalize: normalize$2,
+ exactEquals: exactEquals$6,
+ equals: equals$7,
+ rotationTo: rotationTo,
+ sqlerp: sqlerp,
+ setAxes: setAxes
+ });
+
+ /**
+ * Dual Quaternion
+ * Format: [real, dual]
+ * Quaternion format: XYZW
+ * Make sure to have normalized dual quaternions, otherwise the functions may not work as intended.
+ * @module quat2
+ */
+
+ /**
+ * Creates a new identity dual quat
+ *
+ * @returns {quat2} a new dual quaternion [real -> rotation, dual -> translation]
+ */
+
+ function create$7() {
+ var dq = new ARRAY_TYPE(8);
+
+ if (ARRAY_TYPE != Float32Array) {
+ dq[0] = 0;
+ dq[1] = 0;
+ dq[2] = 0;
+ dq[4] = 0;
+ dq[5] = 0;
+ dq[6] = 0;
+ dq[7] = 0;
+ }
+
+ dq[3] = 1;
+ return dq;
+ }
+ /**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {ReadonlyQuat2} a dual quaternion to clone
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+
+ function clone$7(a) {
+ var dq = new ARRAY_TYPE(8);
+ dq[0] = a[0];
+ dq[1] = a[1];
+ dq[2] = a[2];
+ dq[3] = a[3];
+ dq[4] = a[4];
+ dq[5] = a[5];
+ dq[6] = a[6];
+ dq[7] = a[7];
+ return dq;
+ }
+ /**
+ * Creates a new dual quat initialized with the given values
+ *
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component
+ * @param {Number} y2 Y component
+ * @param {Number} z2 Z component
+ * @param {Number} w2 W component
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+
+ function fromValues$7(x1, y1, z1, w1, x2, y2, z2, w2) {
+ var dq = new ARRAY_TYPE(8);
+ dq[0] = x1;
+ dq[1] = y1;
+ dq[2] = z1;
+ dq[3] = w1;
+ dq[4] = x2;
+ dq[5] = y2;
+ dq[6] = z2;
+ dq[7] = w2;
+ return dq;
+ }
+ /**
+ * Creates a new dual quat from the given values (quat and translation)
+ *
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component (translation)
+ * @param {Number} y2 Y component (translation)
+ * @param {Number} z2 Z component (translation)
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+
+ function fromRotationTranslationValues(x1, y1, z1, w1, x2, y2, z2) {
+ var dq = new ARRAY_TYPE(8);
+ dq[0] = x1;
+ dq[1] = y1;
+ dq[2] = z1;
+ dq[3] = w1;
+ var ax = x2 * 0.5,
+ ay = y2 * 0.5,
+ az = z2 * 0.5;
+ dq[4] = ax * w1 + ay * z1 - az * y1;
+ dq[5] = ay * w1 + az * x1 - ax * z1;
+ dq[6] = az * w1 + ax * y1 - ay * x1;
+ dq[7] = -ax * x1 - ay * y1 - az * z1;
+ return dq;
+ }
+ /**
+ * Creates a dual quat from a quaternion and a translation
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyQuat} q a normalized quaternion
+ * @param {ReadonlyVec3} t tranlation vector
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+
+ function fromRotationTranslation$1(out, q, t) {
+ var ax = t[0] * 0.5,
+ ay = t[1] * 0.5,
+ az = t[2] * 0.5,
+ bx = q[0],
+ by = q[1],
+ bz = q[2],
+ bw = q[3];
+ out[0] = bx;
+ out[1] = by;
+ out[2] = bz;
+ out[3] = bw;
+ out[4] = ax * bw + ay * bz - az * by;
+ out[5] = ay * bw + az * bx - ax * bz;
+ out[6] = az * bw + ax * by - ay * bx;
+ out[7] = -ax * bx - ay * by - az * bz;
+ return out;
+ }
+ /**
+ * Creates a dual quat from a translation
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyVec3} t translation vector
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+
+ function fromTranslation$3(out, t) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = t[0] * 0.5;
+ out[5] = t[1] * 0.5;
+ out[6] = t[2] * 0.5;
+ out[7] = 0;
+ return out;
+ }
+ /**
+ * Creates a dual quat from a quaternion
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyQuat} q the quaternion
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+
+ function fromRotation$4(out, q) {
+ out[0] = q[0];
+ out[1] = q[1];
+ out[2] = q[2];
+ out[3] = q[3];
+ out[4] = 0;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ return out;
+ }
+ /**
+ * Creates a new dual quat from a matrix (4x4)
+ *
+ * @param {quat2} out the dual quaternion
+ * @param {ReadonlyMat4} a the matrix
+ * @returns {quat2} dual quat receiving operation result
+ * @function
+ */
+
+ function fromMat4$1(out, a) {
+ //TODO Optimize this
+ var outer = create$6();
+ getRotation(outer, a);
+ var t = new ARRAY_TYPE(3);
+ getTranslation(t, a);
+ fromRotationTranslation$1(out, outer, t);
+ return out;
+ }
+ /**
+ * Copy the values from one dual quat to another
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the source dual quaternion
+ * @returns {quat2} out
+ * @function
+ */
+
+ function copy$7(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ return out;
+ }
+ /**
+ * Set a dual quat to the identity dual quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @returns {quat2} out
+ */
+
+ function identity$5(out) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = 0;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ return out;
+ }
+ /**
+ * Set the components of a dual quat to the given values
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component
+ * @param {Number} y2 Y component
+ * @param {Number} z2 Z component
+ * @param {Number} w2 W component
+ * @returns {quat2} out
+ * @function
+ */
+
+ function set$7(out, x1, y1, z1, w1, x2, y2, z2, w2) {
+ out[0] = x1;
+ out[1] = y1;
+ out[2] = z1;
+ out[3] = w1;
+ out[4] = x2;
+ out[5] = y2;
+ out[6] = z2;
+ out[7] = w2;
+ return out;
+ }
+ /**
+ * Gets the real part of a dual quat
+ * @param {quat} out real part
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @return {quat} real part
+ */
+
+ var getReal = copy$6;
+ /**
+ * Gets the dual part of a dual quat
+ * @param {quat} out dual part
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @return {quat} dual part
+ */
+
+ function getDual(out, a) {
+ out[0] = a[4];
+ out[1] = a[5];
+ out[2] = a[6];
+ out[3] = a[7];
+ return out;
+ }
+ /**
+ * Set the real component of a dual quat to the given quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat} q a quaternion representing the real part
+ * @returns {quat2} out
+ * @function
+ */
+
+ var setReal = copy$6;
+ /**
+ * Set the dual component of a dual quat to the given quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat} q a quaternion representing the dual part
+ * @returns {quat2} out
+ * @function
+ */
+
+ function setDual(out, q) {
+ out[4] = q[0];
+ out[5] = q[1];
+ out[6] = q[2];
+ out[7] = q[3];
+ return out;
+ }
+ /**
+ * Gets the translation of a normalized dual quat
+ * @param {vec3} out translation
+ * @param {ReadonlyQuat2} a Dual Quaternion to be decomposed
+ * @return {vec3} translation
+ */
+
+ function getTranslation$1(out, a) {
+ var ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3];
+ out[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
+ out[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
+ out[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
+ return out;
+ }
+ /**
+ * Translates a dual quat by the given vector
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to translate
+ * @param {ReadonlyVec3} v vector to translate by
+ * @returns {quat2} out
+ */
+
+ function translate$3(out, a, v) {
+ var ax1 = a[0],
+ ay1 = a[1],
+ az1 = a[2],
+ aw1 = a[3],
+ bx1 = v[0] * 0.5,
+ by1 = v[1] * 0.5,
+ bz1 = v[2] * 0.5,
+ ax2 = a[4],
+ ay2 = a[5],
+ az2 = a[6],
+ aw2 = a[7];
+ out[0] = ax1;
+ out[1] = ay1;
+ out[2] = az1;
+ out[3] = aw1;
+ out[4] = aw1 * bx1 + ay1 * bz1 - az1 * by1 + ax2;
+ out[5] = aw1 * by1 + az1 * bx1 - ax1 * bz1 + ay2;
+ out[6] = aw1 * bz1 + ax1 * by1 - ay1 * bx1 + az2;
+ out[7] = -ax1 * bx1 - ay1 * by1 - az1 * bz1 + aw2;
+ return out;
+ }
+ /**
+ * Rotates a dual quat around the X axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+
+ function rotateX$3(out, a, rad) {
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ ax1 = ax * bw + aw * bx + ay * bz - az * by,
+ ay1 = ay * bw + aw * by + az * bx - ax * bz,
+ az1 = az * bw + aw * bz + ax * by - ay * bx,
+ aw1 = aw * bw - ax * bx - ay * by - az * bz;
+ rotateX$2(out, a, rad);
+ bx = out[0];
+ by = out[1];
+ bz = out[2];
+ bw = out[3];
+ out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ return out;
+ }
+ /**
+ * Rotates a dual quat around the Y axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+
+ function rotateY$3(out, a, rad) {
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ ax1 = ax * bw + aw * bx + ay * bz - az * by,
+ ay1 = ay * bw + aw * by + az * bx - ax * bz,
+ az1 = az * bw + aw * bz + ax * by - ay * bx,
+ aw1 = aw * bw - ax * bx - ay * by - az * bz;
+ rotateY$2(out, a, rad);
+ bx = out[0];
+ by = out[1];
+ bz = out[2];
+ bw = out[3];
+ out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ return out;
+ }
+ /**
+ * Rotates a dual quat around the Z axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+
+ function rotateZ$3(out, a, rad) {
+ var bx = -a[0],
+ by = -a[1],
+ bz = -a[2],
+ bw = a[3],
+ ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7],
+ ax1 = ax * bw + aw * bx + ay * bz - az * by,
+ ay1 = ay * bw + aw * by + az * bx - ax * bz,
+ az1 = az * bw + aw * bz + ax * by - ay * bx,
+ aw1 = aw * bw - ax * bx - ay * by - az * bz;
+ rotateZ$2(out, a, rad);
+ bx = out[0];
+ by = out[1];
+ bz = out[2];
+ bw = out[3];
+ out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ return out;
+ }
+ /**
+ * Rotates a dual quat by a given quaternion (a * q)
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {ReadonlyQuat} q quaternion to rotate by
+ * @returns {quat2} out
+ */
+
+ function rotateByQuatAppend(out, a, q) {
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3],
+ ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ out[0] = ax * qw + aw * qx + ay * qz - az * qy;
+ out[1] = ay * qw + aw * qy + az * qx - ax * qz;
+ out[2] = az * qw + aw * qz + ax * qy - ay * qx;
+ out[3] = aw * qw - ax * qx - ay * qy - az * qz;
+ ax = a[4];
+ ay = a[5];
+ az = a[6];
+ aw = a[7];
+ out[4] = ax * qw + aw * qx + ay * qz - az * qy;
+ out[5] = ay * qw + aw * qy + az * qx - ax * qz;
+ out[6] = az * qw + aw * qz + ax * qy - ay * qx;
+ out[7] = aw * qw - ax * qx - ay * qy - az * qz;
+ return out;
+ }
+ /**
+ * Rotates a dual quat by a given quaternion (q * a)
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat} q quaternion to rotate by
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @returns {quat2} out
+ */
+
+ function rotateByQuatPrepend(out, q, a) {
+ var qx = q[0],
+ qy = q[1],
+ qz = q[2],
+ qw = q[3],
+ bx = a[0],
+ by = a[1],
+ bz = a[2],
+ bw = a[3];
+ out[0] = qx * bw + qw * bx + qy * bz - qz * by;
+ out[1] = qy * bw + qw * by + qz * bx - qx * bz;
+ out[2] = qz * bw + qw * bz + qx * by - qy * bx;
+ out[3] = qw * bw - qx * bx - qy * by - qz * bz;
+ bx = a[4];
+ by = a[5];
+ bz = a[6];
+ bw = a[7];
+ out[4] = qx * bw + qw * bx + qy * bz - qz * by;
+ out[5] = qy * bw + qw * by + qz * bx - qx * bz;
+ out[6] = qz * bw + qw * bz + qx * by - qy * bx;
+ out[7] = qw * bw - qx * bx - qy * by - qz * bz;
+ return out;
+ }
+ /**
+ * Rotates a dual quat around a given axis. Does the normalisation automatically
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @param {Number} rad how far the rotation should be
+ * @returns {quat2} out
+ */
+
+ function rotateAroundAxis(out, a, axis, rad) {
+ //Special case for rad = 0
+ if (Math.abs(rad) < EPSILON) {
+ return copy$7(out, a);
+ }
+
+ var axisLength = Math.hypot(axis[0], axis[1], axis[2]);
+ rad = rad * 0.5;
+ var s = Math.sin(rad);
+ var bx = s * axis[0] / axisLength;
+ var by = s * axis[1] / axisLength;
+ var bz = s * axis[2] / axisLength;
+ var bw = Math.cos(rad);
+ var ax1 = a[0],
+ ay1 = a[1],
+ az1 = a[2],
+ aw1 = a[3];
+ out[0] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;
+ out[1] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;
+ out[2] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;
+ out[3] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;
+ var ax = a[4],
+ ay = a[5],
+ az = a[6],
+ aw = a[7];
+ out[4] = ax * bw + aw * bx + ay * bz - az * by;
+ out[5] = ay * bw + aw * by + az * bx - ax * bz;
+ out[6] = az * bw + aw * bz + ax * by - ay * bx;
+ out[7] = aw * bw - ax * bx - ay * by - az * bz;
+ return out;
+ }
+ /**
+ * Adds two dual quat's
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {quat2} out
+ * @function
+ */
+
+ function add$7(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ out[4] = a[4] + b[4];
+ out[5] = a[5] + b[5];
+ out[6] = a[6] + b[6];
+ out[7] = a[7] + b[7];
+ return out;
+ }
+ /**
+ * Multiplies two dual quat's
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {quat2} out
+ */
+
+ function multiply$7(out, a, b) {
+ var ax0 = a[0],
+ ay0 = a[1],
+ az0 = a[2],
+ aw0 = a[3],
+ bx1 = b[4],
+ by1 = b[5],
+ bz1 = b[6],
+ bw1 = b[7],
+ ax1 = a[4],
+ ay1 = a[5],
+ az1 = a[6],
+ aw1 = a[7],
+ bx0 = b[0],
+ by0 = b[1],
+ bz0 = b[2],
+ bw0 = b[3];
+ out[0] = ax0 * bw0 + aw0 * bx0 + ay0 * bz0 - az0 * by0;
+ out[1] = ay0 * bw0 + aw0 * by0 + az0 * bx0 - ax0 * bz0;
+ out[2] = az0 * bw0 + aw0 * bz0 + ax0 * by0 - ay0 * bx0;
+ out[3] = aw0 * bw0 - ax0 * bx0 - ay0 * by0 - az0 * bz0;
+ out[4] = ax0 * bw1 + aw0 * bx1 + ay0 * bz1 - az0 * by1 + ax1 * bw0 + aw1 * bx0 + ay1 * bz0 - az1 * by0;
+ out[5] = ay0 * bw1 + aw0 * by1 + az0 * bx1 - ax0 * bz1 + ay1 * bw0 + aw1 * by0 + az1 * bx0 - ax1 * bz0;
+ out[6] = az0 * bw1 + aw0 * bz1 + ax0 * by1 - ay0 * bx1 + az1 * bw0 + aw1 * bz0 + ax1 * by0 - ay1 * bx0;
+ out[7] = aw0 * bw1 - ax0 * bx1 - ay0 * by1 - az0 * bz1 + aw1 * bw0 - ax1 * bx0 - ay1 * by0 - az1 * bz0;
+ return out;
+ }
+ /**
+ * Alias for {@link quat2.multiply}
+ * @function
+ */
+
+ var mul$7 = multiply$7;
+ /**
+ * Scales a dual quat by a scalar number
+ *
+ * @param {quat2} out the receiving dual quat
+ * @param {ReadonlyQuat2} a the dual quat to scale
+ * @param {Number} b amount to scale the dual quat by
+ * @returns {quat2} out
+ * @function
+ */
+
+ function scale$7(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ out[4] = a[4] * b;
+ out[5] = a[5] * b;
+ out[6] = a[6] * b;
+ out[7] = a[7] * b;
+ return out;
+ }
+ /**
+ * Calculates the dot product of two dual quat's (The dot product of the real parts)
+ *
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+
+ var dot$3 = dot$2;
+ /**
+ * Performs a linear interpolation between two dual quats's
+ * NOTE: The resulting dual quaternions won't always be normalized (The error is most noticeable when t = 0.5)
+ *
+ * @param {quat2} out the receiving dual quat
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat2} out
+ */
+
+ function lerp$3(out, a, b, t) {
+ var mt = 1 - t;
+ if (dot$3(a, b) < 0) t = -t;
+ out[0] = a[0] * mt + b[0] * t;
+ out[1] = a[1] * mt + b[1] * t;
+ out[2] = a[2] * mt + b[2] * t;
+ out[3] = a[3] * mt + b[3] * t;
+ out[4] = a[4] * mt + b[4] * t;
+ out[5] = a[5] * mt + b[5] * t;
+ out[6] = a[6] * mt + b[6] * t;
+ out[7] = a[7] * mt + b[7] * t;
+ return out;
+ }
+ /**
+ * Calculates the inverse of a dual quat. If they are normalized, conjugate is cheaper
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a dual quat to calculate inverse of
+ * @returns {quat2} out
+ */
+
+ function invert$5(out, a) {
+ var sqlen = squaredLength$3(a);
+ out[0] = -a[0] / sqlen;
+ out[1] = -a[1] / sqlen;
+ out[2] = -a[2] / sqlen;
+ out[3] = a[3] / sqlen;
+ out[4] = -a[4] / sqlen;
+ out[5] = -a[5] / sqlen;
+ out[6] = -a[6] / sqlen;
+ out[7] = a[7] / sqlen;
+ return out;
+ }
+ /**
+ * Calculates the conjugate of a dual quat
+ * If the dual quaternion is normalized, this function is faster than quat2.inverse and produces the same result.
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat2} a quat to calculate conjugate of
+ * @returns {quat2} out
+ */
+
+ function conjugate$1(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a[3];
+ out[4] = -a[4];
+ out[5] = -a[5];
+ out[6] = -a[6];
+ out[7] = a[7];
+ return out;
+ }
+ /**
+ * Calculates the length of a dual quat
+ *
+ * @param {ReadonlyQuat2} a dual quat to calculate length of
+ * @returns {Number} length of a
+ * @function
+ */
+
+ var length$3 = length$2;
+ /**
+ * Alias for {@link quat2.length}
+ * @function
+ */
+
+ var len$3 = length$3;
+ /**
+ * Calculates the squared length of a dual quat
+ *
+ * @param {ReadonlyQuat2} a dual quat to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+
+ var squaredLength$3 = squaredLength$2;
+ /**
+ * Alias for {@link quat2.squaredLength}
+ * @function
+ */
+
+ var sqrLen$3 = squaredLength$3;
+ /**
+ * Normalize a dual quat
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a dual quaternion to normalize
+ * @returns {quat2} out
+ * @function
+ */
+
+ function normalize$3(out, a) {
+ var magnitude = squaredLength$3(a);
+
+ if (magnitude > 0) {
+ magnitude = Math.sqrt(magnitude);
+ var a0 = a[0] / magnitude;
+ var a1 = a[1] / magnitude;
+ var a2 = a[2] / magnitude;
+ var a3 = a[3] / magnitude;
+ var b0 = a[4];
+ var b1 = a[5];
+ var b2 = a[6];
+ var b3 = a[7];
+ var a_dot_b = a0 * b0 + a1 * b1 + a2 * b2 + a3 * b3;
+ out[0] = a0;
+ out[1] = a1;
+ out[2] = a2;
+ out[3] = a3;
+ out[4] = (b0 - a0 * a_dot_b) / magnitude;
+ out[5] = (b1 - a1 * a_dot_b) / magnitude;
+ out[6] = (b2 - a2 * a_dot_b) / magnitude;
+ out[7] = (b3 - a3 * a_dot_b) / magnitude;
+ }
+
+ return out;
+ }
+ /**
+ * Returns a string representation of a dual quatenion
+ *
+ * @param {ReadonlyQuat2} a dual quaternion to represent as a string
+ * @returns {String} string representation of the dual quat
+ */
+
+ function str$7(a) {
+ return "quat2(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ")";
+ }
+ /**
+ * Returns whether or not the dual quaternions have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyQuat2} a the first dual quaternion.
+ * @param {ReadonlyQuat2} b the second dual quaternion.
+ * @returns {Boolean} true if the dual quaternions are equal, false otherwise.
+ */
+
+ function exactEquals$7(a, b) {
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7];
+ }
+ /**
+ * Returns whether or not the dual quaternions have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyQuat2} a the first dual quat.
+ * @param {ReadonlyQuat2} b the second dual quat.
+ * @returns {Boolean} true if the dual quats are equal, false otherwise.
+ */
+
+ function equals$8(a, b) {
+ var a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5],
+ a6 = a[6],
+ a7 = a[7];
+ var b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5],
+ b6 = b[6],
+ b7 = b[7];
+ return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7));
+ }
+
+ var quat2 = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ create: create$7,
+ clone: clone$7,
+ fromValues: fromValues$7,
+ fromRotationTranslationValues: fromRotationTranslationValues,
+ fromRotationTranslation: fromRotationTranslation$1,
+ fromTranslation: fromTranslation$3,
+ fromRotation: fromRotation$4,
+ fromMat4: fromMat4$1,
+ copy: copy$7,
+ identity: identity$5,
+ set: set$7,
+ getReal: getReal,
+ getDual: getDual,
+ setReal: setReal,
+ setDual: setDual,
+ getTranslation: getTranslation$1,
+ translate: translate$3,
+ rotateX: rotateX$3,
+ rotateY: rotateY$3,
+ rotateZ: rotateZ$3,
+ rotateByQuatAppend: rotateByQuatAppend,
+ rotateByQuatPrepend: rotateByQuatPrepend,
+ rotateAroundAxis: rotateAroundAxis,
+ add: add$7,
+ multiply: multiply$7,
+ mul: mul$7,
+ scale: scale$7,
+ dot: dot$3,
+ lerp: lerp$3,
+ invert: invert$5,
+ conjugate: conjugate$1,
+ length: length$3,
+ len: len$3,
+ squaredLength: squaredLength$3,
+ sqrLen: sqrLen$3,
+ normalize: normalize$3,
+ str: str$7,
+ exactEquals: exactEquals$7,
+ equals: equals$8
+ });
+
+ /**
+ * 2 Dimensional Vector
+ * @module vec2
+ */
+
+ /**
+ * Creates a new, empty vec2
+ *
+ * @returns {vec2} a new 2D vector
+ */
+
+ function create$8() {
+ var out = new ARRAY_TYPE(2);
+
+ if (ARRAY_TYPE != Float32Array) {
+ out[0] = 0;
+ out[1] = 0;
+ }
+
+ return out;
+ }
+ /**
+ * Creates a new vec2 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec2} a vector to clone
+ * @returns {vec2} a new 2D vector
+ */
+
+ function clone$8(a) {
+ var out = new ARRAY_TYPE(2);
+ out[0] = a[0];
+ out[1] = a[1];
+ return out;
+ }
+ /**
+ * Creates a new vec2 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} a new 2D vector
+ */
+
+ function fromValues$8(x, y) {
+ var out = new ARRAY_TYPE(2);
+ out[0] = x;
+ out[1] = y;
+ return out;
+ }
+ /**
+ * Copy the values from one vec2 to another
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the source vector
+ * @returns {vec2} out
+ */
+
+ function copy$8(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ return out;
+ }
+ /**
+ * Set the components of a vec2 to the given values
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} out
+ */
+
+ function set$8(out, x, y) {
+ out[0] = x;
+ out[1] = y;
+ return out;
+ }
+ /**
+ * Adds two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+ function add$8(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ return out;
+ }
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+ function subtract$6(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ return out;
+ }
+ /**
+ * Multiplies two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+ function multiply$8(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ return out;
+ }
+ /**
+ * Divides two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+ function divide$2(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ return out;
+ }
+ /**
+ * Math.ceil the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to ceil
+ * @returns {vec2} out
+ */
+
+ function ceil$2(out, a) {
+ out[0] = Math.ceil(a[0]);
+ out[1] = Math.ceil(a[1]);
+ return out;
+ }
+ /**
+ * Math.floor the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to floor
+ * @returns {vec2} out
+ */
+
+ function floor$2(out, a) {
+ out[0] = Math.floor(a[0]);
+ out[1] = Math.floor(a[1]);
+ return out;
+ }
+ /**
+ * Returns the minimum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+ function min$2(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ return out;
+ }
+ /**
+ * Returns the maximum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+
+ function max$2(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ return out;
+ }
+ /**
+ * Math.round the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to round
+ * @returns {vec2} out
+ */
+
+ function round$2(out, a) {
+ out[0] = Math.round(a[0]);
+ out[1] = Math.round(a[1]);
+ return out;
+ }
+ /**
+ * Scales a vec2 by a scalar number
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec2} out
+ */
+
+ function scale$8(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ return out;
+ }
+ /**
+ * Adds two vec2's after scaling the second operand by a scalar value
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec2} out
+ */
+
+ function scaleAndAdd$2(out, a, b, scale) {
+ out[0] = a[0] + b[0] * scale;
+ out[1] = a[1] + b[1] * scale;
+ return out;
+ }
+ /**
+ * Calculates the euclidian distance between two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} distance between a and b
+ */
+
+ function distance$2(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1];
+ return Math.hypot(x, y);
+ }
+ /**
+ * Calculates the squared euclidian distance between two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+
+ function squaredDistance$2(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1];
+ return x * x + y * y;
+ }
+ /**
+ * Calculates the length of a vec2
+ *
+ * @param {ReadonlyVec2} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+
+ function length$4(a) {
+ var x = a[0],
+ y = a[1];
+ return Math.hypot(x, y);
+ }
+ /**
+ * Calculates the squared length of a vec2
+ *
+ * @param {ReadonlyVec2} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+
+ function squaredLength$4(a) {
+ var x = a[0],
+ y = a[1];
+ return x * x + y * y;
+ }
+ /**
+ * Negates the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to negate
+ * @returns {vec2} out
+ */
+
+ function negate$2(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ return out;
+ }
+ /**
+ * Returns the inverse of the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to invert
+ * @returns {vec2} out
+ */
+
+ function inverse$2(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ return out;
+ }
+ /**
+ * Normalize a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to normalize
+ * @returns {vec2} out
+ */
+
+ function normalize$4(out, a) {
+ var x = a[0],
+ y = a[1];
+ var len = x * x + y * y;
+
+ if (len > 0) {
+ //TODO: evaluate use of glm_invsqrt here?
+ len = 1 / Math.sqrt(len);
+ }
+
+ out[0] = a[0] * len;
+ out[1] = a[1] * len;
+ return out;
+ }
+ /**
+ * Calculates the dot product of two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+
+ function dot$4(a, b) {
+ return a[0] * b[0] + a[1] * b[1];
+ }
+ /**
+ * Computes the cross product of two vec2's
+ * Note that the cross product must by definition produce a 3D vector
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec3} out
+ */
+
+ function cross$2(out, a, b) {
+ var z = a[0] * b[1] - a[1] * b[0];
+ out[0] = out[1] = 0;
+ out[2] = z;
+ return out;
+ }
+ /**
+ * Performs a linear interpolation between two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec2} out
+ */
+
+ function lerp$4(out, a, b, t) {
+ var ax = a[0],
+ ay = a[1];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ return out;
+ }
+ /**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec2} out
+ */
+
+ function random$3(out, scale) {
+ scale = scale || 1.0;
+ var r = RANDOM() * 2.0 * Math.PI;
+ out[0] = Math.cos(r) * scale;
+ out[1] = Math.sin(r) * scale;
+ return out;
+ }
+ /**
+ * Transforms the vec2 with a mat2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat2} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+ function transformMat2(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[2] * y;
+ out[1] = m[1] * x + m[3] * y;
+ return out;
+ }
+ /**
+ * Transforms the vec2 with a mat2d
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat2d} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+ function transformMat2d(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[2] * y + m[4];
+ out[1] = m[1] * x + m[3] * y + m[5];
+ return out;
+ }
+ /**
+ * Transforms the vec2 with a mat3
+ * 3rd vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat3} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+ function transformMat3$1(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[3] * y + m[6];
+ out[1] = m[1] * x + m[4] * y + m[7];
+ return out;
+ }
+ /**
+ * Transforms the vec2 with a mat4
+ * 3rd vector component is implicitly '0'
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec2} out
+ */
+
+ function transformMat4$2(out, a, m) {
+ var x = a[0];
+ var y = a[1];
+ out[0] = m[0] * x + m[4] * y + m[12];
+ out[1] = m[1] * x + m[5] * y + m[13];
+ return out;
+ }
+ /**
+ * Rotate a 2D vector
+ * @param {vec2} out The receiving vec2
+ * @param {ReadonlyVec2} a The vec2 point to rotate
+ * @param {ReadonlyVec2} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec2} out
+ */
+
+ function rotate$4(out, a, b, rad) {
+ //Translate point to the origin
+ var p0 = a[0] - b[0],
+ p1 = a[1] - b[1],
+ sinC = Math.sin(rad),
+ cosC = Math.cos(rad); //perform rotation and translate to correct position
+
+ out[0] = p0 * cosC - p1 * sinC + b[0];
+ out[1] = p0 * sinC + p1 * cosC + b[1];
+ return out;
+ }
+ /**
+ * Get the angle between two 2D vectors
+ * @param {ReadonlyVec2} a The first operand
+ * @param {ReadonlyVec2} b The second operand
+ * @returns {Number} The angle in radians
+ */
+
+ function angle$1(a, b) {
+ var x1 = a[0],
+ y1 = a[1],
+ x2 = b[0],
+ y2 = b[1],
+ // mag is the product of the magnitudes of a and b
+ mag = Math.sqrt(x1 * x1 + y1 * y1) * Math.sqrt(x2 * x2 + y2 * y2),
+ // mag &&.. short circuits if mag == 0
+ cosine = mag && (x1 * x2 + y1 * y2) / mag; // Math.min(Math.max(cosine, -1), 1) clamps the cosine between -1 and 1
+
+ return Math.acos(Math.min(Math.max(cosine, -1), 1));
+ }
+ /**
+ * Set the components of a vec2 to zero
+ *
+ * @param {vec2} out the receiving vector
+ * @returns {vec2} out
+ */
+
+ function zero$2(out) {
+ out[0] = 0.0;
+ out[1] = 0.0;
+ return out;
+ }
+ /**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec2} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+
+ function str$8(a) {
+ return "vec2(" + a[0] + ", " + a[1] + ")";
+ }
+ /**
+ * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec2} a The first vector.
+ * @param {ReadonlyVec2} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+ function exactEquals$8(a, b) {
+ return a[0] === b[0] && a[1] === b[1];
+ }
+ /**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec2} a The first vector.
+ * @param {ReadonlyVec2} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+
+ function equals$9(a, b) {
+ var a0 = a[0],
+ a1 = a[1];
+ var b0 = b[0],
+ b1 = b[1];
+ return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1));
+ }
+ /**
+ * Alias for {@link vec2.length}
+ * @function
+ */
+
+ var len$4 = length$4;
+ /**
+ * Alias for {@link vec2.subtract}
+ * @function
+ */
+
+ var sub$6 = subtract$6;
+ /**
+ * Alias for {@link vec2.multiply}
+ * @function
+ */
+
+ var mul$8 = multiply$8;
+ /**
+ * Alias for {@link vec2.divide}
+ * @function
+ */
+
+ var div$2 = divide$2;
+ /**
+ * Alias for {@link vec2.distance}
+ * @function
+ */
+
+ var dist$2 = distance$2;
+ /**
+ * Alias for {@link vec2.squaredDistance}
+ * @function
+ */
+
+ var sqrDist$2 = squaredDistance$2;
+ /**
+ * Alias for {@link vec2.squaredLength}
+ * @function
+ */
+
+ var sqrLen$4 = squaredLength$4;
+ /**
+ * Perform some operation over an array of vec2s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+
+ var forEach$2 = function () {
+ var vec = create$8();
+ return function (a, stride, offset, count, fn, arg) {
+ var i, l;
+
+ if (!stride) {
+ stride = 2;
+ }
+
+ if (!offset) {
+ offset = 0;
+ }
+
+ if (count) {
+ l = Math.min(count * stride + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for (i = offset; i < l; i += stride) {
+ vec[0] = a[i];
+ vec[1] = a[i + 1];
+ fn(vec, vec, arg);
+ a[i] = vec[0];
+ a[i + 1] = vec[1];
+ }
+
+ return a;
+ };
+ }();
+
+ var vec2 = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ create: create$8,
+ clone: clone$8,
+ fromValues: fromValues$8,
+ copy: copy$8,
+ set: set$8,
+ add: add$8,
+ subtract: subtract$6,
+ multiply: multiply$8,
+ divide: divide$2,
+ ceil: ceil$2,
+ floor: floor$2,
+ min: min$2,
+ max: max$2,
+ round: round$2,
+ scale: scale$8,
+ scaleAndAdd: scaleAndAdd$2,
+ distance: distance$2,
+ squaredDistance: squaredDistance$2,
+ length: length$4,
+ squaredLength: squaredLength$4,
+ negate: negate$2,
+ inverse: inverse$2,
+ normalize: normalize$4,
+ dot: dot$4,
+ cross: cross$2,
+ lerp: lerp$4,
+ random: random$3,
+ transformMat2: transformMat2,
+ transformMat2d: transformMat2d,
+ transformMat3: transformMat3$1,
+ transformMat4: transformMat4$2,
+ rotate: rotate$4,
+ angle: angle$1,
+ zero: zero$2,
+ str: str$8,
+ exactEquals: exactEquals$8,
+ equals: equals$9,
+ len: len$4,
+ sub: sub$6,
+ mul: mul$8,
+ div: div$2,
+ dist: dist$2,
+ sqrDist: sqrDist$2,
+ sqrLen: sqrLen$4,
+ forEach: forEach$2
+ });
+
+ exports.glMatrix = common;
+ exports.mat2 = mat2;
+ exports.mat2d = mat2d;
+ exports.mat3 = mat3;
+ exports.mat4 = mat4;
+ exports.quat = quat;
+ exports.quat2 = quat2;
+ exports.vec2 = vec2;
+ exports.vec3 = vec3;
+ exports.vec4 = vec4;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/public/node_modules/gl-matrix/index.d.ts b/public/node_modules/gl-matrix/index.d.ts
new file mode 100644
index 0000000..d8a7b01
--- /dev/null
+++ b/public/node_modules/gl-matrix/index.d.ts
@@ -0,0 +1,3273 @@
+declare module "gl-matrix" {
+
+// prettier-ignore
+export type mat2 =
+ | [number, number,
+ number, number]
+ | Float32Array;
+
+// prettier-ignore
+export type mat2d =
+ | [number, number,
+ number, number,
+ number, number]
+ | Float32Array;
+
+// prettier-ignore
+export type mat3 =
+ | [number, number, number,
+ number, number, number,
+ number, number, number]
+ | Float32Array;
+
+// prettier-ignore
+export type mat4 =
+ | [number, number, number, number,
+ number, number, number, number,
+ number, number, number, number,
+ number, number, number, number]
+ | Float32Array;
+
+export type quat = [number, number, number, number] | Float32Array;
+
+// prettier-ignore
+export type quat2 =
+ | [number, number, number, number,
+ number, number, number, number]
+ | Float32Array;
+
+export type vec2 = [number, number] | Float32Array;
+export type vec3 = [number, number, number] | Float32Array;
+export type vec4 = [number, number, number, number] | Float32Array;
+
+// prettier-ignore
+export type ReadonlyMat2 =
+ | readonly [
+ number, number,
+ number, number
+ ]
+ | Float32Array;
+
+// prettier-ignore
+export type ReadonlyMat2d =
+ | readonly [
+ number, number,
+ number, number,
+ number, number
+ ]
+ | Float32Array;
+
+// prettier-ignore
+export type ReadonlyMat3 =
+ | readonly [
+ number, number, number,
+ number, number, number,
+ number, number, number
+ ]
+ | Float32Array;
+
+// prettier-ignore
+export type ReadonlyMat4 =
+ | readonly [
+ number, number, number, number,
+ number, number, number, number,
+ number, number, number, number,
+ number, number, number, number
+ ]
+ | Float32Array;
+
+export type ReadonlyQuat =
+ | readonly [number, number, number, number]
+ | Float32Array;
+
+export type ReadonlyQuat2 =
+ | readonly [number, number, number, number, number, number, number, number]
+ | Float32Array;
+
+export type ReadonlyVec2 = readonly [number, number] | Float32Array;
+export type ReadonlyVec3 = readonly [number, number, number] | Float32Array;
+export type ReadonlyVec4 =
+ | readonly [number, number, number, number]
+ | Float32Array;
+
+export module glMatrix {
+ /**
+ * Sets the type of array used when creating new vectors and matrices
+ *
+ * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array
+ */
+ export function setMatrixArrayType(type: ArrayConstructor | Float32ArrayConstructor): void;
+ /**
+ * Convert Degree To Radian
+ *
+ * @param {Number} a Angle in Degrees
+ */
+ export function toRadian(a: number): number;
+ /**
+ * Tests whether or not the arguments have approximately the same value, within an absolute
+ * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less
+ * than or equal to 1.0, and a relative tolerance is used for larger values)
+ *
+ * @param {Number} a The first number to test.
+ * @param {Number} b The second number to test.
+ * @returns {Boolean} True if the numbers are approximately equal, false otherwise.
+ */
+ export function equals(a: number, b: number): boolean;
+ /**
+ * Common utilities
+ * @module glMatrix
+ */
+ export const EPSILON: 0.000001;
+ export let ARRAY_TYPE: ArrayConstructor | Float32ArrayConstructor;
+ export const RANDOM: () => number;
+}
+export module mat2 {
+ /**
+ * 2x2 Matrix
+ * @module mat2
+ */
+ /**
+ * Creates a new identity mat2
+ *
+ * @returns {mat2} a new 2x2 matrix
+ */
+ export function create(): mat2;
+ /**
+ * Creates a new mat2 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat2} a matrix to clone
+ * @returns {mat2} a new 2x2 matrix
+ */
+ export function clone(a: ReadonlyMat2): mat2;
+ /**
+ * Copy the values from one mat2 to another
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+ export function copy(out: mat2, a: ReadonlyMat2): mat2;
+ /**
+ * Set a mat2 to the identity matrix
+ *
+ * @param {mat2} out the receiving matrix
+ * @returns {mat2} out
+ */
+ export function identity(out: mat2): mat2;
+ /**
+ * Create a new mat2 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m10 Component in column 1, row 0 position (index 2)
+ * @param {Number} m11 Component in column 1, row 1 position (index 3)
+ * @returns {mat2} out A new 2x2 matrix
+ */
+ export function fromValues(m00: number, m01: number, m10: number, m11: number): mat2;
+ /**
+ * Set the components of a mat2 to the given values
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m10 Component in column 1, row 0 position (index 2)
+ * @param {Number} m11 Component in column 1, row 1 position (index 3)
+ * @returns {mat2} out
+ */
+ export function set(out: mat2, m00: number, m01: number, m10: number, m11: number): mat2;
+ /**
+ * Transpose the values of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+ export function transpose(out: mat2, a: ReadonlyMat2): mat2;
+ /**
+ * Inverts a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+ export function invert(out: mat2, a: ReadonlyMat2): mat2;
+ /**
+ * Calculates the adjugate of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {mat2} out
+ */
+ export function adjoint(out: mat2, a: ReadonlyMat2): mat2;
+ /**
+ * Calculates the determinant of a mat2
+ *
+ * @param {ReadonlyMat2} a the source matrix
+ * @returns {Number} determinant of a
+ */
+ export function determinant(a: ReadonlyMat2): number;
+ /**
+ * Multiplies two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+ export function multiply(out: mat2, a: ReadonlyMat2, b: ReadonlyMat2): mat2;
+ /**
+ * Rotates a mat2 by the given angle
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+ export function rotate(out: mat2, a: ReadonlyMat2, rad: number): mat2;
+ /**
+ * Scales the mat2 by the dimensions in the given vec2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to rotate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat2} out
+ **/
+ export function scale(out: mat2, a: ReadonlyMat2, v: ReadonlyVec2): mat2;
+ /**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.rotate(dest, dest, rad);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+ export function fromRotation(out: mat2, rad: number): mat2;
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.scale(dest, dest, vec);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat2} out
+ */
+ export function fromScaling(out: mat2, v: ReadonlyVec2): mat2;
+ /**
+ * Returns a string representation of a mat2
+ *
+ * @param {ReadonlyMat2} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+ export function str(a: ReadonlyMat2): string;
+ /**
+ * Returns Frobenius norm of a mat2
+ *
+ * @param {ReadonlyMat2} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+ export function frob(a: ReadonlyMat2): number;
+ /**
+ * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
+ * @param {ReadonlyMat2} L the lower triangular matrix
+ * @param {ReadonlyMat2} D the diagonal matrix
+ * @param {ReadonlyMat2} U the upper triangular matrix
+ * @param {ReadonlyMat2} a the input matrix to factorize
+ */
+ export function LDU(L: ReadonlyMat2, D: ReadonlyMat2, U: ReadonlyMat2, a: ReadonlyMat2): ReadonlyMat2[];
+ /**
+ * Adds two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+ export function add(out: mat2, a: ReadonlyMat2, b: ReadonlyMat2): mat2;
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+ export function subtract(out: mat2, a: ReadonlyMat2, b: ReadonlyMat2): mat2;
+ /**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat2} a The first matrix.
+ * @param {ReadonlyMat2} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+ export function exactEquals(a: ReadonlyMat2, b: ReadonlyMat2): boolean;
+ /**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat2} a The first matrix.
+ * @param {ReadonlyMat2} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+ export function equals(a: ReadonlyMat2, b: ReadonlyMat2): boolean;
+ /**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat2} out
+ */
+ export function multiplyScalar(out: mat2, a: ReadonlyMat2, b: number): mat2;
+ /**
+ * Adds two mat2's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat2} out the receiving vector
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat2} out
+ */
+ export function multiplyScalarAndAdd(out: mat2, a: ReadonlyMat2, b: ReadonlyMat2, scale: number): mat2;
+ /**
+ * Multiplies two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+ export function mul(out: mat2, a: ReadonlyMat2, b: ReadonlyMat2): mat2;
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {ReadonlyMat2} a the first operand
+ * @param {ReadonlyMat2} b the second operand
+ * @returns {mat2} out
+ */
+ export function sub(out: mat2, a: ReadonlyMat2, b: ReadonlyMat2): mat2;
+}
+export module mat2d {
+ /**
+ * 2x3 Matrix
+ * @module mat2d
+ * @description
+ * A mat2d contains six elements defined as:
+ *
+ * [a, b,
+ * c, d,
+ * tx, ty]
+ *
+ * This is a short form for the 3x3 matrix:
+ *
+ * [a, b, 0,
+ * c, d, 0,
+ * tx, ty, 1]
+ *
+ * The last column is ignored so the array is shorter and operations are faster.
+ */
+ /**
+ * Creates a new identity mat2d
+ *
+ * @returns {mat2d} a new 2x3 matrix
+ */
+ export function create(): mat2d;
+ /**
+ * Creates a new mat2d initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat2d} a matrix to clone
+ * @returns {mat2d} a new 2x3 matrix
+ */
+ export function clone(a: ReadonlyMat2d): mat2d;
+ /**
+ * Copy the values from one mat2d to another
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+ export function copy(out: mat2d, a: ReadonlyMat2d): mat2d;
+ /**
+ * Set a mat2d to the identity matrix
+ *
+ * @param {mat2d} out the receiving matrix
+ * @returns {mat2d} out
+ */
+ export function identity(out: mat2d): mat2d;
+ /**
+ * Create a new mat2d with the given values
+ *
+ * @param {Number} a Component A (index 0)
+ * @param {Number} b Component B (index 1)
+ * @param {Number} c Component C (index 2)
+ * @param {Number} d Component D (index 3)
+ * @param {Number} tx Component TX (index 4)
+ * @param {Number} ty Component TY (index 5)
+ * @returns {mat2d} A new mat2d
+ */
+ export function fromValues(a: number, b: number, c: number, d: number, tx: number, ty: number): mat2d;
+ /**
+ * Set the components of a mat2d to the given values
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {Number} a Component A (index 0)
+ * @param {Number} b Component B (index 1)
+ * @param {Number} c Component C (index 2)
+ * @param {Number} d Component D (index 3)
+ * @param {Number} tx Component TX (index 4)
+ * @param {Number} ty Component TY (index 5)
+ * @returns {mat2d} out
+ */
+ export function set(out: mat2d, a: number, b: number, c: number, d: number, tx: number, ty: number): mat2d;
+ /**
+ * Inverts a mat2d
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+ export function invert(out: mat2d, a: ReadonlyMat2d): mat2d;
+ /**
+ * Calculates the determinant of a mat2d
+ *
+ * @param {ReadonlyMat2d} a the source matrix
+ * @returns {Number} determinant of a
+ */
+ export function determinant(a: ReadonlyMat2d): number;
+ /**
+ * Multiplies two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+ export function multiply(out: mat2d, a: ReadonlyMat2d, b: ReadonlyMat2d): mat2d;
+ /**
+ * Rotates a mat2d by the given angle
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+ export function rotate(out: mat2d, a: ReadonlyMat2d, rad: number): mat2d;
+ /**
+ * Scales the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to translate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat2d} out
+ **/
+ export function scale(out: mat2d, a: ReadonlyMat2d, v: ReadonlyVec2): mat2d;
+ /**
+ * Translates the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to translate
+ * @param {ReadonlyVec2} v the vec2 to translate the matrix by
+ * @returns {mat2d} out
+ **/
+ export function translate(out: mat2d, a: ReadonlyMat2d, v: ReadonlyVec2): mat2d;
+ /**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.rotate(dest, dest, rad);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+ export function fromRotation(out: mat2d, rad: number): mat2d;
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.scale(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat2d} out
+ */
+ export function fromScaling(out: mat2d, v: ReadonlyVec2): mat2d;
+ /**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.translate(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {ReadonlyVec2} v Translation vector
+ * @returns {mat2d} out
+ */
+ export function fromTranslation(out: mat2d, v: ReadonlyVec2): mat2d;
+ /**
+ * Returns a string representation of a mat2d
+ *
+ * @param {ReadonlyMat2d} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+ export function str(a: ReadonlyMat2d): string;
+ /**
+ * Returns Frobenius norm of a mat2d
+ *
+ * @param {ReadonlyMat2d} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+ export function frob(a: ReadonlyMat2d): number;
+ /**
+ * Adds two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+ export function add(out: mat2d, a: ReadonlyMat2d, b: ReadonlyMat2d): mat2d;
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+ export function subtract(out: mat2d, a: ReadonlyMat2d, b: ReadonlyMat2d): mat2d;
+ /**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat2d} out
+ */
+ export function multiplyScalar(out: mat2d, a: ReadonlyMat2d, b: number): mat2d;
+ /**
+ * Adds two mat2d's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat2d} out the receiving vector
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat2d} out
+ */
+ export function multiplyScalarAndAdd(out: mat2d, a: ReadonlyMat2d, b: ReadonlyMat2d, scale: number): mat2d;
+ /**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat2d} a The first matrix.
+ * @param {ReadonlyMat2d} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+ export function exactEquals(a: ReadonlyMat2d, b: ReadonlyMat2d): boolean;
+ /**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat2d} a The first matrix.
+ * @param {ReadonlyMat2d} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+ export function equals(a: ReadonlyMat2d, b: ReadonlyMat2d): boolean;
+ /**
+ * Multiplies two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+ export function mul(out: mat2d, a: ReadonlyMat2d, b: ReadonlyMat2d): mat2d;
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {ReadonlyMat2d} a the first operand
+ * @param {ReadonlyMat2d} b the second operand
+ * @returns {mat2d} out
+ */
+ export function sub(out: mat2d, a: ReadonlyMat2d, b: ReadonlyMat2d): mat2d;
+}
+export module mat3 {
+ /**
+ * 3x3 Matrix
+ * @module mat3
+ */
+ /**
+ * Creates a new identity mat3
+ *
+ * @returns {mat3} a new 3x3 matrix
+ */
+ export function create(): mat3;
+ /**
+ * Copies the upper-left 3x3 values into the given mat3.
+ *
+ * @param {mat3} out the receiving 3x3 matrix
+ * @param {ReadonlyMat4} a the source 4x4 matrix
+ * @returns {mat3} out
+ */
+ export function fromMat4(out: mat3, a: ReadonlyMat4): mat3;
+ /**
+ * Creates a new mat3 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat3} a matrix to clone
+ * @returns {mat3} a new 3x3 matrix
+ */
+ export function clone(a: ReadonlyMat3): mat3;
+ /**
+ * Copy the values from one mat3 to another
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+ export function copy(out: mat3, a: ReadonlyMat3): mat3;
+ /**
+ * Create a new mat3 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m10 Component in column 1, row 0 position (index 3)
+ * @param {Number} m11 Component in column 1, row 1 position (index 4)
+ * @param {Number} m12 Component in column 1, row 2 position (index 5)
+ * @param {Number} m20 Component in column 2, row 0 position (index 6)
+ * @param {Number} m21 Component in column 2, row 1 position (index 7)
+ * @param {Number} m22 Component in column 2, row 2 position (index 8)
+ * @returns {mat3} A new mat3
+ */
+ export function fromValues(m00: number, m01: number, m02: number, m10: number, m11: number, m12: number, m20: number, m21: number, m22: number): mat3;
+ /**
+ * Set the components of a mat3 to the given values
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m10 Component in column 1, row 0 position (index 3)
+ * @param {Number} m11 Component in column 1, row 1 position (index 4)
+ * @param {Number} m12 Component in column 1, row 2 position (index 5)
+ * @param {Number} m20 Component in column 2, row 0 position (index 6)
+ * @param {Number} m21 Component in column 2, row 1 position (index 7)
+ * @param {Number} m22 Component in column 2, row 2 position (index 8)
+ * @returns {mat3} out
+ */
+ export function set(out: mat3, m00: number, m01: number, m02: number, m10: number, m11: number, m12: number, m20: number, m21: number, m22: number): mat3;
+ /**
+ * Set a mat3 to the identity matrix
+ *
+ * @param {mat3} out the receiving matrix
+ * @returns {mat3} out
+ */
+ export function identity(out: mat3): mat3;
+ /**
+ * Transpose the values of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+ export function transpose(out: mat3, a: ReadonlyMat3): mat3;
+ /**
+ * Inverts a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+ export function invert(out: mat3, a: ReadonlyMat3): mat3;
+ /**
+ * Calculates the adjugate of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {mat3} out
+ */
+ export function adjoint(out: mat3, a: ReadonlyMat3): mat3;
+ /**
+ * Calculates the determinant of a mat3
+ *
+ * @param {ReadonlyMat3} a the source matrix
+ * @returns {Number} determinant of a
+ */
+ export function determinant(a: ReadonlyMat3): number;
+ /**
+ * Multiplies two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+ export function multiply(out: mat3, a: ReadonlyMat3, b: ReadonlyMat3): mat3;
+ /**
+ * Translate a mat3 by the given vector
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to translate
+ * @param {ReadonlyVec2} v vector to translate by
+ * @returns {mat3} out
+ */
+ export function translate(out: mat3, a: ReadonlyMat3, v: ReadonlyVec2): mat3;
+ /**
+ * Rotates a mat3 by the given angle
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+ export function rotate(out: mat3, a: ReadonlyMat3, rad: number): mat3;
+ /**
+ * Scales the mat3 by the dimensions in the given vec2
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to rotate
+ * @param {ReadonlyVec2} v the vec2 to scale the matrix by
+ * @returns {mat3} out
+ **/
+ export function scale(out: mat3, a: ReadonlyMat3, v: ReadonlyVec2): mat3;
+ /**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.translate(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyVec2} v Translation vector
+ * @returns {mat3} out
+ */
+ export function fromTranslation(out: mat3, v: ReadonlyVec2): mat3;
+ /**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.rotate(dest, dest, rad);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+ export function fromRotation(out: mat3, rad: number): mat3;
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.scale(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyVec2} v Scaling vector
+ * @returns {mat3} out
+ */
+ export function fromScaling(out: mat3, v: ReadonlyVec2): mat3;
+ /**
+ * Copies the values from a mat2d into a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat2d} a the matrix to copy
+ * @returns {mat3} out
+ **/
+ export function fromMat2d(out: mat3, a: ReadonlyMat2d): mat3;
+ /**
+ * Calculates a 3x3 matrix from the given quaternion
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyQuat} q Quaternion to create matrix from
+ *
+ * @returns {mat3} out
+ */
+ export function fromQuat(out: mat3, q: ReadonlyQuat): mat3;
+ /**
+ * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {ReadonlyMat4} a Mat4 to derive the normal matrix from
+ *
+ * @returns {mat3} out
+ */
+ export function normalFromMat4(out: mat3, a: ReadonlyMat4): mat3;
+ /**
+ * Generates a 2D projection matrix with the given bounds
+ *
+ * @param {mat3} out mat3 frustum matrix will be written into
+ * @param {number} width Width of your gl context
+ * @param {number} height Height of gl context
+ * @returns {mat3} out
+ */
+ export function projection(out: mat3, width: number, height: number): mat3;
+ /**
+ * Returns a string representation of a mat3
+ *
+ * @param {ReadonlyMat3} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+ export function str(a: ReadonlyMat3): string;
+ /**
+ * Returns Frobenius norm of a mat3
+ *
+ * @param {ReadonlyMat3} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+ export function frob(a: ReadonlyMat3): number;
+ /**
+ * Adds two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+ export function add(out: mat3, a: ReadonlyMat3, b: ReadonlyMat3): mat3;
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+ export function subtract(out: mat3, a: ReadonlyMat3, b: ReadonlyMat3): mat3;
+ /**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat3} out
+ */
+ export function multiplyScalar(out: mat3, a: ReadonlyMat3, b: number): mat3;
+ /**
+ * Adds two mat3's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat3} out the receiving vector
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat3} out
+ */
+ export function multiplyScalarAndAdd(out: mat3, a: ReadonlyMat3, b: ReadonlyMat3, scale: number): mat3;
+ /**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat3} a The first matrix.
+ * @param {ReadonlyMat3} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+ export function exactEquals(a: ReadonlyMat3, b: ReadonlyMat3): boolean;
+ /**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat3} a The first matrix.
+ * @param {ReadonlyMat3} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+ export function equals(a: ReadonlyMat3, b: ReadonlyMat3): boolean;
+ /**
+ * Multiplies two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+ export function mul(out: mat3, a: ReadonlyMat3, b: ReadonlyMat3): mat3;
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {ReadonlyMat3} a the first operand
+ * @param {ReadonlyMat3} b the second operand
+ * @returns {mat3} out
+ */
+ export function sub(out: mat3, a: ReadonlyMat3, b: ReadonlyMat3): mat3;
+}
+export module mat4 {
+ /**
+ * 4x4 Matrix
Format: column-major, when typed out it looks like row-major
The matrices are being post multiplied.
+ * @module mat4
+ */
+ /**
+ * Creates a new identity mat4
+ *
+ * @returns {mat4} a new 4x4 matrix
+ */
+ export function create(): mat4;
+ /**
+ * Creates a new mat4 initialized with values from an existing matrix
+ *
+ * @param {ReadonlyMat4} a matrix to clone
+ * @returns {mat4} a new 4x4 matrix
+ */
+ export function clone(a: ReadonlyMat4): mat4;
+ /**
+ * Copy the values from one mat4 to another
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+ export function copy(out: mat4, a: ReadonlyMat4): mat4;
+ /**
+ * Create a new mat4 with the given values
+ *
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m03 Component in column 0, row 3 position (index 3)
+ * @param {Number} m10 Component in column 1, row 0 position (index 4)
+ * @param {Number} m11 Component in column 1, row 1 position (index 5)
+ * @param {Number} m12 Component in column 1, row 2 position (index 6)
+ * @param {Number} m13 Component in column 1, row 3 position (index 7)
+ * @param {Number} m20 Component in column 2, row 0 position (index 8)
+ * @param {Number} m21 Component in column 2, row 1 position (index 9)
+ * @param {Number} m22 Component in column 2, row 2 position (index 10)
+ * @param {Number} m23 Component in column 2, row 3 position (index 11)
+ * @param {Number} m30 Component in column 3, row 0 position (index 12)
+ * @param {Number} m31 Component in column 3, row 1 position (index 13)
+ * @param {Number} m32 Component in column 3, row 2 position (index 14)
+ * @param {Number} m33 Component in column 3, row 3 position (index 15)
+ * @returns {mat4} A new mat4
+ */
+ export function fromValues(m00: number, m01: number, m02: number, m03: number, m10: number, m11: number, m12: number, m13: number, m20: number, m21: number, m22: number, m23: number, m30: number, m31: number, m32: number, m33: number): mat4;
+ /**
+ * Set the components of a mat4 to the given values
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {Number} m00 Component in column 0, row 0 position (index 0)
+ * @param {Number} m01 Component in column 0, row 1 position (index 1)
+ * @param {Number} m02 Component in column 0, row 2 position (index 2)
+ * @param {Number} m03 Component in column 0, row 3 position (index 3)
+ * @param {Number} m10 Component in column 1, row 0 position (index 4)
+ * @param {Number} m11 Component in column 1, row 1 position (index 5)
+ * @param {Number} m12 Component in column 1, row 2 position (index 6)
+ * @param {Number} m13 Component in column 1, row 3 position (index 7)
+ * @param {Number} m20 Component in column 2, row 0 position (index 8)
+ * @param {Number} m21 Component in column 2, row 1 position (index 9)
+ * @param {Number} m22 Component in column 2, row 2 position (index 10)
+ * @param {Number} m23 Component in column 2, row 3 position (index 11)
+ * @param {Number} m30 Component in column 3, row 0 position (index 12)
+ * @param {Number} m31 Component in column 3, row 1 position (index 13)
+ * @param {Number} m32 Component in column 3, row 2 position (index 14)
+ * @param {Number} m33 Component in column 3, row 3 position (index 15)
+ * @returns {mat4} out
+ */
+ export function set(out: mat4, m00: number, m01: number, m02: number, m03: number, m10: number, m11: number, m12: number, m13: number, m20: number, m21: number, m22: number, m23: number, m30: number, m31: number, m32: number, m33: number): mat4;
+ /**
+ * Set a mat4 to the identity matrix
+ *
+ * @param {mat4} out the receiving matrix
+ * @returns {mat4} out
+ */
+ export function identity(out: mat4): mat4;
+ /**
+ * Transpose the values of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+ export function transpose(out: mat4, a: ReadonlyMat4): mat4;
+ /**
+ * Inverts a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+ export function invert(out: mat4, a: ReadonlyMat4): mat4;
+ /**
+ * Calculates the adjugate of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {mat4} out
+ */
+ export function adjoint(out: mat4, a: ReadonlyMat4): mat4;
+ /**
+ * Calculates the determinant of a mat4
+ *
+ * @param {ReadonlyMat4} a the source matrix
+ * @returns {Number} determinant of a
+ */
+ export function determinant(a: ReadonlyMat4): number;
+ /**
+ * Multiplies two mat4s
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+ export function multiply(out: mat4, a: ReadonlyMat4, b: ReadonlyMat4): mat4;
+ /**
+ * Translate a mat4 by the given vector
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to translate
+ * @param {ReadonlyVec3} v vector to translate by
+ * @returns {mat4} out
+ */
+ export function translate(out: mat4, a: ReadonlyMat4, v: ReadonlyVec3): mat4;
+ /**
+ * Scales the mat4 by the dimensions in the given vec3 not using vectorization
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to scale
+ * @param {ReadonlyVec3} v the vec3 to scale the matrix by
+ * @returns {mat4} out
+ **/
+ export function scale(out: mat4, a: ReadonlyMat4, v: ReadonlyVec3): mat4;
+ /**
+ * Rotates a mat4 by the given angle around the given axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+ export function rotate(out: mat4, a: ReadonlyMat4, rad: number, axis: ReadonlyVec3): mat4;
+ /**
+ * Rotates a matrix by the given angle around the X axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ export function rotateX(out: mat4, a: ReadonlyMat4, rad: number): mat4;
+ /**
+ * Rotates a matrix by the given angle around the Y axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ export function rotateY(out: mat4, a: ReadonlyMat4, rad: number): mat4;
+ /**
+ * Rotates a matrix by the given angle around the Z axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ export function rotateZ(out: mat4, a: ReadonlyMat4, rad: number): mat4;
+ /**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyVec3} v Translation vector
+ * @returns {mat4} out
+ */
+ export function fromTranslation(out: mat4, v: ReadonlyVec3): mat4;
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.scale(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyVec3} v Scaling vector
+ * @returns {mat4} out
+ */
+ export function fromScaling(out: mat4, v: ReadonlyVec3): mat4;
+ /**
+ * Creates a matrix from a given angle around a given axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotate(dest, dest, rad, axis);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+ export function fromRotation(out: mat4, rad: number, axis: ReadonlyVec3): mat4;
+ /**
+ * Creates a matrix from the given angle around the X axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateX(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ export function fromXRotation(out: mat4, rad: number): mat4;
+ /**
+ * Creates a matrix from the given angle around the Y axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateY(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ export function fromYRotation(out: mat4, rad: number): mat4;
+ /**
+ * Creates a matrix from the given angle around the Z axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateZ(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ export function fromZRotation(out: mat4, rad: number): mat4;
+ /**
+ * Creates a matrix from a quaternion rotation and vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @returns {mat4} out
+ */
+ export function fromRotationTranslation(out: mat4, q: any, v: ReadonlyVec3): mat4;
+ /**
+ * Creates a new mat4 from a dual quat.
+ *
+ * @param {mat4} out Matrix
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @returns {mat4} mat4 receiving operation result
+ */
+ export function fromQuat2(out: mat4, a: ReadonlyQuat2): mat4;
+ /**
+ * Returns the translation vector component of a transformation
+ * matrix. If a matrix is built with fromRotationTranslation,
+ * the returned vector will be the same as the translation vector
+ * originally supplied.
+ * @param {vec3} out Vector to receive translation component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {vec3} out
+ */
+ export function getTranslation(out: vec3, mat: ReadonlyMat4): vec3;
+ /**
+ * Returns the scaling factor component of a transformation
+ * matrix. If a matrix is built with fromRotationTranslationScale
+ * with a normalized Quaternion paramter, the returned vector will be
+ * the same as the scaling vector
+ * originally supplied.
+ * @param {vec3} out Vector to receive scaling factor component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {vec3} out
+ */
+ export function getScaling(out: vec3, mat: ReadonlyMat4): vec3;
+ /**
+ * Returns a quaternion representing the rotational component
+ * of a transformation matrix. If a matrix is built with
+ * fromRotationTranslation, the returned quaternion will be the
+ * same as the quaternion originally supplied.
+ * @param {quat} out Quaternion to receive the rotation component
+ * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
+ * @return {quat} out
+ */
+ export function getRotation(out: quat, mat: ReadonlyMat4): quat;
+ /**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @param {ReadonlyVec3} s Scaling vector
+ * @returns {mat4} out
+ */
+ export function fromRotationTranslationScale(out: mat4, q: any, v: ReadonlyVec3, s: ReadonlyVec3): mat4;
+ /**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * mat4.translate(dest, origin);
+ * let quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ * mat4.translate(dest, negativeOrigin);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {ReadonlyVec3} v Translation vector
+ * @param {ReadonlyVec3} s Scaling vector
+ * @param {ReadonlyVec3} o The origin vector around which to scale and rotate
+ * @returns {mat4} out
+ */
+ export function fromRotationTranslationScaleOrigin(out: mat4, q: any, v: ReadonlyVec3, s: ReadonlyVec3, o: ReadonlyVec3): mat4;
+ /**
+ * Calculates a 4x4 matrix from the given quaternion
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {ReadonlyQuat} q Quaternion to create matrix from
+ *
+ * @returns {mat4} out
+ */
+ export function fromQuat(out: mat4, q: ReadonlyQuat): mat4;
+ /**
+ * Generates a frustum matrix with the given bounds
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {Number} left Left bound of the frustum
+ * @param {Number} right Right bound of the frustum
+ * @param {Number} bottom Bottom bound of the frustum
+ * @param {Number} top Top bound of the frustum
+ * @param {Number} near Near bound of the frustum
+ * @param {Number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+ export function frustum(out: mat4, left: number, right: number, bottom: number, top: number, near: number, far: number): mat4;
+ /**
+ * Generates a perspective projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
+ * which matches WebGL/OpenGL's clip volume.
+ * Passing null/undefined/no value for far will generate infinite projection matrix.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum, can be null or Infinity
+ * @returns {mat4} out
+ */
+ export function perspectiveNO(out: mat4, fovy: number, aspect: number, near: number, far: number): mat4;
+ /**
+ * Generates a perspective projection matrix suitable for WebGPU with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
+ * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
+ * Passing null/undefined/no value for far will generate infinite projection matrix.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum, can be null or Infinity
+ * @returns {mat4} out
+ */
+ export function perspectiveZO(out: mat4, fovy: number, aspect: number, near: number, far: number): mat4;
+ /**
+ * Generates a perspective projection matrix with the given field of view.
+ * This is primarily useful for generating projection matrices to be used
+ * with the still experiemental WebVR API.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+ export function perspectiveFromFieldOfView(out: mat4, fov: any, near: number, far: number): mat4;
+ /**
+ * Generates a orthogonal projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
+ * which matches WebGL/OpenGL's clip volume.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+ export function orthoNO(out: mat4, left: number, right: number, bottom: number, top: number, near: number, far: number): mat4;
+ /**
+ * Generates a orthogonal projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
+ * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+ export function orthoZO(out: mat4, left: number, right: number, bottom: number, top: number, near: number, far: number): mat4;
+ /**
+ * Generates a look-at matrix with the given eye position, focal point, and up axis.
+ * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {ReadonlyVec3} eye Position of the viewer
+ * @param {ReadonlyVec3} center Point the viewer is looking at
+ * @param {ReadonlyVec3} up vec3 pointing up
+ * @returns {mat4} out
+ */
+ export function lookAt(out: mat4, eye: ReadonlyVec3, center: ReadonlyVec3, up: ReadonlyVec3): mat4;
+ /**
+ * Generates a matrix that makes something look at something else.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {ReadonlyVec3} eye Position of the viewer
+ * @param {ReadonlyVec3} center Point the viewer is looking at
+ * @param {ReadonlyVec3} up vec3 pointing up
+ * @returns {mat4} out
+ */
+ export function targetTo(out: mat4, eye: ReadonlyVec3, target: any, up: ReadonlyVec3): mat4;
+ /**
+ * Returns a string representation of a mat4
+ *
+ * @param {ReadonlyMat4} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+ export function str(a: ReadonlyMat4): string;
+ /**
+ * Returns Frobenius norm of a mat4
+ *
+ * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+ export function frob(a: ReadonlyMat4): number;
+ /**
+ * Adds two mat4's
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+ export function add(out: mat4, a: ReadonlyMat4, b: ReadonlyMat4): mat4;
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+ export function subtract(out: mat4, a: ReadonlyMat4, b: ReadonlyMat4): mat4;
+ /**
+ * Multiply each element of the matrix by a scalar.
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the matrix to scale
+ * @param {Number} b amount to scale the matrix's elements by
+ * @returns {mat4} out
+ */
+ export function multiplyScalar(out: mat4, a: ReadonlyMat4, b: number): mat4;
+ /**
+ * Adds two mat4's after multiplying each element of the second operand by a scalar value.
+ *
+ * @param {mat4} out the receiving vector
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @param {Number} scale the amount to scale b's elements by before adding
+ * @returns {mat4} out
+ */
+ export function multiplyScalarAndAdd(out: mat4, a: ReadonlyMat4, b: ReadonlyMat4, scale: number): mat4;
+ /**
+ * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyMat4} a The first matrix.
+ * @param {ReadonlyMat4} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+ export function exactEquals(a: ReadonlyMat4, b: ReadonlyMat4): boolean;
+ /**
+ * Returns whether or not the matrices have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyMat4} a The first matrix.
+ * @param {ReadonlyMat4} b The second matrix.
+ * @returns {Boolean} True if the matrices are equal, false otherwise.
+ */
+ export function equals(a: ReadonlyMat4, b: ReadonlyMat4): boolean;
+ /**
+ * Generates a perspective projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
+ * which matches WebGL/OpenGL's clip volume.
+ * Passing null/undefined/no value for far will generate infinite projection matrix.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum, can be null or Infinity
+ * @returns {mat4} out
+ */
+ export function perspective(out: mat4, fovy: number, aspect: number, near: number, far: number): mat4;
+ /**
+ * Generates a orthogonal projection matrix with the given bounds.
+ * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
+ * which matches WebGL/OpenGL's clip volume.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+ export function ortho(out: mat4, left: number, right: number, bottom: number, top: number, near: number, far: number): mat4;
+ /**
+ * Multiplies two mat4s
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+ export function mul(out: mat4, a: ReadonlyMat4, b: ReadonlyMat4): mat4;
+ /**
+ * Subtracts matrix b from matrix a
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {ReadonlyMat4} a the first operand
+ * @param {ReadonlyMat4} b the second operand
+ * @returns {mat4} out
+ */
+ export function sub(out: mat4, a: ReadonlyMat4, b: ReadonlyMat4): mat4;
+}
+export module vec3 {
+ /**
+ * 3 Dimensional Vector
+ * @module vec3
+ */
+ /**
+ * Creates a new, empty vec3
+ *
+ * @returns {vec3} a new 3D vector
+ */
+ export function create(): vec3;
+ /**
+ * Creates a new vec3 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec3} a vector to clone
+ * @returns {vec3} a new 3D vector
+ */
+ export function clone(a: ReadonlyVec3): vec3;
+ /**
+ * Calculates the length of a vec3
+ *
+ * @param {ReadonlyVec3} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+ export function length(a: ReadonlyVec3): number;
+ /**
+ * Creates a new vec3 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} a new 3D vector
+ */
+ export function fromValues(x: number, y: number, z: number): vec3;
+ /**
+ * Copy the values from one vec3 to another
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the source vector
+ * @returns {vec3} out
+ */
+ export function copy(out: vec3, a: ReadonlyVec3): vec3;
+ /**
+ * Set the components of a vec3 to the given values
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} out
+ */
+ export function set(out: vec3, x: number, y: number, z: number): vec3;
+ /**
+ * Adds two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+ export function add(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3): vec3;
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+ export function subtract(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3): vec3;
+ /**
+ * Multiplies two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+ export function multiply(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3): vec3;
+ /**
+ * Divides two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+ export function divide(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3): vec3;
+ /**
+ * Math.ceil the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to ceil
+ * @returns {vec3} out
+ */
+ export function ceil(out: vec3, a: ReadonlyVec3): vec3;
+ /**
+ * Math.floor the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to floor
+ * @returns {vec3} out
+ */
+ export function floor(out: vec3, a: ReadonlyVec3): vec3;
+ /**
+ * Returns the minimum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+ export function min(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3): vec3;
+ /**
+ * Returns the maximum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+ export function max(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3): vec3;
+ /**
+ * Math.round the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to round
+ * @returns {vec3} out
+ */
+ export function round(out: vec3, a: ReadonlyVec3): vec3;
+ /**
+ * Scales a vec3 by a scalar number
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec3} out
+ */
+ export function scale(out: vec3, a: ReadonlyVec3, b: number): vec3;
+ /**
+ * Adds two vec3's after scaling the second operand by a scalar value
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec3} out
+ */
+ export function scaleAndAdd(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3, scale: number): vec3;
+ /**
+ * Calculates the euclidian distance between two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} distance between a and b
+ */
+ export function distance(a: ReadonlyVec3, b: ReadonlyVec3): number;
+ /**
+ * Calculates the squared euclidian distance between two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+ export function squaredDistance(a: ReadonlyVec3, b: ReadonlyVec3): number;
+ /**
+ * Calculates the squared length of a vec3
+ *
+ * @param {ReadonlyVec3} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+ export function squaredLength(a: ReadonlyVec3): number;
+ /**
+ * Negates the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to negate
+ * @returns {vec3} out
+ */
+ export function negate(out: vec3, a: ReadonlyVec3): vec3;
+ /**
+ * Returns the inverse of the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to invert
+ * @returns {vec3} out
+ */
+ export function inverse(out: vec3, a: ReadonlyVec3): vec3;
+ /**
+ * Normalize a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a vector to normalize
+ * @returns {vec3} out
+ */
+ export function normalize(out: vec3, a: ReadonlyVec3): vec3;
+ /**
+ * Calculates the dot product of two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+ export function dot(a: ReadonlyVec3, b: ReadonlyVec3): number;
+ /**
+ * Computes the cross product of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+ export function cross(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3): vec3;
+ /**
+ * Performs a linear interpolation between two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+ export function lerp(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3, t: number): vec3;
+ /**
+ * Performs a hermite interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {ReadonlyVec3} c the third operand
+ * @param {ReadonlyVec3} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+ export function hermite(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3, c: ReadonlyVec3, d: ReadonlyVec3, t: number): vec3;
+ /**
+ * Performs a bezier interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @param {ReadonlyVec3} c the third operand
+ * @param {ReadonlyVec3} d the fourth operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec3} out
+ */
+ export function bezier(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3, c: ReadonlyVec3, d: ReadonlyVec3, t: number): vec3;
+ /**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec3} out
+ */
+ export function random(out: vec3, scale?: number): vec3;
+ /**
+ * Transforms the vec3 with a mat4.
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec3} out
+ */
+ export function transformMat4(out: vec3, a: ReadonlyVec3, m: ReadonlyMat4): vec3;
+ /**
+ * Transforms the vec3 with a mat3.
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyMat3} m the 3x3 matrix to transform with
+ * @returns {vec3} out
+ */
+ export function transformMat3(out: vec3, a: ReadonlyVec3, m: ReadonlyMat3): vec3;
+ /**
+ * Transforms the vec3 with a quat
+ * Can also be used for dual quaternions. (Multiply it with the real part)
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the vector to transform
+ * @param {ReadonlyQuat} q quaternion to transform with
+ * @returns {vec3} out
+ */
+ export function transformQuat(out: vec3, a: ReadonlyVec3, q: ReadonlyQuat): vec3;
+ /**
+ * Rotate a 3D vector around the x-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+ export function rotateX(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3, rad: number): vec3;
+ /**
+ * Rotate a 3D vector around the y-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+ export function rotateY(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3, rad: number): vec3;
+ /**
+ * Rotate a 3D vector around the z-axis
+ * @param {vec3} out The receiving vec3
+ * @param {ReadonlyVec3} a The vec3 point to rotate
+ * @param {ReadonlyVec3} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec3} out
+ */
+ export function rotateZ(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3, rad: number): vec3;
+ /**
+ * Get the angle between two 3D vectors
+ * @param {ReadonlyVec3} a The first operand
+ * @param {ReadonlyVec3} b The second operand
+ * @returns {Number} The angle in radians
+ */
+ export function angle(a: ReadonlyVec3, b: ReadonlyVec3): number;
+ /**
+ * Set the components of a vec3 to zero
+ *
+ * @param {vec3} out the receiving vector
+ * @returns {vec3} out
+ */
+ export function zero(out: vec3): vec3;
+ /**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec3} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+ export function str(a: ReadonlyVec3): string;
+ /**
+ * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec3} a The first vector.
+ * @param {ReadonlyVec3} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+ export function exactEquals(a: ReadonlyVec3, b: ReadonlyVec3): boolean;
+ /**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec3} a The first vector.
+ * @param {ReadonlyVec3} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+ export function equals(a: ReadonlyVec3, b: ReadonlyVec3): boolean;
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+ export function sub(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3): vec3;
+ /**
+ * Multiplies two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+ export function mul(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3): vec3;
+ /**
+ * Divides two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {vec3} out
+ */
+ export function div(out: vec3, a: ReadonlyVec3, b: ReadonlyVec3): vec3;
+ /**
+ * Calculates the euclidian distance between two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} distance between a and b
+ */
+ export function dist(a: ReadonlyVec3, b: ReadonlyVec3): number;
+ /**
+ * Calculates the squared euclidian distance between two vec3's
+ *
+ * @param {ReadonlyVec3} a the first operand
+ * @param {ReadonlyVec3} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+ export function sqrDist(a: ReadonlyVec3, b: ReadonlyVec3): number;
+ /**
+ * Calculates the length of a vec3
+ *
+ * @param {ReadonlyVec3} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+ export function len(a: ReadonlyVec3): number;
+ /**
+ * Calculates the squared length of a vec3
+ *
+ * @param {ReadonlyVec3} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+ export function sqrLen(a: ReadonlyVec3): number;
+ export function forEach(a: any, stride: any, offset: any, count: any, fn: any, arg: any): any;
+}
+export module vec4 {
+ /**
+ * 4 Dimensional Vector
+ * @module vec4
+ */
+ /**
+ * Creates a new, empty vec4
+ *
+ * @returns {vec4} a new 4D vector
+ */
+ export function create(): vec4;
+ /**
+ * Creates a new vec4 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec4} a vector to clone
+ * @returns {vec4} a new 4D vector
+ */
+ export function clone(a: ReadonlyVec4): vec4;
+ /**
+ * Creates a new vec4 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} a new 4D vector
+ */
+ export function fromValues(x: number, y: number, z: number, w: number): vec4;
+ /**
+ * Copy the values from one vec4 to another
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the source vector
+ * @returns {vec4} out
+ */
+ export function copy(out: vec4, a: ReadonlyVec4): vec4;
+ /**
+ * Set the components of a vec4 to the given values
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} out
+ */
+ export function set(out: vec4, x: number, y: number, z: number, w: number): vec4;
+ /**
+ * Adds two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+ export function add(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4): vec4;
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+ export function subtract(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4): vec4;
+ /**
+ * Multiplies two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+ export function multiply(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4): vec4;
+ /**
+ * Divides two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+ export function divide(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4): vec4;
+ /**
+ * Math.ceil the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to ceil
+ * @returns {vec4} out
+ */
+ export function ceil(out: vec4, a: ReadonlyVec4): vec4;
+ /**
+ * Math.floor the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to floor
+ * @returns {vec4} out
+ */
+ export function floor(out: vec4, a: ReadonlyVec4): vec4;
+ /**
+ * Returns the minimum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+ export function min(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4): vec4;
+ /**
+ * Returns the maximum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+ export function max(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4): vec4;
+ /**
+ * Math.round the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to round
+ * @returns {vec4} out
+ */
+ export function round(out: vec4, a: ReadonlyVec4): vec4;
+ /**
+ * Scales a vec4 by a scalar number
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec4} out
+ */
+ export function scale(out: vec4, a: ReadonlyVec4, b: number): vec4;
+ /**
+ * Adds two vec4's after scaling the second operand by a scalar value
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec4} out
+ */
+ export function scaleAndAdd(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4, scale: number): vec4;
+ /**
+ * Calculates the euclidian distance between two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} distance between a and b
+ */
+ export function distance(a: ReadonlyVec4, b: ReadonlyVec4): number;
+ /**
+ * Calculates the squared euclidian distance between two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+ export function squaredDistance(a: ReadonlyVec4, b: ReadonlyVec4): number;
+ /**
+ * Calculates the length of a vec4
+ *
+ * @param {ReadonlyVec4} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+ export function length(a: ReadonlyVec4): number;
+ /**
+ * Calculates the squared length of a vec4
+ *
+ * @param {ReadonlyVec4} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+ export function squaredLength(a: ReadonlyVec4): number;
+ /**
+ * Negates the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to negate
+ * @returns {vec4} out
+ */
+ export function negate(out: vec4, a: ReadonlyVec4): vec4;
+ /**
+ * Returns the inverse of the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to invert
+ * @returns {vec4} out
+ */
+ export function inverse(out: vec4, a: ReadonlyVec4): vec4;
+ /**
+ * Normalize a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a vector to normalize
+ * @returns {vec4} out
+ */
+ export function normalize(out: vec4, a: ReadonlyVec4): vec4;
+ /**
+ * Calculates the dot product of two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+ export function dot(a: ReadonlyVec4, b: ReadonlyVec4): number;
+ /**
+ * Returns the cross-product of three vectors in a 4-dimensional space
+ *
+ * @param {ReadonlyVec4} result the receiving vector
+ * @param {ReadonlyVec4} U the first vector
+ * @param {ReadonlyVec4} V the second vector
+ * @param {ReadonlyVec4} W the third vector
+ * @returns {vec4} result
+ */
+ export function cross(out: any, u: any, v: any, w: any): vec4;
+ /**
+ * Performs a linear interpolation between two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec4} out
+ */
+ export function lerp(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4, t: number): vec4;
+ /**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec4} out
+ */
+ export function random(out: vec4, scale?: number): vec4;
+ /**
+ * Transforms the vec4 with a mat4.
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec4} out
+ */
+ export function transformMat4(out: vec4, a: ReadonlyVec4, m: ReadonlyMat4): vec4;
+ /**
+ * Transforms the vec4 with a quat
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the vector to transform
+ * @param {ReadonlyQuat} q quaternion to transform with
+ * @returns {vec4} out
+ */
+ export function transformQuat(out: vec4, a: ReadonlyVec4, q: ReadonlyQuat): vec4;
+ /**
+ * Set the components of a vec4 to zero
+ *
+ * @param {vec4} out the receiving vector
+ * @returns {vec4} out
+ */
+ export function zero(out: vec4): vec4;
+ /**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec4} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+ export function str(a: ReadonlyVec4): string;
+ /**
+ * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec4} a The first vector.
+ * @param {ReadonlyVec4} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+ export function exactEquals(a: ReadonlyVec4, b: ReadonlyVec4): boolean;
+ /**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec4} a The first vector.
+ * @param {ReadonlyVec4} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+ export function equals(a: ReadonlyVec4, b: ReadonlyVec4): boolean;
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+ export function sub(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4): vec4;
+ /**
+ * Multiplies two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+ export function mul(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4): vec4;
+ /**
+ * Divides two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {vec4} out
+ */
+ export function div(out: vec4, a: ReadonlyVec4, b: ReadonlyVec4): vec4;
+ /**
+ * Calculates the euclidian distance between two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} distance between a and b
+ */
+ export function dist(a: ReadonlyVec4, b: ReadonlyVec4): number;
+ /**
+ * Calculates the squared euclidian distance between two vec4's
+ *
+ * @param {ReadonlyVec4} a the first operand
+ * @param {ReadonlyVec4} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+ export function sqrDist(a: ReadonlyVec4, b: ReadonlyVec4): number;
+ /**
+ * Calculates the length of a vec4
+ *
+ * @param {ReadonlyVec4} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+ export function len(a: ReadonlyVec4): number;
+ /**
+ * Calculates the squared length of a vec4
+ *
+ * @param {ReadonlyVec4} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+ export function sqrLen(a: ReadonlyVec4): number;
+ export function forEach(a: any, stride: any, offset: any, count: any, fn: any, arg: any): any;
+}
+export module quat {
+ /**
+ * Quaternion
+ * @module quat
+ */
+ /**
+ * Creates a new identity quat
+ *
+ * @returns {quat} a new quaternion
+ */
+ export function create(): quat;
+ /**
+ * Set a quat to the identity quaternion
+ *
+ * @param {quat} out the receiving quaternion
+ * @returns {quat} out
+ */
+ export function identity(out: quat): quat;
+ /**
+ * Sets a quat from the given angle and rotation axis,
+ * then returns it.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyVec3} axis the axis around which to rotate
+ * @param {Number} rad the angle in radians
+ * @returns {quat} out
+ **/
+ export function setAxisAngle(out: quat, axis: ReadonlyVec3, rad: number): quat;
+ /**
+ * Gets the rotation axis and angle for a given
+ * quaternion. If a quaternion is created with
+ * setAxisAngle, this method will return the same
+ * values as providied in the original parameter list
+ * OR functionally equivalent values.
+ * Example: The quaternion formed by axis [0, 0, 1] and
+ * angle -90 is the same as the quaternion formed by
+ * [0, 0, 1] and 270. This method favors the latter.
+ * @param {vec3} out_axis Vector receiving the axis of rotation
+ * @param {ReadonlyQuat} q Quaternion to be decomposed
+ * @return {Number} Angle, in radians, of the rotation
+ */
+ export function getAxisAngle(out_axis: vec3, q: ReadonlyQuat): number;
+ /**
+ * Gets the angular distance between two unit quaternions
+ *
+ * @param {ReadonlyQuat} a Origin unit quaternion
+ * @param {ReadonlyQuat} b Destination unit quaternion
+ * @return {Number} Angle, in radians, between the two quaternions
+ */
+ export function getAngle(a: ReadonlyQuat, b: ReadonlyQuat): number;
+ /**
+ * Multiplies two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {quat} out
+ */
+ export function multiply(out: quat, a: ReadonlyQuat, b: ReadonlyQuat): quat;
+ /**
+ * Rotates a quaternion by the given angle about the X axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+ export function rotateX(out: quat, a: ReadonlyQuat, rad: number): quat;
+ /**
+ * Rotates a quaternion by the given angle about the Y axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+ export function rotateY(out: quat, a: ReadonlyQuat, rad: number): quat;
+ /**
+ * Rotates a quaternion by the given angle about the Z axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {ReadonlyQuat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+ export function rotateZ(out: quat, a: ReadonlyQuat, rad: number): quat;
+ /**
+ * Calculates the W component of a quat from the X, Y, and Z components.
+ * Assumes that quaternion is 1 unit in length.
+ * Any existing W component will be ignored.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate W component of
+ * @returns {quat} out
+ */
+ export function calculateW(out: quat, a: ReadonlyQuat): quat;
+ /**
+ * Calculate the exponential of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @returns {quat} out
+ */
+ export function exp(out: quat, a: ReadonlyQuat): quat;
+ /**
+ * Calculate the natural logarithm of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @returns {quat} out
+ */
+ export function ln(out: quat, a: ReadonlyQuat): quat;
+ /**
+ * Calculate the scalar power of a unit quaternion.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate the exponential of
+ * @param {Number} b amount to scale the quaternion by
+ * @returns {quat} out
+ */
+ export function pow(out: quat, a: ReadonlyQuat, b: number): quat;
+ /**
+ * Performs a spherical linear interpolation between two quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ */
+ export function slerp(out: quat, a: ReadonlyQuat, b: ReadonlyQuat, t: number): quat;
+ /**
+ * Generates a random unit quaternion
+ *
+ * @param {quat} out the receiving quaternion
+ * @returns {quat} out
+ */
+ export function random(out: quat): quat;
+ /**
+ * Calculates the inverse of a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate inverse of
+ * @returns {quat} out
+ */
+ export function invert(out: quat, a: ReadonlyQuat): quat;
+ /**
+ * Calculates the conjugate of a quat
+ * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quat to calculate conjugate of
+ * @returns {quat} out
+ */
+ export function conjugate(out: quat, a: ReadonlyQuat): quat;
+ /**
+ * Creates a quaternion from the given 3x3 rotation matrix.
+ *
+ * NOTE: The resultant quaternion is not normalized, so you should be sure
+ * to renormalize the quaternion yourself where necessary.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyMat3} m rotation matrix
+ * @returns {quat} out
+ * @function
+ */
+ export function fromMat3(out: quat, m: ReadonlyMat3): quat;
+ /**
+ * Creates a quaternion from the given euler angle x, y, z.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {x} Angle to rotate around X axis in degrees.
+ * @param {y} Angle to rotate around Y axis in degrees.
+ * @param {z} Angle to rotate around Z axis in degrees.
+ * @returns {quat} out
+ * @function
+ */
+ export function fromEuler(out: quat, x: any, y: any, z: any): quat;
+ /**
+ * Returns a string representation of a quatenion
+ *
+ * @param {ReadonlyQuat} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+ export function str(a: ReadonlyQuat): string;
+ /**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {ReadonlyQuat} a quaternion to clone
+ * @returns {quat} a new quaternion
+ * @function
+ */
+ export const clone: typeof vec4.clone;
+ /**
+ * Creates a new quat initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} a new quaternion
+ * @function
+ */
+ export const fromValues: typeof vec4.fromValues;
+ /**
+ * Copy the values from one quat to another
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the source quaternion
+ * @returns {quat} out
+ * @function
+ */
+ export const copy: typeof vec4.copy;
+ /**
+ * Set the components of a quat to the given values
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} out
+ * @function
+ */
+ export const set: typeof vec4.set;
+ /**
+ * Adds two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {quat} out
+ * @function
+ */
+ export const add: typeof vec4.add;
+ /**
+ * Multiplies two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {quat} out
+ */
+ export function mul(out: quat, a: ReadonlyQuat, b: ReadonlyQuat): quat;
+ /**
+ * Scales a quat by a scalar number
+ *
+ * @param {quat} out the receiving vector
+ * @param {ReadonlyQuat} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {quat} out
+ * @function
+ */
+ export const scale: typeof vec4.scale;
+ /**
+ * Calculates the dot product of two quat's
+ *
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+ export const dot: typeof vec4.dot;
+ /**
+ * Performs a linear interpolation between two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a the first operand
+ * @param {ReadonlyQuat} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat} out
+ * @function
+ */
+ export const lerp: typeof vec4.lerp;
+ /**
+ * Calculates the length of a quat
+ *
+ * @param {ReadonlyQuat} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+ export const length: typeof vec4.length;
+ /**
+ * Alias for {@link quat.length}
+ * @function
+ */
+ export const len: typeof vec4.length;
+ /**
+ * Calculates the squared length of a quat
+ *
+ * @param {ReadonlyQuat} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+ export const squaredLength: typeof vec4.squaredLength;
+ /**
+ * Alias for {@link quat.squaredLength}
+ * @function
+ */
+ export const sqrLen: typeof vec4.squaredLength;
+ /**
+ * Normalize a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {ReadonlyQuat} a quaternion to normalize
+ * @returns {quat} out
+ * @function
+ */
+ export const normalize: typeof vec4.normalize;
+ /**
+ * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyQuat} a The first quaternion.
+ * @param {ReadonlyQuat} b The second quaternion.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+ export const exactEquals: typeof vec4.exactEquals;
+ /**
+ * Returns whether or not the quaternions have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyQuat} a The first vector.
+ * @param {ReadonlyQuat} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+ export const equals: typeof vec4.equals;
+ export function rotationTo(out: any, a: any, b: any): any;
+ export function sqlerp(out: any, a: any, b: any, c: any, d: any, t: any): any;
+ export function setAxes(out: any, view: any, right: any, up: any): vec4;
+
+}
+export module quat2 {
+ /**
+ * Dual Quaternion
+ * Format: [real, dual]
+ * Quaternion format: XYZW
+ * Make sure to have normalized dual quaternions, otherwise the functions may not work as intended.
+ * @module quat2
+ */
+ /**
+ * Creates a new identity dual quat
+ *
+ * @returns {quat2} a new dual quaternion [real -> rotation, dual -> translation]
+ */
+ export function create(): quat2;
+ /**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {ReadonlyQuat2} a dual quaternion to clone
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+ export function clone(a: ReadonlyQuat2): quat2;
+ /**
+ * Creates a new dual quat initialized with the given values
+ *
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component
+ * @param {Number} y2 Y component
+ * @param {Number} z2 Z component
+ * @param {Number} w2 W component
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+ export function fromValues(x1: number, y1: number, z1: number, w1: number, x2: number, y2: number, z2: number, w2: number): quat2;
+ /**
+ * Creates a new dual quat from the given values (quat and translation)
+ *
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component (translation)
+ * @param {Number} y2 Y component (translation)
+ * @param {Number} z2 Z component (translation)
+ * @returns {quat2} new dual quaternion
+ * @function
+ */
+ export function fromRotationTranslationValues(x1: number, y1: number, z1: number, w1: number, x2: number, y2: number, z2: number): quat2;
+ /**
+ * Creates a dual quat from a quaternion and a translation
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyQuat} q a normalized quaternion
+ * @param {ReadonlyVec3} t tranlation vector
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+ export function fromRotationTranslation(out: any, q: ReadonlyQuat, t: ReadonlyVec3): quat2;
+ /**
+ * Creates a dual quat from a translation
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyVec3} t translation vector
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+ export function fromTranslation(out: any, t: ReadonlyVec3): quat2;
+ /**
+ * Creates a dual quat from a quaternion
+ *
+ * @param {ReadonlyQuat2} dual quaternion receiving operation result
+ * @param {ReadonlyQuat} q the quaternion
+ * @returns {quat2} dual quaternion receiving operation result
+ * @function
+ */
+ export function fromRotation(out: any, q: ReadonlyQuat): quat2;
+ /**
+ * Creates a new dual quat from a matrix (4x4)
+ *
+ * @param {quat2} out the dual quaternion
+ * @param {ReadonlyMat4} a the matrix
+ * @returns {quat2} dual quat receiving operation result
+ * @function
+ */
+ export function fromMat4(out: quat2, a: ReadonlyMat4): quat2;
+ /**
+ * Copy the values from one dual quat to another
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the source dual quaternion
+ * @returns {quat2} out
+ * @function
+ */
+ export function copy(out: quat2, a: ReadonlyQuat2): quat2;
+ /**
+ * Set a dual quat to the identity dual quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @returns {quat2} out
+ */
+ export function identity(out: quat2): quat2;
+ /**
+ * Set the components of a dual quat to the given values
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {Number} x1 X component
+ * @param {Number} y1 Y component
+ * @param {Number} z1 Z component
+ * @param {Number} w1 W component
+ * @param {Number} x2 X component
+ * @param {Number} y2 Y component
+ * @param {Number} z2 Z component
+ * @param {Number} w2 W component
+ * @returns {quat2} out
+ * @function
+ */
+ export function set(out: quat2, x1: number, y1: number, z1: number, w1: number, x2: number, y2: number, z2: number, w2: number): quat2;
+ /**
+ * Gets the dual part of a dual quat
+ * @param {quat} out dual part
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @return {quat} dual part
+ */
+ export function getDual(out: quat, a: ReadonlyQuat2): quat;
+ /**
+ * Set the dual component of a dual quat to the given quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat} q a quaternion representing the dual part
+ * @returns {quat2} out
+ * @function
+ */
+ export function setDual(out: quat2, q: ReadonlyQuat): quat2;
+ /**
+ * Gets the translation of a normalized dual quat
+ * @param {vec3} out translation
+ * @param {ReadonlyQuat2} a Dual Quaternion to be decomposed
+ * @return {vec3} translation
+ */
+ export function getTranslation(out: vec3, a: ReadonlyQuat2): vec3;
+ /**
+ * Translates a dual quat by the given vector
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to translate
+ * @param {ReadonlyVec3} v vector to translate by
+ * @returns {quat2} out
+ */
+ export function translate(out: quat2, a: ReadonlyQuat2, v: ReadonlyVec3): quat2;
+ /**
+ * Rotates a dual quat around the X axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+ export function rotateX(out: quat2, a: ReadonlyQuat2, rad: number): quat2;
+ /**
+ * Rotates a dual quat around the Y axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+ export function rotateY(out: quat2, a: ReadonlyQuat2, rad: number): quat2;
+ /**
+ * Rotates a dual quat around the Z axis
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {number} rad how far should the rotation be
+ * @returns {quat2} out
+ */
+ export function rotateZ(out: quat2, a: ReadonlyQuat2, rad: number): quat2;
+ /**
+ * Rotates a dual quat by a given quaternion (a * q)
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {ReadonlyQuat} q quaternion to rotate by
+ * @returns {quat2} out
+ */
+ export function rotateByQuatAppend(out: quat2, a: ReadonlyQuat2, q: ReadonlyQuat): quat2;
+ /**
+ * Rotates a dual quat by a given quaternion (q * a)
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat} q quaternion to rotate by
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @returns {quat2} out
+ */
+ export function rotateByQuatPrepend(out: quat2, q: ReadonlyQuat, a: ReadonlyQuat2): quat2;
+ /**
+ * Rotates a dual quat around a given axis. Does the normalisation automatically
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the dual quaternion to rotate
+ * @param {ReadonlyVec3} axis the axis to rotate around
+ * @param {Number} rad how far the rotation should be
+ * @returns {quat2} out
+ */
+ export function rotateAroundAxis(out: quat2, a: ReadonlyQuat2, axis: ReadonlyVec3, rad: number): quat2;
+ /**
+ * Adds two dual quat's
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {quat2} out
+ * @function
+ */
+ export function add(out: quat2, a: ReadonlyQuat2, b: ReadonlyQuat2): quat2;
+ /**
+ * Multiplies two dual quat's
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {quat2} out
+ */
+ export function multiply(out: quat2, a: ReadonlyQuat2, b: ReadonlyQuat2): quat2;
+ /**
+ * Scales a dual quat by a scalar number
+ *
+ * @param {quat2} out the receiving dual quat
+ * @param {ReadonlyQuat2} a the dual quat to scale
+ * @param {Number} b amount to scale the dual quat by
+ * @returns {quat2} out
+ * @function
+ */
+ export function scale(out: quat2, a: ReadonlyQuat2, b: number): quat2;
+ /**
+ * Performs a linear interpolation between two dual quats's
+ * NOTE: The resulting dual quaternions won't always be normalized (The error is most noticeable when t = 0.5)
+ *
+ * @param {quat2} out the receiving dual quat
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {quat2} out
+ */
+ export function lerp(out: quat2, a: ReadonlyQuat2, b: ReadonlyQuat2, t: number): quat2;
+ /**
+ * Calculates the inverse of a dual quat. If they are normalized, conjugate is cheaper
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a dual quat to calculate inverse of
+ * @returns {quat2} out
+ */
+ export function invert(out: quat2, a: ReadonlyQuat2): quat2;
+ /**
+ * Calculates the conjugate of a dual quat
+ * If the dual quaternion is normalized, this function is faster than quat2.inverse and produces the same result.
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat2} a quat to calculate conjugate of
+ * @returns {quat2} out
+ */
+ export function conjugate(out: quat2, a: ReadonlyQuat2): quat2;
+ /**
+ * Normalize a dual quat
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a dual quaternion to normalize
+ * @returns {quat2} out
+ * @function
+ */
+ export function normalize(out: quat2, a: ReadonlyQuat2): quat2;
+ /**
+ * Returns a string representation of a dual quatenion
+ *
+ * @param {ReadonlyQuat2} a dual quaternion to represent as a string
+ * @returns {String} string representation of the dual quat
+ */
+ export function str(a: ReadonlyQuat2): string;
+ /**
+ * Returns whether or not the dual quaternions have exactly the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyQuat2} a the first dual quaternion.
+ * @param {ReadonlyQuat2} b the second dual quaternion.
+ * @returns {Boolean} true if the dual quaternions are equal, false otherwise.
+ */
+ export function exactEquals(a: ReadonlyQuat2, b: ReadonlyQuat2): boolean;
+ /**
+ * Returns whether or not the dual quaternions have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyQuat2} a the first dual quat.
+ * @param {ReadonlyQuat2} b the second dual quat.
+ * @returns {Boolean} true if the dual quats are equal, false otherwise.
+ */
+ export function equals(a: ReadonlyQuat2, b: ReadonlyQuat2): boolean;
+ /**
+ * Gets the real part of a dual quat
+ * @param {quat} out real part
+ * @param {ReadonlyQuat2} a Dual Quaternion
+ * @return {quat} real part
+ */
+ export const getReal: typeof vec4.copy;
+ /**
+ * Set the real component of a dual quat to the given quaternion
+ *
+ * @param {quat2} out the receiving quaternion
+ * @param {ReadonlyQuat} q a quaternion representing the real part
+ * @returns {quat2} out
+ * @function
+ */
+ export const setReal: typeof vec4.copy;
+ /**
+ * Multiplies two dual quat's
+ *
+ * @param {quat2} out the receiving dual quaternion
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {quat2} out
+ */
+ export function mul(out: quat2, a: ReadonlyQuat2, b: ReadonlyQuat2): quat2;
+ /**
+ * Calculates the dot product of two dual quat's (The dot product of the real parts)
+ *
+ * @param {ReadonlyQuat2} a the first operand
+ * @param {ReadonlyQuat2} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+ export const dot: typeof vec4.dot;
+ /**
+ * Calculates the length of a dual quat
+ *
+ * @param {ReadonlyQuat2} a dual quat to calculate length of
+ * @returns {Number} length of a
+ * @function
+ */
+ export const length: typeof vec4.length;
+ /**
+ * Alias for {@link quat2.length}
+ * @function
+ */
+ export const len: typeof vec4.length;
+ /**
+ * Calculates the squared length of a dual quat
+ *
+ * @param {ReadonlyQuat2} a dual quat to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+ export const squaredLength: typeof vec4.squaredLength;
+ /**
+ * Alias for {@link quat2.squaredLength}
+ * @function
+ */
+ export const sqrLen: typeof vec4.squaredLength;
+}
+export module vec2 {
+ /**
+ * 2 Dimensional Vector
+ * @module vec2
+ */
+ /**
+ * Creates a new, empty vec2
+ *
+ * @returns {vec2} a new 2D vector
+ */
+ export function create(): vec2;
+ /**
+ * Creates a new vec2 initialized with values from an existing vector
+ *
+ * @param {ReadonlyVec2} a vector to clone
+ * @returns {vec2} a new 2D vector
+ */
+ export function clone(a: ReadonlyVec2): vec2;
+ /**
+ * Creates a new vec2 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} a new 2D vector
+ */
+ export function fromValues(x: number, y: number): vec2;
+ /**
+ * Copy the values from one vec2 to another
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the source vector
+ * @returns {vec2} out
+ */
+ export function copy(out: vec2, a: ReadonlyVec2): vec2;
+ /**
+ * Set the components of a vec2 to the given values
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} out
+ */
+ export function set(out: vec2, x: number, y: number): vec2;
+ /**
+ * Adds two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+ export function add(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2): vec2;
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+ export function subtract(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2): vec2;
+ /**
+ * Multiplies two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+ export function multiply(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2): vec2;
+ /**
+ * Divides two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+ export function divide(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2): vec2;
+ /**
+ * Math.ceil the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to ceil
+ * @returns {vec2} out
+ */
+ export function ceil(out: vec2, a: ReadonlyVec2): vec2;
+ /**
+ * Math.floor the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to floor
+ * @returns {vec2} out
+ */
+ export function floor(out: vec2, a: ReadonlyVec2): vec2;
+ /**
+ * Returns the minimum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+ export function min(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2): vec2;
+ /**
+ * Returns the maximum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+ export function max(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2): vec2;
+ /**
+ * Math.round the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to round
+ * @returns {vec2} out
+ */
+ export function round(out: vec2, a: ReadonlyVec2): vec2;
+ /**
+ * Scales a vec2 by a scalar number
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec2} out
+ */
+ export function scale(out: vec2, a: ReadonlyVec2, b: number): vec2;
+ /**
+ * Adds two vec2's after scaling the second operand by a scalar value
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec2} out
+ */
+ export function scaleAndAdd(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2, scale: number): vec2;
+ /**
+ * Calculates the euclidian distance between two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} distance between a and b
+ */
+ export function distance(a: ReadonlyVec2, b: ReadonlyVec2): number;
+ /**
+ * Calculates the squared euclidian distance between two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+ export function squaredDistance(a: ReadonlyVec2, b: ReadonlyVec2): number;
+ /**
+ * Calculates the length of a vec2
+ *
+ * @param {ReadonlyVec2} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+ export function length(a: ReadonlyVec2): number;
+ /**
+ * Calculates the squared length of a vec2
+ *
+ * @param {ReadonlyVec2} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+ export function squaredLength(a: ReadonlyVec2): number;
+ /**
+ * Negates the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to negate
+ * @returns {vec2} out
+ */
+ export function negate(out: vec2, a: ReadonlyVec2): vec2;
+ /**
+ * Returns the inverse of the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to invert
+ * @returns {vec2} out
+ */
+ export function inverse(out: vec2, a: ReadonlyVec2): vec2;
+ /**
+ * Normalize a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a vector to normalize
+ * @returns {vec2} out
+ */
+ export function normalize(out: vec2, a: ReadonlyVec2): vec2;
+ /**
+ * Calculates the dot product of two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+ export function dot(a: ReadonlyVec2, b: ReadonlyVec2): number;
+ /**
+ * Computes the cross product of two vec2's
+ * Note that the cross product must by definition produce a 3D vector
+ *
+ * @param {vec3} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec3} out
+ */
+ export function cross(out: vec3, a: ReadonlyVec2, b: ReadonlyVec2): vec3;
+ /**
+ * Performs a linear interpolation between two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
+ * @returns {vec2} out
+ */
+ export function lerp(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2, t: number): vec2;
+ /**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec2} out
+ */
+ export function random(out: vec2, scale?: number): vec2;
+ /**
+ * Transforms the vec2 with a mat2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat2} m matrix to transform with
+ * @returns {vec2} out
+ */
+ export function transformMat2(out: vec2, a: ReadonlyVec2, m: ReadonlyMat2): vec2;
+ /**
+ * Transforms the vec2 with a mat2d
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat2d} m matrix to transform with
+ * @returns {vec2} out
+ */
+ export function transformMat2d(out: vec2, a: ReadonlyVec2, m: ReadonlyMat2d): vec2;
+ /**
+ * Transforms the vec2 with a mat3
+ * 3rd vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat3} m matrix to transform with
+ * @returns {vec2} out
+ */
+ export function transformMat3(out: vec2, a: ReadonlyVec2, m: ReadonlyMat3): vec2;
+ /**
+ * Transforms the vec2 with a mat4
+ * 3rd vector component is implicitly '0'
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the vector to transform
+ * @param {ReadonlyMat4} m matrix to transform with
+ * @returns {vec2} out
+ */
+ export function transformMat4(out: vec2, a: ReadonlyVec2, m: ReadonlyMat4): vec2;
+ /**
+ * Rotate a 2D vector
+ * @param {vec2} out The receiving vec2
+ * @param {ReadonlyVec2} a The vec2 point to rotate
+ * @param {ReadonlyVec2} b The origin of the rotation
+ * @param {Number} rad The angle of rotation in radians
+ * @returns {vec2} out
+ */
+ export function rotate(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2, rad: number): vec2;
+ /**
+ * Get the angle between two 2D vectors
+ * @param {ReadonlyVec2} a The first operand
+ * @param {ReadonlyVec2} b The second operand
+ * @returns {Number} The angle in radians
+ */
+ export function angle(a: ReadonlyVec2, b: ReadonlyVec2): number;
+ /**
+ * Set the components of a vec2 to zero
+ *
+ * @param {vec2} out the receiving vector
+ * @returns {vec2} out
+ */
+ export function zero(out: vec2): vec2;
+ /**
+ * Returns a string representation of a vector
+ *
+ * @param {ReadonlyVec2} a vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+ export function str(a: ReadonlyVec2): string;
+ /**
+ * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
+ *
+ * @param {ReadonlyVec2} a The first vector.
+ * @param {ReadonlyVec2} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+ export function exactEquals(a: ReadonlyVec2, b: ReadonlyVec2): boolean;
+ /**
+ * Returns whether or not the vectors have approximately the same elements in the same position.
+ *
+ * @param {ReadonlyVec2} a The first vector.
+ * @param {ReadonlyVec2} b The second vector.
+ * @returns {Boolean} True if the vectors are equal, false otherwise.
+ */
+ export function equals(a: ReadonlyVec2, b: ReadonlyVec2): boolean;
+ /**
+ * Calculates the length of a vec2
+ *
+ * @param {ReadonlyVec2} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+ export function len(a: ReadonlyVec2): number;
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+ export function sub(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2): vec2;
+ /**
+ * Multiplies two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+ export function mul(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2): vec2;
+ /**
+ * Divides two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {vec2} out
+ */
+ export function div(out: vec2, a: ReadonlyVec2, b: ReadonlyVec2): vec2;
+ /**
+ * Calculates the euclidian distance between two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} distance between a and b
+ */
+ export function dist(a: ReadonlyVec2, b: ReadonlyVec2): number;
+ /**
+ * Calculates the squared euclidian distance between two vec2's
+ *
+ * @param {ReadonlyVec2} a the first operand
+ * @param {ReadonlyVec2} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+ export function sqrDist(a: ReadonlyVec2, b: ReadonlyVec2): number;
+ /**
+ * Calculates the squared length of a vec2
+ *
+ * @param {ReadonlyVec2} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+ export function sqrLen(a: ReadonlyVec2): number;
+ export function forEach(a: any, stride: any, offset: any, count: any, fn: any, arg: any): any;
+}
+
+
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/mat2/package.json b/public/node_modules/gl-matrix/mat2/package.json
new file mode 100644
index 0000000..1f131c4
--- /dev/null
+++ b/public/node_modules/gl-matrix/mat2/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "gl-matrix/mat2",
+ "main": "../cjs/mat2.js",
+ "module": "../esm/mat2.js"
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/mat2d/package.json b/public/node_modules/gl-matrix/mat2d/package.json
new file mode 100644
index 0000000..f9af4d7
--- /dev/null
+++ b/public/node_modules/gl-matrix/mat2d/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "gl-matrix/mat2d",
+ "main": "../cjs/mat2d.js",
+ "module": "../esm/mat2d.js"
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/mat3/package.json b/public/node_modules/gl-matrix/mat3/package.json
new file mode 100644
index 0000000..23f5f95
--- /dev/null
+++ b/public/node_modules/gl-matrix/mat3/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "gl-matrix/mat3",
+ "main": "../cjs/mat3.js",
+ "module": "../esm/mat3.js"
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/mat4/package.json b/public/node_modules/gl-matrix/mat4/package.json
new file mode 100644
index 0000000..9de35a9
--- /dev/null
+++ b/public/node_modules/gl-matrix/mat4/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "gl-matrix/mat4",
+ "main": "../cjs/mat4.js",
+ "module": "../esm/mat4.js"
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/package.json b/public/node_modules/gl-matrix/package.json
new file mode 100644
index 0000000..6d2fbf1
--- /dev/null
+++ b/public/node_modules/gl-matrix/package.json
@@ -0,0 +1,27 @@
+{
+ "version": "3.4.3",
+ "name": "gl-matrix",
+ "description": "Javascript Matrix and Vector library for High Performance WebGL apps",
+ "sideEffects": false,
+ "main": "cjs/index.js",
+ "module": "esm/index.js",
+ "homepage": "http://glmatrix.net",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/toji/gl-matrix/issues"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/toji/gl-matrix.git"
+ },
+ "contributors": [
+ {
+ "name": "Brandon Jones",
+ "email": "tojiro@gmail.com"
+ },
+ {
+ "name": "Colin MacKenzie IV",
+ "email": "sinisterchipmunk@gmail.com"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/quat/package.json b/public/node_modules/gl-matrix/quat/package.json
new file mode 100644
index 0000000..264ee35
--- /dev/null
+++ b/public/node_modules/gl-matrix/quat/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "gl-matrix/quat",
+ "main": "../cjs/quat.js",
+ "module": "../esm/quat.js"
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/quat2/package.json b/public/node_modules/gl-matrix/quat2/package.json
new file mode 100644
index 0000000..119de4e
--- /dev/null
+++ b/public/node_modules/gl-matrix/quat2/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "gl-matrix/quat2",
+ "main": "../cjs/quat2.js",
+ "module": "../esm/quat2.js"
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/types.d.ts/package.json b/public/node_modules/gl-matrix/types.d.ts/package.json
new file mode 100644
index 0000000..1f79746
--- /dev/null
+++ b/public/node_modules/gl-matrix/types.d.ts/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "gl-matrix/types.d.ts",
+ "main": "../cjs/types.d.ts",
+ "module": "../esm/types.d.ts"
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/vec2/package.json b/public/node_modules/gl-matrix/vec2/package.json
new file mode 100644
index 0000000..b58bf53
--- /dev/null
+++ b/public/node_modules/gl-matrix/vec2/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "gl-matrix/vec2",
+ "main": "../cjs/vec2.js",
+ "module": "../esm/vec2.js"
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/vec3/package.json b/public/node_modules/gl-matrix/vec3/package.json
new file mode 100644
index 0000000..6dbaa7b
--- /dev/null
+++ b/public/node_modules/gl-matrix/vec3/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "gl-matrix/vec3",
+ "main": "../cjs/vec3.js",
+ "module": "../esm/vec3.js"
+}
\ No newline at end of file
diff --git a/public/node_modules/gl-matrix/vec4/package.json b/public/node_modules/gl-matrix/vec4/package.json
new file mode 100644
index 0000000..c51be75
--- /dev/null
+++ b/public/node_modules/gl-matrix/vec4/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "gl-matrix/vec4",
+ "main": "../cjs/vec4.js",
+ "module": "../esm/vec4.js"
+}
\ No newline at end of file
diff --git a/public/scripts/does-it-glider-app.js b/public/scripts/does-it-glider-app.js
deleted file mode 100644
index c638d6c..0000000
--- a/public/scripts/does-it-glider-app.js
+++ /dev/null
@@ -1,198 +0,0 @@
-// does it glider app
-//
-
-import {gol_field} from './gol-field.js'
-import {apply_rules, set_state} from './gol-play.js'
-import {draw} from './does-it-glider-draw.js'
-
-console.log('script started')
-
-// initialize
-d3.select('body').style('margin', '0px')
-
-const app = d3.select('.does-it-glider-app')
-
-// Create the title
-let touch_target = app.append("span")
- .classed("touch-target", true)
- .style("z-index", "2")
-
-const _title = "Does it Glider?"
-const _sub_title = "Tap here to paste Wordle score."
-// max width reference: "##################################"
-// abbove is max width on smallest mobile (iPhone SE)
-
-touch_target.append("div")
- .attr("class", "title")
- .html(_title)
-touch_target.append("div")
- .attr("class", "title sub-title")
- .html(_sub_title)
-
-// make a gol field in the app DOM element
-const field = gol_field(app)
-
-// make a new 2D array the size of the 5x6 start pattern
-let start = []
-// set the start pattern using life_seed format
-start[0] = 'β¬β¬β¬β¬β¬'
-start[1] = 'β¬β¬β¬β¬β¬'
-start[2] = 'β¬β¬β¬β¬β¬'
-start[3] = 'β¬β¬β¬β¬β¬'
-start[4] = 'β¬β¬β¬β¬β¬'
-start[5] = 'β¬β¬β¬β¬β¬'
-
-// get the width and height of the gol_field
-let field_h = field.node().getBoundingClientRect().height
-let field_w = field.node().getBoundingClientRect().width
-// divide field_h and field_w by 20px and round to int
-field_h = Math.round(field_h / 20)
-field_w = Math.round(field_w / 20)
-// make a new 2D array the size of the g element divide by 20px
-// let state = new Array(field_h).fill(new Array(field_w).fill('β¬'))
-let state = Array.from({length: field_h}, () => Array.from({length: field_w}, () => 'β¬'))
-
-// copy the start into the center of the state
-set_state(start, state)
-
-// render start as a 2D array of rects in the svg
-draw(field, state)
-
-let beat = (60 * 1000) / 180 // 180bpm for animations, units are in msec
-
-// run the game of life
-// call apply_rules() and draw() every beat msecs
-setInterval(() => {
- // apply the rules to the state
- state = apply_rules(state)
- // draw the state
- draw(field, state)
-}, beat/4)
-
-let life_seed = []
-
-// d3.select('body').on('paste', event => {
-d3.selectAll('.touch-target').on('drag', e => {
- console.log('drag event blocked')
- e.stopPropagation()
- e.preventDefault()
-})
-d3.selectAll('.touch-target').on('zoom', e => {
- console.log('zoom event blocked')
- e.stopPropagation()
- e.preventDefault()
-})
-d3.selectAll('.touch-target').on('scroll', e => {
- console.log('scroll event blocked')
- e.stopPropagation()
- e.preventDefault()
-})
-
-const get_clipboard = (pasted_clipboard) => {
- console.log('click event heard')
-
- let pasted_lines = []
- console.log(`pasted_clipboard: ${pasted_clipboard}`)
- pasted_lines = pasted_clipboard.split(/\r\n|\r|\n/ug)
- console.log(`split lines: ${pasted_lines}`)
-
- // filter pasted_lines for only lines that are length 5
- // and contain only 'β¬', 'π¨', 'π©', or 'β¬'
- let wordle_guesses = []
- wordle_guesses = pasted_lines
- .filter(line => line.match(/β¬|π¨|π©|β¬|π¦|π§|o|b/ug)?.length == 5)
- // this is only lines with exactly 5 wordle squares
- console.log(`filtered wordle_guesses: ${wordle_guesses}`)
-
- // convert all 'π¨'|'π©' in wordle_guesses to 'β¬' and 'β¬'|'β¬' to 'β¬'
- life_seed = []
- wordle_guesses.map(guess =>
- life_seed.push(
- guess
- // need an intermediate character to avoid double replacement
- .replace(/π¨|π©|π¦|π§|o/g,'o')
- .replace(/β¬|β¬|b/g,'β¬')
- .replace(/o/g,'β¬') // replace intermediate character
- )
- )
- console.log(`life_seed: ${life_seed}`)
-
- let beat_pasted = beat
- let beat_wordle_guesses = beat
- let beat_life_seed = beat
- // draw/render pasted_lines in the .paste-line divs
- const draw_pasted_lines = () => {
- app
- .selectAll('.paste-line')
- .data(pasted_lines)
- .join(
- enter => enter.append('div').classed('paste-line', true)
- .style('min-height', '1.5em'),
- update => update,
- exit => exit
- .remove()
- )
- // new line effect on both enter and update
- .html(line => line || ' ')
- .transition()
- .delay(0)
- .duration(beat_pasted)
- .remove()
- }
-
- const draw_guesses = () => {
- app
- .selectAll('.paste-line')
- .data(life_seed)
- // d3.data() stores the array life_seed on the parent DOM element
- // then d3.join() compares new data to previous data
- // and calls enter, update, or exit on each element of data array
- // as appropriate for diff of new data comapred to previous data
- .join(
- enter => enter.append('div').classed('paste-line', true),
- update => update,
- exit => exit
- .remove()
- ) //join returns enter and update merged
- .selection(0)
- .transition()
- .delay(beat_pasted)
- .duration(0)
- .selection()
- .html((_data, i) => wordle_guesses[i])
- .transition()
- .delay(beat_wordle_guesses)
- .duration(0)
- .selection()
- .html(d => d)
- .transition()
- .delay(beat_wordle_guesses)
- .duration(0)
- .remove()
-
- }
-
- const load_new_state = (life_seed) => {
- // log time of event
- console.log(`Enter load_new_state: ${new Date().getTime()}`)
- // clear the state
- state = Array.from({length: field_h}, () => Array.from({length: field_w}, () => 'β¬'))
- // copy the life_seed into the center of the state
- set_state(life_seed, state)
- draw(field, state)
- }
-
- draw_pasted_lines()
- // draw_guesses()
- setTimeout(
- load_new_state.bind(null, life_seed),
- beat_pasted + beat_wordle_guesses + beat_life_seed
- )
-}
-
-d3.select('.touch-target').on('click', event => {
- event.preventDefault()
- navigator.clipboard.readText().then(get_clipboard)
-})
-
-
diff --git a/public/scripts/does-it-glider-draw.js b/public/scripts/does-it-glider-draw.js
deleted file mode 100644
index 1634be6..0000000
--- a/public/scripts/does-it-glider-draw.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// does-it-glider-draw.js
-// modify the DOM from a 2D array of Conway's Game of Life (gol_state)
-export const draw = (g, state) => {
- // render/draw each live cell in state as a white rect in the svg
- // clear all of the old rects first
- let all = g.selectAll("rect.live_cell")
- all.remove()
- // loop over 2D array state
- for(let y = 0; y < state.length; y++) {
- for(let x = 0; x < state[0].length; x++) {
- // if the cell is alive
- // console.log(state[y][x])
- if (state[y][x] == 'β¬') {
- // draw a white rect in the svg
- g.append("rect").classed("live_cell", true)
- .attr("x", `${x * 20}px`)
- .attr("y", `${y * 20}px`)
- .attr("width", `${20}px`)
- .attr("height", `${20}px`)
- .attr("fill", "#ffffff")
- }
- }
- }
-}
diff --git a/public/scripts/gol-field.js b/public/scripts/gol-field.js
deleted file mode 100644
index ac656c8..0000000
--- a/public/scripts/gol-field.js
+++ /dev/null
@@ -1,62 +0,0 @@
-// gol-field.js - Game of Life - field
-// INPUT a d3 selection
-// adds a graph paper pattern to it
-// makes it zoom+pan in response to mouse and touch events
-// RETURN a d3 selection of the field that other gol functions can use
-
-export const gol_field = (app) => {
- // Create the SVG
- const svg = app.append("svg")
- .style("pointer-events", "all")
- //make this element behind all others
- .style("z-index", "-1")
- .attr("width", "400%")
- .attr("height", "400%")
- .style("position", "absolute")
- .style("left", "-150%")
- .style("top", "-150%");
-
- // create a g element inside the svg
- // need this g element so we can transform it
- // and leave the svg container static
- const g = svg.append("g");
-
- // Create the graph paper pattern
- const pattern = g.append("defs")
- .append("pattern")
- .attr("id", "grid")
- .attr("width", "20px")
- .attr("height", "20px")
- .attr("patternUnits", "userSpaceOnUse");
-
- pattern.append("path")
- .attr("fill", "none")
- .attr("d", "M 20 0 L 0 0 0 20")
- .attr("stroke-width", "0.5px")
- .attr("stroke", "#86888a");
-
- g.append("rect")
- .attr("width", "100%")
- .attr("height", "100%")
- .attr("fill", "#212121");
-
- g.append("rect")
- .attr("width", "100%")
- .attr("height", "100%")
- .attr("fill", "url(#grid)")
-
- function zoomed({transform}) {
- // use svg zoom and drag units to transform the g element
- g.attr("transform", transform)
- }
-
- // hook the drag and zoom events to the svg
- // it's important that the transform is relative to the svg
- // then applied to the g element
- svg.call(d3.zoom()
- .scaleExtent([.25, 2]) // 1/4 zoom limit because default size is 400%
- .on("zoom", zoomed)
- )
-
- return g
-}
\ No newline at end of file
diff --git a/public/scripts/gol-play.js b/public/scripts/gol-play.js
deleted file mode 100644
index cb8bbc3..0000000
--- a/public/scripts/gol-play.js
+++ /dev/null
@@ -1,67 +0,0 @@
-// gol-play.js - play Conway's Game of Life
-
-// set_state
-// INPUT a 2D array for start and 2D array for destination
-// copy start array to the center of the destination array
-// RETURN nothing, modifies destination array
-export const set_state = (start, dest) => {
- // set width and height to the size of the dest array
- const height = dest.length
- const width = dest[0].length
- // copy the state into the center of the new_state
- // NOTE: wraps around in case the state is smaller than the new_state
- // loop over 2D array state wrapping around if needed
- // and copy it into the center of new_state
- for(let y = 0; y < start.length; y++) {
- for(let x = 0; x < start[0].length; x++) {
- let wrap_y = (y + Math.round((height - start.length) / 2) + height) % height
- let wrap_x = (x + Math.round((width - start[0].length) / 2) + width) % width
- dest[wrap_y][wrap_x] = start[y][x]
- }
- }
-}
-
-// apply_rules
-// INPUT a 2D array of the old state
-// run Conway's Game of Life rules on it
-// makes it zoom+pan in response to mouse and touch events
-// RETURN a 2D array of the new state
-export const apply_rules = (state) => {
- // Conway's Game of Life rules are:
- // 1. Any live cell with two or three live neighbours survives.
- // 2. Any dead cell with three live neighbours becomes a live cell.
- // 3. All other live cells die in the next generation. Similarly, all other dead cells stay dead.
- // RULES_LOOKUP is a lookup table for the rules
- const RULES_LOOKUP = {
- 'β¬': ['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
- 'β¬': ['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬']
- }
- const height = state.length;
- const width = state[0].length;
- // make a new_state the size as state and fill it with dead cells
- let new_state = Array.from({length: height}, () => Array.from({length: width}, () => 'β¬'))
- // loop over 2D array state
- // and apply the rules to each cell
- for(let y = 0; y < height; y++) {
- for(let x = 0; x < width; x++) {
- // count the number of neighbors that are alive
- let alive_neighbors = 0
- // loop over the 3x3 grid around the cell
- for(let ny = y-1; ny <= y+1; ny++) {
- for(let nx = x-1; nx <= x+1; nx++) {
- // ignore the cell itself
- if (nx == x && ny == y) continue
- // wrap around the edges of the state
- let wrapped_nx = (nx + width) % width
- let wrapped_ny = (ny + height) % height
- // count the alive neighbors
- if (state[wrapped_ny][wrapped_nx] == 'β¬') {
- alive_neighbors += 1
- }
- }
- }
- new_state[y][x] = RULES_LOOKUP[state[y][x]][alive_neighbors]
- }
- }
- return new_state
-}
diff --git a/public/shaders/tutorial-001.frag b/public/shaders/tutorial-001.frag
new file mode 100644
index 0000000..9996f19
--- /dev/null
+++ b/public/shaders/tutorial-001.frag
@@ -0,0 +1,38 @@
+////////////////////////////////////////////////////////////////////////////////
+// (c) 2023, David 'Duppy' Proctor, Interface Arts
+//
+// tutorial-001
+// fragment shader
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+
+#define PI 3.1415926535897932384626433832795
+#define TAU (2.0*PI)
+
+uniform vec2 u_resolution;
+uniform float u_time;
+
+void main() {
+ vec2 uv = gl_FragCoord.xy / u_resolution;
+ vec3 col = vec3(0.0);
+
+ float _time = u_time / 12.0;
+ float rotation = 2.17 * _time;
+ rotation = rotation + TAU * sin(_time * 1.0 * TAU);
+
+ // rotate uv slowly over time
+ vec2 _uv = vec2(uv.x * cos(rotation) - uv.y * sin(rotation), uv.x * sin(rotation) + uv.y * cos(rotation));
+
+ col.r = sin(0.57 * TAU * _uv.x * sin(_time * 2.0 * TAU));
+ col.g = cos(0.47 * TAU * _uv.y * sin(_time * 2.1 * TAU));
+ col.b = sin(length(_uv) * 0.5 * 1.0 * TAU * sin(_time * 1.0 * TAU));
+
+ gl_FragColor = vec4(col, 1.0);
+}
diff --git a/public/src/conway/grid.js b/public/src/conway/grid.js
new file mode 100644
index 0000000..52ee6aa
--- /dev/null
+++ b/public/src/conway/grid.js
@@ -0,0 +1,78 @@
+////////////////////////////////////////////////////////////////////////////////
+// (c) 2023, David 'Duppy' Proctor, Interface Arts
+//
+// conway
+// grid
+////////////////////////////////////////////////////////////////////////////////
+
+// INPUT a d3 selection
+// adds a graph paper pattern to it
+// makes it zoom+pan in response to mouse and touch events
+// RETURN a d3 selection of the field that other gol functions can use
+export const append_grid = (app, cell_px = 20, w = 12, h = false,) => {
+ if (!app || app.empty()) {
+ return d3.select(null)
+ }
+ if (!h) h = w
+ const G_WIDTH = cell_px * w
+ const G_HEIGHT = cell_px * h
+ const p_w = app.node().clientWidth
+ const p_h = app.node().clientHeight
+ const G_PAD_LEFT = (G_WIDTH - p_w) / 2
+ const G_PAD_TOP = (G_HEIGHT - p_h) / 2
+ // Create the SVG
+ const svg = app.insert('svg', 'span.touch-target') // insert before the touch target so it renders underneath
+ .attr('width', `${p_w}px`)
+ .attr('height', `${p_h}px`)
+ // create a g element inside the svg
+ // need this g element so we can transform it
+ // and leave the svg container static
+ const g = svg.append('g')
+ .attr('width', `100%`)
+ .attr('height', `100%`)
+ .attr('transform', `translate(${-G_PAD_LEFT}, ${-G_PAD_TOP})`)
+
+ // Create the graph paper pattern
+ const pattern = g.append('defs')
+ .append('pattern')
+ .attr('id', 'grid-pattern') // WARN this ID name must match the url(CSS selector) used in the grid-fill class
+ .attr('class', 'cell dead')
+ .attr('width', `${cell_px}px`)
+ .attr('height', `${cell_px}px`)
+ .attr('patternUnits', 'userSpaceOnUse')
+
+ // color the background of the entire parttern
+ pattern.append('rect').attr('class', 'pattern-background')
+ .attr('width', `${cell_px}px`)
+ .attr('height', `${cell_px}px`)
+ // add the grid lines
+ pattern.append('path').attr('class', 'pattern-line')
+ .attr('d', `M ${cell_px},0 L 0,0 0,${cell_px}`); // draw top and left edges of each cell
+
+ g.append('rect').classed('grid-background', true)
+ .attr('width', `${G_WIDTH}px`)
+ .attr('height', `${G_HEIGHT}px`)
+
+ g.append('rect').classed('grid-fill', true) // CSS will fill this with #grid-pattern
+ .attr('width', `${G_WIDTH}px`)
+ .attr('height', `${G_HEIGHT}px`)
+ .style('fill', 'url(#grid-pattern)')
+
+ function zoomed({ transform }) {
+ // use svg zoom and drag units to transform the g element
+ // avoid the common bug of applying the transform to the svg
+ transform = transform.translate(-G_PAD_LEFT, -G_PAD_TOP) // adjust for starting offset
+ g.attr('transform', transform)
+ }
+
+ // hook the drag and zoom events to the svg
+ // it's important that the transform is relative to the svg
+ // then applied to the g element
+ // TODO figure out how to use .extent() or .translateExtent() properly
+ svg.call(d3.zoom()
+ .scaleExtent([1/cell_px, 4]) // 1/4 zoom limit because default size is 400%
+ .on('zoom', zoomed)
+ )
+
+ return g
+} // end grid()
diff --git a/public/src/conway/play.js b/public/src/conway/play.js
new file mode 100644
index 0000000..58ca5ad
--- /dev/null
+++ b/public/src/conway/play.js
@@ -0,0 +1,225 @@
+////////////////////////////////////////////////////////////////////////////////
+// (c) 2023, David 'Duppy' Proctor, Interface Arts
+//
+// conway
+// play
+////////////////////////////////////////////////////////////////////////////////
+
+import { settings } from '/src/does-it-glider/settings.js'
+
+// play Conway's Game of Life
+
+// start in red blue mode, but if we ever see a 'β¬', switch permanently to white mode
+let rule_set = 'π₯π¦'
+
+// add_seed
+// INPUT a seed and a destination grid
+// TODO LOW PRI accept an optional x,y offset for the seed, default to center
+// copy (overwriting) seed to the center of the destination grid
+// RETURN nothing, modifies destination array
+export const add_seed = (seed, grid) => {
+ const sh = seed.length, sw = seed[0].length // HACK assumes seed[0] is same length as all rows
+ const gh = grid.length, gw = grid[0].length
+ // coordinates of upper left corner of seed when seed is centered in grid
+ const cx = Math.round((gw - sw) / 2), cy = Math.round((gh - sh) / 2)
+ // loop over seed wrapping around if needed
+ // and copy each cell into the center of grid
+ for (let y = cy, sy = 0; sy < sh; y++, sy++) {
+ for(let x = cx, sx = 0; sx < sw; x++, sx++) {
+ // copy the seed into the grid, cropping if needed
+ if (settings.WRAP_GRID) {
+ // wrap around the edges of the grid
+ grid[(y + gh) % gh][(x + gw) % gw] = seed[sy][sx]
+ } else {
+ // clip instead of wrap
+ if (x >=0 && y >= 0 && x < gw && y < gh) {
+ grid[y][x] = seed[sy][sx]
+ }
+ }
+ }
+ }
+} // end add_seed()
+
+// Conway's Game of Life rules are:
+// 1. Dead cells with three live neighbours become a live cell.
+// 2. Dead cells with <3 or >3 neighbours stay dead.
+// 3. A live cell with 2 or 3 live neighbours stays alive.
+// 4. A live cell with <2 or >3 live neighbours dies.
+// 'β¬' is a live cell, also 'b' or 'X'
+// 'β¬' is a dead cell, also 'o' or '.'
+const CONWAY_RULES_LOOKUP = { // Original Conway's Game of Life rules
+ 'β¬': [ // rule lookup for live cells
+ 'β¬', // with 0 neighbors, dies
+ 'β¬', // with 1 neighbors, dies
+ 'β¬', // with 2 neighbors, stays alive
+ 'β¬', // with 3 neighbors, stays alive
+ 'β¬', // with 4 neighbors, dies
+ 'β¬', // with 5 neighbors, dies
+ 'β¬', // with 6 neighbors, dies
+ 'β¬', // with 7 neighbors, dies
+ 'β¬', // with 8 neighbors, dies
+ ],
+ 'β¬': [ // rule lookup for dead cells
+ 'β¬', // with 0 neighbors, stays dead
+ 'β¬', // with 1 neighbors, stays dead
+ 'β¬', // with 2 neighbors, stays dead
+ 'β¬', // with 3 neighbors, becomes alive
+ 'β¬', // with 4 neighbors, stays dead
+ 'β¬', // with 5 neighbors, stays dead
+ 'β¬', // with 6 neighbors, stays dead
+ 'β¬', // with 7 neighbors, stays dead
+ 'β¬', // with 8 neighbors, stays dead
+ ],
+}
+//
+// Red Teamπ₯ Blue Teamπ¦ rules are:
+// 'π₯' is a live red team cell, also 'R'
+// 'π¦' is a live blue team cell. also 'B'
+// 'β¬' is a dead cell, also 'o' or '.'
+// 0. If you treat both red and blue cells as live, the rules produce the same result as Conway's Game of Life.
+// 1. Dead cells with 3 neighbours become a red cell if 2 or 3 are red. π₯π₯π¦, π₯π₯π₯
+// 2. Dead cells with 3 neighbours become a blue cell if 2 or 3 are blue. π¦π¦π₯, π¦π¦π¦
+// 3. Dead cells with <3 or >3 neighbours stay dead.
+// 3. A red cell with 3 neighbours and 1, 2, 3 red neighbours stays red. π₯π¦π¦, π₯π₯π¦, π₯π₯π₯
+// 4. A red cell with 3 neighbours and 0 red neighbours (3 blue) becomes blue. π¦π¦π¦
+// 5. A red cell with 2 neighbours and 1, 2 red neighbours stays red. π₯π¦, π₯π₯
+// 6. A red cell with 2 neighbours and 0 red neighbours (2 blue) becomes blue. π¦π¦
+// 7. A red cell with <2 or >3 neighbours of any color dies.
+// 8. A blue cell with 3 neighbours and 1, 2, 3 blue neighbours stays blue. π¦π₯π₯, π¦π¦π₯, π¦π¦π¦
+// 9. A blue cell with 3 neighbours and 0 blue neighbours (3 red) becomes red. π₯π₯π₯
+// 10. A blue cell with 2 neighbours and 1, 2 blue neighbours stays blue. π¦π₯, π¦π¦
+// 11. A blue cell with 2 neighbours and 0 blue neighbours (2 red) becomes red.π₯π₯
+// 12. A blue cell with <2 or >3 neighbours of any color dies.
+const RED_TEAM_BLUE_TEAM_LOOKUP = {
+ // lookup new cell by old state, count of live neighbors, and count of red neighbors
+ // count of blue neighbors is always live_neighbors - red_neighbors, it's value is redundant
+ // arbitrarily chose to index by count of red neighbors
+ // Example: new_state = RED_TEAM_BLUE_TEAM_LOOKUP[old_state][live_neighbors][red_neighbors]
+ 'π₯': [
+ /* 0 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 1 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 2 */['π¦', 'π₯', 'π₯', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 3 */['π¦', 'π₯', 'π₯', 'π₯', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 4 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 5 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 6 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 7 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 8 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ ],
+ 'π¦': [
+ // REMEMBER: we index by red neighbors, so the rule at index(row) 2 is the rule for 2 live neighbors
+ // 2nd row first element is 2 - 0 -> 2 blue neighbors, next element is 2 - 1 -> 1 blue neighbor, etc.
+ /* 0 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 1 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 2 */['π¦', 'π¦', 'π₯', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 3 */['π¦', 'π¦', 'π¦', 'π₯', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 4 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 5 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 6 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 7 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 8 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ ],
+ 'β¬': [
+ /* 0 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 1 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 2 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 3 */['π¦', 'π¦', 'π₯', 'π₯', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'], // HACK overloading the meaning of red_team_neighbors
+ /* 4 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 5 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 6 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 7 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 8 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ ],
+ 'β¬': [
+ /* 0 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 1 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 2 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 3 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 4 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 5 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 6 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 7 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ /* 8 */['β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬', 'β¬'],
+ ],
+}
+// add aliases for cell values
+RED_TEAM_BLUE_TEAM_LOOKUP['R'] = RED_TEAM_BLUE_TEAM_LOOKUP['π₯']
+RED_TEAM_BLUE_TEAM_LOOKUP['B'] = RED_TEAM_BLUE_TEAM_LOOKUP['π¦']
+RED_TEAM_BLUE_TEAM_LOOKUP['o'] = RED_TEAM_BLUE_TEAM_LOOKUP['β¬']
+RED_TEAM_BLUE_TEAM_LOOKUP['.'] = RED_TEAM_BLUE_TEAM_LOOKUP['β¬']
+RED_TEAM_BLUE_TEAM_LOOKUP['b'] = RED_TEAM_BLUE_TEAM_LOOKUP['β¬']
+RED_TEAM_BLUE_TEAM_LOOKUP['X'] = RED_TEAM_BLUE_TEAM_LOOKUP['β¬']
+
+// apply_rules
+// INPUT a read-only 2D Array old grid, pre-allocted 2D array for the new grid state
+// run Conway's Game of Life rules on it
+// RETURN true if successful, false if error
+export const apply_rules = (grid, new_grid) => {
+ let success = true
+ // get the height and width of the state
+ const h = grid.length, w = grid[0].length
+ // check that the new_grid is the same size as the grid
+ if (new_grid.length != h || new_grid[0].length != w) {
+ console.error(`apply_rules() error: new_grid is not the same size as grid`)
+ return false
+ }
+
+ // loop over 2D array state
+ // and apply the rules to each cell
+ for(let y = 0; y < h; y++) {
+ for (let x = 0; x < w; x++) {
+ // if we see a 'β¬' anywhere, change the rules to white mode
+ if (rule_set == 'π₯π¦' && grid[y][x] == 'β¬') {
+ rule_set = 'β¬'
+ }
+ if (rule_set == 'β¬' && (grid[y][x] == 'π₯' || grid[y][x] == 'π¦')) {
+ grid[y][x] = 'β¬'
+ }
+ // count the number of neighbors that are alive
+ let live_neighbors = 0
+ let red_team_neighbors = 0
+ // don't need blue count because it can be computed from live_neighbors - red_team_neighbors
+ // loop over the 3x3 grid around the cell
+ let peek = 'β¬'
+ for(let ny = y-1; ny <= y+1; ny++) {
+ for(let nx = x-1; nx <= x+1; nx++) {
+ // don't count the cell itself, it is not a neighbor
+ if (nx == x && ny == y) continue
+ if (settings.WRAP_GRID) {
+ // wrap around the edges of the grid
+ peek = grid[(ny + h) % h][(nx + w) % w]
+ } else {
+ // don't wrap
+ if (nx < 0 || ny < 0 || nx >= w || ny >= h) {
+ peek = 'β¬' // HACK a continue might be faster, but I'm opting for clarity
+ } else {
+ peek = grid[ny][nx]
+ }
+ }
+ // count the alive neighbors
+ if (peek == 'o' || peek == '.' || peek == 'β¬') {
+ continue
+ }
+ live_neighbors += 1
+ if (peek == 'π₯' || peek == 'R') { // TODO fix this to use is_red_team()
+ red_team_neighbors += 1
+ }
+ // blue_team_neighbors += 1
+ // Don't count blue neighbors here because it can be computed from live_neighbors - red_team_neighbors
+ }
+ }
+ if (rule_set == 'β¬') {
+ red_team_neighbors = 8 // HACK force the result to be white, not red or blue
+ }
+ // blue_team_neighbors = live_neighbors - red_team_neighbors // treats white as blue
+ // actually don't need to track blue_team_neighbors because we look up from red_team_neighbors
+ if (RED_TEAM_BLUE_TEAM_LOOKUP[grid[y][x]]) {
+ new_grid[y][x] = RED_TEAM_BLUE_TEAM_LOOKUP[grid[y][x]][live_neighbors][red_team_neighbors]
+ } else {
+ success = false
+ console.error(`apply_rules() error: unknown cell state ${grid[y][x]}`)
+ }
+ }
+ }
+ return success
+} // end apply_rules()
diff --git a/public/src/conway/shaders.js b/public/src/conway/shaders.js
new file mode 100644
index 0000000..539f9fa
--- /dev/null
+++ b/public/src/conway/shaders.js
@@ -0,0 +1,156 @@
+////////////////////////////////////////////////////////////////////////////////
+// (c) 2023, David 'Duppy' Proctor, Interface Arts
+//
+// conway_shaders is an implementation of Conway's Game of Life in WebGL
+// contains vertex and fragment shaders as javascript string literals
+////////////////////////////////////////////////////////////////////////////////
+
+import { settings } from '/src/does-it-glider/settings.js'
+
+// define a null op glsl so that the glsl-literal vscode extension will highlight the syntax
+const glsl = (x) => x+'' // HACK force glsl to return a string so we can use .replace()
+
+const cell_w = `${settings.CELL_PX.toFixed(3)}`
+const cell_h = `${settings.CELL_PX.toFixed(3)}`
+const border = `${settings.BORDER_PX.toFixed(3)}`
+const epsilon = `${0.000001.toFixed(9)}`
+
+export const vertex_shader_src = glsl`
+ precision mediump float;
+ // in
+ attribute vec2 a_position, a_gridCoord;
+ uniform float u_scale;
+ uniform vec2 u_translation;
+ // out
+ varying vec2 v_gridCoord;
+
+ void main() {
+ // in u_scale and u_translation from app pan+zoom feature
+ vec2 zoomed = (u_scale * a_position) + u_translation;
+ // out
+ gl_Position = vec4(zoomed, 0.0, 1.0);
+ v_gridCoord = a_gridCoord;
+ }
+` // end vertex_shader_src
+
+export const grid_frag_shader_src = glsl`
+ precision mediump float;
+ // in
+ uniform float u_tick;
+ varying vec2 v_gridCoord; // take advantage of interpolation instead of undoing the scale+translation
+
+ float is_border(vec2 uv) {
+ float cx = floor(0.5 + mod(uv.x, __cell_w));
+ float cy = floor(0.5 + mod(uv.y, __cell_h));
+ // BUG #6 this is incorrectly false at the intersection of the grid lines
+ float result = sign(cx - __border - __epsilon)
+ * sign(cy - __border - __epsilon);
+ // result is -1.0 for the first border pixels and +1 for the background
+ // subtracting epsilon makes the sign() certain to be -1.0 not 0.0
+ // convert to 1.0 for border pixels and 0.0 for background
+ result = sign(1.0 - result);
+ return result;
+ }
+
+ void main() {
+ vec3 color;
+ float if_border = sign(is_border(v_gridCoord));
+ float if_background = sign(1.0 - if_border);
+ color = if_background * vec3(1.0/16.0); // color of background
+ color += if_border * vec3(6.0/16.0); // color of border
+ gl_FragColor = vec4(color, 1.0);
+ }
+`
+// ??? I wasn't able to get literal expansion working
+// ??? because maybe cell_w is not in glsl context
+// ??? it is replacing __cell_w with '' instead of the expected '16.000'
+// ??? this isn't really a language issue, it's the glsl formatting extension
+// ??? it's looking for "glsl`" specifcally and not glsl('shader source code')
+.replace(/\b__cell_w\b/ug, cell_w)
+.replace(/\b__cell_h\b/ug, cell_h)
+.replace(/\b__border\b/ug, border)
+.replace(/\b__epsilon\b/ug, epsilon)
+// end grid_frag_shader_src
+
+export const rainbow_fragment_shader_src = glsl`
+ precision mediump float;
+
+ #define PI (3.1415926535897932384626433832795)
+ #define TAU (2.0*PI)
+
+ uniform vec2 u_resolution;
+ uniform float u_tick;
+
+ // receive the zoom info from the vertex shader
+ varying float v_scale;
+ varying vec2 v_translation;
+
+ void main() {
+ vec2 frag_coord = gl_FragCoord.xy / u_resolution;
+ // shift origin to center of screen
+ frag_coord = 2.0*frag_coord - 1.0;
+ // scale and translate
+ vec2 uv = v_scale * (frag_coord + v_translation);
+ // shift back to lower left
+ uv = (uv + 1.0) / 2.0;
+ vec3 col = vec3(0.0);
+
+ float _time = ((1.0 /_fps) * u_tick); // convert frame count to seconds
+ // therefore sin(freq * TAU * _time) is a sin wave with frequency 'freq' in Hz
+ float rotation = 2.17 * _time;
+ rotation = rotation + TAU*sin(_time*1.0*TAU);
+
+ // rotate uv slowly over time
+ vec2 _uv = vec2(
+ uv.x*cos(rotation) - uv.y*sin(rotation),
+ uv.x*sin(rotation) + uv.y*cos(rotation)
+ );
+
+ col.r = sin(0.57*TAU * _uv.x * sin(_time * 2.0*TAU));
+ col.g = cos(0.47*TAU * _uv.y * sin(_time * 2.1*TAU));
+ col.b = sin(length(_uv)*0.5 * 1.0*TAU * sin(_time * 1.0*TAU));
+
+ gl_FragColor = vec4(col, 1.0);
+ }
+` // end fragment_shader
+
+export const checker_frag_shader_src = glsl`
+ precision mediump float;
+
+ uniform vec2 u_resolution;
+ uniform float u_tick;
+
+ // receive the zoom info from the vertex shader
+ varying float v_scale;
+ varying vec2 v_translation;
+ varying vec2 v_gridCoord; // take advantage of interpolation instead of undoing the scale+translation
+
+ float checker(vec2 uv, float repeats) {
+ float cx = floor(0.5 + repeats * uv.x);
+ float cy = floor(0.5 + repeats * uv.y);
+ float result = mod(cx + cy, 2.0);
+ return sign(result);
+ }
+
+ void main() {
+ vec2 frag_coord = gl_FragCoord.xy / u_resolution;
+ // shift origin to center of screen
+ frag_coord = 2.0*frag_coord - 1.0;
+ // scale and translate
+ vec2 uv = v_scale * (frag_coord + v_translation);
+ // shift back to lower left
+ uv = v_gridCoord;
+ uv = (uv + 1.0) / 2.0;
+
+
+ vec3 ambient = vec3(0.04);
+ vec3 direction = vec3(0.0, 1.0, 1.0);
+ vec3 lightColor = vec3(length(uv)) / 1.25; // the 1.5 is arbitrary
+ vec3 light = vec3(clamp(ambient + lightColor, 0.0, 1.0));
+
+ vec3 color = vec3(1.0 * checker(uv, 128.0));
+ gl_FragColor = vec4(color * light, 1.0);
+ // gl_FragColor = vec4(sign(uv.x-0.5), 0.0, sign(uv.y-0.5), 1.0);
+ }
+` // end checker_frag_shader_src
+
diff --git a/public/src/does-it-glider/draw.js b/public/src/does-it-glider/draw.js
new file mode 100644
index 0000000..eba7aac
--- /dev/null
+++ b/public/src/does-it-glider/draw.js
@@ -0,0 +1,70 @@
+////////////////////////////////////////////////////////////////////////////////
+// (c) 2023, David 'Duppy' Proctor, Interface Arts
+//
+// does it glider
+// draw
+////////////////////////////////////////////////////////////////////////////////
+
+let draw_count = 0, sum_total = 0, sum_remove = 0
+let min = Infinity, max = 0
+let total = 0, time = 0
+
+const COLOR_TO_CLASS = {
+ 'β¬': false,
+ 'o': false,
+ '.': false,
+ 'β¬':'β¬',
+ 'b': 'β¬',
+ 'X': 'β¬',
+ 'π₯':'π₯',
+ 'R': 'π₯',
+ 'π¦':'π¦',
+ 'B': 'π¦',
+}
+// modify the DOM from a 2D array of Conway's Game of Life (gol_state)
+export const draw = (g, state, cell_px) => { // HACK - do better than passing cell_px down, add some class
+ const startTime = performance.now()
+
+ // render/draw each live cell in state as a white rect in the svg
+ // clear all of the old rects first
+ const all = g.selectAll('rect.cell')
+ all.remove()
+ const removeTime = performance.now() - startTime
+ // loop over 2D array state
+ for(let y = 0; y < state.length; y++) {
+ for(let x = 0; x < state[0].length; x++) {
+ if (COLOR_TO_CLASS[state[y][x]]) {
+ // draw a white rect in the svg
+ g.insert('rect', '.grid-lines') // render this before/below grid-lines but after grid-background
+ .classed('cell', true)
+ .classed(COLOR_TO_CLASS[state[y][x]], true)
+ .attr('x', `${x * cell_px}px`)
+ .attr('y', `${y * cell_px}px`)
+ .attr('width', `${cell_px}px`)
+ .attr('height', `${cell_px}px`)
+ }
+ }
+ }
+
+ const draw_time = performance.now() - startTime
+ if (draw_time > 33.33) {
+ console.log(`draw time: ${draw_time.toFixed(3)}ms`)
+ }
+}
+
+/*******************************************************************************
+ * Speed test results
+ * for y, for x, with g.insert and .attr('x', `${x * cell_px}px`)
+ * total: 5.03ms, remove: 0.52ms, min: 3.50ms, max: 12.40ms
+ * total: 5.28ms, remove: 0.52ms, min: 3.60ms, max: 19.00ms
+ * total: 5.44ms, remove: 0.60ms, min: 3.80ms, max: 23.20ms
+ * total: 5.98ms, remove: 0.78ms, min: 3.90ms, max: 22.20ms
+ * total: 7.71ms, remove: 1.25ms, min: 5.20ms, max: 31.20ms
+ * total: 7.05ms, remove: 1.14ms, min: 5.50ms, max: 15.90ms
+ * total: 7.92ms, remove: 1.31ms, min: 5.80ms, max: 27.30ms
+ * total: 6.39ms, remove: 0.91ms, min: 4.70ms, max: 21.90ms
+ * total: 7.43ms, remove: 1.22ms, min: 5.70ms, max: 18.20ms
+ * total: 6.69ms, remove: 1.06ms, min: 4.90ms, max: 19.30ms
+ *
+ * next results making data in loop and d3 enter, update, exit pattern
+ *******************************************************************************/
diff --git a/public/src/does-it-glider/main.js b/public/src/does-it-glider/main.js
new file mode 100644
index 0000000..49f4a33
--- /dev/null
+++ b/public/src/does-it-glider/main.js
@@ -0,0 +1,338 @@
+//////////////////////////////////////////////////////////////////////
+// (c) 2023, David 'Duppy' Proctor, Interface Arts
+//
+// main
+// top-level code for does-it-glider
+//////////////////////////////////////////////////////////////////////
+
+// Configuration
+import { settings } from '/src/does-it-glider/settings.js'
+import { d3_plus as d3 } from '/lib/d3-helper.js'
+
+// Conway's Game of Life modules
+import { apply_rules, add_seed } from '/src/conway/play.js'
+import { append_grid } from '/src/conway/grid.js'
+
+// does-it-glider svg modules
+import { draw } from '/src/does-it-glider/draw.js'
+
+// WebGL modules
+import { webgl_context } from '/src/mywebgl/render.js'
+
+// Init
+// get query params
+const urlParams = new URLSearchParams(window.location.search)
+const version = urlParams.get('v') || 'stable'
+const use_gl = version == 'beta' || version == 'both'
+const use_svg = version == 'stable' || version == 'both'
+// warn if using the beta version
+if (use_gl) {
+ console.warn(`Using Beta WebGL version.`)
+}
+// initialize
+let app = d3.select('.does-it-glider-app')
+if (app.empty()) {
+ app = d3.select('body').mynew(`div.does-it-glider-app`, ':first-child')
+}
+
+// Position the divs using flex grid
+// get the width and height of the app
+let app_rect = app.node().getBoundingClientRect()
+app.style('display', 'flex')
+ .style('flex-direction', (app_rect.width > app_rect.height) ? 'row' : 'column')
+
+// top half
+let svg_div = d3.select() // initialize to empty selection
+let webgl_div = d3.select() // initialize to empty selection
+
+if (use_svg) {
+ svg_div = app.mynew('div.top')
+ .style('background', '#000000ff') // out of bounds color
+}
+
+// bottom half
+if (use_gl) {
+ webgl_div = app.mynew('div.bottom')
+ .style('background', '#e600ffff') // should never see this
+}
+
+app.selectAll('.top,.bottom') // styles in common for both divs
+ .style('overflow', 'hidden') // tested, this is needed to avoid scroll bars
+ .style('position', 'relative')
+ .style('flex', '1')
+
+// Create the title
+let touch_target = app.append('span')
+ .classed('touch-target', true)
+
+const _title = 'Does it Glider?'
+const _sub_title = 'Tap here to paste Wordle score.'
+// max width reference: '##################################'
+// abbove is max width on smallest mobile (iPhone SE)
+
+touch_target.append('div')
+ .attr('class', 'title')
+ .html(_title)
+
+touch_target.append('div')
+ .attr('class', 'title sub-title')
+ .html(_sub_title)
+
+// make a grid in the app DOM element
+let grid_sel = d3.select()
+if (use_svg) {
+ grid_sel = append_grid(svg_div, settings.CELL_PX, settings.GRID_WIDTH, settings.GRID_HEIGHT)
+}
+
+// make a new 2D array the size of the 5x6 start pattern
+let seed = []
+// set the start pattern using life_seed format
+seed[0] = 'β¬β¬β¬β¬β¬'
+seed[1] = 'β¬β¬β¬β¬β¬'
+seed[2] = 'β¬β¬β¬β¬β¬'
+seed[3] = 'β¬β¬β¬β¬β¬'
+seed[4] = 'β¬β¬β¬β¬β¬'
+seed[5] = 'β¬β¬β¬β¬β¬'
+
+//test a wordle fight pattern
+/*
+ooRRRoooooBoooB
+ooRRRoooooooBBo
+RRRRRoooooBBBBB
+ooooooooooooooo
+ooooooooooooooo
+ooooooooooooooo
+*/
+
+let red_team = []
+red_team[0] = 'ooRRR'
+red_team[1] = 'ooRRR'
+red_team[2] = 'RRRRR'
+red_team[3] = 'ooooo'
+red_team[4] = 'ooooo'
+red_team[5] = 'ooooo'
+
+let blue_team = []
+blue_team[0] = 'BoooB'
+blue_team[1] = 'ooBBo'
+blue_team[2] = 'BBBBB'
+blue_team[3] = 'ooooo'
+blue_team[4] = 'ooooo'
+blue_team[5] = 'ooooo'
+
+let partial_mosquito = []
+partial_mosquito[0] = 'ooooo'
+partial_mosquito[1] = 'ooooo'
+partial_mosquito[2] = 'oooBo'
+partial_mosquito[3] = 'ooooB'
+partial_mosquito[4] = 'BoooB'
+partial_mosquito[5] = 'oBBBB'
+
+let fight_paces = 5
+// join red team and blue team into start with red team on left and fight_paces dead cells in between
+seed = red_team.map((row, i) => row + 'β¬'.repeat(fight_paces) + blue_team[i])
+
+seed.forEach((row, i) => {
+ seed[i] = row
+ .replace(/π¦/g, 'B')
+ .replace(/π₯/g, 'R')
+ .replace(/β¬/g, 'b')
+ .replace(/X/g, 'b')
+ .replace(/β¬/g, 'o')
+ .replace(/\./g, 'o')
+})
+
+// get the width and height of the grid
+let grid_h = settings.GRID_HEIGHT
+let grid_w = settings.GRID_WIDTH
+// make a new 2D array the size of the g element divide by 20px
+let grid_ping = Array.from({ length: grid_h }, () => Array.from({ length: grid_w }, () => 'β¬'))
+let grid_pong = Array.from({ length: grid_h }, () => Array.from({ length: grid_w }, () => 'β¬'))
+
+const load_new_state = (life_seed) => {
+ console.time('load_new_state')
+
+ let grid
+ // clear the state
+ if (ping_pong) {
+ grid = grid_ping // if ping_pong is true, then we just finished applying rule to grid_ping, replace it
+ } else {
+ grid = grid_pong
+ }
+ // clear the grid in place
+ for (let row of grid) {
+ for (let i = 0; i < row.length; i++) {
+ row[i] = 'β¬'
+ }
+ }
+
+ // copy the life_seed into the center of the state
+ add_seed(life_seed, grid)
+ // FIX #10 try insta draw to the new seed not visible during the pause_for_new dela
+ draw(grid_sel, grid, settings.CELL_PX)
+ pause_for_new = Math.round(1.333 * 60) // secs * frames/sec => units of frames
+
+ console.timeEnd('load_new_state')
+}
+
+let tick = 0
+let num_ticks = Math.round((settings.BEAT / 4) / (1000 / 60)) // BEATmsec / (1000msec/60frame) -> num_ticks has units of frames
+let pause_for_new = Math.round(1.333 * 60) // to pause for N seconds, set N sec * 60 frames/sec then round() so that mod (%) works
+let ping_pong = true
+load_new_state(seed)
+
+const event_loop = () => {
+ if (pause_for_new == 0) { // apply the rules to the state
+ if (tick % num_ticks == 0) { // only apply rules every num_ticks frames
+ ping_pong = !ping_pong
+ if (ping_pong) { // TODO why wasn't [grid_ping, grid_pong] = [grid_pong, grid_ping] working?
+ apply_rules(grid_pong, grid_ping) // ping_pong is true, grid_ping gets the new state
+ } else {
+ apply_rules(grid_ping, grid_pong)
+ }
+ if (ping_pong) {
+ draw(grid_sel, grid_ping, settings.CELL_PX)
+ } else {
+ draw(grid_sel, grid_pong, settings.CELL_PX)
+ }
+ }
+ } else {
+ pause_for_new-- // HACK, there must be a better way to pause for new and also draw only n frames
+ }
+ tick++
+ requestAnimationFrame(event_loop) // BUG this might fix issue #5. trying again
+}
+requestAnimationFrame(event_loop)
+
+let life_seed = []
+
+const parse_clipboard = (pasted_clipboard) => {
+ let pasted_lines = []
+ // for importing RLE patterns
+ pasted_lines = pasted_clipboard.replace(/\$|!/ug, '\n') // '$' used as end of line and '!' used as end of seed in RLE format
+ pasted_lines = pasted_lines.split(/\r\n|\r|\n/ug)
+
+ // filter pasted_lines for only lines that are length 5
+ // and contain only 'β¬', 'π¨', 'π©', or 'β¬' (or their aliases)
+ let wordle_guesses = []
+ wordle_guesses = pasted_lines
+ .filter(line => line.match(/^(β¬|π¨|π©|β¬|π¦|π§|o|b|R|B|X|\.){5,5}$/ug))
+ // this is only the lines with exactly 5 wordle squares
+ console.log(`filtered wordle_guesses:\n${wordle_guesses.join('\n')}`)
+
+ // convert all 'π¨'|'π©' in wordle_guesses to 'β¬' and 'β¬'|'β¬' to 'β¬'
+ life_seed = []
+ wordle_guesses.map(guess =>
+ life_seed.push(
+ guess
+ // need an intermediate character to avoid double replacement
+ // try red team π₯ blue team π¦ fight idea
+ .replace(/β¬|β¬/ug, 'β¬')
+ .replace(/\./ug, 'β¬')
+ .replace(/o/ug, 'β¬')
+ .replace(/π¨|π§/ug, 'β¬') // hits in wrong location are red team
+ .replace(/π©|π¦/ug, 'β¬') // hits in correct location are blue team
+ .replace(/X/ug, 'β¬')
+ .replace(/b/ug, 'β¬')
+ )
+ )
+ console.log(`life_seed:\n${life_seed.join('\n')}`)
+
+ let beat_pasted = settings.BEAT
+ let beat_wordle_guesses = settings.BEAT
+ let beat_life_seed = settings.BEAT
+ // draw/render pasted_lines in the .paste-line divs
+ const draw_pasted_lines = () => {
+ const last_line = pasted_lines.length - 1
+ app
+ .selectAll('.paste-line')
+ .data(pasted_lines)
+ .join(
+ enter => enter.append('div').classed('paste-line', true),
+ update => update,
+ exit => exit
+ .remove()
+ )
+ // new line effect on both enter and update
+ .html(line => line || ' ')
+ .transition().duration(beat_pasted)
+ .remove()
+ .on('end',
+ (_d, i) => { if (i == last_line) draw_wordle_guesses() }
+ )
+ }
+
+ const draw_wordle_guesses = () => {
+ const last_line = wordle_guesses.length - 1
+ app
+ .selectAll('.paste-line')
+ .data(wordle_guesses)
+ // d3.data() stores the array life_seed on the parent DOM element
+ // then d3.join() compares new data to previous data
+ // and calls enter, update, or exit on each element of data array
+ // as appropriate for diff of new data comapred to previous data
+ .join(
+ enter => enter.append('div').classed('paste-line', true),
+ update => update,
+ exit => exit
+ .remove()
+ ) //join returns enter and update merged
+ .html(d => d)
+ .transition().duration(beat_wordle_guesses)
+ .remove()
+ .on('end',
+ (_d, i) => {
+ if (i == last_line) draw_life_seed()
+ }
+ )
+ }
+
+ const draw_life_seed = () => {
+ const last_line = life_seed.length - 1
+ console.log(`draw_life_seed: last_line = ${last_line}`)
+ app
+ .selectAll('.paste-line')
+ .data(life_seed)
+ .join(
+ enter => enter.append('div').classed('paste-line', true),
+ update => update,
+ exit => exit
+ .remove()
+ ) //join returns enter and update merged
+ .html(d => d)
+ .transition().duration(beat_life_seed)
+ .remove()
+ .on('end',
+ (_d, i) => {
+ console.log(`.data(life_seed): [${i}] = ${_d}\n`)
+ if (i == last_line) // fixed #8
+ load_new_state(life_seed || seed)
+ }
+ )
+ }
+
+ draw_pasted_lines() // this function will chain to the next functions
+ // ??? is there a better method that hooks into the end of the CSS animation instead of D3?
+ // ??? if so, then am I using d3 for anything other than zoom transform or a fancier jquery?
+ // draw_wordle_guesses()
+ // draw_life_seed()
+ // load_new_state(life_seed || start)
+} // end parse_clipboard()
+
+const get_clipboard_text = async (event) => {
+ // get clipboard text
+ const pasted_clipboard = await navigator.clipboard.readText()
+ // BUG #2: pasted_clipboard not working on mobile browsers
+ console.log(`pasted_clipboard:\r\n${pasted_clipboard}`)
+ parse_clipboard(pasted_clipboard)
+}
+
+// paste from clickboard on click(touch) to deal with mobile browsers
+d3.select('.touch-target').on('click', get_clipboard_text)
+// also listen for paste event anywhere on the page
+d3.select('body').on('paste', get_clipboard_text)
+
+// make a webgl canvas in the left_div
+if (use_gl) {
+ const gl = webgl_context(webgl_div)
+}
diff --git a/public/src/does-it-glider/settings.js b/public/src/does-it-glider/settings.js
new file mode 100644
index 0000000..10acda8
--- /dev/null
+++ b/public/src/does-it-glider/settings.js
@@ -0,0 +1,23 @@
+////////////////////////////////////////////////////////////////////////////////
+// (c) 2023, David 'Duppy' Proctor, Interface Arts
+//
+// settings
+// global constants
+//
+////////////////////////////////////////////////////////////////////////////////
+// XXX
+export const settings = {
+ // game of life configuration
+ GRID_WIDTH: 192, // in cells
+ GRID_HEIGHT: 192, // in cells
+ WRAP_GRID: false,
+
+ // shader source constants
+ CELL_PX: 16,
+ BORDER_PX: 1, // defined as inwards from the edge of the cell at CELL_PX
+
+ // UI preferences
+ BEAT: (60 * 1000) / 180.0,
+ // Use BEAT for the speed of animations and life simulation
+ // (60sec/ min * 1000msec/sec) / 120.0BPM -> msec/BEAT
+}
diff --git a/public/src/mywebgl/render.js b/public/src/mywebgl/render.js
new file mode 100644
index 0000000..cfe760e
--- /dev/null
+++ b/public/src/mywebgl/render.js
@@ -0,0 +1,218 @@
+//////////////////////////////////////////////////////////////////////
+// (c) 2023, David 'Duppy' Proctor, Interface Arts
+//
+// render_sandbox
+// webgl_context
+//////////////////////////////////////////////////////////////////////
+
+import { mat2d, vec2 } from '/node_modules/gl-matrix/esm/index.js'
+
+import {
+ vertex_shader_src,
+ checker_frag_shader_src, // may enable as fragment_shader_src for testing
+ rainbow_fragment_shader_src, // may enable as fragment_shader_src for testing
+ grid_frag_shader_src as fragment_shader_src, // may enable as fragment_shader_src for
+ // conway_frag_shader_src as fragment_shader_src, // the real Conway's Game of Life
+} from '/src/conway/shaders.js'
+
+import { settings } from '/src/does-it-glider/settings.js'
+
+// webgl_context
+// INPUT parent element
+// RETURN a webgl context
+export const webgl_context = (parent) => {
+ // use D3js to create a canvas with webgl context in the parent element
+ // https://observablehq.com/@mourner/webgl-2-boilerplate
+ // get the width and height of the parent element
+ const p_w = parent.node().clientWidth
+ const p_h = parent.node().clientHeight
+ const cell_px = settings.CELL_PX
+ const gw = settings.GRID_WIDTH * cell_px // num cells * px/cell -> num pixels
+ const gh = settings.GRID_HEIGHT * cell_px
+
+ //BUGBUG #4 render does not respond to resize events
+
+ // set parent to rare background color to help debug if canvas is not covering entire parent
+ parent.style('background', '#654321')
+ // calculate left and top offsets to center the canvas
+ const G_PAD_LEFT = (gw - p_w) / 2
+ const G_PAD_TOP = (gh - p_h) / 2
+ const canvas = parent
+ .append('canvas')
+ .attr('width', gw)
+ .attr('height', gh)
+ .style('position', 'absolute')
+ .style('left', `${-G_PAD_LEFT}px`)
+ .style('top', `${-G_PAD_TOP}px`)
+ .attr('transform', `translate(${-G_PAD_LEFT}, ${-G_PAD_TOP})`)
+ .style('background', '#123456') // rare color to help debug if shader is not rendering entire canvas
+
+ const webgl_version = 'webgl2'
+ const gl = canvas.node().getContext(webgl_version)
+ if (!gl) {
+ console.error(`Your browser does not support ${webgl_version}.`)
+ let parent = d3.select(canvas.node().parentNode.parentNode)
+ parent.html(`Your browser does not support ${webgl_version}.
Please try a different browser.`)
+ parent
+ .style('padding', '1em')
+ .style('font-size', '2em')
+ //return an empty d3.selection
+ return d3.select()
+ }
+
+ // Compile a vertex shader from string literal vertex_shader_src
+ const vertex_shader = gl.createShader(gl.VERTEX_SHADER)
+ gl.shaderSource(vertex_shader, vertex_shader_src)
+ gl.compileShader(vertex_shader)
+ if (!gl.getShaderParameter(vertex_shader, gl.COMPILE_STATUS)) {
+ console.error(`WebGL vertex compile err: ${gl.getShaderInfoLog(vertex_shader)}`)
+ return
+ }
+ // Compile a fragment shader from string literal fragment_shader_src
+ const fragment_shader = gl.createShader(gl.FRAGMENT_SHADER)
+ gl.shaderSource(fragment_shader, fragment_shader_src)
+ gl.compileShader(fragment_shader)
+ if (!gl.getShaderParameter(fragment_shader, gl.COMPILE_STATUS)) {
+ console.error(`WebGL frag compile err: ${gl.getShaderInfoLog(fragment_shader)}`)
+ return
+ }
+
+ // Create a program and attach the shaders
+ const program = gl.createProgram()
+ gl.attachShader(program, vertex_shader)
+ gl.attachShader(program, fragment_shader)
+ gl.linkProgram(program)
+ // Check if the program was linked successfully
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+ console.error(gl.getProgramInfoLog(program))
+ return
+ }
+
+ // set the viewport to the canvas size
+ gl.viewport(0, 0, gw, gh)
+
+ // Use the program
+ gl.useProgram(program)
+ // Get the location of the uniform variable
+ let uResolutionLocation = gl.getUniformLocation(program, 'u_resolution')
+
+ // Set the value of the uniform variable
+ let resolution = [gw, gh]
+ gl.uniform2fv(uResolutionLocation, resolution)
+
+ // Get the location of the uniform tick variable
+ let uTickLocation = gl.getUniformLocation(program, 'u_tick')
+
+ // Create a buffer for the rectangle's vertices
+ const buffer = gl.createBuffer()
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ // make a rectangle from 2 triangles
+ new Float32Array([
+ -1.0, -1.0, 0.0, gh, // lower left in clip space is 0, 1 in grid space
+ +1.0, -1.0, gw, gh, // lower right in clip space is 1, 1 in grid space
+ -1.0, +1.0, 0.0, 0.0, // upper left in clip space is 0, 0 in grid space
+ +1.0, +1.0, gw, 0.0, // upper right in clip space is 1, 0 in grid space
+ ]),
+ gl.STATIC_DRAW
+ )
+
+ // Get the location of the a_position attribute
+ const aPositionLocation = gl.getAttribLocation(program, 'a_position')
+ const aGridCoordLoc = gl.getAttribLocation(program, 'a_gridCoord')
+
+ // Enable the attribute
+ gl.enableVertexAttribArray(aPositionLocation)
+ gl.enableVertexAttribArray(aGridCoordLoc)
+
+ // Tell the attribute how to get data out of the buffer
+ gl.vertexAttribPointer(
+ aPositionLocation,
+ 2,
+ gl.FLOAT,
+ false,
+ 4 * Float32Array.BYTES_PER_ELEMENT,
+ 0,
+ )
+ gl.vertexAttribPointer(
+ aGridCoordLoc,
+ 2,
+ gl.FLOAT,
+ false,
+ 4 * Float32Array.BYTES_PER_ELEMENT,
+ 2 * Float32Array.BYTES_PER_ELEMENT,
+ )
+
+ // Get the location of the uniform variable
+ let uScaleLocation = gl.getUniformLocation(program, 'u_scale')
+ let uTranslationLocation = gl.getUniformLocation(program, 'u_translation')
+
+ // create functions to map DOM coords to gl coords
+ const map_DOM_to_gl_x = d3.scaleLinear().domain([0, gw]).range([-1, 1])
+ const map_DOM_to_gl_y = d3.scaleLinear().domain([0, gh]).range([1, -1])
+
+ // set the initial scale and translation
+ let gl_scale = 1.0
+ let gl_translation = [0.0, 0.0]
+
+ // hook the pan and zoom events to the parent
+ // and apply pan and to the canvas
+ function apply_zoom({ transform }) {
+ // use parent zoom and drag units to transform the canvas element
+ // only for debugging, canvas doesn't transform. use vertex shader
+ canvas.attr('transform', transform)
+ // set the scale global that draw will pass
+ gl_scale = transform.k // scale is same for all coords and centers of zoom and drag
+
+ // map transform's translation to gl_translation coord space
+ gl_translation = [
+ map_DOM_to_gl_x(transform.x),
+ map_DOM_to_gl_y(transform.y),
+ ]
+
+ // move gl coords relative to WebGL viewport center scaled by gl_scale
+ gl_translation[0] += gl_scale
+ gl_translation[1] -= gl_scale
+ }
+
+ canvas.call(d3.zoom()
+ .scaleExtent([1/cell_px, 4])
+ .on('zoom', apply_zoom)
+ )
+
+ // Draw the rectangle
+ // THIS IS THE EVENT LOOP
+ function draw() {
+ // assume requestAnimationFrame is called 60 times per second
+ // 2^53 / 60 / 60 / 60 / 24 / 365 = 4,760,274 years
+ // 60fps is too fast. Only aplply the rules and draw some of the time.
+ if (tick % 8 == 0) { // every 20 frames is 1/3 of a second, so 3 fps
+ // TODO #7 add smart pause that does not redraw if no game state change and no window resize or zoom
+ if (tick == 0) {
+ // do some init on the first frame if needed
+ console.log('first frame')
+ // clear the gl background
+ gl.clearColor(5, 0, 3, 1)
+ gl.clear(gl.COLOR_BUFFER_BIT)
+ }
+ // Set the value of the uniform tick variable
+ gl.uniform1f(uTickLocation, tick)
+ // this should more precisely be the time that it will be when the next AnimationFrame is called and renders
+ // unless I just use tick for frame number. Conway doesn't need precise timing. It's not a game.
+ // set the scale and translation for the vertex shader
+ gl.uniform1f(uScaleLocation, gl_scale)
+ gl.uniform2fv(uTranslationLocation, gl_translation)
+ // Draw the scene. In this case TRIANGLE_STRIP is just 2 triangles that make a rectangle.
+ // This is the minimum way to draw a rectangle in WebGL.
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
+ }
+ tick++
+ requestAnimationFrame(draw)
+ }
+ let tick = 0
+ draw()
+
+ // return the context
+ return gl
+} // end webgl_context()
diff --git a/test/funny_usernames.csv b/test/funny_usernames.csv
new file mode 100644
index 0000000..c90ca24
--- /dev/null
+++ b/test/funny_usernames.csv
@@ -0,0 +1,8 @@
+Username,CUID,Timestamp,Comment
+MuffinAvenger,cuid-46071,2023-11-23 07:07:33,I'm not just a muffin; I'm a hero.
+SirQuacksALot,cuid-33980,2023-11-25 13:02:18,"Quack, quack, quack, it's a trap!"
+NinjaPenguin,cuid-89116,2023-11-04 19:57:16,Covert operations in the Arctic!
+SofaKingCool,cuid-69615,2023-11-23 20:07:18,Too cool for average furniture.
+LordOfTheFries,cuid-91142,2023-11-19 21:33:52,Fries before guys.
+WaffleIronMan,cuid-43674,2023-11-07 21:52:44,Ironing out the waffles.
+BananaBandit,cuid-33985,2023-11-01 12:55:57,"Stealing bananas, one bunch at a time."