[
  {
    "path": ".gitignore",
    "content": ".orig\n\n# Created by https://www.gitignore.io/api/vim,emacs,sublimetext,webstorm,eclipse\n\n### Vim ###\n[._]*.s[a-w][a-z]\n[._]s[a-w][a-z]\n*.un~\nSession.vim\n.netrwhist\n*~\n\n\n### Emacs ###\n# -*- mode: gitignore; -*-\n*~\n\\#*\\#\n/.emacs.desktop\n/.emacs.desktop.lock\n*.elc\nauto-save-list\ntramp\n.\\#*\n\n# Org-mode\n.org-id-locations\n*_archive\n\n# flymake-mode\n*_flymake.*\n\n# eshell files\n/eshell/history\n/eshell/lastdir\n\n# elpa packages\n/elpa/\n\n# reftex files\n*.rel\n\n# AUCTeX auto folder\n/auto/\n\n# cask packages\n.cask/\n\n\n### SublimeText ###\n# cache files for sublime text\n*.tmlanguage.cache\n*.tmPreferences.cache\n*.stTheme.cache\n\n# workspace files are user-specific\n*.sublime-workspace\n\n# project files should be checked into the repository, unless a significant\n# proportion of contributors will probably not be using SublimeText\n# *.sublime-project\n\n# sftp configuration file\nsftp-config.json\n\n\n### WebStorm ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio\n\n*.iml\n\n## Directory-based project format:\n.idea/\n# if you remove the above rule, at least ignore the following:\n\n# User-specific stuff:\n# .idea/workspace.xml\n# .idea/tasks.xml\n# .idea/dictionaries\n\n# Sensitive or high-churn files:\n# .idea/dataSources.ids\n# .idea/dataSources.xml\n# .idea/sqlDataSources.xml\n# .idea/dynamic.xml\n# .idea/uiDesigner.xml\n\n# Gradle:\n# .idea/gradle.xml\n# .idea/libraries\n\n# Mongo Explorer plugin:\n# .idea/mongoSettings.xml\n\n## File-based project format:\n*.ipr\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\n/out/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\n\n\n### Eclipse ###\n*.pydevproject\n.metadata\n.gradle\nbin/\ntmp/\n*.tmp\n*.bak\n*.swp\n*~.nib\nlocal.properties\n.settings/\n.loadpath\n\n# Eclipse Core\n.project\n\n# External tool builders\n.externalToolBuilders/\n\n# Locally stored \"Eclipse launch configurations\"\n*.launch\n\n# CDT-specific\n.cproject\n\n# JDT-specific (Eclipse Java Development Tools)\n.classpath\n\n# Java annotation processor (APT)\n.factorypath\n\n# PDT-specific\n.buildpath\n\n# sbteclipse plugin\n.target\n\n# TeXlipse plugin\n.texlipse\n\n# VS Code\njsconfig.json\n\ndebug/\n\n.DS_Store\n\nnode_modules/\nnpm-debug.log"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - 4.4"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 Shuai Shao (shrekshao) and Contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# minimal-gltf-loader\n[![Build Status](https://travis-ci.org/shrekshao/minimal-gltf-loader.svg?branch=master)](https://travis-ci.org/shrekshao/minimal-gltf-loader)\n[![License](http://img.shields.io/:license-mit-blue.svg)](https://github.com/shrekshao/minimal-gltf-loader/blob/master/LICENSE.md)\n\nA minimal, engine-agnostic JavaScript glTF Loader, with a raw WebGL 2 simple renderer example using the loader.\n\n## Viewer Screenshot\n![](img/drone.gif)\n![](img/helmet-pbr.png)\n![](img/skin.gif)\n![](img/viewer-screenshot-buggy-bbox.png)\n\n## Live Demo\n\n[click here for live demo](https://shrekshao.github.io/minimal-gltf-loader/examples/webgl2-renderer.html)\n\n# Usage\n\n```javascript\nimport {vec3, vec4, quat, mat4} from 'gl-matrix';\nvar MinimalGLTFLoader = require('build/minimal-gltf-loader.js');\n\nvar glTFLoader = new MinimalGLTFLoader.glTFLoader();\nglTFLoader.loadGLTF(url, function(glTF){\n    //...\n});\n```\n\n\n## Loading Features\n\n* [x] Accessors\n    - [ ] Progressive loading / rendering\n* [x] Buffers\n* [x] BufferViews\n* [x] Images\n* [x] Meshes\n* [x] Nodes\n* [x] Primitives\n* [x] Samplers\n* [x] Textures\n* [x] ~~Shader Loader~~ (not part of the core of glTF 2.0)\n* [x] Animations\n* [x] Cameras\n* [x] Materials\n* [x] Skins\n\n## Formats\n\n* [x] glTF (.gltf) with separate resources: .bin (geometry, animation, skins), .glsl (shaders), and image files\n* [ ] glTF (.gltf) with embedded resources\n* [ ] Binary glTF (.glb) using the [KHR_binary_glTF](https://github.com/KhronosGroup/glTF/blob/master/extensions/Khronos/KHR_binary_glTF/README.md) extension\n\n## Examples\n\n* [x] WebGL 2 simple renderer\n    * [x] baseColorFactor\n    * [x] baseColorTexture\n    * [x] normalTexture\n    * [x] Skybox\n    * [x] PBR\n    * [x] Animation\n    * [ ] Interpolations\n        - [x] LINEAR\n        - [ ] STEP\n        - [ ] CATMULLROMSPLINE\n        - [ ] CUBICSPLINE\n    * [x] Skin\n    * [ ] Camera (from glTF)\n    * [ ] Progressive rendering (No plan for this)\n    * [ ] Occlusion Culling experiment \n        * [x] Bounding Box\n            * [x] AABB (Axis Aligned Bounding Box, *static)\n            * [x] OBB (Object/Oriented Bounding Box)\n        * [x] Scene Bounding Box (fast iterated) And auto centered and scaled\n        * [ ] Build octree\n        * [ ] Occlusion Query with hierarchy\n\n\n## Credits\n\n* [glTF sample Model](https://github.com/KhronosGroup/glTF-Sample-Models) and [Buster Drone By LaVADraGoN](https://sketchfab.com/models/294e79652f494130ad2ab00a13fdbafd)\n* Great thanks to Trung Le ([@trungtle](https://github.com/trungtle)) and Patrick Cozzi ([@pjcozzi](https://github.com/pjcozzi)) for contributing and advising. \n* gl-Matrix by Brandon Jones ([@toji](https://github.com/toji)) and Colin MacKenzie IV ([@sinisterchipmunk](https://github.com/sinisterchipmunk))\n* [glTF-WebGL-PBR](https://github.com/KhronosGroup/glTF-WebGL-PBR)\n\n\n\n---\n# minimal-gltf-loader-typescript\n\nA minimal, engine-agnostic TypeScript glTF Loader.\n\n## What's new in gltf-loader-typescript\n\nThis loader is a new instance of the minimal-gltf-loader. \n\nIn this branch, the author updated the loading file fuction from XMLHttpRequest to fetch API and used Promise and async/await to make loading procedure much more clearer.\n\nIn glTF 2.0 standard, the target attribute on bufferView is optional. Different 3D softwares have different interpretation of glTF exporter.\nFor instance, the glTF files exported by Cinema4D have filled target attribute, but those exported by Blender 2.80+ **will NOT** have the target attribute filled. (Can see the issue in the following link:\n[KhronosGroup/glTF-Blender-IO#142](https://github.com/KhronosGroup/glTF-Blender-IO/issues/142))\nTherefore, before binding buffer, the loader should infer the target attribute is whether ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER accoring to the usage of bufferview.\n## Usage\n\n```typescript\nimport {vec3, vec4, quat, mat4} from 'gl-matrix';\nimport {GLTFLoader, GLTF} from './src/glTFLoader.ts'\n\nlet gl : WebGLRenderingContext | WebGL2RenderingContext;\n\nnew GLTFLoader(gl).loadGLTF('YourURL').then((glTF: GLTF) => {\n    // Create with glTF object, and proceed rendering process...\n}).catch (() => {\n    // Error control...\n});\n```"
  },
  {
    "path": "build/app.js",
    "content": "/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 7);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"EPSILON\", function() { return EPSILON; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ARRAY_TYPE\", function() { return ARRAY_TYPE; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RANDOM\", function() { return RANDOM; });\n/* harmony export (immutable) */ __webpack_exports__[\"setMatrixArrayType\"] = setMatrixArrayType;\n/* harmony export (immutable) */ __webpack_exports__[\"toRadian\"] = toRadian;\n/* harmony export (immutable) */ __webpack_exports__[\"equals\"] = equals;\n/**\r\n * Common utilities\r\n * @module glMatrix\r\n */\r\n\r\n// Configuration Constants\r\nvar EPSILON = 0.000001;\r\nvar ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;\r\nvar RANDOM = Math.random;\r\n\r\n/**\r\n * Sets the type of array used when creating new vectors and matrices\r\n *\r\n * @param {Type} type Array type, such as Float32Array or Array\r\n */\r\nfunction setMatrixArrayType(type) {\r\n  ARRAY_TYPE = type;\r\n}\r\n\r\nvar degree = Math.PI / 180;\r\n\r\n/**\r\n * Convert Degree To Radian\r\n *\r\n * @param {Number} a Angle in Degrees\r\n */\r\nfunction toRadian(a) {\r\n  return a * degree;\r\n}\r\n\r\n/**\r\n * Tests whether or not the arguments have approximately the same value, within an absolute\r\n * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less\r\n * than or equal to 1.0, and a relative tolerance is used for larger values)\r\n *\r\n * @param {Number} a The first number to test.\r\n * @param {Number} b The second number to test.\r\n * @returns {Boolean} True if the numbers are approximately equal, false otherwise.\r\n */\r\nfunction equals(a, b) {\r\n  return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));\r\n}\n\n/***/ }),\n/* 1 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__gl_matrix_common_js__ = __webpack_require__(0);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__gl_matrix_mat2_js__ = __webpack_require__(8);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__gl_matrix_mat2d_js__ = __webpack_require__(9);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__gl_matrix_mat3_js__ = __webpack_require__(2);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__gl_matrix_mat4_js__ = __webpack_require__(3);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__gl_matrix_quat_js__ = __webpack_require__(4);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__gl_matrix_quat2_js__ = __webpack_require__(10);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__gl_matrix_vec2_js__ = __webpack_require__(11);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__gl_matrix_vec3_js__ = __webpack_require__(5);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__gl_matrix_vec4_js__ = __webpack_require__(6);\n/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, \"glMatrix\", function() { return __WEBPACK_IMPORTED_MODULE_0__gl_matrix_common_js__; });\n/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, \"mat2\", function() { return __WEBPACK_IMPORTED_MODULE_1__gl_matrix_mat2_js__; });\n/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, \"mat2d\", function() { return __WEBPACK_IMPORTED_MODULE_2__gl_matrix_mat2d_js__; });\n/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, \"mat3\", function() { return __WEBPACK_IMPORTED_MODULE_3__gl_matrix_mat3_js__; });\n/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, \"mat4\", function() { return __WEBPACK_IMPORTED_MODULE_4__gl_matrix_mat4_js__; });\n/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, \"quat\", function() { return __WEBPACK_IMPORTED_MODULE_5__gl_matrix_quat_js__; });\n/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, \"quat2\", function() { return __WEBPACK_IMPORTED_MODULE_6__gl_matrix_quat2_js__; });\n/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, \"vec2\", function() { return __WEBPACK_IMPORTED_MODULE_7__gl_matrix_vec2_js__; });\n/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, \"vec3\", function() { return __WEBPACK_IMPORTED_MODULE_8__gl_matrix_vec3_js__; });\n/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, \"vec4\", function() { return __WEBPACK_IMPORTED_MODULE_9__gl_matrix_vec4_js__; });\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\n\n/***/ }),\n/* 2 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (immutable) */ __webpack_exports__[\"create\"] = create;\n/* harmony export (immutable) */ __webpack_exports__[\"fromMat4\"] = fromMat4;\n/* harmony export (immutable) */ __webpack_exports__[\"clone\"] = clone;\n/* harmony export (immutable) */ __webpack_exports__[\"copy\"] = copy;\n/* harmony export (immutable) */ __webpack_exports__[\"fromValues\"] = fromValues;\n/* harmony export (immutable) */ __webpack_exports__[\"set\"] = set;\n/* harmony export (immutable) */ __webpack_exports__[\"identity\"] = identity;\n/* harmony export (immutable) */ __webpack_exports__[\"transpose\"] = transpose;\n/* harmony export (immutable) */ __webpack_exports__[\"invert\"] = invert;\n/* harmony export (immutable) */ __webpack_exports__[\"adjoint\"] = adjoint;\n/* harmony export (immutable) */ __webpack_exports__[\"determinant\"] = determinant;\n/* harmony export (immutable) */ __webpack_exports__[\"multiply\"] = multiply;\n/* harmony export (immutable) */ __webpack_exports__[\"translate\"] = translate;\n/* harmony export (immutable) */ __webpack_exports__[\"rotate\"] = rotate;\n/* harmony export (immutable) */ __webpack_exports__[\"scale\"] = scale;\n/* harmony export (immutable) */ __webpack_exports__[\"fromTranslation\"] = fromTranslation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromRotation\"] = fromRotation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromScaling\"] = fromScaling;\n/* harmony export (immutable) */ __webpack_exports__[\"fromMat2d\"] = fromMat2d;\n/* harmony export (immutable) */ __webpack_exports__[\"fromQuat\"] = fromQuat;\n/* harmony export (immutable) */ __webpack_exports__[\"normalFromMat4\"] = normalFromMat4;\n/* harmony export (immutable) */ __webpack_exports__[\"projection\"] = projection;\n/* harmony export (immutable) */ __webpack_exports__[\"str\"] = str;\n/* harmony export (immutable) */ __webpack_exports__[\"frob\"] = frob;\n/* harmony export (immutable) */ __webpack_exports__[\"add\"] = add;\n/* harmony export (immutable) */ __webpack_exports__[\"subtract\"] = subtract;\n/* harmony export (immutable) */ __webpack_exports__[\"multiplyScalar\"] = multiplyScalar;\n/* harmony export (immutable) */ __webpack_exports__[\"multiplyScalarAndAdd\"] = multiplyScalarAndAdd;\n/* harmony export (immutable) */ __webpack_exports__[\"exactEquals\"] = exactEquals;\n/* harmony export (immutable) */ __webpack_exports__[\"equals\"] = equals;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mul\", function() { return mul; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sub\", function() { return sub; });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_js__ = __webpack_require__(0);\n\r\n\r\n/**\r\n * 3x3 Matrix\r\n * @module mat3\r\n */\r\n\r\n/**\r\n * Creates a new identity mat3\r\n *\r\n * @returns {mat3} a new 3x3 matrix\r\n */\r\nfunction create() {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](9);\r\n  if (__WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"] != Float32Array) {\r\n    out[1] = 0;\r\n    out[2] = 0;\r\n    out[3] = 0;\r\n    out[5] = 0;\r\n    out[6] = 0;\r\n    out[7] = 0;\r\n  }\r\n  out[0] = 1;\r\n  out[4] = 1;\r\n  out[8] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Copies the upper-left 3x3 values into the given mat3.\r\n *\r\n * @param {mat3} out the receiving 3x3 matrix\r\n * @param {mat4} a   the source 4x4 matrix\r\n * @returns {mat3} out\r\n */\r\nfunction fromMat4(out, a) {\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[4];\r\n  out[4] = a[5];\r\n  out[5] = a[6];\r\n  out[6] = a[8];\r\n  out[7] = a[9];\r\n  out[8] = a[10];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new mat3 initialized with values from an existing matrix\r\n *\r\n * @param {mat3} a matrix to clone\r\n * @returns {mat3} a new 3x3 matrix\r\n */\r\nfunction clone(a) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](9);\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  out[4] = a[4];\r\n  out[5] = a[5];\r\n  out[6] = a[6];\r\n  out[7] = a[7];\r\n  out[8] = a[8];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Copy the values from one mat3 to another\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the source matrix\r\n * @returns {mat3} out\r\n */\r\nfunction copy(out, a) {\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  out[4] = a[4];\r\n  out[5] = a[5];\r\n  out[6] = a[6];\r\n  out[7] = a[7];\r\n  out[8] = a[8];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Create a new mat3 with the given values\r\n *\r\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\r\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\r\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\r\n * @param {Number} m10 Component in column 1, row 0 position (index 3)\r\n * @param {Number} m11 Component in column 1, row 1 position (index 4)\r\n * @param {Number} m12 Component in column 1, row 2 position (index 5)\r\n * @param {Number} m20 Component in column 2, row 0 position (index 6)\r\n * @param {Number} m21 Component in column 2, row 1 position (index 7)\r\n * @param {Number} m22 Component in column 2, row 2 position (index 8)\r\n * @returns {mat3} A new mat3\r\n */\r\nfunction fromValues(m00, m01, m02, m10, m11, m12, m20, m21, m22) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](9);\r\n  out[0] = m00;\r\n  out[1] = m01;\r\n  out[2] = m02;\r\n  out[3] = m10;\r\n  out[4] = m11;\r\n  out[5] = m12;\r\n  out[6] = m20;\r\n  out[7] = m21;\r\n  out[8] = m22;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set the components of a mat3 to the given values\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\r\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\r\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\r\n * @param {Number} m10 Component in column 1, row 0 position (index 3)\r\n * @param {Number} m11 Component in column 1, row 1 position (index 4)\r\n * @param {Number} m12 Component in column 1, row 2 position (index 5)\r\n * @param {Number} m20 Component in column 2, row 0 position (index 6)\r\n * @param {Number} m21 Component in column 2, row 1 position (index 7)\r\n * @param {Number} m22 Component in column 2, row 2 position (index 8)\r\n * @returns {mat3} out\r\n */\r\nfunction set(out, m00, m01, m02, m10, m11, m12, m20, m21, m22) {\r\n  out[0] = m00;\r\n  out[1] = m01;\r\n  out[2] = m02;\r\n  out[3] = m10;\r\n  out[4] = m11;\r\n  out[5] = m12;\r\n  out[6] = m20;\r\n  out[7] = m21;\r\n  out[8] = m22;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set a mat3 to the identity matrix\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @returns {mat3} out\r\n */\r\nfunction identity(out) {\r\n  out[0] = 1;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = 1;\r\n  out[5] = 0;\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transpose the values of a mat3\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the source matrix\r\n * @returns {mat3} out\r\n */\r\nfunction transpose(out, a) {\r\n  // If we are transposing ourselves we can skip a few steps but have to cache some values\r\n  if (out === a) {\r\n    var a01 = a[1],\r\n        a02 = a[2],\r\n        a12 = a[5];\r\n    out[1] = a[3];\r\n    out[2] = a[6];\r\n    out[3] = a01;\r\n    out[5] = a[7];\r\n    out[6] = a02;\r\n    out[7] = a12;\r\n  } else {\r\n    out[0] = a[0];\r\n    out[1] = a[3];\r\n    out[2] = a[6];\r\n    out[3] = a[1];\r\n    out[4] = a[4];\r\n    out[5] = a[7];\r\n    out[6] = a[2];\r\n    out[7] = a[5];\r\n    out[8] = a[8];\r\n  }\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Inverts a mat3\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the source matrix\r\n * @returns {mat3} out\r\n */\r\nfunction invert(out, a) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2];\r\n  var a10 = a[3],\r\n      a11 = a[4],\r\n      a12 = a[5];\r\n  var a20 = a[6],\r\n      a21 = a[7],\r\n      a22 = a[8];\r\n\r\n  var b01 = a22 * a11 - a12 * a21;\r\n  var b11 = -a22 * a10 + a12 * a20;\r\n  var b21 = a21 * a10 - a11 * a20;\r\n\r\n  // Calculate the determinant\r\n  var det = a00 * b01 + a01 * b11 + a02 * b21;\r\n\r\n  if (!det) {\r\n    return null;\r\n  }\r\n  det = 1.0 / det;\r\n\r\n  out[0] = b01 * det;\r\n  out[1] = (-a22 * a01 + a02 * a21) * det;\r\n  out[2] = (a12 * a01 - a02 * a11) * det;\r\n  out[3] = b11 * det;\r\n  out[4] = (a22 * a00 - a02 * a20) * det;\r\n  out[5] = (-a12 * a00 + a02 * a10) * det;\r\n  out[6] = b21 * det;\r\n  out[7] = (-a21 * a00 + a01 * a20) * det;\r\n  out[8] = (a11 * a00 - a01 * a10) * det;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the adjugate of a mat3\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the source matrix\r\n * @returns {mat3} out\r\n */\r\nfunction adjoint(out, a) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2];\r\n  var a10 = a[3],\r\n      a11 = a[4],\r\n      a12 = a[5];\r\n  var a20 = a[6],\r\n      a21 = a[7],\r\n      a22 = a[8];\r\n\r\n  out[0] = a11 * a22 - a12 * a21;\r\n  out[1] = a02 * a21 - a01 * a22;\r\n  out[2] = a01 * a12 - a02 * a11;\r\n  out[3] = a12 * a20 - a10 * a22;\r\n  out[4] = a00 * a22 - a02 * a20;\r\n  out[5] = a02 * a10 - a00 * a12;\r\n  out[6] = a10 * a21 - a11 * a20;\r\n  out[7] = a01 * a20 - a00 * a21;\r\n  out[8] = a00 * a11 - a01 * a10;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the determinant of a mat3\r\n *\r\n * @param {mat3} a the source matrix\r\n * @returns {Number} determinant of a\r\n */\r\nfunction determinant(a) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2];\r\n  var a10 = a[3],\r\n      a11 = a[4],\r\n      a12 = a[5];\r\n  var a20 = a[6],\r\n      a21 = a[7],\r\n      a22 = a[8];\r\n\r\n  return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);\r\n}\r\n\r\n/**\r\n * Multiplies two mat3's\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the first operand\r\n * @param {mat3} b the second operand\r\n * @returns {mat3} out\r\n */\r\nfunction multiply(out, a, b) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2];\r\n  var a10 = a[3],\r\n      a11 = a[4],\r\n      a12 = a[5];\r\n  var a20 = a[6],\r\n      a21 = a[7],\r\n      a22 = a[8];\r\n\r\n  var b00 = b[0],\r\n      b01 = b[1],\r\n      b02 = b[2];\r\n  var b10 = b[3],\r\n      b11 = b[4],\r\n      b12 = b[5];\r\n  var b20 = b[6],\r\n      b21 = b[7],\r\n      b22 = b[8];\r\n\r\n  out[0] = b00 * a00 + b01 * a10 + b02 * a20;\r\n  out[1] = b00 * a01 + b01 * a11 + b02 * a21;\r\n  out[2] = b00 * a02 + b01 * a12 + b02 * a22;\r\n\r\n  out[3] = b10 * a00 + b11 * a10 + b12 * a20;\r\n  out[4] = b10 * a01 + b11 * a11 + b12 * a21;\r\n  out[5] = b10 * a02 + b11 * a12 + b12 * a22;\r\n\r\n  out[6] = b20 * a00 + b21 * a10 + b22 * a20;\r\n  out[7] = b20 * a01 + b21 * a11 + b22 * a21;\r\n  out[8] = b20 * a02 + b21 * a12 + b22 * a22;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Translate a mat3 by the given vector\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the matrix to translate\r\n * @param {vec2} v vector to translate by\r\n * @returns {mat3} out\r\n */\r\nfunction translate(out, a, v) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2],\r\n      a10 = a[3],\r\n      a11 = a[4],\r\n      a12 = a[5],\r\n      a20 = a[6],\r\n      a21 = a[7],\r\n      a22 = a[8],\r\n      x = v[0],\r\n      y = v[1];\r\n\r\n  out[0] = a00;\r\n  out[1] = a01;\r\n  out[2] = a02;\r\n\r\n  out[3] = a10;\r\n  out[4] = a11;\r\n  out[5] = a12;\r\n\r\n  out[6] = x * a00 + y * a10 + a20;\r\n  out[7] = x * a01 + y * a11 + a21;\r\n  out[8] = x * a02 + y * a12 + a22;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a mat3 by the given angle\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat3} out\r\n */\r\nfunction rotate(out, a, rad) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2],\r\n      a10 = a[3],\r\n      a11 = a[4],\r\n      a12 = a[5],\r\n      a20 = a[6],\r\n      a21 = a[7],\r\n      a22 = a[8],\r\n      s = Math.sin(rad),\r\n      c = Math.cos(rad);\r\n\r\n  out[0] = c * a00 + s * a10;\r\n  out[1] = c * a01 + s * a11;\r\n  out[2] = c * a02 + s * a12;\r\n\r\n  out[3] = c * a10 - s * a00;\r\n  out[4] = c * a11 - s * a01;\r\n  out[5] = c * a12 - s * a02;\r\n\r\n  out[6] = a20;\r\n  out[7] = a21;\r\n  out[8] = a22;\r\n  return out;\r\n};\r\n\r\n/**\r\n * Scales the mat3 by the dimensions in the given vec2\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the matrix to rotate\r\n * @param {vec2} v the vec2 to scale the matrix by\r\n * @returns {mat3} out\r\n **/\r\nfunction scale(out, a, v) {\r\n  var x = v[0],\r\n      y = v[1];\r\n\r\n  out[0] = x * a[0];\r\n  out[1] = x * a[1];\r\n  out[2] = x * a[2];\r\n\r\n  out[3] = y * a[3];\r\n  out[4] = y * a[4];\r\n  out[5] = y * a[5];\r\n\r\n  out[6] = a[6];\r\n  out[7] = a[7];\r\n  out[8] = a[8];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a vector translation\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat3.identity(dest);\r\n *     mat3.translate(dest, dest, vec);\r\n *\r\n * @param {mat3} out mat3 receiving operation result\r\n * @param {vec2} v Translation vector\r\n * @returns {mat3} out\r\n */\r\nfunction fromTranslation(out, v) {\r\n  out[0] = 1;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = 1;\r\n  out[5] = 0;\r\n  out[6] = v[0];\r\n  out[7] = v[1];\r\n  out[8] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a given angle\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat3.identity(dest);\r\n *     mat3.rotate(dest, dest, rad);\r\n *\r\n * @param {mat3} out mat3 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat3} out\r\n */\r\nfunction fromRotation(out, rad) {\r\n  var s = Math.sin(rad),\r\n      c = Math.cos(rad);\r\n\r\n  out[0] = c;\r\n  out[1] = s;\r\n  out[2] = 0;\r\n\r\n  out[3] = -s;\r\n  out[4] = c;\r\n  out[5] = 0;\r\n\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a vector scaling\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat3.identity(dest);\r\n *     mat3.scale(dest, dest, vec);\r\n *\r\n * @param {mat3} out mat3 receiving operation result\r\n * @param {vec2} v Scaling vector\r\n * @returns {mat3} out\r\n */\r\nfunction fromScaling(out, v) {\r\n  out[0] = v[0];\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n\r\n  out[3] = 0;\r\n  out[4] = v[1];\r\n  out[5] = 0;\r\n\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Copies the values from a mat2d into a mat3\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat2d} a the matrix to copy\r\n * @returns {mat3} out\r\n **/\r\nfunction fromMat2d(out, a) {\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = 0;\r\n\r\n  out[3] = a[2];\r\n  out[4] = a[3];\r\n  out[5] = 0;\r\n\r\n  out[6] = a[4];\r\n  out[7] = a[5];\r\n  out[8] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n* Calculates a 3x3 matrix from the given quaternion\r\n*\r\n* @param {mat3} out mat3 receiving operation result\r\n* @param {quat} q Quaternion to create matrix from\r\n*\r\n* @returns {mat3} out\r\n*/\r\nfunction fromQuat(out, q) {\r\n  var x = q[0],\r\n      y = q[1],\r\n      z = q[2],\r\n      w = q[3];\r\n  var x2 = x + x;\r\n  var y2 = y + y;\r\n  var z2 = z + z;\r\n\r\n  var xx = x * x2;\r\n  var yx = y * x2;\r\n  var yy = y * y2;\r\n  var zx = z * x2;\r\n  var zy = z * y2;\r\n  var zz = z * z2;\r\n  var wx = w * x2;\r\n  var wy = w * y2;\r\n  var wz = w * z2;\r\n\r\n  out[0] = 1 - yy - zz;\r\n  out[3] = yx - wz;\r\n  out[6] = zx + wy;\r\n\r\n  out[1] = yx + wz;\r\n  out[4] = 1 - xx - zz;\r\n  out[7] = zy - wx;\r\n\r\n  out[2] = zx - wy;\r\n  out[5] = zy + wx;\r\n  out[8] = 1 - xx - yy;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix\r\n*\r\n* @param {mat3} out mat3 receiving operation result\r\n* @param {mat4} a Mat4 to derive the normal matrix from\r\n*\r\n* @returns {mat3} out\r\n*/\r\nfunction normalFromMat4(out, a) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2],\r\n      a03 = a[3];\r\n  var a10 = a[4],\r\n      a11 = a[5],\r\n      a12 = a[6],\r\n      a13 = a[7];\r\n  var a20 = a[8],\r\n      a21 = a[9],\r\n      a22 = a[10],\r\n      a23 = a[11];\r\n  var a30 = a[12],\r\n      a31 = a[13],\r\n      a32 = a[14],\r\n      a33 = a[15];\r\n\r\n  var b00 = a00 * a11 - a01 * a10;\r\n  var b01 = a00 * a12 - a02 * a10;\r\n  var b02 = a00 * a13 - a03 * a10;\r\n  var b03 = a01 * a12 - a02 * a11;\r\n  var b04 = a01 * a13 - a03 * a11;\r\n  var b05 = a02 * a13 - a03 * a12;\r\n  var b06 = a20 * a31 - a21 * a30;\r\n  var b07 = a20 * a32 - a22 * a30;\r\n  var b08 = a20 * a33 - a23 * a30;\r\n  var b09 = a21 * a32 - a22 * a31;\r\n  var b10 = a21 * a33 - a23 * a31;\r\n  var b11 = a22 * a33 - a23 * a32;\r\n\r\n  // Calculate the determinant\r\n  var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\r\n\r\n  if (!det) {\r\n    return null;\r\n  }\r\n  det = 1.0 / det;\r\n\r\n  out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\r\n  out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\r\n  out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\r\n\r\n  out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\r\n  out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\r\n  out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\r\n\r\n  out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\r\n  out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\r\n  out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a 2D projection matrix with the given bounds\r\n *\r\n * @param {mat3} out mat3 frustum matrix will be written into\r\n * @param {number} width Width of your gl context\r\n * @param {number} height Height of gl context\r\n * @returns {mat3} out\r\n */\r\nfunction projection(out, width, height) {\r\n  out[0] = 2 / width;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = -2 / height;\r\n  out[5] = 0;\r\n  out[6] = -1;\r\n  out[7] = 1;\r\n  out[8] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns a string representation of a mat3\r\n *\r\n * @param {mat3} a matrix to represent as a string\r\n * @returns {String} string representation of the matrix\r\n */\r\nfunction str(a) {\r\n  return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' + a[8] + ')';\r\n}\r\n\r\n/**\r\n * Returns Frobenius norm of a mat3\r\n *\r\n * @param {mat3} a the matrix to calculate Frobenius norm of\r\n * @returns {Number} Frobenius norm\r\n */\r\nfunction frob(a) {\r\n  return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2));\r\n}\r\n\r\n/**\r\n * Adds two mat3's\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the first operand\r\n * @param {mat3} b the second operand\r\n * @returns {mat3} out\r\n */\r\nfunction add(out, a, b) {\r\n  out[0] = a[0] + b[0];\r\n  out[1] = a[1] + b[1];\r\n  out[2] = a[2] + b[2];\r\n  out[3] = a[3] + b[3];\r\n  out[4] = a[4] + b[4];\r\n  out[5] = a[5] + b[5];\r\n  out[6] = a[6] + b[6];\r\n  out[7] = a[7] + b[7];\r\n  out[8] = a[8] + b[8];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Subtracts matrix b from matrix a\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the first operand\r\n * @param {mat3} b the second operand\r\n * @returns {mat3} out\r\n */\r\nfunction subtract(out, a, b) {\r\n  out[0] = a[0] - b[0];\r\n  out[1] = a[1] - b[1];\r\n  out[2] = a[2] - b[2];\r\n  out[3] = a[3] - b[3];\r\n  out[4] = a[4] - b[4];\r\n  out[5] = a[5] - b[5];\r\n  out[6] = a[6] - b[6];\r\n  out[7] = a[7] - b[7];\r\n  out[8] = a[8] - b[8];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Multiply each element of the matrix by a scalar.\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {mat3} a the matrix to scale\r\n * @param {Number} b amount to scale the matrix's elements by\r\n * @returns {mat3} out\r\n */\r\nfunction multiplyScalar(out, a, b) {\r\n  out[0] = a[0] * b;\r\n  out[1] = a[1] * b;\r\n  out[2] = a[2] * b;\r\n  out[3] = a[3] * b;\r\n  out[4] = a[4] * b;\r\n  out[5] = a[5] * b;\r\n  out[6] = a[6] * b;\r\n  out[7] = a[7] * b;\r\n  out[8] = a[8] * b;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two mat3's after multiplying each element of the second operand by a scalar value.\r\n *\r\n * @param {mat3} out the receiving vector\r\n * @param {mat3} a the first operand\r\n * @param {mat3} b the second operand\r\n * @param {Number} scale the amount to scale b's elements by before adding\r\n * @returns {mat3} out\r\n */\r\nfunction multiplyScalarAndAdd(out, a, b, scale) {\r\n  out[0] = a[0] + b[0] * scale;\r\n  out[1] = a[1] + b[1] * scale;\r\n  out[2] = a[2] + b[2] * scale;\r\n  out[3] = a[3] + b[3] * scale;\r\n  out[4] = a[4] + b[4] * scale;\r\n  out[5] = a[5] + b[5] * scale;\r\n  out[6] = a[6] + b[6] * scale;\r\n  out[7] = a[7] + b[7] * scale;\r\n  out[8] = a[8] + b[8] * scale;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {mat3} a The first matrix.\r\n * @param {mat3} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\r\nfunction exactEquals(a, b) {\r\n  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];\r\n}\r\n\r\n/**\r\n * Returns whether or not the matrices have approximately the same elements in the same position.\r\n *\r\n * @param {mat3} a The first matrix.\r\n * @param {mat3} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\r\nfunction equals(a, b) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3],\r\n      a4 = a[4],\r\n      a5 = a[5],\r\n      a6 = a[6],\r\n      a7 = a[7],\r\n      a8 = a[8];\r\n  var b0 = b[0],\r\n      b1 = b[1],\r\n      b2 = b[2],\r\n      b3 = b[3],\r\n      b4 = b[4],\r\n      b5 = b[5],\r\n      b6 = b[6],\r\n      b7 = b[7],\r\n      b8 = b[8];\r\n  return Math.abs(a0 - b0) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a8), Math.abs(b8));\r\n}\r\n\r\n/**\r\n * Alias for {@link mat3.multiply}\r\n * @function\r\n */\r\nvar mul = multiply;\r\n\r\n/**\r\n * Alias for {@link mat3.subtract}\r\n * @function\r\n */\r\nvar sub = subtract;\n\n/***/ }),\n/* 3 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (immutable) */ __webpack_exports__[\"create\"] = create;\n/* harmony export (immutable) */ __webpack_exports__[\"clone\"] = clone;\n/* harmony export (immutable) */ __webpack_exports__[\"copy\"] = copy;\n/* harmony export (immutable) */ __webpack_exports__[\"fromValues\"] = fromValues;\n/* harmony export (immutable) */ __webpack_exports__[\"set\"] = set;\n/* harmony export (immutable) */ __webpack_exports__[\"identity\"] = identity;\n/* harmony export (immutable) */ __webpack_exports__[\"transpose\"] = transpose;\n/* harmony export (immutable) */ __webpack_exports__[\"invert\"] = invert;\n/* harmony export (immutable) */ __webpack_exports__[\"adjoint\"] = adjoint;\n/* harmony export (immutable) */ __webpack_exports__[\"determinant\"] = determinant;\n/* harmony export (immutable) */ __webpack_exports__[\"multiply\"] = multiply;\n/* harmony export (immutable) */ __webpack_exports__[\"translate\"] = translate;\n/* harmony export (immutable) */ __webpack_exports__[\"scale\"] = scale;\n/* harmony export (immutable) */ __webpack_exports__[\"rotate\"] = rotate;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateX\"] = rotateX;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateY\"] = rotateY;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateZ\"] = rotateZ;\n/* harmony export (immutable) */ __webpack_exports__[\"fromTranslation\"] = fromTranslation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromScaling\"] = fromScaling;\n/* harmony export (immutable) */ __webpack_exports__[\"fromRotation\"] = fromRotation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromXRotation\"] = fromXRotation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromYRotation\"] = fromYRotation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromZRotation\"] = fromZRotation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromRotationTranslation\"] = fromRotationTranslation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromQuat2\"] = fromQuat2;\n/* harmony export (immutable) */ __webpack_exports__[\"getTranslation\"] = getTranslation;\n/* harmony export (immutable) */ __webpack_exports__[\"getScaling\"] = getScaling;\n/* harmony export (immutable) */ __webpack_exports__[\"getRotation\"] = getRotation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromRotationTranslationScale\"] = fromRotationTranslationScale;\n/* harmony export (immutable) */ __webpack_exports__[\"fromRotationTranslationScaleOrigin\"] = fromRotationTranslationScaleOrigin;\n/* harmony export (immutable) */ __webpack_exports__[\"fromQuat\"] = fromQuat;\n/* harmony export (immutable) */ __webpack_exports__[\"frustum\"] = frustum;\n/* harmony export (immutable) */ __webpack_exports__[\"perspective\"] = perspective;\n/* harmony export (immutable) */ __webpack_exports__[\"perspectiveFromFieldOfView\"] = perspectiveFromFieldOfView;\n/* harmony export (immutable) */ __webpack_exports__[\"ortho\"] = ortho;\n/* harmony export (immutable) */ __webpack_exports__[\"lookAt\"] = lookAt;\n/* harmony export (immutable) */ __webpack_exports__[\"targetTo\"] = targetTo;\n/* harmony export (immutable) */ __webpack_exports__[\"str\"] = str;\n/* harmony export (immutable) */ __webpack_exports__[\"frob\"] = frob;\n/* harmony export (immutable) */ __webpack_exports__[\"add\"] = add;\n/* harmony export (immutable) */ __webpack_exports__[\"subtract\"] = subtract;\n/* harmony export (immutable) */ __webpack_exports__[\"multiplyScalar\"] = multiplyScalar;\n/* harmony export (immutable) */ __webpack_exports__[\"multiplyScalarAndAdd\"] = multiplyScalarAndAdd;\n/* harmony export (immutable) */ __webpack_exports__[\"exactEquals\"] = exactEquals;\n/* harmony export (immutable) */ __webpack_exports__[\"equals\"] = equals;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mul\", function() { return mul; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sub\", function() { return sub; });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_js__ = __webpack_require__(0);\n\r\n\r\n/**\r\n * 4x4 Matrix<br>Format: column-major, when typed out it looks like row-major<br>The matrices are being post multiplied.\r\n * @module mat4\r\n */\r\n\r\n/**\r\n * Creates a new identity mat4\r\n *\r\n * @returns {mat4} a new 4x4 matrix\r\n */\r\nfunction create() {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](16);\r\n  if (__WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"] != Float32Array) {\r\n    out[1] = 0;\r\n    out[2] = 0;\r\n    out[3] = 0;\r\n    out[4] = 0;\r\n    out[6] = 0;\r\n    out[7] = 0;\r\n    out[8] = 0;\r\n    out[9] = 0;\r\n    out[11] = 0;\r\n    out[12] = 0;\r\n    out[13] = 0;\r\n    out[14] = 0;\r\n  }\r\n  out[0] = 1;\r\n  out[5] = 1;\r\n  out[10] = 1;\r\n  out[15] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new mat4 initialized with values from an existing matrix\r\n *\r\n * @param {mat4} a matrix to clone\r\n * @returns {mat4} a new 4x4 matrix\r\n */\r\nfunction clone(a) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](16);\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  out[4] = a[4];\r\n  out[5] = a[5];\r\n  out[6] = a[6];\r\n  out[7] = a[7];\r\n  out[8] = a[8];\r\n  out[9] = a[9];\r\n  out[10] = a[10];\r\n  out[11] = a[11];\r\n  out[12] = a[12];\r\n  out[13] = a[13];\r\n  out[14] = a[14];\r\n  out[15] = a[15];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Copy the values from one mat4 to another\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the source matrix\r\n * @returns {mat4} out\r\n */\r\nfunction copy(out, a) {\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  out[4] = a[4];\r\n  out[5] = a[5];\r\n  out[6] = a[6];\r\n  out[7] = a[7];\r\n  out[8] = a[8];\r\n  out[9] = a[9];\r\n  out[10] = a[10];\r\n  out[11] = a[11];\r\n  out[12] = a[12];\r\n  out[13] = a[13];\r\n  out[14] = a[14];\r\n  out[15] = a[15];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Create a new mat4 with the given values\r\n *\r\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\r\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\r\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\r\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\r\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\r\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\r\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\r\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\r\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\r\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\r\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\r\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\r\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\r\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\r\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\r\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\r\n * @returns {mat4} A new mat4\r\n */\r\nfunction fromValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](16);\r\n  out[0] = m00;\r\n  out[1] = m01;\r\n  out[2] = m02;\r\n  out[3] = m03;\r\n  out[4] = m10;\r\n  out[5] = m11;\r\n  out[6] = m12;\r\n  out[7] = m13;\r\n  out[8] = m20;\r\n  out[9] = m21;\r\n  out[10] = m22;\r\n  out[11] = m23;\r\n  out[12] = m30;\r\n  out[13] = m31;\r\n  out[14] = m32;\r\n  out[15] = m33;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set the components of a mat4 to the given values\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\r\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\r\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\r\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\r\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\r\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\r\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\r\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\r\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\r\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\r\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\r\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\r\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\r\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\r\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\r\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\r\n * @returns {mat4} out\r\n */\r\nfunction set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\r\n  out[0] = m00;\r\n  out[1] = m01;\r\n  out[2] = m02;\r\n  out[3] = m03;\r\n  out[4] = m10;\r\n  out[5] = m11;\r\n  out[6] = m12;\r\n  out[7] = m13;\r\n  out[8] = m20;\r\n  out[9] = m21;\r\n  out[10] = m22;\r\n  out[11] = m23;\r\n  out[12] = m30;\r\n  out[13] = m31;\r\n  out[14] = m32;\r\n  out[15] = m33;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set a mat4 to the identity matrix\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @returns {mat4} out\r\n */\r\nfunction identity(out) {\r\n  out[0] = 1;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = 0;\r\n  out[5] = 1;\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = 0;\r\n  out[9] = 0;\r\n  out[10] = 1;\r\n  out[11] = 0;\r\n  out[12] = 0;\r\n  out[13] = 0;\r\n  out[14] = 0;\r\n  out[15] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transpose the values of a mat4\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the source matrix\r\n * @returns {mat4} out\r\n */\r\nfunction transpose(out, a) {\r\n  // If we are transposing ourselves we can skip a few steps but have to cache some values\r\n  if (out === a) {\r\n    var a01 = a[1],\r\n        a02 = a[2],\r\n        a03 = a[3];\r\n    var a12 = a[6],\r\n        a13 = a[7];\r\n    var a23 = a[11];\r\n\r\n    out[1] = a[4];\r\n    out[2] = a[8];\r\n    out[3] = a[12];\r\n    out[4] = a01;\r\n    out[6] = a[9];\r\n    out[7] = a[13];\r\n    out[8] = a02;\r\n    out[9] = a12;\r\n    out[11] = a[14];\r\n    out[12] = a03;\r\n    out[13] = a13;\r\n    out[14] = a23;\r\n  } else {\r\n    out[0] = a[0];\r\n    out[1] = a[4];\r\n    out[2] = a[8];\r\n    out[3] = a[12];\r\n    out[4] = a[1];\r\n    out[5] = a[5];\r\n    out[6] = a[9];\r\n    out[7] = a[13];\r\n    out[8] = a[2];\r\n    out[9] = a[6];\r\n    out[10] = a[10];\r\n    out[11] = a[14];\r\n    out[12] = a[3];\r\n    out[13] = a[7];\r\n    out[14] = a[11];\r\n    out[15] = a[15];\r\n  }\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Inverts a mat4\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the source matrix\r\n * @returns {mat4} out\r\n */\r\nfunction invert(out, a) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2],\r\n      a03 = a[3];\r\n  var a10 = a[4],\r\n      a11 = a[5],\r\n      a12 = a[6],\r\n      a13 = a[7];\r\n  var a20 = a[8],\r\n      a21 = a[9],\r\n      a22 = a[10],\r\n      a23 = a[11];\r\n  var a30 = a[12],\r\n      a31 = a[13],\r\n      a32 = a[14],\r\n      a33 = a[15];\r\n\r\n  var b00 = a00 * a11 - a01 * a10;\r\n  var b01 = a00 * a12 - a02 * a10;\r\n  var b02 = a00 * a13 - a03 * a10;\r\n  var b03 = a01 * a12 - a02 * a11;\r\n  var b04 = a01 * a13 - a03 * a11;\r\n  var b05 = a02 * a13 - a03 * a12;\r\n  var b06 = a20 * a31 - a21 * a30;\r\n  var b07 = a20 * a32 - a22 * a30;\r\n  var b08 = a20 * a33 - a23 * a30;\r\n  var b09 = a21 * a32 - a22 * a31;\r\n  var b10 = a21 * a33 - a23 * a31;\r\n  var b11 = a22 * a33 - a23 * a32;\r\n\r\n  // Calculate the determinant\r\n  var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\r\n\r\n  if (!det) {\r\n    return null;\r\n  }\r\n  det = 1.0 / det;\r\n\r\n  out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\r\n  out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\r\n  out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\r\n  out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;\r\n  out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\r\n  out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\r\n  out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\r\n  out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;\r\n  out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\r\n  out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\r\n  out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\r\n  out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;\r\n  out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;\r\n  out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;\r\n  out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;\r\n  out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the adjugate of a mat4\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the source matrix\r\n * @returns {mat4} out\r\n */\r\nfunction adjoint(out, a) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2],\r\n      a03 = a[3];\r\n  var a10 = a[4],\r\n      a11 = a[5],\r\n      a12 = a[6],\r\n      a13 = a[7];\r\n  var a20 = a[8],\r\n      a21 = a[9],\r\n      a22 = a[10],\r\n      a23 = a[11];\r\n  var a30 = a[12],\r\n      a31 = a[13],\r\n      a32 = a[14],\r\n      a33 = a[15];\r\n\r\n  out[0] = a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22);\r\n  out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));\r\n  out[2] = a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12);\r\n  out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));\r\n  out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));\r\n  out[5] = a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22);\r\n  out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));\r\n  out[7] = a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12);\r\n  out[8] = a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21);\r\n  out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));\r\n  out[10] = a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11);\r\n  out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));\r\n  out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));\r\n  out[13] = a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21);\r\n  out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));\r\n  out[15] = a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the determinant of a mat4\r\n *\r\n * @param {mat4} a the source matrix\r\n * @returns {Number} determinant of a\r\n */\r\nfunction determinant(a) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2],\r\n      a03 = a[3];\r\n  var a10 = a[4],\r\n      a11 = a[5],\r\n      a12 = a[6],\r\n      a13 = a[7];\r\n  var a20 = a[8],\r\n      a21 = a[9],\r\n      a22 = a[10],\r\n      a23 = a[11];\r\n  var a30 = a[12],\r\n      a31 = a[13],\r\n      a32 = a[14],\r\n      a33 = a[15];\r\n\r\n  var b00 = a00 * a11 - a01 * a10;\r\n  var b01 = a00 * a12 - a02 * a10;\r\n  var b02 = a00 * a13 - a03 * a10;\r\n  var b03 = a01 * a12 - a02 * a11;\r\n  var b04 = a01 * a13 - a03 * a11;\r\n  var b05 = a02 * a13 - a03 * a12;\r\n  var b06 = a20 * a31 - a21 * a30;\r\n  var b07 = a20 * a32 - a22 * a30;\r\n  var b08 = a20 * a33 - a23 * a30;\r\n  var b09 = a21 * a32 - a22 * a31;\r\n  var b10 = a21 * a33 - a23 * a31;\r\n  var b11 = a22 * a33 - a23 * a32;\r\n\r\n  // Calculate the determinant\r\n  return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\r\n}\r\n\r\n/**\r\n * Multiplies two mat4s\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the first operand\r\n * @param {mat4} b the second operand\r\n * @returns {mat4} out\r\n */\r\nfunction multiply(out, a, b) {\r\n  var a00 = a[0],\r\n      a01 = a[1],\r\n      a02 = a[2],\r\n      a03 = a[3];\r\n  var a10 = a[4],\r\n      a11 = a[5],\r\n      a12 = a[6],\r\n      a13 = a[7];\r\n  var a20 = a[8],\r\n      a21 = a[9],\r\n      a22 = a[10],\r\n      a23 = a[11];\r\n  var a30 = a[12],\r\n      a31 = a[13],\r\n      a32 = a[14],\r\n      a33 = a[15];\r\n\r\n  // Cache only the current line of the second matrix\r\n  var b0 = b[0],\r\n      b1 = b[1],\r\n      b2 = b[2],\r\n      b3 = b[3];\r\n  out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\r\n  out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\r\n  out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\r\n  out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\r\n\r\n  b0 = b[4];b1 = b[5];b2 = b[6];b3 = b[7];\r\n  out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\r\n  out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\r\n  out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\r\n  out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\r\n\r\n  b0 = b[8];b1 = b[9];b2 = b[10];b3 = b[11];\r\n  out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\r\n  out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\r\n  out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\r\n  out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\r\n\r\n  b0 = b[12];b1 = b[13];b2 = b[14];b3 = b[15];\r\n  out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\r\n  out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\r\n  out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\r\n  out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Translate a mat4 by the given vector\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the matrix to translate\r\n * @param {vec3} v vector to translate by\r\n * @returns {mat4} out\r\n */\r\nfunction translate(out, a, v) {\r\n  var x = v[0],\r\n      y = v[1],\r\n      z = v[2];\r\n  var a00 = void 0,\r\n      a01 = void 0,\r\n      a02 = void 0,\r\n      a03 = void 0;\r\n  var a10 = void 0,\r\n      a11 = void 0,\r\n      a12 = void 0,\r\n      a13 = void 0;\r\n  var a20 = void 0,\r\n      a21 = void 0,\r\n      a22 = void 0,\r\n      a23 = void 0;\r\n\r\n  if (a === out) {\r\n    out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];\r\n    out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];\r\n    out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];\r\n    out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];\r\n  } else {\r\n    a00 = a[0];a01 = a[1];a02 = a[2];a03 = a[3];\r\n    a10 = a[4];a11 = a[5];a12 = a[6];a13 = a[7];\r\n    a20 = a[8];a21 = a[9];a22 = a[10];a23 = a[11];\r\n\r\n    out[0] = a00;out[1] = a01;out[2] = a02;out[3] = a03;\r\n    out[4] = a10;out[5] = a11;out[6] = a12;out[7] = a13;\r\n    out[8] = a20;out[9] = a21;out[10] = a22;out[11] = a23;\r\n\r\n    out[12] = a00 * x + a10 * y + a20 * z + a[12];\r\n    out[13] = a01 * x + a11 * y + a21 * z + a[13];\r\n    out[14] = a02 * x + a12 * y + a22 * z + a[14];\r\n    out[15] = a03 * x + a13 * y + a23 * z + a[15];\r\n  }\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Scales the mat4 by the dimensions in the given vec3 not using vectorization\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the matrix to scale\r\n * @param {vec3} v the vec3 to scale the matrix by\r\n * @returns {mat4} out\r\n **/\r\nfunction scale(out, a, v) {\r\n  var x = v[0],\r\n      y = v[1],\r\n      z = v[2];\r\n\r\n  out[0] = a[0] * x;\r\n  out[1] = a[1] * x;\r\n  out[2] = a[2] * x;\r\n  out[3] = a[3] * x;\r\n  out[4] = a[4] * y;\r\n  out[5] = a[5] * y;\r\n  out[6] = a[6] * y;\r\n  out[7] = a[7] * y;\r\n  out[8] = a[8] * z;\r\n  out[9] = a[9] * z;\r\n  out[10] = a[10] * z;\r\n  out[11] = a[11] * z;\r\n  out[12] = a[12];\r\n  out[13] = a[13];\r\n  out[14] = a[14];\r\n  out[15] = a[15];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a mat4 by the given angle around the given axis\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @param {vec3} axis the axis to rotate around\r\n * @returns {mat4} out\r\n */\r\nfunction rotate(out, a, rad, axis) {\r\n  var x = axis[0],\r\n      y = axis[1],\r\n      z = axis[2];\r\n  var len = Math.sqrt(x * x + y * y + z * z);\r\n  var s = void 0,\r\n      c = void 0,\r\n      t = void 0;\r\n  var a00 = void 0,\r\n      a01 = void 0,\r\n      a02 = void 0,\r\n      a03 = void 0;\r\n  var a10 = void 0,\r\n      a11 = void 0,\r\n      a12 = void 0,\r\n      a13 = void 0;\r\n  var a20 = void 0,\r\n      a21 = void 0,\r\n      a22 = void 0,\r\n      a23 = void 0;\r\n  var b00 = void 0,\r\n      b01 = void 0,\r\n      b02 = void 0;\r\n  var b10 = void 0,\r\n      b11 = void 0,\r\n      b12 = void 0;\r\n  var b20 = void 0,\r\n      b21 = void 0,\r\n      b22 = void 0;\r\n\r\n  if (len < __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"]) {\r\n    return null;\r\n  }\r\n\r\n  len = 1 / len;\r\n  x *= len;\r\n  y *= len;\r\n  z *= len;\r\n\r\n  s = Math.sin(rad);\r\n  c = Math.cos(rad);\r\n  t = 1 - c;\r\n\r\n  a00 = a[0];a01 = a[1];a02 = a[2];a03 = a[3];\r\n  a10 = a[4];a11 = a[5];a12 = a[6];a13 = a[7];\r\n  a20 = a[8];a21 = a[9];a22 = a[10];a23 = a[11];\r\n\r\n  // Construct the elements of the rotation matrix\r\n  b00 = x * x * t + c;b01 = y * x * t + z * s;b02 = z * x * t - y * s;\r\n  b10 = x * y * t - z * s;b11 = y * y * t + c;b12 = z * y * t + x * s;\r\n  b20 = x * z * t + y * s;b21 = y * z * t - x * s;b22 = z * z * t + c;\r\n\r\n  // Perform rotation-specific matrix multiplication\r\n  out[0] = a00 * b00 + a10 * b01 + a20 * b02;\r\n  out[1] = a01 * b00 + a11 * b01 + a21 * b02;\r\n  out[2] = a02 * b00 + a12 * b01 + a22 * b02;\r\n  out[3] = a03 * b00 + a13 * b01 + a23 * b02;\r\n  out[4] = a00 * b10 + a10 * b11 + a20 * b12;\r\n  out[5] = a01 * b10 + a11 * b11 + a21 * b12;\r\n  out[6] = a02 * b10 + a12 * b11 + a22 * b12;\r\n  out[7] = a03 * b10 + a13 * b11 + a23 * b12;\r\n  out[8] = a00 * b20 + a10 * b21 + a20 * b22;\r\n  out[9] = a01 * b20 + a11 * b21 + a21 * b22;\r\n  out[10] = a02 * b20 + a12 * b21 + a22 * b22;\r\n  out[11] = a03 * b20 + a13 * b21 + a23 * b22;\r\n\r\n  if (a !== out) {\r\n    // If the source and destination differ, copy the unchanged last row\r\n    out[12] = a[12];\r\n    out[13] = a[13];\r\n    out[14] = a[14];\r\n    out[15] = a[15];\r\n  }\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a matrix by the given angle around the X axis\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\r\nfunction rotateX(out, a, rad) {\r\n  var s = Math.sin(rad);\r\n  var c = Math.cos(rad);\r\n  var a10 = a[4];\r\n  var a11 = a[5];\r\n  var a12 = a[6];\r\n  var a13 = a[7];\r\n  var a20 = a[8];\r\n  var a21 = a[9];\r\n  var a22 = a[10];\r\n  var a23 = a[11];\r\n\r\n  if (a !== out) {\r\n    // If the source and destination differ, copy the unchanged rows\r\n    out[0] = a[0];\r\n    out[1] = a[1];\r\n    out[2] = a[2];\r\n    out[3] = a[3];\r\n    out[12] = a[12];\r\n    out[13] = a[13];\r\n    out[14] = a[14];\r\n    out[15] = a[15];\r\n  }\r\n\r\n  // Perform axis-specific matrix multiplication\r\n  out[4] = a10 * c + a20 * s;\r\n  out[5] = a11 * c + a21 * s;\r\n  out[6] = a12 * c + a22 * s;\r\n  out[7] = a13 * c + a23 * s;\r\n  out[8] = a20 * c - a10 * s;\r\n  out[9] = a21 * c - a11 * s;\r\n  out[10] = a22 * c - a12 * s;\r\n  out[11] = a23 * c - a13 * s;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a matrix by the given angle around the Y axis\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\r\nfunction rotateY(out, a, rad) {\r\n  var s = Math.sin(rad);\r\n  var c = Math.cos(rad);\r\n  var a00 = a[0];\r\n  var a01 = a[1];\r\n  var a02 = a[2];\r\n  var a03 = a[3];\r\n  var a20 = a[8];\r\n  var a21 = a[9];\r\n  var a22 = a[10];\r\n  var a23 = a[11];\r\n\r\n  if (a !== out) {\r\n    // If the source and destination differ, copy the unchanged rows\r\n    out[4] = a[4];\r\n    out[5] = a[5];\r\n    out[6] = a[6];\r\n    out[7] = a[7];\r\n    out[12] = a[12];\r\n    out[13] = a[13];\r\n    out[14] = a[14];\r\n    out[15] = a[15];\r\n  }\r\n\r\n  // Perform axis-specific matrix multiplication\r\n  out[0] = a00 * c - a20 * s;\r\n  out[1] = a01 * c - a21 * s;\r\n  out[2] = a02 * c - a22 * s;\r\n  out[3] = a03 * c - a23 * s;\r\n  out[8] = a00 * s + a20 * c;\r\n  out[9] = a01 * s + a21 * c;\r\n  out[10] = a02 * s + a22 * c;\r\n  out[11] = a03 * s + a23 * c;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a matrix by the given angle around the Z axis\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\r\nfunction rotateZ(out, a, rad) {\r\n  var s = Math.sin(rad);\r\n  var c = Math.cos(rad);\r\n  var a00 = a[0];\r\n  var a01 = a[1];\r\n  var a02 = a[2];\r\n  var a03 = a[3];\r\n  var a10 = a[4];\r\n  var a11 = a[5];\r\n  var a12 = a[6];\r\n  var a13 = a[7];\r\n\r\n  if (a !== out) {\r\n    // If the source and destination differ, copy the unchanged last row\r\n    out[8] = a[8];\r\n    out[9] = a[9];\r\n    out[10] = a[10];\r\n    out[11] = a[11];\r\n    out[12] = a[12];\r\n    out[13] = a[13];\r\n    out[14] = a[14];\r\n    out[15] = a[15];\r\n  }\r\n\r\n  // Perform axis-specific matrix multiplication\r\n  out[0] = a00 * c + a10 * s;\r\n  out[1] = a01 * c + a11 * s;\r\n  out[2] = a02 * c + a12 * s;\r\n  out[3] = a03 * c + a13 * s;\r\n  out[4] = a10 * c - a00 * s;\r\n  out[5] = a11 * c - a01 * s;\r\n  out[6] = a12 * c - a02 * s;\r\n  out[7] = a13 * c - a03 * s;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a vector translation\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.translate(dest, dest, vec);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {vec3} v Translation vector\r\n * @returns {mat4} out\r\n */\r\nfunction fromTranslation(out, v) {\r\n  out[0] = 1;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = 0;\r\n  out[5] = 1;\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = 0;\r\n  out[9] = 0;\r\n  out[10] = 1;\r\n  out[11] = 0;\r\n  out[12] = v[0];\r\n  out[13] = v[1];\r\n  out[14] = v[2];\r\n  out[15] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a vector scaling\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.scale(dest, dest, vec);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {vec3} v Scaling vector\r\n * @returns {mat4} out\r\n */\r\nfunction fromScaling(out, v) {\r\n  out[0] = v[0];\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = 0;\r\n  out[5] = v[1];\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = 0;\r\n  out[9] = 0;\r\n  out[10] = v[2];\r\n  out[11] = 0;\r\n  out[12] = 0;\r\n  out[13] = 0;\r\n  out[14] = 0;\r\n  out[15] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a given angle around a given axis\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.rotate(dest, dest, rad, axis);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @param {vec3} axis the axis to rotate around\r\n * @returns {mat4} out\r\n */\r\nfunction fromRotation(out, rad, axis) {\r\n  var x = axis[0],\r\n      y = axis[1],\r\n      z = axis[2];\r\n  var len = Math.sqrt(x * x + y * y + z * z);\r\n  var s = void 0,\r\n      c = void 0,\r\n      t = void 0;\r\n\r\n  if (len < __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"]) {\r\n    return null;\r\n  }\r\n\r\n  len = 1 / len;\r\n  x *= len;\r\n  y *= len;\r\n  z *= len;\r\n\r\n  s = Math.sin(rad);\r\n  c = Math.cos(rad);\r\n  t = 1 - c;\r\n\r\n  // Perform rotation-specific matrix multiplication\r\n  out[0] = x * x * t + c;\r\n  out[1] = y * x * t + z * s;\r\n  out[2] = z * x * t - y * s;\r\n  out[3] = 0;\r\n  out[4] = x * y * t - z * s;\r\n  out[5] = y * y * t + c;\r\n  out[6] = z * y * t + x * s;\r\n  out[7] = 0;\r\n  out[8] = x * z * t + y * s;\r\n  out[9] = y * z * t - x * s;\r\n  out[10] = z * z * t + c;\r\n  out[11] = 0;\r\n  out[12] = 0;\r\n  out[13] = 0;\r\n  out[14] = 0;\r\n  out[15] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from the given angle around the X axis\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.rotateX(dest, dest, rad);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\r\nfunction fromXRotation(out, rad) {\r\n  var s = Math.sin(rad);\r\n  var c = Math.cos(rad);\r\n\r\n  // Perform axis-specific matrix multiplication\r\n  out[0] = 1;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = 0;\r\n  out[5] = c;\r\n  out[6] = s;\r\n  out[7] = 0;\r\n  out[8] = 0;\r\n  out[9] = -s;\r\n  out[10] = c;\r\n  out[11] = 0;\r\n  out[12] = 0;\r\n  out[13] = 0;\r\n  out[14] = 0;\r\n  out[15] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from the given angle around the Y axis\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.rotateY(dest, dest, rad);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\r\nfunction fromYRotation(out, rad) {\r\n  var s = Math.sin(rad);\r\n  var c = Math.cos(rad);\r\n\r\n  // Perform axis-specific matrix multiplication\r\n  out[0] = c;\r\n  out[1] = 0;\r\n  out[2] = -s;\r\n  out[3] = 0;\r\n  out[4] = 0;\r\n  out[5] = 1;\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = s;\r\n  out[9] = 0;\r\n  out[10] = c;\r\n  out[11] = 0;\r\n  out[12] = 0;\r\n  out[13] = 0;\r\n  out[14] = 0;\r\n  out[15] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from the given angle around the Z axis\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.rotateZ(dest, dest, rad);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\r\nfunction fromZRotation(out, rad) {\r\n  var s = Math.sin(rad);\r\n  var c = Math.cos(rad);\r\n\r\n  // Perform axis-specific matrix multiplication\r\n  out[0] = c;\r\n  out[1] = s;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = -s;\r\n  out[5] = c;\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = 0;\r\n  out[9] = 0;\r\n  out[10] = 1;\r\n  out[11] = 0;\r\n  out[12] = 0;\r\n  out[13] = 0;\r\n  out[14] = 0;\r\n  out[15] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a quaternion rotation and vector translation\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.translate(dest, vec);\r\n *     let quatMat = mat4.create();\r\n *     quat4.toMat4(quat, quatMat);\r\n *     mat4.multiply(dest, quatMat);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {quat4} q Rotation quaternion\r\n * @param {vec3} v Translation vector\r\n * @returns {mat4} out\r\n */\r\nfunction fromRotationTranslation(out, q, v) {\r\n  // Quaternion math\r\n  var x = q[0],\r\n      y = q[1],\r\n      z = q[2],\r\n      w = q[3];\r\n  var x2 = x + x;\r\n  var y2 = y + y;\r\n  var z2 = z + z;\r\n\r\n  var xx = x * x2;\r\n  var xy = x * y2;\r\n  var xz = x * z2;\r\n  var yy = y * y2;\r\n  var yz = y * z2;\r\n  var zz = z * z2;\r\n  var wx = w * x2;\r\n  var wy = w * y2;\r\n  var wz = w * z2;\r\n\r\n  out[0] = 1 - (yy + zz);\r\n  out[1] = xy + wz;\r\n  out[2] = xz - wy;\r\n  out[3] = 0;\r\n  out[4] = xy - wz;\r\n  out[5] = 1 - (xx + zz);\r\n  out[6] = yz + wx;\r\n  out[7] = 0;\r\n  out[8] = xz + wy;\r\n  out[9] = yz - wx;\r\n  out[10] = 1 - (xx + yy);\r\n  out[11] = 0;\r\n  out[12] = v[0];\r\n  out[13] = v[1];\r\n  out[14] = v[2];\r\n  out[15] = 1;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new mat4 from a dual quat.\r\n *\r\n * @param {mat4} out Matrix\r\n * @param {quat2} a Dual Quaternion\r\n * @returns {mat4} mat4 receiving operation result\r\n */\r\nfunction fromQuat2(out, a) {\r\n  var translation = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](3);\r\n  var bx = -a[0],\r\n      by = -a[1],\r\n      bz = -a[2],\r\n      bw = a[3],\r\n      ax = a[4],\r\n      ay = a[5],\r\n      az = a[6],\r\n      aw = a[7];\r\n\r\n  var magnitude = bx * bx + by * by + bz * bz + bw * bw;\r\n  //Only scale if it makes sense\r\n  if (magnitude > 0) {\r\n    translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;\r\n    translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;\r\n    translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;\r\n  } else {\r\n    translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;\r\n    translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;\r\n    translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;\r\n  }\r\n  fromRotationTranslation(out, a, translation);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the translation vector component of a transformation\r\n *  matrix. If a matrix is built with fromRotationTranslation,\r\n *  the returned vector will be the same as the translation vector\r\n *  originally supplied.\r\n * @param  {vec3} out Vector to receive translation component\r\n * @param  {mat4} mat Matrix to be decomposed (input)\r\n * @return {vec3} out\r\n */\r\nfunction getTranslation(out, mat) {\r\n  out[0] = mat[12];\r\n  out[1] = mat[13];\r\n  out[2] = mat[14];\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the scaling factor component of a transformation\r\n *  matrix. If a matrix is built with fromRotationTranslationScale\r\n *  with a normalized Quaternion paramter, the returned vector will be\r\n *  the same as the scaling vector\r\n *  originally supplied.\r\n * @param  {vec3} out Vector to receive scaling factor component\r\n * @param  {mat4} mat Matrix to be decomposed (input)\r\n * @return {vec3} out\r\n */\r\nfunction getScaling(out, mat) {\r\n  var m11 = mat[0];\r\n  var m12 = mat[1];\r\n  var m13 = mat[2];\r\n  var m21 = mat[4];\r\n  var m22 = mat[5];\r\n  var m23 = mat[6];\r\n  var m31 = mat[8];\r\n  var m32 = mat[9];\r\n  var m33 = mat[10];\r\n\r\n  out[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);\r\n  out[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);\r\n  out[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns a quaternion representing the rotational component\r\n *  of a transformation matrix. If a matrix is built with\r\n *  fromRotationTranslation, the returned quaternion will be the\r\n *  same as the quaternion originally supplied.\r\n * @param {quat} out Quaternion to receive the rotation component\r\n * @param {mat4} mat Matrix to be decomposed (input)\r\n * @return {quat} out\r\n */\r\nfunction getRotation(out, mat) {\r\n  // Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm\r\n  var trace = mat[0] + mat[5] + mat[10];\r\n  var S = 0;\r\n\r\n  if (trace > 0) {\r\n    S = Math.sqrt(trace + 1.0) * 2;\r\n    out[3] = 0.25 * S;\r\n    out[0] = (mat[6] - mat[9]) / S;\r\n    out[1] = (mat[8] - mat[2]) / S;\r\n    out[2] = (mat[1] - mat[4]) / S;\r\n  } else if (mat[0] > mat[5] && mat[0] > mat[10]) {\r\n    S = Math.sqrt(1.0 + mat[0] - mat[5] - mat[10]) * 2;\r\n    out[3] = (mat[6] - mat[9]) / S;\r\n    out[0] = 0.25 * S;\r\n    out[1] = (mat[1] + mat[4]) / S;\r\n    out[2] = (mat[8] + mat[2]) / S;\r\n  } else if (mat[5] > mat[10]) {\r\n    S = Math.sqrt(1.0 + mat[5] - mat[0] - mat[10]) * 2;\r\n    out[3] = (mat[8] - mat[2]) / S;\r\n    out[0] = (mat[1] + mat[4]) / S;\r\n    out[1] = 0.25 * S;\r\n    out[2] = (mat[6] + mat[9]) / S;\r\n  } else {\r\n    S = Math.sqrt(1.0 + mat[10] - mat[0] - mat[5]) * 2;\r\n    out[3] = (mat[1] - mat[4]) / S;\r\n    out[0] = (mat[8] + mat[2]) / S;\r\n    out[1] = (mat[6] + mat[9]) / S;\r\n    out[2] = 0.25 * S;\r\n  }\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a quaternion rotation, vector translation and vector scale\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.translate(dest, vec);\r\n *     let quatMat = mat4.create();\r\n *     quat4.toMat4(quat, quatMat);\r\n *     mat4.multiply(dest, quatMat);\r\n *     mat4.scale(dest, scale)\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {quat4} q Rotation quaternion\r\n * @param {vec3} v Translation vector\r\n * @param {vec3} s Scaling vector\r\n * @returns {mat4} out\r\n */\r\nfunction fromRotationTranslationScale(out, q, v, s) {\r\n  // Quaternion math\r\n  var x = q[0],\r\n      y = q[1],\r\n      z = q[2],\r\n      w = q[3];\r\n  var x2 = x + x;\r\n  var y2 = y + y;\r\n  var z2 = z + z;\r\n\r\n  var xx = x * x2;\r\n  var xy = x * y2;\r\n  var xz = x * z2;\r\n  var yy = y * y2;\r\n  var yz = y * z2;\r\n  var zz = z * z2;\r\n  var wx = w * x2;\r\n  var wy = w * y2;\r\n  var wz = w * z2;\r\n  var sx = s[0];\r\n  var sy = s[1];\r\n  var sz = s[2];\r\n\r\n  out[0] = (1 - (yy + zz)) * sx;\r\n  out[1] = (xy + wz) * sx;\r\n  out[2] = (xz - wy) * sx;\r\n  out[3] = 0;\r\n  out[4] = (xy - wz) * sy;\r\n  out[5] = (1 - (xx + zz)) * sy;\r\n  out[6] = (yz + wx) * sy;\r\n  out[7] = 0;\r\n  out[8] = (xz + wy) * sz;\r\n  out[9] = (yz - wx) * sz;\r\n  out[10] = (1 - (xx + yy)) * sz;\r\n  out[11] = 0;\r\n  out[12] = v[0];\r\n  out[13] = v[1];\r\n  out[14] = v[2];\r\n  out[15] = 1;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.translate(dest, vec);\r\n *     mat4.translate(dest, origin);\r\n *     let quatMat = mat4.create();\r\n *     quat4.toMat4(quat, quatMat);\r\n *     mat4.multiply(dest, quatMat);\r\n *     mat4.scale(dest, scale)\r\n *     mat4.translate(dest, negativeOrigin);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {quat4} q Rotation quaternion\r\n * @param {vec3} v Translation vector\r\n * @param {vec3} s Scaling vector\r\n * @param {vec3} o The origin vector around which to scale and rotate\r\n * @returns {mat4} out\r\n */\r\nfunction fromRotationTranslationScaleOrigin(out, q, v, s, o) {\r\n  // Quaternion math\r\n  var x = q[0],\r\n      y = q[1],\r\n      z = q[2],\r\n      w = q[3];\r\n  var x2 = x + x;\r\n  var y2 = y + y;\r\n  var z2 = z + z;\r\n\r\n  var xx = x * x2;\r\n  var xy = x * y2;\r\n  var xz = x * z2;\r\n  var yy = y * y2;\r\n  var yz = y * z2;\r\n  var zz = z * z2;\r\n  var wx = w * x2;\r\n  var wy = w * y2;\r\n  var wz = w * z2;\r\n\r\n  var sx = s[0];\r\n  var sy = s[1];\r\n  var sz = s[2];\r\n\r\n  var ox = o[0];\r\n  var oy = o[1];\r\n  var oz = o[2];\r\n\r\n  var out0 = (1 - (yy + zz)) * sx;\r\n  var out1 = (xy + wz) * sx;\r\n  var out2 = (xz - wy) * sx;\r\n  var out4 = (xy - wz) * sy;\r\n  var out5 = (1 - (xx + zz)) * sy;\r\n  var out6 = (yz + wx) * sy;\r\n  var out8 = (xz + wy) * sz;\r\n  var out9 = (yz - wx) * sz;\r\n  var out10 = (1 - (xx + yy)) * sz;\r\n\r\n  out[0] = out0;\r\n  out[1] = out1;\r\n  out[2] = out2;\r\n  out[3] = 0;\r\n  out[4] = out4;\r\n  out[5] = out5;\r\n  out[6] = out6;\r\n  out[7] = 0;\r\n  out[8] = out8;\r\n  out[9] = out9;\r\n  out[10] = out10;\r\n  out[11] = 0;\r\n  out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);\r\n  out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);\r\n  out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);\r\n  out[15] = 1;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates a 4x4 matrix from the given quaternion\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {quat} q Quaternion to create matrix from\r\n *\r\n * @returns {mat4} out\r\n */\r\nfunction fromQuat(out, q) {\r\n  var x = q[0],\r\n      y = q[1],\r\n      z = q[2],\r\n      w = q[3];\r\n  var x2 = x + x;\r\n  var y2 = y + y;\r\n  var z2 = z + z;\r\n\r\n  var xx = x * x2;\r\n  var yx = y * x2;\r\n  var yy = y * y2;\r\n  var zx = z * x2;\r\n  var zy = z * y2;\r\n  var zz = z * z2;\r\n  var wx = w * x2;\r\n  var wy = w * y2;\r\n  var wz = w * z2;\r\n\r\n  out[0] = 1 - yy - zz;\r\n  out[1] = yx + wz;\r\n  out[2] = zx - wy;\r\n  out[3] = 0;\r\n\r\n  out[4] = yx - wz;\r\n  out[5] = 1 - xx - zz;\r\n  out[6] = zy + wx;\r\n  out[7] = 0;\r\n\r\n  out[8] = zx + wy;\r\n  out[9] = zy - wx;\r\n  out[10] = 1 - xx - yy;\r\n  out[11] = 0;\r\n\r\n  out[12] = 0;\r\n  out[13] = 0;\r\n  out[14] = 0;\r\n  out[15] = 1;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a frustum matrix with the given bounds\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {Number} left Left bound of the frustum\r\n * @param {Number} right Right bound of the frustum\r\n * @param {Number} bottom Bottom bound of the frustum\r\n * @param {Number} top Top bound of the frustum\r\n * @param {Number} near Near bound of the frustum\r\n * @param {Number} far Far bound of the frustum\r\n * @returns {mat4} out\r\n */\r\nfunction frustum(out, left, right, bottom, top, near, far) {\r\n  var rl = 1 / (right - left);\r\n  var tb = 1 / (top - bottom);\r\n  var nf = 1 / (near - far);\r\n  out[0] = near * 2 * rl;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = 0;\r\n  out[5] = near * 2 * tb;\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = (right + left) * rl;\r\n  out[9] = (top + bottom) * tb;\r\n  out[10] = (far + near) * nf;\r\n  out[11] = -1;\r\n  out[12] = 0;\r\n  out[13] = 0;\r\n  out[14] = far * near * 2 * nf;\r\n  out[15] = 0;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a perspective projection matrix with the given bounds.\r\n * Passing null/undefined/no value for far will generate infinite projection matrix.\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {number} fovy Vertical field of view in radians\r\n * @param {number} aspect Aspect ratio. typically viewport width/height\r\n * @param {number} near Near bound of the frustum\r\n * @param {number} far Far bound of the frustum, can be null or Infinity\r\n * @returns {mat4} out\r\n */\r\nfunction perspective(out, fovy, aspect, near, far) {\r\n  var f = 1.0 / Math.tan(fovy / 2),\r\n      nf = void 0;\r\n  out[0] = f / aspect;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = 0;\r\n  out[5] = f;\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = 0;\r\n  out[9] = 0;\r\n  out[11] = -1;\r\n  out[12] = 0;\r\n  out[13] = 0;\r\n  out[15] = 0;\r\n  if (far != null && far !== Infinity) {\r\n    nf = 1 / (near - far);\r\n    out[10] = (far + near) * nf;\r\n    out[14] = 2 * far * near * nf;\r\n  } else {\r\n    out[10] = -1;\r\n    out[14] = -2 * near;\r\n  }\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a perspective projection matrix with the given field of view.\r\n * This is primarily useful for generating projection matrices to be used\r\n * with the still experiemental WebVR API.\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees\r\n * @param {number} near Near bound of the frustum\r\n * @param {number} far Far bound of the frustum\r\n * @returns {mat4} out\r\n */\r\nfunction perspectiveFromFieldOfView(out, fov, near, far) {\r\n  var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);\r\n  var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);\r\n  var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);\r\n  var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);\r\n  var xScale = 2.0 / (leftTan + rightTan);\r\n  var yScale = 2.0 / (upTan + downTan);\r\n\r\n  out[0] = xScale;\r\n  out[1] = 0.0;\r\n  out[2] = 0.0;\r\n  out[3] = 0.0;\r\n  out[4] = 0.0;\r\n  out[5] = yScale;\r\n  out[6] = 0.0;\r\n  out[7] = 0.0;\r\n  out[8] = -((leftTan - rightTan) * xScale * 0.5);\r\n  out[9] = (upTan - downTan) * yScale * 0.5;\r\n  out[10] = far / (near - far);\r\n  out[11] = -1.0;\r\n  out[12] = 0.0;\r\n  out[13] = 0.0;\r\n  out[14] = far * near / (near - far);\r\n  out[15] = 0.0;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a orthogonal projection matrix with the given bounds\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {number} left Left bound of the frustum\r\n * @param {number} right Right bound of the frustum\r\n * @param {number} bottom Bottom bound of the frustum\r\n * @param {number} top Top bound of the frustum\r\n * @param {number} near Near bound of the frustum\r\n * @param {number} far Far bound of the frustum\r\n * @returns {mat4} out\r\n */\r\nfunction ortho(out, left, right, bottom, top, near, far) {\r\n  var lr = 1 / (left - right);\r\n  var bt = 1 / (bottom - top);\r\n  var nf = 1 / (near - far);\r\n  out[0] = -2 * lr;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 0;\r\n  out[4] = 0;\r\n  out[5] = -2 * bt;\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  out[8] = 0;\r\n  out[9] = 0;\r\n  out[10] = 2 * nf;\r\n  out[11] = 0;\r\n  out[12] = (left + right) * lr;\r\n  out[13] = (top + bottom) * bt;\r\n  out[14] = (far + near) * nf;\r\n  out[15] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a look-at matrix with the given eye position, focal point, and up axis.\r\n * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {vec3} eye Position of the viewer\r\n * @param {vec3} center Point the viewer is looking at\r\n * @param {vec3} up vec3 pointing up\r\n * @returns {mat4} out\r\n */\r\nfunction lookAt(out, eye, center, up) {\r\n  var x0 = void 0,\r\n      x1 = void 0,\r\n      x2 = void 0,\r\n      y0 = void 0,\r\n      y1 = void 0,\r\n      y2 = void 0,\r\n      z0 = void 0,\r\n      z1 = void 0,\r\n      z2 = void 0,\r\n      len = void 0;\r\n  var eyex = eye[0];\r\n  var eyey = eye[1];\r\n  var eyez = eye[2];\r\n  var upx = up[0];\r\n  var upy = up[1];\r\n  var upz = up[2];\r\n  var centerx = center[0];\r\n  var centery = center[1];\r\n  var centerz = center[2];\r\n\r\n  if (Math.abs(eyex - centerx) < __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] && Math.abs(eyey - centery) < __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] && Math.abs(eyez - centerz) < __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"]) {\r\n    return identity(out);\r\n  }\r\n\r\n  z0 = eyex - centerx;\r\n  z1 = eyey - centery;\r\n  z2 = eyez - centerz;\r\n\r\n  len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);\r\n  z0 *= len;\r\n  z1 *= len;\r\n  z2 *= len;\r\n\r\n  x0 = upy * z2 - upz * z1;\r\n  x1 = upz * z0 - upx * z2;\r\n  x2 = upx * z1 - upy * z0;\r\n  len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);\r\n  if (!len) {\r\n    x0 = 0;\r\n    x1 = 0;\r\n    x2 = 0;\r\n  } else {\r\n    len = 1 / len;\r\n    x0 *= len;\r\n    x1 *= len;\r\n    x2 *= len;\r\n  }\r\n\r\n  y0 = z1 * x2 - z2 * x1;\r\n  y1 = z2 * x0 - z0 * x2;\r\n  y2 = z0 * x1 - z1 * x0;\r\n\r\n  len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);\r\n  if (!len) {\r\n    y0 = 0;\r\n    y1 = 0;\r\n    y2 = 0;\r\n  } else {\r\n    len = 1 / len;\r\n    y0 *= len;\r\n    y1 *= len;\r\n    y2 *= len;\r\n  }\r\n\r\n  out[0] = x0;\r\n  out[1] = y0;\r\n  out[2] = z0;\r\n  out[3] = 0;\r\n  out[4] = x1;\r\n  out[5] = y1;\r\n  out[6] = z1;\r\n  out[7] = 0;\r\n  out[8] = x2;\r\n  out[9] = y2;\r\n  out[10] = z2;\r\n  out[11] = 0;\r\n  out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);\r\n  out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);\r\n  out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);\r\n  out[15] = 1;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a matrix that makes something look at something else.\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {vec3} eye Position of the viewer\r\n * @param {vec3} center Point the viewer is looking at\r\n * @param {vec3} up vec3 pointing up\r\n * @returns {mat4} out\r\n */\r\nfunction targetTo(out, eye, target, up) {\r\n  var eyex = eye[0],\r\n      eyey = eye[1],\r\n      eyez = eye[2],\r\n      upx = up[0],\r\n      upy = up[1],\r\n      upz = up[2];\r\n\r\n  var z0 = eyex - target[0],\r\n      z1 = eyey - target[1],\r\n      z2 = eyez - target[2];\r\n\r\n  var len = z0 * z0 + z1 * z1 + z2 * z2;\r\n  if (len > 0) {\r\n    len = 1 / Math.sqrt(len);\r\n    z0 *= len;\r\n    z1 *= len;\r\n    z2 *= len;\r\n  }\r\n\r\n  var x0 = upy * z2 - upz * z1,\r\n      x1 = upz * z0 - upx * z2,\r\n      x2 = upx * z1 - upy * z0;\r\n\r\n  len = x0 * x0 + x1 * x1 + x2 * x2;\r\n  if (len > 0) {\r\n    len = 1 / Math.sqrt(len);\r\n    x0 *= len;\r\n    x1 *= len;\r\n    x2 *= len;\r\n  }\r\n\r\n  out[0] = x0;\r\n  out[1] = x1;\r\n  out[2] = x2;\r\n  out[3] = 0;\r\n  out[4] = z1 * x2 - z2 * x1;\r\n  out[5] = z2 * x0 - z0 * x2;\r\n  out[6] = z0 * x1 - z1 * x0;\r\n  out[7] = 0;\r\n  out[8] = z0;\r\n  out[9] = z1;\r\n  out[10] = z2;\r\n  out[11] = 0;\r\n  out[12] = eyex;\r\n  out[13] = eyey;\r\n  out[14] = eyez;\r\n  out[15] = 1;\r\n  return out;\r\n};\r\n\r\n/**\r\n * Returns a string representation of a mat4\r\n *\r\n * @param {mat4} a matrix to represent as a string\r\n * @returns {String} string representation of the matrix\r\n */\r\nfunction str(a) {\r\n  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] + ')';\r\n}\r\n\r\n/**\r\n * Returns Frobenius norm of a mat4\r\n *\r\n * @param {mat4} a the matrix to calculate Frobenius norm of\r\n * @returns {Number} Frobenius norm\r\n */\r\nfunction frob(a) {\r\n  return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2));\r\n}\r\n\r\n/**\r\n * Adds two mat4's\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the first operand\r\n * @param {mat4} b the second operand\r\n * @returns {mat4} out\r\n */\r\nfunction add(out, a, b) {\r\n  out[0] = a[0] + b[0];\r\n  out[1] = a[1] + b[1];\r\n  out[2] = a[2] + b[2];\r\n  out[3] = a[3] + b[3];\r\n  out[4] = a[4] + b[4];\r\n  out[5] = a[5] + b[5];\r\n  out[6] = a[6] + b[6];\r\n  out[7] = a[7] + b[7];\r\n  out[8] = a[8] + b[8];\r\n  out[9] = a[9] + b[9];\r\n  out[10] = a[10] + b[10];\r\n  out[11] = a[11] + b[11];\r\n  out[12] = a[12] + b[12];\r\n  out[13] = a[13] + b[13];\r\n  out[14] = a[14] + b[14];\r\n  out[15] = a[15] + b[15];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Subtracts matrix b from matrix a\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the first operand\r\n * @param {mat4} b the second operand\r\n * @returns {mat4} out\r\n */\r\nfunction subtract(out, a, b) {\r\n  out[0] = a[0] - b[0];\r\n  out[1] = a[1] - b[1];\r\n  out[2] = a[2] - b[2];\r\n  out[3] = a[3] - b[3];\r\n  out[4] = a[4] - b[4];\r\n  out[5] = a[5] - b[5];\r\n  out[6] = a[6] - b[6];\r\n  out[7] = a[7] - b[7];\r\n  out[8] = a[8] - b[8];\r\n  out[9] = a[9] - b[9];\r\n  out[10] = a[10] - b[10];\r\n  out[11] = a[11] - b[11];\r\n  out[12] = a[12] - b[12];\r\n  out[13] = a[13] - b[13];\r\n  out[14] = a[14] - b[14];\r\n  out[15] = a[15] - b[15];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Multiply each element of the matrix by a scalar.\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {mat4} a the matrix to scale\r\n * @param {Number} b amount to scale the matrix's elements by\r\n * @returns {mat4} out\r\n */\r\nfunction multiplyScalar(out, a, b) {\r\n  out[0] = a[0] * b;\r\n  out[1] = a[1] * b;\r\n  out[2] = a[2] * b;\r\n  out[3] = a[3] * b;\r\n  out[4] = a[4] * b;\r\n  out[5] = a[5] * b;\r\n  out[6] = a[6] * b;\r\n  out[7] = a[7] * b;\r\n  out[8] = a[8] * b;\r\n  out[9] = a[9] * b;\r\n  out[10] = a[10] * b;\r\n  out[11] = a[11] * b;\r\n  out[12] = a[12] * b;\r\n  out[13] = a[13] * b;\r\n  out[14] = a[14] * b;\r\n  out[15] = a[15] * b;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two mat4's after multiplying each element of the second operand by a scalar value.\r\n *\r\n * @param {mat4} out the receiving vector\r\n * @param {mat4} a the first operand\r\n * @param {mat4} b the second operand\r\n * @param {Number} scale the amount to scale b's elements by before adding\r\n * @returns {mat4} out\r\n */\r\nfunction multiplyScalarAndAdd(out, a, b, scale) {\r\n  out[0] = a[0] + b[0] * scale;\r\n  out[1] = a[1] + b[1] * scale;\r\n  out[2] = a[2] + b[2] * scale;\r\n  out[3] = a[3] + b[3] * scale;\r\n  out[4] = a[4] + b[4] * scale;\r\n  out[5] = a[5] + b[5] * scale;\r\n  out[6] = a[6] + b[6] * scale;\r\n  out[7] = a[7] + b[7] * scale;\r\n  out[8] = a[8] + b[8] * scale;\r\n  out[9] = a[9] + b[9] * scale;\r\n  out[10] = a[10] + b[10] * scale;\r\n  out[11] = a[11] + b[11] * scale;\r\n  out[12] = a[12] + b[12] * scale;\r\n  out[13] = a[13] + b[13] * scale;\r\n  out[14] = a[14] + b[14] * scale;\r\n  out[15] = a[15] + b[15] * scale;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {mat4} a The first matrix.\r\n * @param {mat4} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\r\nfunction exactEquals(a, b) {\r\n  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];\r\n}\r\n\r\n/**\r\n * Returns whether or not the matrices have approximately the same elements in the same position.\r\n *\r\n * @param {mat4} a The first matrix.\r\n * @param {mat4} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\r\nfunction equals(a, b) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3];\r\n  var a4 = a[4],\r\n      a5 = a[5],\r\n      a6 = a[6],\r\n      a7 = a[7];\r\n  var a8 = a[8],\r\n      a9 = a[9],\r\n      a10 = a[10],\r\n      a11 = a[11];\r\n  var a12 = a[12],\r\n      a13 = a[13],\r\n      a14 = a[14],\r\n      a15 = a[15];\r\n\r\n  var b0 = b[0],\r\n      b1 = b[1],\r\n      b2 = b[2],\r\n      b3 = b[3];\r\n  var b4 = b[4],\r\n      b5 = b[5],\r\n      b6 = b[6],\r\n      b7 = b[7];\r\n  var b8 = b[8],\r\n      b9 = b[9],\r\n      b10 = b[10],\r\n      b11 = b[11];\r\n  var b12 = b[12],\r\n      b13 = b[13],\r\n      b14 = b[14],\r\n      b15 = b[15];\r\n\r\n  return Math.abs(a0 - b0) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a15), Math.abs(b15));\r\n}\r\n\r\n/**\r\n * Alias for {@link mat4.multiply}\r\n * @function\r\n */\r\nvar mul = multiply;\r\n\r\n/**\r\n * Alias for {@link mat4.subtract}\r\n * @function\r\n */\r\nvar sub = subtract;\n\n/***/ }),\n/* 4 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (immutable) */ __webpack_exports__[\"create\"] = create;\n/* harmony export (immutable) */ __webpack_exports__[\"identity\"] = identity;\n/* harmony export (immutable) */ __webpack_exports__[\"setAxisAngle\"] = setAxisAngle;\n/* harmony export (immutable) */ __webpack_exports__[\"getAxisAngle\"] = getAxisAngle;\n/* harmony export (immutable) */ __webpack_exports__[\"multiply\"] = multiply;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateX\"] = rotateX;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateY\"] = rotateY;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateZ\"] = rotateZ;\n/* harmony export (immutable) */ __webpack_exports__[\"calculateW\"] = calculateW;\n/* harmony export (immutable) */ __webpack_exports__[\"slerp\"] = slerp;\n/* harmony export (immutable) */ __webpack_exports__[\"random\"] = random;\n/* harmony export (immutable) */ __webpack_exports__[\"invert\"] = invert;\n/* harmony export (immutable) */ __webpack_exports__[\"conjugate\"] = conjugate;\n/* harmony export (immutable) */ __webpack_exports__[\"fromMat3\"] = fromMat3;\n/* harmony export (immutable) */ __webpack_exports__[\"fromEuler\"] = fromEuler;\n/* harmony export (immutable) */ __webpack_exports__[\"str\"] = str;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"clone\", function() { return clone; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"fromValues\", function() { return fromValues; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"copy\", function() { return copy; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"set\", function() { return set; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"add\", function() { return add; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mul\", function() { return mul; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"scale\", function() { return scale; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"dot\", function() { return dot; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"lerp\", function() { return lerp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"length\", function() { return length; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"len\", function() { return len; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"squaredLength\", function() { return squaredLength; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sqrLen\", function() { return sqrLen; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"normalize\", function() { return normalize; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"exactEquals\", function() { return exactEquals; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"equals\", function() { return equals; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"rotationTo\", function() { return rotationTo; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sqlerp\", function() { return sqlerp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"setAxes\", function() { return setAxes; });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_js__ = __webpack_require__(0);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__mat3_js__ = __webpack_require__(2);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__vec3_js__ = __webpack_require__(5);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__vec4_js__ = __webpack_require__(6);\n\r\n\r\n\r\n\r\n\r\n/**\r\n * Quaternion\r\n * @module quat\r\n */\r\n\r\n/**\r\n * Creates a new identity quat\r\n *\r\n * @returns {quat} a new quaternion\r\n */\r\nfunction create() {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](4);\r\n  if (__WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"] != Float32Array) {\r\n    out[0] = 0;\r\n    out[1] = 0;\r\n    out[2] = 0;\r\n  }\r\n  out[3] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set a quat to the identity quaternion\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @returns {quat} out\r\n */\r\nfunction identity(out) {\r\n  out[0] = 0;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Sets a quat from the given angle and rotation axis,\r\n * then returns it.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {vec3} axis the axis around which to rotate\r\n * @param {Number} rad the angle in radians\r\n * @returns {quat} out\r\n **/\r\nfunction setAxisAngle(out, axis, rad) {\r\n  rad = rad * 0.5;\r\n  var s = Math.sin(rad);\r\n  out[0] = s * axis[0];\r\n  out[1] = s * axis[1];\r\n  out[2] = s * axis[2];\r\n  out[3] = Math.cos(rad);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Gets the rotation axis and angle for a given\r\n *  quaternion. If a quaternion is created with\r\n *  setAxisAngle, this method will return the same\r\n *  values as providied in the original parameter list\r\n *  OR functionally equivalent values.\r\n * Example: The quaternion formed by axis [0, 0, 1] and\r\n *  angle -90 is the same as the quaternion formed by\r\n *  [0, 0, 1] and 270. This method favors the latter.\r\n * @param  {vec3} out_axis  Vector receiving the axis of rotation\r\n * @param  {quat} q     Quaternion to be decomposed\r\n * @return {Number}     Angle, in radians, of the rotation\r\n */\r\nfunction getAxisAngle(out_axis, q) {\r\n  var rad = Math.acos(q[3]) * 2.0;\r\n  var s = Math.sin(rad / 2.0);\r\n  if (s > __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"]) {\r\n    out_axis[0] = q[0] / s;\r\n    out_axis[1] = q[1] / s;\r\n    out_axis[2] = q[2] / s;\r\n  } else {\r\n    // If s is zero, return any axis (no rotation - axis does not matter)\r\n    out_axis[0] = 1;\r\n    out_axis[1] = 0;\r\n    out_axis[2] = 0;\r\n  }\r\n  return rad;\r\n}\r\n\r\n/**\r\n * Multiplies two quat's\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {quat} a the first operand\r\n * @param {quat} b the second operand\r\n * @returns {quat} out\r\n */\r\nfunction multiply(out, a, b) {\r\n  var ax = a[0],\r\n      ay = a[1],\r\n      az = a[2],\r\n      aw = a[3];\r\n  var bx = b[0],\r\n      by = b[1],\r\n      bz = b[2],\r\n      bw = b[3];\r\n\r\n  out[0] = ax * bw + aw * bx + ay * bz - az * by;\r\n  out[1] = ay * bw + aw * by + az * bx - ax * bz;\r\n  out[2] = az * bw + aw * bz + ax * by - ay * bx;\r\n  out[3] = aw * bw - ax * bx - ay * by - az * bz;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a quaternion by the given angle about the X axis\r\n *\r\n * @param {quat} out quat receiving operation result\r\n * @param {quat} a quat to rotate\r\n * @param {number} rad angle (in radians) to rotate\r\n * @returns {quat} out\r\n */\r\nfunction rotateX(out, a, rad) {\r\n  rad *= 0.5;\r\n\r\n  var ax = a[0],\r\n      ay = a[1],\r\n      az = a[2],\r\n      aw = a[3];\r\n  var bx = Math.sin(rad),\r\n      bw = Math.cos(rad);\r\n\r\n  out[0] = ax * bw + aw * bx;\r\n  out[1] = ay * bw + az * bx;\r\n  out[2] = az * bw - ay * bx;\r\n  out[3] = aw * bw - ax * bx;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a quaternion by the given angle about the Y axis\r\n *\r\n * @param {quat} out quat receiving operation result\r\n * @param {quat} a quat to rotate\r\n * @param {number} rad angle (in radians) to rotate\r\n * @returns {quat} out\r\n */\r\nfunction rotateY(out, a, rad) {\r\n  rad *= 0.5;\r\n\r\n  var ax = a[0],\r\n      ay = a[1],\r\n      az = a[2],\r\n      aw = a[3];\r\n  var by = Math.sin(rad),\r\n      bw = Math.cos(rad);\r\n\r\n  out[0] = ax * bw - az * by;\r\n  out[1] = ay * bw + aw * by;\r\n  out[2] = az * bw + ax * by;\r\n  out[3] = aw * bw - ay * by;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a quaternion by the given angle about the Z axis\r\n *\r\n * @param {quat} out quat receiving operation result\r\n * @param {quat} a quat to rotate\r\n * @param {number} rad angle (in radians) to rotate\r\n * @returns {quat} out\r\n */\r\nfunction rotateZ(out, a, rad) {\r\n  rad *= 0.5;\r\n\r\n  var ax = a[0],\r\n      ay = a[1],\r\n      az = a[2],\r\n      aw = a[3];\r\n  var bz = Math.sin(rad),\r\n      bw = Math.cos(rad);\r\n\r\n  out[0] = ax * bw + ay * bz;\r\n  out[1] = ay * bw - ax * bz;\r\n  out[2] = az * bw + aw * bz;\r\n  out[3] = aw * bw - az * bz;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the W component of a quat from the X, Y, and Z components.\r\n * Assumes that quaternion is 1 unit in length.\r\n * Any existing W component will be ignored.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {quat} a quat to calculate W component of\r\n * @returns {quat} out\r\n */\r\nfunction calculateW(out, a) {\r\n  var x = a[0],\r\n      y = a[1],\r\n      z = a[2];\r\n\r\n  out[0] = x;\r\n  out[1] = y;\r\n  out[2] = z;\r\n  out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));\r\n  return out;\r\n}\r\n\r\n/**\r\n * Performs a spherical linear interpolation between two quat\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {quat} a the first operand\r\n * @param {quat} b the second operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {quat} out\r\n */\r\nfunction slerp(out, a, b, t) {\r\n  // benchmarks:\r\n  //    http://jsperf.com/quaternion-slerp-implementations\r\n  var ax = a[0],\r\n      ay = a[1],\r\n      az = a[2],\r\n      aw = a[3];\r\n  var bx = b[0],\r\n      by = b[1],\r\n      bz = b[2],\r\n      bw = b[3];\r\n\r\n  var omega = void 0,\r\n      cosom = void 0,\r\n      sinom = void 0,\r\n      scale0 = void 0,\r\n      scale1 = void 0;\r\n\r\n  // calc cosine\r\n  cosom = ax * bx + ay * by + az * bz + aw * bw;\r\n  // adjust signs (if necessary)\r\n  if (cosom < 0.0) {\r\n    cosom = -cosom;\r\n    bx = -bx;\r\n    by = -by;\r\n    bz = -bz;\r\n    bw = -bw;\r\n  }\r\n  // calculate coefficients\r\n  if (1.0 - cosom > __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"]) {\r\n    // standard case (slerp)\r\n    omega = Math.acos(cosom);\r\n    sinom = Math.sin(omega);\r\n    scale0 = Math.sin((1.0 - t) * omega) / sinom;\r\n    scale1 = Math.sin(t * omega) / sinom;\r\n  } else {\r\n    // \"from\" and \"to\" quaternions are very close\r\n    //  ... so we can do a linear interpolation\r\n    scale0 = 1.0 - t;\r\n    scale1 = t;\r\n  }\r\n  // calculate final values\r\n  out[0] = scale0 * ax + scale1 * bx;\r\n  out[1] = scale0 * ay + scale1 * by;\r\n  out[2] = scale0 * az + scale1 * bz;\r\n  out[3] = scale0 * aw + scale1 * bw;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a random quaternion\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @returns {quat} out\r\n */\r\nfunction random(out) {\r\n  // Implementation of http://planning.cs.uiuc.edu/node198.html\r\n  // TODO: Calling random 3 times is probably not the fastest solution\r\n  var u1 = __WEBPACK_IMPORTED_MODULE_0__common_js__[\"RANDOM\"]();\r\n  var u2 = __WEBPACK_IMPORTED_MODULE_0__common_js__[\"RANDOM\"]();\r\n  var u3 = __WEBPACK_IMPORTED_MODULE_0__common_js__[\"RANDOM\"]();\r\n\r\n  var sqrt1MinusU1 = Math.sqrt(1 - u1);\r\n  var sqrtU1 = Math.sqrt(u1);\r\n\r\n  out[0] = sqrt1MinusU1 * Math.sin(2.0 * Math.PI * u2);\r\n  out[1] = sqrt1MinusU1 * Math.cos(2.0 * Math.PI * u2);\r\n  out[2] = sqrtU1 * Math.sin(2.0 * Math.PI * u3);\r\n  out[3] = sqrtU1 * Math.cos(2.0 * Math.PI * u3);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the inverse of a quat\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {quat} a quat to calculate inverse of\r\n * @returns {quat} out\r\n */\r\nfunction invert(out, a) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3];\r\n  var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;\r\n  var invDot = dot ? 1.0 / dot : 0;\r\n\r\n  // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0\r\n\r\n  out[0] = -a0 * invDot;\r\n  out[1] = -a1 * invDot;\r\n  out[2] = -a2 * invDot;\r\n  out[3] = a3 * invDot;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the conjugate of a quat\r\n * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {quat} a quat to calculate conjugate of\r\n * @returns {quat} out\r\n */\r\nfunction conjugate(out, a) {\r\n  out[0] = -a[0];\r\n  out[1] = -a[1];\r\n  out[2] = -a[2];\r\n  out[3] = a[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a quaternion from the given 3x3 rotation matrix.\r\n *\r\n * NOTE: The resultant quaternion is not normalized, so you should be sure\r\n * to renormalize the quaternion yourself where necessary.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {mat3} m rotation matrix\r\n * @returns {quat} out\r\n * @function\r\n */\r\nfunction fromMat3(out, m) {\r\n  // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes\r\n  // article \"Quaternion Calculus and Fast Animation\".\r\n  var fTrace = m[0] + m[4] + m[8];\r\n  var fRoot = void 0;\r\n\r\n  if (fTrace > 0.0) {\r\n    // |w| > 1/2, may as well choose w > 1/2\r\n    fRoot = Math.sqrt(fTrace + 1.0); // 2w\r\n    out[3] = 0.5 * fRoot;\r\n    fRoot = 0.5 / fRoot; // 1/(4w)\r\n    out[0] = (m[5] - m[7]) * fRoot;\r\n    out[1] = (m[6] - m[2]) * fRoot;\r\n    out[2] = (m[1] - m[3]) * fRoot;\r\n  } else {\r\n    // |w| <= 1/2\r\n    var i = 0;\r\n    if (m[4] > m[0]) i = 1;\r\n    if (m[8] > m[i * 3 + i]) i = 2;\r\n    var j = (i + 1) % 3;\r\n    var k = (i + 2) % 3;\r\n\r\n    fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0);\r\n    out[i] = 0.5 * fRoot;\r\n    fRoot = 0.5 / fRoot;\r\n    out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot;\r\n    out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;\r\n    out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;\r\n  }\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a quaternion from the given euler angle x, y, z.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {x} Angle to rotate around X axis in degrees.\r\n * @param {y} Angle to rotate around Y axis in degrees.\r\n * @param {z} Angle to rotate around Z axis in degrees.\r\n * @returns {quat} out\r\n * @function\r\n */\r\nfunction fromEuler(out, x, y, z) {\r\n  var halfToRad = 0.5 * Math.PI / 180.0;\r\n  x *= halfToRad;\r\n  y *= halfToRad;\r\n  z *= halfToRad;\r\n\r\n  var sx = Math.sin(x);\r\n  var cx = Math.cos(x);\r\n  var sy = Math.sin(y);\r\n  var cy = Math.cos(y);\r\n  var sz = Math.sin(z);\r\n  var cz = Math.cos(z);\r\n\r\n  out[0] = sx * cy * cz - cx * sy * sz;\r\n  out[1] = cx * sy * cz + sx * cy * sz;\r\n  out[2] = cx * cy * sz - sx * sy * cz;\r\n  out[3] = cx * cy * cz + sx * sy * sz;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns a string representation of a quatenion\r\n *\r\n * @param {quat} a vector to represent as a string\r\n * @returns {String} string representation of the vector\r\n */\r\nfunction str(a) {\r\n  return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';\r\n}\r\n\r\n/**\r\n * Creates a new quat initialized with values from an existing quaternion\r\n *\r\n * @param {quat} a quaternion to clone\r\n * @returns {quat} a new quaternion\r\n * @function\r\n */\r\nvar clone = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"clone\"];\r\n\r\n/**\r\n * Creates a new quat initialized with the given values\r\n *\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @param {Number} w W component\r\n * @returns {quat} a new quaternion\r\n * @function\r\n */\r\nvar fromValues = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"fromValues\"];\r\n\r\n/**\r\n * Copy the values from one quat to another\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {quat} a the source quaternion\r\n * @returns {quat} out\r\n * @function\r\n */\r\nvar copy = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"copy\"];\r\n\r\n/**\r\n * Set the components of a quat to the given values\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @param {Number} w W component\r\n * @returns {quat} out\r\n * @function\r\n */\r\nvar set = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"set\"];\r\n\r\n/**\r\n * Adds two quat's\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {quat} a the first operand\r\n * @param {quat} b the second operand\r\n * @returns {quat} out\r\n * @function\r\n */\r\nvar add = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"add\"];\r\n\r\n/**\r\n * Alias for {@link quat.multiply}\r\n * @function\r\n */\r\nvar mul = multiply;\r\n\r\n/**\r\n * Scales a quat by a scalar number\r\n *\r\n * @param {quat} out the receiving vector\r\n * @param {quat} a the vector to scale\r\n * @param {Number} b amount to scale the vector by\r\n * @returns {quat} out\r\n * @function\r\n */\r\nvar scale = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"scale\"];\r\n\r\n/**\r\n * Calculates the dot product of two quat's\r\n *\r\n * @param {quat} a the first operand\r\n * @param {quat} b the second operand\r\n * @returns {Number} dot product of a and b\r\n * @function\r\n */\r\nvar dot = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"dot\"];\r\n\r\n/**\r\n * Performs a linear interpolation between two quat's\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {quat} a the first operand\r\n * @param {quat} b the second operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {quat} out\r\n * @function\r\n */\r\nvar lerp = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"lerp\"];\r\n\r\n/**\r\n * Calculates the length of a quat\r\n *\r\n * @param {quat} a vector to calculate length of\r\n * @returns {Number} length of a\r\n */\r\nvar length = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"length\"];\r\n\r\n/**\r\n * Alias for {@link quat.length}\r\n * @function\r\n */\r\nvar len = length;\r\n\r\n/**\r\n * Calculates the squared length of a quat\r\n *\r\n * @param {quat} a vector to calculate squared length of\r\n * @returns {Number} squared length of a\r\n * @function\r\n */\r\nvar squaredLength = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"squaredLength\"];\r\n\r\n/**\r\n * Alias for {@link quat.squaredLength}\r\n * @function\r\n */\r\nvar sqrLen = squaredLength;\r\n\r\n/**\r\n * Normalize a quat\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {quat} a quaternion to normalize\r\n * @returns {quat} out\r\n * @function\r\n */\r\nvar normalize = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"normalize\"];\r\n\r\n/**\r\n * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {quat} a The first quaternion.\r\n * @param {quat} b The second quaternion.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\r\nvar exactEquals = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"exactEquals\"];\r\n\r\n/**\r\n * Returns whether or not the quaternions have approximately the same elements in the same position.\r\n *\r\n * @param {quat} a The first vector.\r\n * @param {quat} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\r\nvar equals = __WEBPACK_IMPORTED_MODULE_3__vec4_js__[\"equals\"];\r\n\r\n/**\r\n * Sets a quaternion to represent the shortest rotation from one\r\n * vector to another.\r\n *\r\n * Both vectors are assumed to be unit length.\r\n *\r\n * @param {quat} out the receiving quaternion.\r\n * @param {vec3} a the initial vector\r\n * @param {vec3} b the destination vector\r\n * @returns {quat} out\r\n */\r\nvar rotationTo = function () {\r\n  var tmpvec3 = __WEBPACK_IMPORTED_MODULE_2__vec3_js__[\"create\"]();\r\n  var xUnitVec3 = __WEBPACK_IMPORTED_MODULE_2__vec3_js__[\"fromValues\"](1, 0, 0);\r\n  var yUnitVec3 = __WEBPACK_IMPORTED_MODULE_2__vec3_js__[\"fromValues\"](0, 1, 0);\r\n\r\n  return function (out, a, b) {\r\n    var dot = __WEBPACK_IMPORTED_MODULE_2__vec3_js__[\"dot\"](a, b);\r\n    if (dot < -0.999999) {\r\n      __WEBPACK_IMPORTED_MODULE_2__vec3_js__[\"cross\"](tmpvec3, xUnitVec3, a);\r\n      if (__WEBPACK_IMPORTED_MODULE_2__vec3_js__[\"len\"](tmpvec3) < 0.000001) __WEBPACK_IMPORTED_MODULE_2__vec3_js__[\"cross\"](tmpvec3, yUnitVec3, a);\r\n      __WEBPACK_IMPORTED_MODULE_2__vec3_js__[\"normalize\"](tmpvec3, tmpvec3);\r\n      setAxisAngle(out, tmpvec3, Math.PI);\r\n      return out;\r\n    } else if (dot > 0.999999) {\r\n      out[0] = 0;\r\n      out[1] = 0;\r\n      out[2] = 0;\r\n      out[3] = 1;\r\n      return out;\r\n    } else {\r\n      __WEBPACK_IMPORTED_MODULE_2__vec3_js__[\"cross\"](tmpvec3, a, b);\r\n      out[0] = tmpvec3[0];\r\n      out[1] = tmpvec3[1];\r\n      out[2] = tmpvec3[2];\r\n      out[3] = 1 + dot;\r\n      return normalize(out, out);\r\n    }\r\n  };\r\n}();\r\n\r\n/**\r\n * Performs a spherical linear interpolation with two control points\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {quat} a the first operand\r\n * @param {quat} b the second operand\r\n * @param {quat} c the third operand\r\n * @param {quat} d the fourth operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {quat} out\r\n */\r\nvar sqlerp = function () {\r\n  var temp1 = create();\r\n  var temp2 = create();\r\n\r\n  return function (out, a, b, c, d, t) {\r\n    slerp(temp1, a, d, t);\r\n    slerp(temp2, b, c, t);\r\n    slerp(out, temp1, temp2, 2 * t * (1 - t));\r\n\r\n    return out;\r\n  };\r\n}();\r\n\r\n/**\r\n * Sets the specified quaternion with values corresponding to the given\r\n * axes. Each axis is a vec3 and is expected to be unit length and\r\n * perpendicular to all other specified axes.\r\n *\r\n * @param {vec3} view  the vector representing the viewing direction\r\n * @param {vec3} right the vector representing the local \"right\" direction\r\n * @param {vec3} up    the vector representing the local \"up\" direction\r\n * @returns {quat} out\r\n */\r\nvar setAxes = function () {\r\n  var matr = __WEBPACK_IMPORTED_MODULE_1__mat3_js__[\"create\"]();\r\n\r\n  return function (out, view, right, up) {\r\n    matr[0] = right[0];\r\n    matr[3] = right[1];\r\n    matr[6] = right[2];\r\n\r\n    matr[1] = up[0];\r\n    matr[4] = up[1];\r\n    matr[7] = up[2];\r\n\r\n    matr[2] = -view[0];\r\n    matr[5] = -view[1];\r\n    matr[8] = -view[2];\r\n\r\n    return normalize(out, fromMat3(out, matr));\r\n  };\r\n}();\n\n/***/ }),\n/* 5 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (immutable) */ __webpack_exports__[\"create\"] = create;\n/* harmony export (immutable) */ __webpack_exports__[\"clone\"] = clone;\n/* harmony export (immutable) */ __webpack_exports__[\"length\"] = length;\n/* harmony export (immutable) */ __webpack_exports__[\"fromValues\"] = fromValues;\n/* harmony export (immutable) */ __webpack_exports__[\"copy\"] = copy;\n/* harmony export (immutable) */ __webpack_exports__[\"set\"] = set;\n/* harmony export (immutable) */ __webpack_exports__[\"add\"] = add;\n/* harmony export (immutable) */ __webpack_exports__[\"subtract\"] = subtract;\n/* harmony export (immutable) */ __webpack_exports__[\"multiply\"] = multiply;\n/* harmony export (immutable) */ __webpack_exports__[\"divide\"] = divide;\n/* harmony export (immutable) */ __webpack_exports__[\"ceil\"] = ceil;\n/* harmony export (immutable) */ __webpack_exports__[\"floor\"] = floor;\n/* harmony export (immutable) */ __webpack_exports__[\"min\"] = min;\n/* harmony export (immutable) */ __webpack_exports__[\"max\"] = max;\n/* harmony export (immutable) */ __webpack_exports__[\"round\"] = round;\n/* harmony export (immutable) */ __webpack_exports__[\"scale\"] = scale;\n/* harmony export (immutable) */ __webpack_exports__[\"scaleAndAdd\"] = scaleAndAdd;\n/* harmony export (immutable) */ __webpack_exports__[\"distance\"] = distance;\n/* harmony export (immutable) */ __webpack_exports__[\"squaredDistance\"] = squaredDistance;\n/* harmony export (immutable) */ __webpack_exports__[\"squaredLength\"] = squaredLength;\n/* harmony export (immutable) */ __webpack_exports__[\"negate\"] = negate;\n/* harmony export (immutable) */ __webpack_exports__[\"inverse\"] = inverse;\n/* harmony export (immutable) */ __webpack_exports__[\"normalize\"] = normalize;\n/* harmony export (immutable) */ __webpack_exports__[\"dot\"] = dot;\n/* harmony export (immutable) */ __webpack_exports__[\"cross\"] = cross;\n/* harmony export (immutable) */ __webpack_exports__[\"lerp\"] = lerp;\n/* harmony export (immutable) */ __webpack_exports__[\"hermite\"] = hermite;\n/* harmony export (immutable) */ __webpack_exports__[\"bezier\"] = bezier;\n/* harmony export (immutable) */ __webpack_exports__[\"random\"] = random;\n/* harmony export (immutable) */ __webpack_exports__[\"transformMat4\"] = transformMat4;\n/* harmony export (immutable) */ __webpack_exports__[\"transformMat3\"] = transformMat3;\n/* harmony export (immutable) */ __webpack_exports__[\"transformQuat\"] = transformQuat;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateX\"] = rotateX;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateY\"] = rotateY;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateZ\"] = rotateZ;\n/* harmony export (immutable) */ __webpack_exports__[\"angle\"] = angle;\n/* harmony export (immutable) */ __webpack_exports__[\"str\"] = str;\n/* harmony export (immutable) */ __webpack_exports__[\"exactEquals\"] = exactEquals;\n/* harmony export (immutable) */ __webpack_exports__[\"equals\"] = equals;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sub\", function() { return sub; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mul\", function() { return mul; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"div\", function() { return div; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"dist\", function() { return dist; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sqrDist\", function() { return sqrDist; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"len\", function() { return len; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sqrLen\", function() { return sqrLen; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"forEach\", function() { return forEach; });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_js__ = __webpack_require__(0);\n\r\n\r\n/**\r\n * 3 Dimensional Vector\r\n * @module vec3\r\n */\r\n\r\n/**\r\n * Creates a new, empty vec3\r\n *\r\n * @returns {vec3} a new 3D vector\r\n */\r\nfunction create() {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](3);\r\n  if (__WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"] != Float32Array) {\r\n    out[0] = 0;\r\n    out[1] = 0;\r\n    out[2] = 0;\r\n  }\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new vec3 initialized with values from an existing vector\r\n *\r\n * @param {vec3} a vector to clone\r\n * @returns {vec3} a new 3D vector\r\n */\r\nfunction clone(a) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](3);\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the length of a vec3\r\n *\r\n * @param {vec3} a vector to calculate length of\r\n * @returns {Number} length of a\r\n */\r\nfunction length(a) {\r\n  var x = a[0];\r\n  var y = a[1];\r\n  var z = a[2];\r\n  return Math.sqrt(x * x + y * y + z * z);\r\n}\r\n\r\n/**\r\n * Creates a new vec3 initialized with the given values\r\n *\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @returns {vec3} a new 3D vector\r\n */\r\nfunction fromValues(x, y, z) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](3);\r\n  out[0] = x;\r\n  out[1] = y;\r\n  out[2] = z;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Copy the values from one vec3 to another\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the source vector\r\n * @returns {vec3} out\r\n */\r\nfunction copy(out, a) {\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set the components of a vec3 to the given values\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @returns {vec3} out\r\n */\r\nfunction set(out, x, y, z) {\r\n  out[0] = x;\r\n  out[1] = y;\r\n  out[2] = z;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @returns {vec3} out\r\n */\r\nfunction add(out, a, b) {\r\n  out[0] = a[0] + b[0];\r\n  out[1] = a[1] + b[1];\r\n  out[2] = a[2] + b[2];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Subtracts vector b from vector a\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @returns {vec3} out\r\n */\r\nfunction subtract(out, a, b) {\r\n  out[0] = a[0] - b[0];\r\n  out[1] = a[1] - b[1];\r\n  out[2] = a[2] - b[2];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Multiplies two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @returns {vec3} out\r\n */\r\nfunction multiply(out, a, b) {\r\n  out[0] = a[0] * b[0];\r\n  out[1] = a[1] * b[1];\r\n  out[2] = a[2] * b[2];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Divides two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @returns {vec3} out\r\n */\r\nfunction divide(out, a, b) {\r\n  out[0] = a[0] / b[0];\r\n  out[1] = a[1] / b[1];\r\n  out[2] = a[2] / b[2];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Math.ceil the components of a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a vector to ceil\r\n * @returns {vec3} out\r\n */\r\nfunction ceil(out, a) {\r\n  out[0] = Math.ceil(a[0]);\r\n  out[1] = Math.ceil(a[1]);\r\n  out[2] = Math.ceil(a[2]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Math.floor the components of a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a vector to floor\r\n * @returns {vec3} out\r\n */\r\nfunction floor(out, a) {\r\n  out[0] = Math.floor(a[0]);\r\n  out[1] = Math.floor(a[1]);\r\n  out[2] = Math.floor(a[2]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the minimum of two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @returns {vec3} out\r\n */\r\nfunction min(out, a, b) {\r\n  out[0] = Math.min(a[0], b[0]);\r\n  out[1] = Math.min(a[1], b[1]);\r\n  out[2] = Math.min(a[2], b[2]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the maximum of two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @returns {vec3} out\r\n */\r\nfunction max(out, a, b) {\r\n  out[0] = Math.max(a[0], b[0]);\r\n  out[1] = Math.max(a[1], b[1]);\r\n  out[2] = Math.max(a[2], b[2]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Math.round the components of a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a vector to round\r\n * @returns {vec3} out\r\n */\r\nfunction round(out, a) {\r\n  out[0] = Math.round(a[0]);\r\n  out[1] = Math.round(a[1]);\r\n  out[2] = Math.round(a[2]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Scales a vec3 by a scalar number\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the vector to scale\r\n * @param {Number} b amount to scale the vector by\r\n * @returns {vec3} out\r\n */\r\nfunction scale(out, a, b) {\r\n  out[0] = a[0] * b;\r\n  out[1] = a[1] * b;\r\n  out[2] = a[2] * b;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two vec3's after scaling the second operand by a scalar value\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @param {Number} scale the amount to scale b by before adding\r\n * @returns {vec3} out\r\n */\r\nfunction scaleAndAdd(out, a, b, scale) {\r\n  out[0] = a[0] + b[0] * scale;\r\n  out[1] = a[1] + b[1] * scale;\r\n  out[2] = a[2] + b[2] * scale;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the euclidian distance between two vec3's\r\n *\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @returns {Number} distance between a and b\r\n */\r\nfunction distance(a, b) {\r\n  var x = b[0] - a[0];\r\n  var y = b[1] - a[1];\r\n  var z = b[2] - a[2];\r\n  return Math.sqrt(x * x + y * y + z * z);\r\n}\r\n\r\n/**\r\n * Calculates the squared euclidian distance between two vec3's\r\n *\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @returns {Number} squared distance between a and b\r\n */\r\nfunction squaredDistance(a, b) {\r\n  var x = b[0] - a[0];\r\n  var y = b[1] - a[1];\r\n  var z = b[2] - a[2];\r\n  return x * x + y * y + z * z;\r\n}\r\n\r\n/**\r\n * Calculates the squared length of a vec3\r\n *\r\n * @param {vec3} a vector to calculate squared length of\r\n * @returns {Number} squared length of a\r\n */\r\nfunction squaredLength(a) {\r\n  var x = a[0];\r\n  var y = a[1];\r\n  var z = a[2];\r\n  return x * x + y * y + z * z;\r\n}\r\n\r\n/**\r\n * Negates the components of a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a vector to negate\r\n * @returns {vec3} out\r\n */\r\nfunction negate(out, a) {\r\n  out[0] = -a[0];\r\n  out[1] = -a[1];\r\n  out[2] = -a[2];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the inverse of the components of a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a vector to invert\r\n * @returns {vec3} out\r\n */\r\nfunction inverse(out, a) {\r\n  out[0] = 1.0 / a[0];\r\n  out[1] = 1.0 / a[1];\r\n  out[2] = 1.0 / a[2];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Normalize a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a vector to normalize\r\n * @returns {vec3} out\r\n */\r\nfunction normalize(out, a) {\r\n  var x = a[0];\r\n  var y = a[1];\r\n  var z = a[2];\r\n  var len = x * x + y * y + z * z;\r\n  if (len > 0) {\r\n    //TODO: evaluate use of glm_invsqrt here?\r\n    len = 1 / Math.sqrt(len);\r\n    out[0] = a[0] * len;\r\n    out[1] = a[1] * len;\r\n    out[2] = a[2] * len;\r\n  }\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the dot product of two vec3's\r\n *\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @returns {Number} dot product of a and b\r\n */\r\nfunction dot(a, b) {\r\n  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\r\n}\r\n\r\n/**\r\n * Computes the cross product of two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @returns {vec3} out\r\n */\r\nfunction cross(out, a, b) {\r\n  var ax = a[0],\r\n      ay = a[1],\r\n      az = a[2];\r\n  var bx = b[0],\r\n      by = b[1],\r\n      bz = b[2];\r\n\r\n  out[0] = ay * bz - az * by;\r\n  out[1] = az * bx - ax * bz;\r\n  out[2] = ax * by - ay * bx;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Performs a linear interpolation between two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {vec3} out\r\n */\r\nfunction lerp(out, a, b, t) {\r\n  var ax = a[0];\r\n  var ay = a[1];\r\n  var az = a[2];\r\n  out[0] = ax + t * (b[0] - ax);\r\n  out[1] = ay + t * (b[1] - ay);\r\n  out[2] = az + t * (b[2] - az);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Performs a hermite interpolation with two control points\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @param {vec3} c the third operand\r\n * @param {vec3} d the fourth operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {vec3} out\r\n */\r\nfunction hermite(out, a, b, c, d, t) {\r\n  var factorTimes2 = t * t;\r\n  var factor1 = factorTimes2 * (2 * t - 3) + 1;\r\n  var factor2 = factorTimes2 * (t - 2) + t;\r\n  var factor3 = factorTimes2 * (t - 1);\r\n  var factor4 = factorTimes2 * (3 - 2 * t);\r\n\r\n  out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\r\n  out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\r\n  out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Performs a bezier interpolation with two control points\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the first operand\r\n * @param {vec3} b the second operand\r\n * @param {vec3} c the third operand\r\n * @param {vec3} d the fourth operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {vec3} out\r\n */\r\nfunction bezier(out, a, b, c, d, t) {\r\n  var inverseFactor = 1 - t;\r\n  var inverseFactorTimesTwo = inverseFactor * inverseFactor;\r\n  var factorTimes2 = t * t;\r\n  var factor1 = inverseFactorTimesTwo * inverseFactor;\r\n  var factor2 = 3 * t * inverseFactorTimesTwo;\r\n  var factor3 = 3 * factorTimes2 * inverseFactor;\r\n  var factor4 = factorTimes2 * t;\r\n\r\n  out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\r\n  out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\r\n  out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a random vector with the given scale\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned\r\n * @returns {vec3} out\r\n */\r\nfunction random(out, scale) {\r\n  scale = scale || 1.0;\r\n\r\n  var r = __WEBPACK_IMPORTED_MODULE_0__common_js__[\"RANDOM\"]() * 2.0 * Math.PI;\r\n  var z = __WEBPACK_IMPORTED_MODULE_0__common_js__[\"RANDOM\"]() * 2.0 - 1.0;\r\n  var zScale = Math.sqrt(1.0 - z * z) * scale;\r\n\r\n  out[0] = Math.cos(r) * zScale;\r\n  out[1] = Math.sin(r) * zScale;\r\n  out[2] = z * scale;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transforms the vec3 with a mat4.\r\n * 4th vector component is implicitly '1'\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the vector to transform\r\n * @param {mat4} m matrix to transform with\r\n * @returns {vec3} out\r\n */\r\nfunction transformMat4(out, a, m) {\r\n  var x = a[0],\r\n      y = a[1],\r\n      z = a[2];\r\n  var w = m[3] * x + m[7] * y + m[11] * z + m[15];\r\n  w = w || 1.0;\r\n  out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;\r\n  out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;\r\n  out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transforms the vec3 with a mat3.\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the vector to transform\r\n * @param {mat3} m the 3x3 matrix to transform with\r\n * @returns {vec3} out\r\n */\r\nfunction transformMat3(out, a, m) {\r\n  var x = a[0],\r\n      y = a[1],\r\n      z = a[2];\r\n  out[0] = x * m[0] + y * m[3] + z * m[6];\r\n  out[1] = x * m[1] + y * m[4] + z * m[7];\r\n  out[2] = x * m[2] + y * m[5] + z * m[8];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transforms the vec3 with a quat\r\n * Can also be used for dual quaternions. (Multiply it with the real part)\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec3} a the vector to transform\r\n * @param {quat} q quaternion to transform with\r\n * @returns {vec3} out\r\n */\r\nfunction transformQuat(out, a, q) {\r\n  // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed\r\n  var qx = q[0],\r\n      qy = q[1],\r\n      qz = q[2],\r\n      qw = q[3];\r\n  var x = a[0],\r\n      y = a[1],\r\n      z = a[2];\r\n  // var qvec = [qx, qy, qz];\r\n  // var uv = vec3.cross([], qvec, a);\r\n  var uvx = qy * z - qz * y,\r\n      uvy = qz * x - qx * z,\r\n      uvz = qx * y - qy * x;\r\n  // var uuv = vec3.cross([], qvec, uv);\r\n  var uuvx = qy * uvz - qz * uvy,\r\n      uuvy = qz * uvx - qx * uvz,\r\n      uuvz = qx * uvy - qy * uvx;\r\n  // vec3.scale(uv, uv, 2 * w);\r\n  var w2 = qw * 2;\r\n  uvx *= w2;\r\n  uvy *= w2;\r\n  uvz *= w2;\r\n  // vec3.scale(uuv, uuv, 2);\r\n  uuvx *= 2;\r\n  uuvy *= 2;\r\n  uuvz *= 2;\r\n  // return vec3.add(out, a, vec3.add(out, uv, uuv));\r\n  out[0] = x + uvx + uuvx;\r\n  out[1] = y + uvy + uuvy;\r\n  out[2] = z + uvz + uuvz;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotate a 3D vector around the x-axis\r\n * @param {vec3} out The receiving vec3\r\n * @param {vec3} a The vec3 point to rotate\r\n * @param {vec3} b The origin of the rotation\r\n * @param {Number} c The angle of rotation\r\n * @returns {vec3} out\r\n */\r\nfunction rotateX(out, a, b, c) {\r\n  var p = [],\r\n      r = [];\r\n  //Translate point to the origin\r\n  p[0] = a[0] - b[0];\r\n  p[1] = a[1] - b[1];\r\n  p[2] = a[2] - b[2];\r\n\r\n  //perform rotation\r\n  r[0] = p[0];\r\n  r[1] = p[1] * Math.cos(c) - p[2] * Math.sin(c);\r\n  r[2] = p[1] * Math.sin(c) + p[2] * Math.cos(c);\r\n\r\n  //translate to correct position\r\n  out[0] = r[0] + b[0];\r\n  out[1] = r[1] + b[1];\r\n  out[2] = r[2] + b[2];\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotate a 3D vector around the y-axis\r\n * @param {vec3} out The receiving vec3\r\n * @param {vec3} a The vec3 point to rotate\r\n * @param {vec3} b The origin of the rotation\r\n * @param {Number} c The angle of rotation\r\n * @returns {vec3} out\r\n */\r\nfunction rotateY(out, a, b, c) {\r\n  var p = [],\r\n      r = [];\r\n  //Translate point to the origin\r\n  p[0] = a[0] - b[0];\r\n  p[1] = a[1] - b[1];\r\n  p[2] = a[2] - b[2];\r\n\r\n  //perform rotation\r\n  r[0] = p[2] * Math.sin(c) + p[0] * Math.cos(c);\r\n  r[1] = p[1];\r\n  r[2] = p[2] * Math.cos(c) - p[0] * Math.sin(c);\r\n\r\n  //translate to correct position\r\n  out[0] = r[0] + b[0];\r\n  out[1] = r[1] + b[1];\r\n  out[2] = r[2] + b[2];\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotate a 3D vector around the z-axis\r\n * @param {vec3} out The receiving vec3\r\n * @param {vec3} a The vec3 point to rotate\r\n * @param {vec3} b The origin of the rotation\r\n * @param {Number} c The angle of rotation\r\n * @returns {vec3} out\r\n */\r\nfunction rotateZ(out, a, b, c) {\r\n  var p = [],\r\n      r = [];\r\n  //Translate point to the origin\r\n  p[0] = a[0] - b[0];\r\n  p[1] = a[1] - b[1];\r\n  p[2] = a[2] - b[2];\r\n\r\n  //perform rotation\r\n  r[0] = p[0] * Math.cos(c) - p[1] * Math.sin(c);\r\n  r[1] = p[0] * Math.sin(c) + p[1] * Math.cos(c);\r\n  r[2] = p[2];\r\n\r\n  //translate to correct position\r\n  out[0] = r[0] + b[0];\r\n  out[1] = r[1] + b[1];\r\n  out[2] = r[2] + b[2];\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Get the angle between two 3D vectors\r\n * @param {vec3} a The first operand\r\n * @param {vec3} b The second operand\r\n * @returns {Number} The angle in radians\r\n */\r\nfunction angle(a, b) {\r\n  var tempA = fromValues(a[0], a[1], a[2]);\r\n  var tempB = fromValues(b[0], b[1], b[2]);\r\n\r\n  normalize(tempA, tempA);\r\n  normalize(tempB, tempB);\r\n\r\n  var cosine = dot(tempA, tempB);\r\n\r\n  if (cosine > 1.0) {\r\n    return 0;\r\n  } else if (cosine < -1.0) {\r\n    return Math.PI;\r\n  } else {\r\n    return Math.acos(cosine);\r\n  }\r\n}\r\n\r\n/**\r\n * Returns a string representation of a vector\r\n *\r\n * @param {vec3} a vector to represent as a string\r\n * @returns {String} string representation of the vector\r\n */\r\nfunction str(a) {\r\n  return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';\r\n}\r\n\r\n/**\r\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {vec3} a The first vector.\r\n * @param {vec3} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\r\nfunction exactEquals(a, b) {\r\n  return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];\r\n}\r\n\r\n/**\r\n * Returns whether or not the vectors have approximately the same elements in the same position.\r\n *\r\n * @param {vec3} a The first vector.\r\n * @param {vec3} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\r\nfunction equals(a, b) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2];\r\n  var b0 = b[0],\r\n      b1 = b[1],\r\n      b2 = b[2];\r\n  return Math.abs(a0 - b0) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a2), Math.abs(b2));\r\n}\r\n\r\n/**\r\n * Alias for {@link vec3.subtract}\r\n * @function\r\n */\r\nvar sub = subtract;\r\n\r\n/**\r\n * Alias for {@link vec3.multiply}\r\n * @function\r\n */\r\nvar mul = multiply;\r\n\r\n/**\r\n * Alias for {@link vec3.divide}\r\n * @function\r\n */\r\nvar div = divide;\r\n\r\n/**\r\n * Alias for {@link vec3.distance}\r\n * @function\r\n */\r\nvar dist = distance;\r\n\r\n/**\r\n * Alias for {@link vec3.squaredDistance}\r\n * @function\r\n */\r\nvar sqrDist = squaredDistance;\r\n\r\n/**\r\n * Alias for {@link vec3.length}\r\n * @function\r\n */\r\nvar len = length;\r\n\r\n/**\r\n * Alias for {@link vec3.squaredLength}\r\n * @function\r\n */\r\nvar sqrLen = squaredLength;\r\n\r\n/**\r\n * Perform some operation over an array of vec3s.\r\n *\r\n * @param {Array} a the array of vectors to iterate over\r\n * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed\r\n * @param {Number} offset Number of elements to skip at the beginning of the array\r\n * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array\r\n * @param {Function} fn Function to call for each vector in the array\r\n * @param {Object} [arg] additional argument to pass to fn\r\n * @returns {Array} a\r\n * @function\r\n */\r\nvar forEach = function () {\r\n  var vec = create();\r\n\r\n  return function (a, stride, offset, count, fn, arg) {\r\n    var i = void 0,\r\n        l = void 0;\r\n    if (!stride) {\r\n      stride = 3;\r\n    }\r\n\r\n    if (!offset) {\r\n      offset = 0;\r\n    }\r\n\r\n    if (count) {\r\n      l = Math.min(count * stride + offset, a.length);\r\n    } else {\r\n      l = a.length;\r\n    }\r\n\r\n    for (i = offset; i < l; i += stride) {\r\n      vec[0] = a[i];vec[1] = a[i + 1];vec[2] = a[i + 2];\r\n      fn(vec, vec, arg);\r\n      a[i] = vec[0];a[i + 1] = vec[1];a[i + 2] = vec[2];\r\n    }\r\n\r\n    return a;\r\n  };\r\n}();\n\n/***/ }),\n/* 6 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (immutable) */ __webpack_exports__[\"create\"] = create;\n/* harmony export (immutable) */ __webpack_exports__[\"clone\"] = clone;\n/* harmony export (immutable) */ __webpack_exports__[\"fromValues\"] = fromValues;\n/* harmony export (immutable) */ __webpack_exports__[\"copy\"] = copy;\n/* harmony export (immutable) */ __webpack_exports__[\"set\"] = set;\n/* harmony export (immutable) */ __webpack_exports__[\"add\"] = add;\n/* harmony export (immutable) */ __webpack_exports__[\"subtract\"] = subtract;\n/* harmony export (immutable) */ __webpack_exports__[\"multiply\"] = multiply;\n/* harmony export (immutable) */ __webpack_exports__[\"divide\"] = divide;\n/* harmony export (immutable) */ __webpack_exports__[\"ceil\"] = ceil;\n/* harmony export (immutable) */ __webpack_exports__[\"floor\"] = floor;\n/* harmony export (immutable) */ __webpack_exports__[\"min\"] = min;\n/* harmony export (immutable) */ __webpack_exports__[\"max\"] = max;\n/* harmony export (immutable) */ __webpack_exports__[\"round\"] = round;\n/* harmony export (immutable) */ __webpack_exports__[\"scale\"] = scale;\n/* harmony export (immutable) */ __webpack_exports__[\"scaleAndAdd\"] = scaleAndAdd;\n/* harmony export (immutable) */ __webpack_exports__[\"distance\"] = distance;\n/* harmony export (immutable) */ __webpack_exports__[\"squaredDistance\"] = squaredDistance;\n/* harmony export (immutable) */ __webpack_exports__[\"length\"] = length;\n/* harmony export (immutable) */ __webpack_exports__[\"squaredLength\"] = squaredLength;\n/* harmony export (immutable) */ __webpack_exports__[\"negate\"] = negate;\n/* harmony export (immutable) */ __webpack_exports__[\"inverse\"] = inverse;\n/* harmony export (immutable) */ __webpack_exports__[\"normalize\"] = normalize;\n/* harmony export (immutable) */ __webpack_exports__[\"dot\"] = dot;\n/* harmony export (immutable) */ __webpack_exports__[\"lerp\"] = lerp;\n/* harmony export (immutable) */ __webpack_exports__[\"random\"] = random;\n/* harmony export (immutable) */ __webpack_exports__[\"transformMat4\"] = transformMat4;\n/* harmony export (immutable) */ __webpack_exports__[\"transformQuat\"] = transformQuat;\n/* harmony export (immutable) */ __webpack_exports__[\"str\"] = str;\n/* harmony export (immutable) */ __webpack_exports__[\"exactEquals\"] = exactEquals;\n/* harmony export (immutable) */ __webpack_exports__[\"equals\"] = equals;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sub\", function() { return sub; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mul\", function() { return mul; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"div\", function() { return div; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"dist\", function() { return dist; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sqrDist\", function() { return sqrDist; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"len\", function() { return len; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sqrLen\", function() { return sqrLen; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"forEach\", function() { return forEach; });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_js__ = __webpack_require__(0);\n\r\n\r\n/**\r\n * 4 Dimensional Vector\r\n * @module vec4\r\n */\r\n\r\n/**\r\n * Creates a new, empty vec4\r\n *\r\n * @returns {vec4} a new 4D vector\r\n */\r\nfunction create() {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](4);\r\n  if (__WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"] != Float32Array) {\r\n    out[0] = 0;\r\n    out[1] = 0;\r\n    out[2] = 0;\r\n    out[3] = 0;\r\n  }\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new vec4 initialized with values from an existing vector\r\n *\r\n * @param {vec4} a vector to clone\r\n * @returns {vec4} a new 4D vector\r\n */\r\nfunction clone(a) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](4);\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new vec4 initialized with the given values\r\n *\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @param {Number} w W component\r\n * @returns {vec4} a new 4D vector\r\n */\r\nfunction fromValues(x, y, z, w) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](4);\r\n  out[0] = x;\r\n  out[1] = y;\r\n  out[2] = z;\r\n  out[3] = w;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Copy the values from one vec4 to another\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the source vector\r\n * @returns {vec4} out\r\n */\r\nfunction copy(out, a) {\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set the components of a vec4 to the given values\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @param {Number} w W component\r\n * @returns {vec4} out\r\n */\r\nfunction set(out, x, y, z, w) {\r\n  out[0] = x;\r\n  out[1] = y;\r\n  out[2] = z;\r\n  out[3] = w;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @returns {vec4} out\r\n */\r\nfunction add(out, a, b) {\r\n  out[0] = a[0] + b[0];\r\n  out[1] = a[1] + b[1];\r\n  out[2] = a[2] + b[2];\r\n  out[3] = a[3] + b[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Subtracts vector b from vector a\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @returns {vec4} out\r\n */\r\nfunction subtract(out, a, b) {\r\n  out[0] = a[0] - b[0];\r\n  out[1] = a[1] - b[1];\r\n  out[2] = a[2] - b[2];\r\n  out[3] = a[3] - b[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Multiplies two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @returns {vec4} out\r\n */\r\nfunction multiply(out, a, b) {\r\n  out[0] = a[0] * b[0];\r\n  out[1] = a[1] * b[1];\r\n  out[2] = a[2] * b[2];\r\n  out[3] = a[3] * b[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Divides two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @returns {vec4} out\r\n */\r\nfunction divide(out, a, b) {\r\n  out[0] = a[0] / b[0];\r\n  out[1] = a[1] / b[1];\r\n  out[2] = a[2] / b[2];\r\n  out[3] = a[3] / b[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Math.ceil the components of a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a vector to ceil\r\n * @returns {vec4} out\r\n */\r\nfunction ceil(out, a) {\r\n  out[0] = Math.ceil(a[0]);\r\n  out[1] = Math.ceil(a[1]);\r\n  out[2] = Math.ceil(a[2]);\r\n  out[3] = Math.ceil(a[3]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Math.floor the components of a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a vector to floor\r\n * @returns {vec4} out\r\n */\r\nfunction floor(out, a) {\r\n  out[0] = Math.floor(a[0]);\r\n  out[1] = Math.floor(a[1]);\r\n  out[2] = Math.floor(a[2]);\r\n  out[3] = Math.floor(a[3]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the minimum of two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @returns {vec4} out\r\n */\r\nfunction min(out, a, b) {\r\n  out[0] = Math.min(a[0], b[0]);\r\n  out[1] = Math.min(a[1], b[1]);\r\n  out[2] = Math.min(a[2], b[2]);\r\n  out[3] = Math.min(a[3], b[3]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the maximum of two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @returns {vec4} out\r\n */\r\nfunction max(out, a, b) {\r\n  out[0] = Math.max(a[0], b[0]);\r\n  out[1] = Math.max(a[1], b[1]);\r\n  out[2] = Math.max(a[2], b[2]);\r\n  out[3] = Math.max(a[3], b[3]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Math.round the components of a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a vector to round\r\n * @returns {vec4} out\r\n */\r\nfunction round(out, a) {\r\n  out[0] = Math.round(a[0]);\r\n  out[1] = Math.round(a[1]);\r\n  out[2] = Math.round(a[2]);\r\n  out[3] = Math.round(a[3]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Scales a vec4 by a scalar number\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the vector to scale\r\n * @param {Number} b amount to scale the vector by\r\n * @returns {vec4} out\r\n */\r\nfunction scale(out, a, b) {\r\n  out[0] = a[0] * b;\r\n  out[1] = a[1] * b;\r\n  out[2] = a[2] * b;\r\n  out[3] = a[3] * b;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two vec4's after scaling the second operand by a scalar value\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @param {Number} scale the amount to scale b by before adding\r\n * @returns {vec4} out\r\n */\r\nfunction scaleAndAdd(out, a, b, scale) {\r\n  out[0] = a[0] + b[0] * scale;\r\n  out[1] = a[1] + b[1] * scale;\r\n  out[2] = a[2] + b[2] * scale;\r\n  out[3] = a[3] + b[3] * scale;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the euclidian distance between two vec4's\r\n *\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @returns {Number} distance between a and b\r\n */\r\nfunction distance(a, b) {\r\n  var x = b[0] - a[0];\r\n  var y = b[1] - a[1];\r\n  var z = b[2] - a[2];\r\n  var w = b[3] - a[3];\r\n  return Math.sqrt(x * x + y * y + z * z + w * w);\r\n}\r\n\r\n/**\r\n * Calculates the squared euclidian distance between two vec4's\r\n *\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @returns {Number} squared distance between a and b\r\n */\r\nfunction squaredDistance(a, b) {\r\n  var x = b[0] - a[0];\r\n  var y = b[1] - a[1];\r\n  var z = b[2] - a[2];\r\n  var w = b[3] - a[3];\r\n  return x * x + y * y + z * z + w * w;\r\n}\r\n\r\n/**\r\n * Calculates the length of a vec4\r\n *\r\n * @param {vec4} a vector to calculate length of\r\n * @returns {Number} length of a\r\n */\r\nfunction length(a) {\r\n  var x = a[0];\r\n  var y = a[1];\r\n  var z = a[2];\r\n  var w = a[3];\r\n  return Math.sqrt(x * x + y * y + z * z + w * w);\r\n}\r\n\r\n/**\r\n * Calculates the squared length of a vec4\r\n *\r\n * @param {vec4} a vector to calculate squared length of\r\n * @returns {Number} squared length of a\r\n */\r\nfunction squaredLength(a) {\r\n  var x = a[0];\r\n  var y = a[1];\r\n  var z = a[2];\r\n  var w = a[3];\r\n  return x * x + y * y + z * z + w * w;\r\n}\r\n\r\n/**\r\n * Negates the components of a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a vector to negate\r\n * @returns {vec4} out\r\n */\r\nfunction negate(out, a) {\r\n  out[0] = -a[0];\r\n  out[1] = -a[1];\r\n  out[2] = -a[2];\r\n  out[3] = -a[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the inverse of the components of a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a vector to invert\r\n * @returns {vec4} out\r\n */\r\nfunction inverse(out, a) {\r\n  out[0] = 1.0 / a[0];\r\n  out[1] = 1.0 / a[1];\r\n  out[2] = 1.0 / a[2];\r\n  out[3] = 1.0 / a[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Normalize a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a vector to normalize\r\n * @returns {vec4} out\r\n */\r\nfunction normalize(out, a) {\r\n  var x = a[0];\r\n  var y = a[1];\r\n  var z = a[2];\r\n  var w = a[3];\r\n  var len = x * x + y * y + z * z + w * w;\r\n  if (len > 0) {\r\n    len = 1 / Math.sqrt(len);\r\n    out[0] = x * len;\r\n    out[1] = y * len;\r\n    out[2] = z * len;\r\n    out[3] = w * len;\r\n  }\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the dot product of two vec4's\r\n *\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @returns {Number} dot product of a and b\r\n */\r\nfunction dot(a, b) {\r\n  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];\r\n}\r\n\r\n/**\r\n * Performs a linear interpolation between two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the first operand\r\n * @param {vec4} b the second operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {vec4} out\r\n */\r\nfunction lerp(out, a, b, t) {\r\n  var ax = a[0];\r\n  var ay = a[1];\r\n  var az = a[2];\r\n  var aw = a[3];\r\n  out[0] = ax + t * (b[0] - ax);\r\n  out[1] = ay + t * (b[1] - ay);\r\n  out[2] = az + t * (b[2] - az);\r\n  out[3] = aw + t * (b[3] - aw);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a random vector with the given scale\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned\r\n * @returns {vec4} out\r\n */\r\nfunction random(out, scale) {\r\n  scale = scale || 1.0;\r\n\r\n  // Marsaglia, George. Choosing a Point from the Surface of a\r\n  // Sphere. Ann. Math. Statist. 43 (1972), no. 2, 645--646.\r\n  // http://projecteuclid.org/euclid.aoms/1177692644;\r\n  var v1, v2, v3, v4;\r\n  var s1, s2;\r\n  do {\r\n    v1 = __WEBPACK_IMPORTED_MODULE_0__common_js__[\"RANDOM\"]() * 2 - 1;\r\n    v2 = __WEBPACK_IMPORTED_MODULE_0__common_js__[\"RANDOM\"]() * 2 - 1;\r\n    s1 = v1 * v1 + v2 * v2;\r\n  } while (s1 >= 1);\r\n  do {\r\n    v3 = __WEBPACK_IMPORTED_MODULE_0__common_js__[\"RANDOM\"]() * 2 - 1;\r\n    v4 = __WEBPACK_IMPORTED_MODULE_0__common_js__[\"RANDOM\"]() * 2 - 1;\r\n    s2 = v3 * v3 + v4 * v4;\r\n  } while (s2 >= 1);\r\n\r\n  var d = Math.sqrt((1 - s1) / s2);\r\n  out[0] = scale * v1;\r\n  out[1] = scale * v2;\r\n  out[2] = scale * v3 * d;\r\n  out[3] = scale * v4 * d;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transforms the vec4 with a mat4.\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the vector to transform\r\n * @param {mat4} m matrix to transform with\r\n * @returns {vec4} out\r\n */\r\nfunction transformMat4(out, a, m) {\r\n  var x = a[0],\r\n      y = a[1],\r\n      z = a[2],\r\n      w = a[3];\r\n  out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;\r\n  out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;\r\n  out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;\r\n  out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transforms the vec4 with a quat\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {vec4} a the vector to transform\r\n * @param {quat} q quaternion to transform with\r\n * @returns {vec4} out\r\n */\r\nfunction transformQuat(out, a, q) {\r\n  var x = a[0],\r\n      y = a[1],\r\n      z = a[2];\r\n  var qx = q[0],\r\n      qy = q[1],\r\n      qz = q[2],\r\n      qw = q[3];\r\n\r\n  // calculate quat * vec\r\n  var ix = qw * x + qy * z - qz * y;\r\n  var iy = qw * y + qz * x - qx * z;\r\n  var iz = qw * z + qx * y - qy * x;\r\n  var iw = -qx * x - qy * y - qz * z;\r\n\r\n  // calculate result * inverse quat\r\n  out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;\r\n  out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;\r\n  out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;\r\n  out[3] = a[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns a string representation of a vector\r\n *\r\n * @param {vec4} a vector to represent as a string\r\n * @returns {String} string representation of the vector\r\n */\r\nfunction str(a) {\r\n  return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';\r\n}\r\n\r\n/**\r\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {vec4} a The first vector.\r\n * @param {vec4} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\r\nfunction exactEquals(a, b) {\r\n  return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];\r\n}\r\n\r\n/**\r\n * Returns whether or not the vectors have approximately the same elements in the same position.\r\n *\r\n * @param {vec4} a The first vector.\r\n * @param {vec4} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\r\nfunction equals(a, b) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3];\r\n  var b0 = b[0],\r\n      b1 = b[1],\r\n      b2 = b[2],\r\n      b3 = b[3];\r\n  return Math.abs(a0 - b0) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a3), Math.abs(b3));\r\n}\r\n\r\n/**\r\n * Alias for {@link vec4.subtract}\r\n * @function\r\n */\r\nvar sub = subtract;\r\n\r\n/**\r\n * Alias for {@link vec4.multiply}\r\n * @function\r\n */\r\nvar mul = multiply;\r\n\r\n/**\r\n * Alias for {@link vec4.divide}\r\n * @function\r\n */\r\nvar div = divide;\r\n\r\n/**\r\n * Alias for {@link vec4.distance}\r\n * @function\r\n */\r\nvar dist = distance;\r\n\r\n/**\r\n * Alias for {@link vec4.squaredDistance}\r\n * @function\r\n */\r\nvar sqrDist = squaredDistance;\r\n\r\n/**\r\n * Alias for {@link vec4.length}\r\n * @function\r\n */\r\nvar len = length;\r\n\r\n/**\r\n * Alias for {@link vec4.squaredLength}\r\n * @function\r\n */\r\nvar sqrLen = squaredLength;\r\n\r\n/**\r\n * Perform some operation over an array of vec4s.\r\n *\r\n * @param {Array} a the array of vectors to iterate over\r\n * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed\r\n * @param {Number} offset Number of elements to skip at the beginning of the array\r\n * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array\r\n * @param {Function} fn Function to call for each vector in the array\r\n * @param {Object} [arg] additional argument to pass to fn\r\n * @returns {Array} a\r\n * @function\r\n */\r\nvar forEach = function () {\r\n  var vec = create();\r\n\r\n  return function (a, stride, offset, count, fn, arg) {\r\n    var i = void 0,\r\n        l = void 0;\r\n    if (!stride) {\r\n      stride = 4;\r\n    }\r\n\r\n    if (!offset) {\r\n      offset = 0;\r\n    }\r\n\r\n    if (count) {\r\n      l = Math.min(count * stride + offset, a.length);\r\n    } else {\r\n      l = a.length;\r\n    }\r\n\r\n    for (i = offset; i < l; i += stride) {\r\n      vec[0] = a[i];vec[1] = a[i + 1];vec[2] = a[i + 2];vec[3] = a[i + 3];\r\n      fn(vec, vec, arg);\r\n      a[i] = vec[0];a[i + 1] = vec[1];a[i + 2] = vec[2];a[i + 3] = vec[3];\r\n    }\r\n\r\n    return a;\r\n  };\r\n}();\n\n/***/ }),\n/* 7 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_gl_matrix__ = __webpack_require__(1);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__css_style_css__ = __webpack_require__(13);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__css_style_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__css_style_css__);\n\r\nvar MinimalGLTFLoader = __webpack_require__(12);\r\n// require('./lib/minimal-gltf-loader.js');\r\n\r\n\r\n\r\n\r\n// utils\r\nvar Utils = Utils || {};\r\n(function () {\r\n    'use strict';\r\n\r\n    Utils.getShaderSource = function(id) {\r\n        return document.getElementById(id).textContent.replace(/^\\s+|\\s+$/g, '');\r\n    };\r\n\r\n    function createShader(gl, source, type) {\r\n        var shader = gl.createShader(type);\r\n        gl.shaderSource(shader, source);\r\n        gl.compileShader(shader);\r\n        return shader;\r\n    }\r\n\r\n    Utils.createProgram = function(gl, vertexShaderSource, fragmentShaderSource) {\r\n        var program = gl.createProgram();\r\n        var vshader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER);\r\n        var fshader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);\r\n        gl.attachShader(program, vshader);\r\n        gl.deleteShader(vshader);\r\n        gl.attachShader(program, fshader);\r\n        gl.deleteShader(fshader);\r\n        gl.linkProgram(program);\r\n\r\n        var log = gl.getProgramInfoLog(program);\r\n        if (log) {\r\n            console.log(log);\r\n        }\r\n\r\n        log = gl.getShaderInfoLog(vshader);\r\n        if (log) {\r\n            console.log(log);\r\n        }\r\n\r\n        log = gl.getShaderInfoLog(fshader);\r\n        if (log) {\r\n            console.log(log);\r\n        }\r\n\r\n        return program;\r\n    };\r\n\r\n    var loadImage = Utils.loadImage = function(url, onload) {\r\n        var img = new Image();\r\n        img.crossOrigin = \"Anonymous\";\r\n        img.src = url;\r\n        // img.onload = function() {\r\n        //     onload(img);\r\n        // };\r\n        img.onload = onload;\r\n        return img;\r\n    };\r\n\r\n    Utils.loadImages = function(urls, onload) {\r\n        var imgs = [];\r\n        var imgsToLoad = urls.length;\r\n\r\n        function onImgLoad() {\r\n            if (--imgsToLoad <= 0) {\r\n                onload(imgs);\r\n            }\r\n        }\r\n\r\n        for (var i = 0; i < imgsToLoad; ++i) {\r\n            imgs.push(loadImage(urls[i], onImgLoad));\r\n        }\r\n    };\r\n\r\n})();\r\n\r\n\r\n\r\n\r\n\r\n(function()  {\r\n    'use strict';\r\n\r\n    // var selectedGltfSampleModel = 'Drone';\r\n    var selectedGltfSampleModel = 'DamagedHelmet';\r\n\r\n    var drawBoundingBox = false;\r\n    var boundingBoxType = 'obb';\r\n\r\n    var curAnimationId = 0;\r\n    var playAllAnimationTogether = false;\r\n    var animationSelectionList = document.getElementById(\"animations\");\r\n\r\n    animationSelectionList.addEventListener(\"change\", function() {\r\n        curAnimationId = this.selectedIndex;\r\n    });\r\n\r\n    document.getElementById(\"gltf-model\").addEventListener(\"change\", function() {\r\n        // selectedGltfSampleModel = this.value;\r\n        var uri = this.value;\r\n        // if (selectedGltfSampleModel == 'Drone') {\r\n        //     uri = 'https://raw.githubusercontent.com/shrekshao/minimal-gltf-loader/store-drone-model/glTFs/glTF_version_2/buster_drone/scene.gltf';\r\n        // } else {\r\n        //     uri = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/'\r\n        //     + selectedGltfSampleModel\r\n        //     + '/glTF/'\r\n        //     + selectedGltfSampleModel\r\n        //     + '.gltf';\r\n        // }\r\n\r\n        glTFLoader.loadGLTF(uri, function(glTF) {\r\n            // var scene = scenes[0];\r\n            scenes = [];\r\n            // TODO: delete gl resources\r\n            // scene = null;\r\n\r\n            setupScene(glTF);\r\n        });\r\n\r\n    });\r\n\r\n    document.getElementById(\"bbox-toggle\").addEventListener(\"change\", function() {\r\n        drawBoundingBox = this.checked;\r\n    });\r\n\r\n    document.getElementById(\"play-all-animations\").addEventListener(\"change\", function() {\r\n        playAllAnimationTogether = this.checked;\r\n    });\r\n\r\n    document.getElementById(\"bbox-type\").addEventListener(\"change\", function() {\r\n        boundingBoxType = this.value;\r\n    });\r\n\r\n    var canvas = document.createElement('canvas');\r\n    // canvas.width = Math.min(window.innerWidth, window.innerHeight);\r\n    // canvas.height = canvas.width;\r\n    canvas.width = window.innerWidth;\r\n    canvas.height = window.innerHeight;\r\n    document.body.appendChild(canvas);\r\n\r\n    var gl = canvas.getContext( 'webgl2', { antialias: true } );\r\n    var isWebGL2 = !!gl;\r\n    if(!isWebGL2) {\r\n        document.getElementById('info').innerHTML = 'WebGL 2 is not available.  See <a href=\"https://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation\">How to get a WebGL 2 implementation</a>';\r\n        return;\r\n    }\r\n\r\n    canvas.oncontextmenu = function (e) {\r\n        e.preventDefault();\r\n    };\r\n\r\n    // Scene object for runtime renderer\r\n    var Scene = function(glTFScene, glTF, id) {\r\n        this.glTFScene = glTFScene;\r\n        this.glTF = glTF;\r\n        this.id = id;\r\n\r\n        // runtime renderer context\r\n        this.rootTransform = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n        // @temp, assume every node is in current scene\r\n        this.nodeMatrix = new Array(glTF.nodes.length);\r\n        var i, len;\r\n        for(i = 0, len = this.nodeMatrix.length; i < len; i++) {\r\n            this.nodeMatrix[i] = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n        }\r\n\r\n        // TODO: runtime joint matrix\r\n    };\r\n\r\n    var BOUNDING_BOX = {\r\n        vertexData: new Float32Array([\r\n            0.0, 0.0, 0.0,\r\n            1.0, 0.0, 0.0,\r\n            0.0, 0.0, 0.0,\r\n            0.0, 1.0, 0.0,\r\n            0.0, 0.0, 0.0,\r\n            0.0, 0.0, 1.0,\r\n\r\n            0.0, 1.0, 1.0,\r\n            1.0, 1.0, 1.0,\r\n            0.0, 1.0, 1.0,\r\n            0.0, 1.0, 0.0,\r\n            0.0, 1.0, 1.0,\r\n            0.0, 0.0, 1.0,\r\n\r\n            1.0, 1.0, 0.0,\r\n            1.0, 1.0, 1.0,\r\n            1.0, 1.0, 0.0,\r\n            0.0, 1.0, 0.0,\r\n            1.0, 1.0, 0.0,\r\n            1.0, 0.0, 0.0,\r\n\r\n            1.0, 0.0, 1.0,\r\n            1.0, 0.0, 0.0,\r\n            1.0, 0.0, 1.0,\r\n            1.0, 1.0, 1.0,\r\n            1.0, 0.0, 1.0,\r\n            0.0, 0.0, 1.0\r\n        ]),\r\n\r\n        vertexArray: gl.createVertexArray(),\r\n        vertexBuffer: gl.createBuffer(),\r\n\r\n        program: Utils.createProgram(gl, __webpack_require__(18), __webpack_require__(19)),\r\n        positionLocation: 0,\r\n        uniformMvpLocation: 0, \r\n\r\n        \r\n        draw: (function() {\r\n            var MVP = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n            return (function(bbox, nodeTransform, V, P) {\r\n                // gl.useProgram(this.program);\r\n\r\n                __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(MVP, nodeTransform, bbox.transform);\r\n                __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(MVP, V, MVP);\r\n                __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(MVP, P, MVP);\r\n\r\n                gl.uniformMatrix4fv(this.uniformMvpLocation, false, MVP);\r\n                // gl.bindVertexArray(this.vertexArray);\r\n                gl.drawArrays(gl.LINES, 0, 24);\r\n                // gl.bindVertexArray(null);\r\n            });\r\n        })()\r\n    };\r\n\r\n    \r\n\r\n    var defaultSampler = gl.createSampler();\r\n    gl.samplerParameteri(defaultSampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);\r\n    gl.samplerParameteri(defaultSampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\r\n    gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_S, gl.REPEAT);\r\n    gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_T, gl.REPEAT);\r\n    // gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_R, gl.REPEAT);\r\n    // gl.samplerParameterf(defaultSampler, gl.TEXTURE_MIN_LOD, -1000.0);\r\n    // gl.samplerParameterf(defaultSampler, gl.TEXTURE_MAX_LOD, 1000.0);\r\n    // gl.samplerParameteri(defaultSampler, gl.TEXTURE_COMPARE_MODE, gl.NONE);\r\n    // gl.samplerParameteri(defaultSampler, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n    BOUNDING_BOX.uniformMvpLocation = gl.getUniformLocation(BOUNDING_BOX.program, \"u_MVP\");\r\n\r\n    gl.bindVertexArray(BOUNDING_BOX.vertexArray);\r\n\r\n    gl.bindBuffer(gl.ARRAY_BUFFER, BOUNDING_BOX.vertexBuffer);\r\n    gl.bufferData(gl.ARRAY_BUFFER, BOUNDING_BOX.vertexData, gl.STATIC_DRAW);\r\n    gl.vertexAttribPointer(BOUNDING_BOX.positionLocation, 3, gl.FLOAT, false, 0, 0);\r\n    gl.enableVertexAttribArray(BOUNDING_BOX.positionLocation);\r\n\r\n    gl.bindVertexArray(null);\r\n\r\n\r\n    var BRDF_LUT = {\r\n        texture: null,\r\n        textureIndex: 29,\r\n\r\n        createTexture: function (img) {\r\n            this.texture = gl.createTexture();\r\n            gl.bindTexture(gl.TEXTURE_2D, this.texture);\r\n            gl.texImage2D(\r\n                gl.TEXTURE_2D,  // assumed\r\n                0,        // Level of details\r\n                gl.RG16F, // Format\r\n                gl.RG,\r\n                // gl.RGBA, // Format\r\n                // gl.RGBA,\r\n                // gl.UNSIGNED_BYTE, // Size of each channel\r\n                gl.FLOAT,\r\n                img\r\n            );\r\n            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\r\n            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\r\n            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\r\n            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\r\n            gl.bindTexture(gl.TEXTURE_2D, null);\r\n        }\r\n    }\r\n\r\n\r\n    // Environment maps\r\n    var CUBE_MAP = {\r\n        textureIndex: 31,\r\n        texture: null,\r\n\r\n        // IBL\r\n        textureIBLDiffuseIndex: 30,\r\n        textureIBLDiffuse: null,\r\n\r\n        // loading asset --------------------\r\n        // TODO: use webpack to pack these\r\n        uris: [\r\n            '../textures/environment/px.jpg',\r\n            '../textures/environment/nx.jpg',\r\n            '../textures/environment/py.jpg',\r\n            '../textures/environment/ny.jpg',\r\n            '../textures/environment/pz.jpg',\r\n            '../textures/environment/nz.jpg',\r\n\r\n            // ibl diffuse\r\n            '../textures/environment/diffuse/bakedDiffuse_01.jpg',\r\n            '../textures/environment/diffuse/bakedDiffuse_02.jpg',\r\n            '../textures/environment/diffuse/bakedDiffuse_03.jpg',\r\n            '../textures/environment/diffuse/bakedDiffuse_04.jpg',\r\n            '../textures/environment/diffuse/bakedDiffuse_05.jpg',\r\n            '../textures/environment/diffuse/bakedDiffuse_06.jpg',\r\n\r\n            // '../textures/papermill/environment_right_0.jpg',\r\n            // '../textures/papermill/environment_left_0.jpg',\r\n            // '../textures/papermill/environment_top_0.jpg',\r\n            // '../textures/papermill/environment_bottom_0.jpg',\r\n            // '../textures/papermill/environment_front_0.jpg',\r\n            // '../textures/papermill/environment_back_0.jpg',\r\n\r\n            // '../textures/papermill/diffuse/diffuse_right_0.jpg',\r\n            // '../textures/papermill/diffuse/diffuse_left_0.jpg',\r\n            // '../textures/papermill/diffuse/diffuse_top_0.jpg',\r\n            // '../textures/papermill/diffuse/diffuse_bottom_0.jpg',\r\n            // '../textures/papermill/diffuse/diffuse_front_0.jpg',\r\n            // '../textures/papermill/diffuse/diffuse_back_0.jpg',\r\n\r\n            // @tmp, ugly, load brdfLUT here\r\n            '../textures/brdfLUT.png'\r\n        ],\r\n\r\n        images: null,\r\n\r\n        loadAll: function() {\r\n            Utils.loadImages(this.uris, this.onloadAll.bind(this));\r\n        },\r\n\r\n        onloadAll: function(imgs) {\r\n            this.images = imgs;\r\n            console.log('all cube maps loaded');\r\n\r\n            this.texture = gl.createTexture();\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.texture);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.NONE);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);\r\n\r\n            for (var i = 0; i < 6; i++) {\r\n                gl.texImage2D(\r\n                    gl.TEXTURE_CUBE_MAP_POSITIVE_X + i,\r\n                    0,\r\n                    gl.RGBA,\r\n                    gl.RGBA,\r\n                    gl.UNSIGNED_BYTE,\r\n                    this.images[i]\r\n                );\r\n            }\r\n            gl.generateMipmap(gl.TEXTURE_CUBE_MAP);\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);\r\n\r\n\r\n\r\n            this.textureIBLDiffuse = gl.createTexture();\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.textureIBLDiffuse);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.NONE);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);\r\n\r\n            for (var i = 0; i < 6; i++) {\r\n                gl.texImage2D(\r\n                    gl.TEXTURE_CUBE_MAP_POSITIVE_X + i,\r\n                    0,\r\n                    gl.RGBA,\r\n                    gl.RGBA,\r\n                    gl.UNSIGNED_BYTE,\r\n                    this.images[i + 6]\r\n                );\r\n            }\r\n\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);\r\n\r\n\r\n\r\n            // @tmp\r\n            BRDF_LUT.createTexture(this.images[this.images.length - 1]);\r\n\r\n            if (this.finishLoadingCallback) {\r\n                this.finishLoadingCallback();\r\n            }\r\n        },\r\n\r\n        finishLoadingCallback: null,\r\n\r\n\r\n        // runtime stuffs -------------------------\r\n        vertexData: new Float32Array([         \r\n            -1.0,  1.0, -1.0,\r\n            -1.0, -1.0, -1.0,\r\n            1.0, -1.0, -1.0,\r\n            1.0, -1.0, -1.0,\r\n            1.0,  1.0, -1.0,\r\n            -1.0,  1.0, -1.0,\r\n\r\n            -1.0, -1.0,  1.0,\r\n            -1.0, -1.0, -1.0,\r\n            -1.0,  1.0, -1.0,\r\n            -1.0,  1.0, -1.0,\r\n            -1.0,  1.0,  1.0,\r\n            -1.0, -1.0,  1.0,\r\n\r\n            1.0, -1.0, -1.0,\r\n            1.0, -1.0,  1.0,\r\n            1.0,  1.0,  1.0,\r\n            1.0,  1.0,  1.0,\r\n            1.0,  1.0, -1.0,\r\n            1.0, -1.0, -1.0,\r\n\r\n            -1.0, -1.0,  1.0,\r\n            -1.0,  1.0,  1.0,\r\n            1.0,  1.0,  1.0,\r\n            1.0,  1.0,  1.0,\r\n            1.0, -1.0,  1.0,\r\n            -1.0, -1.0,  1.0,\r\n\r\n            -1.0,  1.0, -1.0,\r\n            1.0,  1.0, -1.0,\r\n            1.0,  1.0,  1.0,\r\n            1.0,  1.0,  1.0,\r\n            -1.0,  1.0,  1.0,\r\n            -1.0,  1.0, -1.0,\r\n\r\n            -1.0, -1.0, -1.0,\r\n            -1.0, -1.0,  1.0,\r\n            1.0, -1.0, -1.0,\r\n            1.0, -1.0, -1.0,\r\n            -1.0, -1.0,  1.0,\r\n            1.0, -1.0,  1.0\r\n        ]),\r\n\r\n        \r\n        vertexArray: gl.createVertexArray(),\r\n        vertexBuffer: gl.createBuffer(),\r\n\r\n        program: Utils.createProgram(gl, __webpack_require__(20), __webpack_require__(21)),\r\n        positionLocation: 0,\r\n        uniformMvpLocation: 0, \r\n        uniformEnvironmentLocation: 0,\r\n\r\n        \r\n        draw: (function() {\r\n            var MVP = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n            return (function(V, P) {\r\n                __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].copy(MVP, V);\r\n                MVP[12] = 0.0;\r\n                MVP[13] = 0.0;\r\n                MVP[14] = 0.0;\r\n                MVP[15] = 1.0;\r\n                __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(MVP, P, MVP);\r\n\r\n                gl.useProgram(this.program);\r\n                gl.activeTexture(gl.TEXTURE0 + this.textureIndex);\r\n                gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.texture);\r\n                gl.uniformMatrix4fv(this.uniformMvpLocation, false, MVP);\r\n                gl.uniform1i(this.uniformEnvironmentLocation, this.textureIndex);\r\n                gl.bindVertexArray(this.vertexArray);\r\n                gl.drawArrays(gl.TRIANGLES, 0, 36);\r\n                gl.bindVertexArray(null);\r\n            });\r\n        })()\r\n    };\r\n\r\n    CUBE_MAP.uniformMvpLocation = gl.getUniformLocation(CUBE_MAP.program, \"u_MVP\");\r\n    CUBE_MAP.uniformEnvironmentLocation = gl.getUniformLocation(CUBE_MAP.program, \"u_environment\");\r\n\r\n    gl.bindVertexArray(CUBE_MAP.vertexArray);\r\n    \r\n    gl.bindBuffer(gl.ARRAY_BUFFER, CUBE_MAP.vertexBuffer);\r\n    gl.bufferData(gl.ARRAY_BUFFER, CUBE_MAP.vertexData, gl.STATIC_DRAW);\r\n    gl.vertexAttribPointer(CUBE_MAP.positionLocation, 3, gl.FLOAT, false, 0, 0);\r\n    gl.enableVertexAttribArray(CUBE_MAP.positionLocation);\r\n\r\n    gl.bindVertexArray(null);\r\n\r\n\r\n    \r\n    var Shader_Static = {\r\n        shaderVersionLine: '#version 300 es\\n',\r\n        \r\n        bitMasks: {\r\n            // vertex shader\r\n            HAS_SKIN: 1,\r\n            SKIN_VEC8: 2,\r\n\r\n            // fragment shader\r\n            HAS_BASECOLORMAP: 4,\r\n            HAS_NORMALMAP: 8,\r\n            HAS_METALROUGHNESSMAP: 16,\r\n            HAS_OCCLUSIONMAP: 32,\r\n            HAS_EMISSIVEMAP: 64\r\n        },\r\n\r\n        vsMasterCode: __webpack_require__(22),\r\n        fsMasterCode: __webpack_require__(23),\r\n\r\n        programObjects: {}    // < flags, Shader Object >\r\n    };\r\n\r\n    var Shader = function() {\r\n        this.flags = 0;\r\n        this.programObject = null;\r\n    };\r\n\r\n    Shader.prototype.hasSkin = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_SKIN;\r\n    };\r\n    Shader.prototype.hasBaseColorMap = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_BASECOLORMAP;\r\n    };\r\n    Shader.prototype.hasNormalMap = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_NORMALMAP;\r\n    };\r\n    Shader.prototype.hasMetalRoughnessMap = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_METALROUGHNESSMAP;\r\n    };\r\n    Shader.prototype.hasOcclusionMap = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_OCCLUSIONMAP;\r\n    };\r\n    Shader.prototype.hasEmissiveMap = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_EMISSIVEMAP;\r\n    };\r\n\r\n\r\n    Shader.prototype.defineMacro = function(macro) {\r\n        if (Shader_Static.bitMasks[macro] !== undefined) {\r\n            this.flags = Shader_Static.bitMasks[macro] | this.flags;\r\n        } else {\r\n            console.log('WARNING: ' + macro + ' is not a valid macro');\r\n        }\r\n    };\r\n\r\n    Shader.prototype.compile = function() {\r\n        var existingProgramObject = Shader_Static.programObjects[this.flags];\r\n        if (existingProgramObject) {\r\n            this.programObject = existingProgramObject;\r\n            return;\r\n        }\r\n\r\n\r\n        // new program\r\n\r\n        var vsDefine = '';\r\n        var fsDefine = '';\r\n\r\n        // define macros\r\n\r\n        if (this.flags & Shader_Static.bitMasks.HAS_SKIN) {\r\n            vsDefine += '#define HAS_SKIN\\n';\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.SKIN_VEC8) {\r\n            vsDefine += '#define SKIN_VEC8\\n';\r\n        }\r\n\r\n        if (this.flags & Shader_Static.bitMasks.HAS_BASECOLORMAP) {\r\n            fsDefine += '#define HAS_BASECOLORMAP\\n';\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_NORMALMAP) {\r\n            fsDefine += '#define HAS_NORMALMAP\\n';\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_METALROUGHNESSMAP) {\r\n            fsDefine += '#define HAS_METALROUGHNESSMAP\\n';\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_OCCLUSIONMAP) {\r\n            fsDefine += '#define HAS_OCCLUSIONMAP\\n';\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_EMISSIVEMAP) {\r\n            fsDefine += '#define HAS_EMISSIVEMAP\\n';\r\n        }\r\n\r\n\r\n        // concat\r\n        var vertexShaderSource = \r\n            Shader_Static.shaderVersionLine +\r\n            vsDefine +\r\n            Shader_Static.vsMasterCode;\r\n        \r\n        var fragmentShaderSource = \r\n            Shader_Static.shaderVersionLine +\r\n            fsDefine +\r\n            Shader_Static.fsMasterCode;\r\n\r\n        // compile\r\n        var program = Utils.createProgram(gl, vertexShaderSource, fragmentShaderSource);\r\n        this.programObject = {\r\n            program: program,\r\n    \r\n            uniformLocations: {},\r\n\r\n            uniformBlockIndices: {}\r\n        };\r\n\r\n        // uniform block id\r\n        if (this.flags & Shader_Static.bitMasks.HAS_SKIN) {\r\n            this.programObject.uniformBlockIndices.JointMatrix = gl.getUniformBlockIndex(program, \"JointMatrix\");\r\n        }\r\n\r\n        // uniform locations\r\n        var us = this.programObject.uniformLocations;\r\n\r\n        us.MVP = gl.getUniformLocation(program, 'u_MVP');\r\n        us.MVNormal = gl.getUniformLocation(program, 'u_MVNormal');\r\n        us.MV = gl.getUniformLocation(program, 'u_MV');\r\n        us.baseColorFactor = gl.getUniformLocation(program, 'u_baseColorFactor');\r\n        us.metallicFactor = gl.getUniformLocation(program, 'u_metallicFactor');\r\n        us.roughnessFactor = gl.getUniformLocation(program, 'u_roughnessFactor');\r\n\r\n        if (this.flags & Shader_Static.bitMasks.HAS_BASECOLORMAP) {\r\n            us.baseColorTexture = gl.getUniformLocation(program, 'u_baseColorTexture');\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_NORMALMAP) {\r\n            us.normalTexture = gl.getUniformLocation(program, 'u_normalTexture');\r\n            us.normalTextureScale = gl.getUniformLocation(program, 'u_normalTextureScale');\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_METALROUGHNESSMAP) {\r\n            us.metallicRoughnessTexture = gl.getUniformLocation(program, 'u_metallicRoughnessTexture');\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_OCCLUSIONMAP) {\r\n            us.occlusionTexture = gl.getUniformLocation(program, 'u_occlusionTexture');\r\n            us.occlusionStrength = gl.getUniformLocation(program, 'u_occlusionStrength');\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_EMISSIVEMAP) {\r\n            us.emissiveTexture = gl.getUniformLocation(program, 'u_emissiveTexture');\r\n            us.emissiveFactor = gl.getUniformLocation(program, 'u_emissiveFactor');\r\n        }\r\n\r\n        us.diffuseEnvSampler = gl.getUniformLocation(program, 'u_DiffuseEnvSampler');\r\n        us.specularEnvSampler = gl.getUniformLocation(program, 'u_SpecularEnvSampler');\r\n        us.brdfLUT = gl.getUniformLocation(program, 'u_brdfLUT');\r\n\r\n        // set static uniform values in cubemap\r\n        gl.useProgram(program);\r\n        gl.uniform1i(us.brdfLUT, BRDF_LUT.textureIndex);\r\n        gl.uniform1i(us.specularEnvSampler, CUBE_MAP.textureIndex);\r\n        gl.uniform1i(us.diffuseEnvSampler, CUBE_MAP.textureIBLDiffuseIndex);\r\n        gl.useProgram(null);\r\n\r\n        Shader_Static.programObjects[this.flags] = this.programObject;\r\n    };\r\n\r\n    // -- Initialize vertex array\r\n    var POSITION_LOCATION = 0; // set with GLSL layout qualifier\r\n    var NORMAL_LOCATION = 1; // set with GLSL layout qualifier\r\n    var TEXCOORD_0_LOCATION = 2; // set with GLSL layout qualifier\r\n    var JOINTS_0_LOCATION = 3; // set with GLSL layout qualifier\r\n    var JOINTS_1_LOCATION = 5; // set with GLSL layout qualifier\r\n    var WEIGHTS_0_LOCATION = 4; // set with GLSL layout qualifier\r\n    var WEIGHTS_1_LOCATION = 6; // set with GLSL layout qualifier\r\n    \r\n    // -- Mouse Behaviour\r\n    var isDisplayRotation = true;\r\n    var s = 1;\r\n    var eulerX = 0;\r\n    var eulerY = 0;\r\n    // var s = 1;\r\n    // var t = -100;\r\n    var translate = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\r\n    // var t = -5;\r\n    var modelMatrix = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n    var mouseDown = false;\r\n    var mouseButtonId = 0;\r\n    var lastMouseY = 0;\r\n    var lastMouseX = 0;\r\n    var identityQ = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"quat\"].create();\r\n    window.onmousedown = function(event) {\r\n        mouseDown = true;\r\n        mouseButtonId = event.which;\r\n        lastMouseY = event.clientY;\r\n        lastMouseX = event.clientX;\r\n        if (mouseButtonId === 1) {\r\n            isDisplayRotation = false;\r\n        }\r\n    };\r\n    window.onmouseup = function(event) {\r\n        mouseDown = false;\r\n        isDisplayRotation = true;\r\n    };\r\n    window.onmousemove = function(event) {\r\n        if(!mouseDown) {\r\n            return;\r\n        }\r\n        var newY = event.clientY;\r\n        var newX = event.clientX;\r\n        \r\n        var deltaY = newY - lastMouseY;\r\n        var deltaX = newX - lastMouseX;\r\n        \r\n        // s *= (1 + deltaY / 1000);\r\n\r\n        switch(mouseButtonId) {\r\n            case 1:\r\n            // left: rotation\r\n            eulerX += -deltaY * 0.01;\r\n            eulerY += deltaX * 0.01;\r\n            break;\r\n            case 3:\r\n            // right\r\n            translate[0] += deltaX * 0.001;\r\n            translate[1] += -deltaY * 0.001;\r\n            break;\r\n        }\r\n        \r\n        \r\n        lastMouseY = newY;\r\n        lastMouseX = newX;\r\n    };\r\n    window.onwheel = function(event) {\r\n        translate[2] += -event.deltaY * 0.001;\r\n        // translate[2] *= 1 + (-event.deltaY * 0.01);\r\n    };\r\n\r\n    \r\n    // 2.0\r\n    // var gltfUrl = '../glTFs/glTF_version_2/Duck/glTF/Duck.gltf';\r\n    var gltfUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/DamagedHelmet/glTF/DamagedHelmet.gltf';\r\n\r\n    var glTFLoader = new MinimalGLTFLoader.glTFLoader(gl);\r\n\r\n    var glTFModelCount = 1;\r\n    var scenes = [];\r\n\r\n    gl.enable(gl.CULL_FACE);\r\n    gl.cullFace(gl.BACK);\r\n    gl.frontFace(gl.CCW);\r\n    var isFaceCulling = true;\r\n\r\n\r\n    function setupScene(glTF, replaceScene) {\r\n        var i, len;\r\n\r\n        // update animation list\r\n        for(i = animationSelectionList.options.length - 1 ; i >= 0 ; i--) {\r\n            animationSelectionList.remove(i);\r\n        }\r\n        if (glTF.animations) {\r\n            var option;\r\n            for (i = 0, len = glTF.animations.length; i < len; i++) {\r\n                option = document.createElement(\"option\");\r\n                option.text = glTF.animations[i].name || i;\r\n                animationSelectionList.add(option);\r\n            }    \r\n        }\r\n        curAnimationId = 0;\r\n\r\n        // ----------------\r\n        \r\n        var curGltfScene = glTF.scenes[glTF.defaultScene];\r\n\r\n        var sceneDeltaTranslate = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(curGltfScene.boundingBox.transform[0] * 1.2, 0, 0);\r\n        var tmpVec3Translate = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\r\n\r\n        var newGltfRuntimeScene;\r\n        if (!replaceScene) {\r\n            newGltfRuntimeScene = new Scene(curGltfScene, glTF, scenes.length);\r\n            scenes.push(newGltfRuntimeScene);\r\n        } else {\r\n            newGltfRuntimeScene = scenes[replaceScene.id] = new Scene(curGltfScene, glTF, replaceScene.id);\r\n        }\r\n        \r\n        // for (i = 0, len = glTFModelCount; i < len; i++) {\r\n        //     scenes.push(new Scene(curGltfScene, glTF));\r\n        //     // vec3.scale(tmpVec3Translate, sceneDeltaTranslate, i);\r\n        //     // mat4.fromTranslation(scenes[i].rootTransform, tmpVec3Translate);\r\n        // }\r\n        \r\n\r\n        \r\n        if (scenes.length === 1) {\r\n            // first model, adjust camera\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].identity(modelMatrix);\r\n            \r\n            // center\r\n            s = 1.0 / Math.max( curGltfScene.boundingBox.transform[0], Math.max(curGltfScene.boundingBox.transform[5], curGltfScene.boundingBox.transform[10]) );\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].getTranslation(translate, curGltfScene.boundingBox.transform);\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(translate, translate, -1);\r\n            translate[0] += - 0.5 * curGltfScene.boundingBox.transform[0];\r\n            translate[1] += - 0.5 * curGltfScene.boundingBox.transform[5];\r\n            translate[2] += - 0.5 * curGltfScene.boundingBox.transform[10];\r\n    \r\n            s *= 0.5;\r\n    \r\n            modelMatrix[0] = s;\r\n            modelMatrix[5] = s;\r\n            modelMatrix[10] = s;\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].translate(modelMatrix, modelMatrix, translate);\r\n    \r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].set(translate, 0, 0, -1.5);\r\n            s = 1;\r\n        }\r\n        \r\n\r\n\r\n        // var in loop\r\n        var mesh;\r\n        var primitive;\r\n        var vertexBuffer;\r\n        var indexBuffer;\r\n        var vertexArray;\r\n\r\n        var nid, lenNodes;\r\n        var mid, lenMeshes;\r\n        \r\n        var attribute;\r\n        var material;\r\n\r\n        var image, texture, sampler;\r\n\r\n        var accessor, bufferView;\r\n\r\n        var animation, animationSampler, channel;\r\n\r\n        var skin;\r\n\r\n        // create buffers\r\n        for (i = 0, len = glTF.bufferViews.length; i < len; i++) {\r\n            bufferView = glTF.bufferViews[i];\r\n            bufferView.createBuffer(gl);\r\n            bufferView.bindData(gl);\r\n        }\r\n\r\n        \r\n        // create textures\r\n        if (glTF.textures) {\r\n            for (i = 0, len = glTF.textures.length; i < len; i++) {\r\n                texture = glTF.textures[i];\r\n                texture.createTexture(gl);\r\n            }\r\n        }\r\n\r\n        // create samplers\r\n        if (glTF.samplers) {\r\n            for (i = 0, len = glTF.samplers.length; i < len; i++) {\r\n                sampler = glTF.samplers[i];\r\n                \r\n                sampler.createSampler(gl);\r\n            }\r\n        }\r\n\r\n        if (glTF.skins) {\r\n            // gl.useProgram(programSkinBaseColor.program);\r\n            // gl.uniformBlockBinding(programSkinBaseColor.program, programSkinBaseColor.uniformBlockIndexJointMatrix, 0);\r\n            // gl.useProgram(null);\r\n            for (i = 0, len = glTF.skins.length; i < len; i++) {\r\n                skin = glTF.skins[i];\r\n                \r\n                skin.jointMatrixUniformBuffer = gl.createBuffer();\r\n\r\n                // gl.bindBufferBase(gl.UNIFORM_BUFFER, i, skin.jointMatrixUniformBuffer);\r\n                gl.bindBufferBase(gl.UNIFORM_BUFFER, skin.uniformBlockID, skin.jointMatrixUniformBuffer);\r\n\r\n                gl.bindBuffer(gl.UNIFORM_BUFFER, skin.jointMatrixUniformBuffer);\r\n                gl.bufferData(gl.UNIFORM_BUFFER, skin.jointMatrixUnidormBufferData, gl.DYNAMIC_DRAW);\r\n                gl.bufferSubData(gl.UNIFORM_BUFFER, 0, skin.jointMatrixUnidormBufferData);\r\n                gl.bindBuffer(gl.UNIFORM_BUFFER, null);\r\n            }\r\n        }\r\n\r\n\r\n\r\n        function setupAttribuite(attrib, location) {\r\n            if (attrib !== undefined) {\r\n                // var accessor = glTF.accessors[ attrib ];\r\n                var accessor = attrib;\r\n                var bufferView = accessor.bufferView;\r\n                if (bufferView.target === null) {\r\n                    // console.log('WARNING: the bufferview of this accessor should have a target, or it should represent non buffer data (like animation)');\r\n                    gl.bindBuffer(gl.ARRAY_BUFFER, bufferView.buffer);\r\n                    gl.bufferData(gl.ARRAY_BUFFER, bufferView.data, gl.STATIC_DRAW);\r\n                } else {\r\n                    gl.bindBuffer(bufferView.target, bufferView.buffer);\r\n                }\r\n                accessor.prepareVertexAttrib(location, gl);\r\n                return true;\r\n            }\r\n            return false;\r\n        }\r\n\r\n\r\n        // create vaos & materials shader source setup\r\n        for (mid = 0, lenMeshes = glTF.meshes.length; mid < lenMeshes; mid++) {\r\n            mesh = glTF.meshes[mid];\r\n            // vertexArrayMaps[mid] = [];\r\n\r\n            for (i = 0, len = mesh.primitives.length; i < len; ++i) {\r\n                primitive = mesh.primitives[i];\r\n                primitive.shader = new Shader();\r\n                // WebGL2: create vertexArray\r\n                primitive.vertexArray = vertexArray = gl.createVertexArray();\r\n                gl.bindVertexArray(vertexArray);\r\n                \r\n                \r\n                setupAttribuite(primitive.attributes.POSITION, POSITION_LOCATION);\r\n                setupAttribuite(primitive.attributes.NORMAL, NORMAL_LOCATION);\r\n\r\n                // @tmp, should consider together with material\r\n                setupAttribuite(primitive.attributes.TEXCOORD_0, TEXCOORD_0_LOCATION);\r\n                \r\n\r\n                if (\r\n                    setupAttribuite(primitive.attributes.JOINTS_0, JOINTS_0_LOCATION) &&\r\n                    setupAttribuite(primitive.attributes.WEIGHTS_0, WEIGHTS_0_LOCATION)\r\n                ) {\r\n                    // assume these two attributes always appear together\r\n                    primitive.shader.defineMacro('HAS_SKIN');\r\n                }\r\n                \r\n\r\n                if (\r\n                    setupAttribuite(primitive.attributes.JOINTS_1, JOINTS_1_LOCATION) &&\r\n                    setupAttribuite(primitive.attributes.WEIGHTS_1, WEIGHTS_1_LOCATION)\r\n                ) {\r\n                    // assume these two attributes always appear together\r\n                    primitive.shader.defineMacro('SKIN_VEC8');\r\n                }\r\n\r\n                // indices ( assume use indices )\r\n                if (primitive.indices !== null) {\r\n                    accessor = glTF.accessors[ primitive.indices ];\r\n                    bufferView = accessor.bufferView;\r\n                    if (bufferView.target === null) {\r\n                        // console.log('WARNING: the bufferview of this accessor should have a target, or it should represent non buffer data (like animation)');\r\n                        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferView.buffer);\r\n                        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, bufferView.data, gl.STATIC_DRAW);\r\n                    } else {\r\n                        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferView.buffer);\r\n                    }\r\n                }\r\n                \r\n                \r\n\r\n                gl.bindVertexArray(null);\r\n\r\n                gl.bindBuffer(gl.ARRAY_BUFFER, null);\r\n                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\r\n\r\n\r\n\r\n                // material shader setup\r\n                material = primitive.material;\r\n                if (material) {\r\n                    if (material.pbrMetallicRoughness.baseColorTexture) {\r\n                        primitive.shader.defineMacro('HAS_BASECOLORMAP');\r\n                    }\r\n                    if (material.pbrMetallicRoughness.metallicRoughnessTexture) {\r\n                        primitive.shader.defineMacro('HAS_METALROUGHNESSMAP');\r\n                    }\r\n                    if (material.normalTexture) {\r\n                        primitive.shader.defineMacro('HAS_NORMALMAP');\r\n                    }\r\n                    if (material.occlusionTexture) {\r\n                        primitive.shader.defineMacro('HAS_OCCLUSIONMAP');\r\n                    }\r\n                    if (material.emissiveTexture) {\r\n                        primitive.shader.defineMacro('HAS_EMISSIVEMAP');\r\n                    }\r\n                }\r\n                \r\n\r\n                primitive.shader.compile();\r\n\r\n            }\r\n            \r\n        }\r\n\r\n\r\n        return newGltfRuntimeScene;\r\n    }\r\n\r\n\r\n\r\n\r\n    // -- Render preparation\r\n    gl.enable(gl.DEPTH_TEST);\r\n    gl.depthFunc(gl.LEQUAL);\r\n\r\n\r\n\r\n    var Renderer = Renderer || {};\r\n\r\n    var program = null; // current program object\r\n\r\n    (function() {\r\n        'use strict';\r\n\r\n\r\n        var scale = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\r\n        \r\n        var r = 0.0;\r\n        var rotationSpeedY= 0.01;\r\n        // var rotationSpeedY= 0.0;\r\n\r\n        var perspective = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].perspective(perspective, 0.785, canvas.width / canvas.height, 0.01, 100);\r\n\r\n        var modelView = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n\r\n        var localMV = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n        var localMVP = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n        var localMVNormal = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n\r\n        var VP = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n\r\n        var hasIndices = true;\r\n\r\n        var hasSkin = false;\r\n        var uniformBlockID;     // same for uniform block binding id\r\n\r\n        var curScene;\r\n\r\n\r\n        function activeAndBindTexture(uniformLocation, textureInfo) {\r\n            gl.uniform1i(uniformLocation, textureInfo.index);\r\n            gl.activeTexture(gl.TEXTURE0 + textureInfo.index);\r\n            var texture = curScene.glTF.textures[ textureInfo.index ];\r\n            gl.bindTexture(gl.TEXTURE_2D, texture.texture);\r\n            var sampler;\r\n            if (texture.sampler) {\r\n                sampler = texture.sampler.sampler;\r\n            } else {\r\n                sampler = defaultSampler;\r\n            }\r\n\r\n            gl.bindSampler(textureInfo.index, sampler);\r\n        }\r\n        \r\n\r\n        var defaultColor = [1.0, 1.0, 1.0, 1.0];\r\n        var drawPrimitive = Renderer.drawPrimitive = function(primitive, matrix) {\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].multiply(localMV, modelView, matrix);\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].multiply(localMVP, perspective, localMV);\r\n            // mat4.multiply(localMVP, VP, matrix);\r\n\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].invert(localMVNormal, localMV);\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].transpose(localMVNormal, localMVNormal);\r\n\r\n\r\n            var texture, sampler;\r\n            var baseColor = defaultColor;\r\n\r\n            var shader = primitive.shader;\r\n            var material = primitive.material;\r\n            \r\n\r\n            if (material !== null) {\r\n                var pbrMetallicRoughness = material.pbrMetallicRoughness;\r\n                baseColor = pbrMetallicRoughness.baseColorFactor;\r\n                \r\n                if (primitive.material.doubleSided === isFaceCulling) {\r\n                    isFaceCulling = !primitive.material.doubleSided;\r\n                    if (isFaceCulling) {\r\n                        gl.enable(gl.CULL_FACE);\r\n                    } else {\r\n                        gl.disable(gl.CULL_FACE);\r\n                    }\r\n                }\r\n            }\r\n\r\n            \r\n            \r\n            if (program != primitive.shader.programObject) {\r\n                program = primitive.shader.programObject;\r\n                gl.useProgram(program.program);\r\n            }\r\n\r\n            if (material) {\r\n                // base color texture\r\n                if (shader.hasBaseColorMap()) {\r\n                    activeAndBindTexture(program.uniformLocations.baseColorTexture, pbrMetallicRoughness.baseColorTexture);\r\n                }\r\n\r\n                // normal texture\r\n                if (shader.hasNormalMap()) {\r\n                    activeAndBindTexture(program.uniformLocations.normalTexture, material.normalTexture);\r\n                    gl.uniform1f(program.uniformLocations.normalTextureScale, material.normalTexture.scale);\r\n                }\r\n\r\n                // metallic roughness texture\r\n                if (shader.hasMetalRoughnessMap()) {\r\n                    activeAndBindTexture(program.uniformLocations.metallicRoughnessTexture, pbrMetallicRoughness.metallicRoughnessTexture);\r\n                }\r\n                \r\n                gl.uniform1f(program.uniformLocations.metallicFactor, pbrMetallicRoughness.metallicFactor);\r\n                gl.uniform1f(program.uniformLocations.roughnessFactor, pbrMetallicRoughness.roughnessFactor);\r\n\r\n                // occlusion texture\r\n                if (shader.hasOcclusionMap()) {\r\n                    activeAndBindTexture(program.uniformLocations.occlusionTexture, material.occlusionTexture);\r\n                    gl.uniform1f(program.uniformLocations.occlusionStrength, material.occlusionTexture.strength);\r\n                }\r\n\r\n                // emissive texture\r\n                if (shader.hasEmissiveMap()) {\r\n                    activeAndBindTexture(program.uniformLocations.emissiveTexture, material.emissiveTexture);\r\n                    gl.uniform3fv(program.uniformLocations.emissiveFactor, material.emissiveFactor);\r\n                }\r\n            }\r\n            \r\n            \r\n            // TODO: skin JointMatrix uniform block\r\n            if (shader.hasSkin()) {\r\n                gl.uniformBlockBinding(program.program, program.uniformBlockIndices.JointMatrix, uniformBlockID);\r\n            }\r\n            \r\n\r\n            gl.activeTexture(gl.TEXTURE0 + BRDF_LUT.textureIndex);\r\n            gl.bindTexture(gl.TEXTURE_2D, BRDF_LUT.texture);\r\n\r\n            // console.log( (gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)).toString(16) );            \r\n\r\n            gl.activeTexture(gl.TEXTURE0 + CUBE_MAP.textureIndex);\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, CUBE_MAP.texture);\r\n\r\n            gl.activeTexture(gl.TEXTURE0 + CUBE_MAP.textureIBLDiffuseIndex);\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, CUBE_MAP.textureIBLDiffuse);\r\n\r\n            gl.uniform4fv(program.uniformLocations.baseColorFactor, baseColor);\r\n            \r\n            gl.uniformMatrix4fv(program.uniformLocations.MV, false, localMV);\r\n            gl.uniformMatrix4fv(program.uniformLocations.MVP, false, localMVP);\r\n            gl.uniformMatrix4fv(program.uniformLocations.MVNormal, false, localMVNormal);\r\n            \r\n\r\n            gl.bindVertexArray(primitive.vertexArray);\r\n\r\n            if (primitive.indices !== null) {\r\n                gl.drawElements(primitive.mode, primitive.indicesLength, primitive.indicesComponentType, primitive.indicesOffset);\r\n            } else {\r\n                gl.drawArrays(primitive.mode, primitive.drawArraysOffset, primitive.drawArraysCount);\r\n            }\r\n\r\n\r\n            gl.bindVertexArray(null);\r\n\r\n        }\r\n\r\n        \r\n\r\n        var tmpMat4 = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n        var inverseTransformMat4 = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\r\n        \r\n        // @todo: \r\n        // in a real engine, it is better to simply parse the node tree stucture\r\n        // to compute transform matrices,\r\n        // then sort node array by material and render use a for loop\r\n        // to minimize context switch\r\n        var drawNode = Renderer.drawNode = function (node, nodeID, nodeMatrix, parentModelMatrix) {\r\n            var matrix = nodeMatrix[nodeID];\r\n            \r\n            if (parentModelMatrix !== undefined) {\r\n                __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(matrix, parentModelMatrix, node.matrix);\r\n            } else {\r\n                // from scene root, parent is identity\r\n                __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].copy(matrix, node.matrix);\r\n            }\r\n            // mat4.mul(matrix, parentModelMatrix, node.matrix);\r\n\r\n            hasSkin = false;\r\n            if (node.skin !== null) {\r\n                // mesh node with skin\r\n                hasSkin = true;\r\n                var skin = node.skin;\r\n                uniformBlockID = skin.uniformBlockID;\r\n                var joints = node.skin.joints;\r\n                var jointNode;\r\n\r\n                __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].invert(inverseTransformMat4, matrix);\r\n\r\n\r\n                // @tmp: assume joint nodes are always in the front of the scene node list\r\n                // so that their matrices are ready to use\r\n                for (i = 0, len = joints.length; i < len; i++) {\r\n                    jointNode = joints[i];\r\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(tmpMat4, nodeMatrix[jointNode.nodeID], skin.inverseBindMatrix[i]);\r\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(tmpMat4, inverseTransformMat4, tmpMat4);\r\n\r\n                    // if (skin.skeleton !== null) {\r\n                    //     mat4.mul(tmpMat4, inverseSkeletonRootMat4, tmpMat4);\r\n                    // }\r\n\r\n                    skin.jointMatrixUnidormBufferData.set(tmpMat4, i * 16);\r\n                }\r\n\r\n                gl.bindBuffer(gl.UNIFORM_BUFFER, skin.jointMatrixUniformBuffer);\r\n                gl.bufferSubData(gl.UNIFORM_BUFFER, 0, skin.jointMatrixUnidormBufferData, 0, skin.jointMatrixUnidormBufferData.length);\r\n            }\r\n\r\n\r\n            var i, len;\r\n\r\n            // draw cur node's mesh\r\n            if (node.mesh !== null) {\r\n                // drawMesh(glTF.meshes[node.mesh], matrix);\r\n\r\n                // var mesh = glTF.meshes[node.mesh];\r\n                var mesh = node.mesh;\r\n                for (i = 0, len = mesh.primitives.length; i < len; i++) {\r\n                    // draw primitive\r\n                    drawPrimitive(mesh.primitives[i], matrix);\r\n                }\r\n\r\n                // BOUNDING_BOX.draw(mesh.boundingBox, matrix, modelView, perspective);\r\n                // gl.useProgram(program);\r\n            }\r\n            \r\n            if (node.skin !== null) {\r\n                gl.bindBuffer(gl.UNIFORM_BUFFER, null);\r\n            }\r\n            \r\n\r\n            // draw children\r\n            \r\n            var childNodeID;\r\n            for (i = 0, len = node.children.length; i < len; i++) {\r\n                // childNodeID = node.children[i];\r\n                // drawNode(glTF.nodes[childNodeID], childNodeID, matrix);\r\n                drawNode(node.children[i], node.children[i].nodeID, nodeMatrix, matrix);\r\n            }\r\n        }\r\n\r\n\r\n        function applyAnimation(animation, glTF) {\r\n            var j, lenj;\r\n            var channel, animationSampler, node;\r\n\r\n            for (j = 0, lenj = animation.samplers.length; j < lenj; j++) {\r\n                animation.samplers[j].getValue(timeParameter);\r\n            }\r\n\r\n            for (j = 0, lenj = animation.channels.length; j < lenj; j++) {\r\n                channel = animation.channels[j];\r\n                animationSampler = channel.sampler;\r\n                node = glTF.nodes[channel.target.nodeID];\r\n\r\n                switch (channel.target.path) {\r\n                    case 'rotation':\r\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].copy(node.rotation, animationSampler.curValue);\r\n                    break;\r\n\r\n                    case 'translation':\r\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].copy(node.translation, animationSampler.curValue);\r\n                    break;\r\n\r\n                    case 'scale':\r\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].copy(node.scale, animationSampler.curValue);\r\n                    break;\r\n                }\r\n\r\n                node.updateMatrixFromTRS();\r\n                \r\n            }\r\n        }\r\n\r\n        var drawScene = Renderer.drawScene = function (scene) {\r\n            // animation\r\n            var animation;\r\n            var i, len;\r\n\r\n            var glTF = scene.glTF;\r\n            if (glTF.animations) {\r\n                if (playAllAnimationTogether) {\r\n                    for (i = 0, len = glTF.animations.length; i < len; i++) {\r\n                        animation = glTF.animations[i];\r\n                        applyAnimation(animation, glTF);\r\n                    }\r\n                } else {\r\n                    animation = glTF.animations[curAnimationId];\r\n                    applyAnimation(animation, glTF);\r\n                }\r\n            }\r\n\r\n\r\n            for (var i = 0, len = scene.glTFScene.nodes.length; i < len; i++) {\r\n                drawNode( scene.glTFScene.nodes[i], scene.glTFScene.nodes[i].nodeID, scene.nodeMatrix, scene.rootTransform );\r\n            }\r\n        }\r\n\r\n        var drawSceneBBox = Renderer.drawSceneBBox = function (glTF, scene, bboxType) {\r\n            var node, mesh, bbox;\r\n            // @temp: assume all nodes are in cur scene\r\n            // @potential fix: can label each node's scene at the setup\r\n            var i, len;\r\n            for (i = 0, len = scene.nodeMatrix.length; i < len; i++) {\r\n                node = glTF.nodes[i];\r\n\r\n                if (bboxType == 'bvh') {\r\n                    // bvh\r\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(localMVP, scene.rootTransform, node.bvh.transform);\r\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(localMVP, VP, localMVP);\r\n                    gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\r\n                    gl.drawArrays(gl.LINES, 0, 24);\r\n                }\r\n                else if (node.mesh !== null) {\r\n                    // mesh = glTF.meshes[node.mesh];\r\n                    mesh = node.mesh;\r\n\r\n                    if (bboxType == 'aabb') {\r\n                        // aabb\r\n                        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(localMVP, scene.rootTransform, node.aabb.transform);\r\n                        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(localMVP, VP, localMVP);\r\n                    } else {\r\n                        // obb (assume object node is static)\r\n                        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(localMVP, scene.nodeMatrix[i], mesh.boundingBox.transform);\r\n                        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(localMVP, VP, localMVP);\r\n                    }\r\n\r\n                    gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\r\n                        \r\n                    gl.drawArrays(gl.LINES, 0, 24);\r\n\r\n                }   \r\n            }\r\n\r\n            // // scene bounding box\r\n            // mat4.mul(localMVP, scene.rootTransform, scene.glTFScene.boundingBox.transform);\r\n            // mat4.mul(localMVP, VP, localMVP);\r\n            // gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\r\n            // gl.drawArrays(gl.LINES, 0, 24);\r\n        }\r\n        \r\n\r\n        var timeStampZero = performance.now();\r\n        var timeParameter = 0;\r\n\r\n        // -- Render loop\r\n        // function render() {\r\n        var render = Renderer.render = function(timestamp) {\r\n            var i, len;\r\n            var j, lenj;\r\n            var node;\r\n\r\n\r\n            gl.clearColor(0.0, 0.0, 0.0, 1.0);\r\n            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\r\n\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].set(scale, s, s, s);\r\n            // mat4.identity(modelView);\r\n            // mat4.translate(modelView, modelView, translate);\r\n            // mat4.scale(modelView, modelView, scale);\r\n            // mat4.fromRotationTranslationScale(modelView, identityQ, translate, scale);\r\n            // mat4.mul(modelView, modelView, modelMatrix);\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].identity(modelView);\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].translate(modelView, modelView, translate);\r\n            if (isDisplayRotation) {\r\n                r += rotationSpeedY;\r\n            }\r\n            \r\n\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].rotateX(modelView, modelView, eulerX);\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].rotateY(modelView, modelView, r);\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].scale(modelView, modelView, scale);\r\n            \r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(modelView, modelView, modelMatrix);\r\n\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].rotateY(modelView, modelView, eulerY); \r\n\r\n            \r\n\r\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(VP, perspective, modelView);\r\n\r\n\r\n            for (i = 0, len = scenes.length; i < len; i++) {\r\n                curScene = scenes[i];\r\n\r\n                drawScene(scenes[i]);\r\n            }\r\n\r\n            if (drawBoundingBox) {\r\n                gl.useProgram(BOUNDING_BOX.program);\r\n                gl.bindVertexArray(BOUNDING_BOX.vertexArray);\r\n\r\n                for (i = 0, len = scenes.length; i < len; i++) {\r\n                    drawSceneBBox(scenes[i].glTF, scenes[i], boundingBoxType);\r\n                }\r\n\r\n\r\n                gl.bindVertexArray(null);\r\n            }\r\n\r\n\r\n            // cube map\r\n\r\n            CUBE_MAP.draw(modelView, perspective);\r\n\r\n            program = null;\r\n\r\n            timeParameter = (timestamp - timeStampZero) * 0.001;\r\n            requestAnimationFrame(render);\r\n        }\r\n\r\n    })();\r\n\r\n\r\n    CUBE_MAP.finishLoadingCallback = function() {\r\n        glTFLoader.loadGLTF(gltfUrl, function(glTF) {\r\n            setupScene(glTF);\r\n            Renderer.render();\r\n        });\r\n    };\r\n\r\n    CUBE_MAP.loadAll();\r\n\r\n})();\r\n\n\n/***/ }),\n/* 8 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (immutable) */ __webpack_exports__[\"create\"] = create;\n/* harmony export (immutable) */ __webpack_exports__[\"clone\"] = clone;\n/* harmony export (immutable) */ __webpack_exports__[\"copy\"] = copy;\n/* harmony export (immutable) */ __webpack_exports__[\"identity\"] = identity;\n/* harmony export (immutable) */ __webpack_exports__[\"fromValues\"] = fromValues;\n/* harmony export (immutable) */ __webpack_exports__[\"set\"] = set;\n/* harmony export (immutable) */ __webpack_exports__[\"transpose\"] = transpose;\n/* harmony export (immutable) */ __webpack_exports__[\"invert\"] = invert;\n/* harmony export (immutable) */ __webpack_exports__[\"adjoint\"] = adjoint;\n/* harmony export (immutable) */ __webpack_exports__[\"determinant\"] = determinant;\n/* harmony export (immutable) */ __webpack_exports__[\"multiply\"] = multiply;\n/* harmony export (immutable) */ __webpack_exports__[\"rotate\"] = rotate;\n/* harmony export (immutable) */ __webpack_exports__[\"scale\"] = scale;\n/* harmony export (immutable) */ __webpack_exports__[\"fromRotation\"] = fromRotation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromScaling\"] = fromScaling;\n/* harmony export (immutable) */ __webpack_exports__[\"str\"] = str;\n/* harmony export (immutable) */ __webpack_exports__[\"frob\"] = frob;\n/* harmony export (immutable) */ __webpack_exports__[\"LDU\"] = LDU;\n/* harmony export (immutable) */ __webpack_exports__[\"add\"] = add;\n/* harmony export (immutable) */ __webpack_exports__[\"subtract\"] = subtract;\n/* harmony export (immutable) */ __webpack_exports__[\"exactEquals\"] = exactEquals;\n/* harmony export (immutable) */ __webpack_exports__[\"equals\"] = equals;\n/* harmony export (immutable) */ __webpack_exports__[\"multiplyScalar\"] = multiplyScalar;\n/* harmony export (immutable) */ __webpack_exports__[\"multiplyScalarAndAdd\"] = multiplyScalarAndAdd;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mul\", function() { return mul; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sub\", function() { return sub; });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_js__ = __webpack_require__(0);\n\r\n\r\n/**\r\n * 2x2 Matrix\r\n * @module mat2\r\n */\r\n\r\n/**\r\n * Creates a new identity mat2\r\n *\r\n * @returns {mat2} a new 2x2 matrix\r\n */\r\nfunction create() {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](4);\r\n  if (__WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"] != Float32Array) {\r\n    out[1] = 0;\r\n    out[2] = 0;\r\n  }\r\n  out[0] = 1;\r\n  out[3] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new mat2 initialized with values from an existing matrix\r\n *\r\n * @param {mat2} a matrix to clone\r\n * @returns {mat2} a new 2x2 matrix\r\n */\r\nfunction clone(a) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](4);\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Copy the values from one mat2 to another\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {mat2} a the source matrix\r\n * @returns {mat2} out\r\n */\r\nfunction copy(out, a) {\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set a mat2 to the identity matrix\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @returns {mat2} out\r\n */\r\nfunction identity(out) {\r\n  out[0] = 1;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Create a new mat2 with the given values\r\n *\r\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\r\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\r\n * @param {Number} m10 Component in column 1, row 0 position (index 2)\r\n * @param {Number} m11 Component in column 1, row 1 position (index 3)\r\n * @returns {mat2} out A new 2x2 matrix\r\n */\r\nfunction fromValues(m00, m01, m10, m11) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](4);\r\n  out[0] = m00;\r\n  out[1] = m01;\r\n  out[2] = m10;\r\n  out[3] = m11;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set the components of a mat2 to the given values\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\r\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\r\n * @param {Number} m10 Component in column 1, row 0 position (index 2)\r\n * @param {Number} m11 Component in column 1, row 1 position (index 3)\r\n * @returns {mat2} out\r\n */\r\nfunction set(out, m00, m01, m10, m11) {\r\n  out[0] = m00;\r\n  out[1] = m01;\r\n  out[2] = m10;\r\n  out[3] = m11;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transpose the values of a mat2\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {mat2} a the source matrix\r\n * @returns {mat2} out\r\n */\r\nfunction transpose(out, a) {\r\n  // If we are transposing ourselves we can skip a few steps but have to cache\r\n  // some values\r\n  if (out === a) {\r\n    var a1 = a[1];\r\n    out[1] = a[2];\r\n    out[2] = a1;\r\n  } else {\r\n    out[0] = a[0];\r\n    out[1] = a[2];\r\n    out[2] = a[1];\r\n    out[3] = a[3];\r\n  }\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Inverts a mat2\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {mat2} a the source matrix\r\n * @returns {mat2} out\r\n */\r\nfunction invert(out, a) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3];\r\n\r\n  // Calculate the determinant\r\n  var det = a0 * a3 - a2 * a1;\r\n\r\n  if (!det) {\r\n    return null;\r\n  }\r\n  det = 1.0 / det;\r\n\r\n  out[0] = a3 * det;\r\n  out[1] = -a1 * det;\r\n  out[2] = -a2 * det;\r\n  out[3] = a0 * det;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the adjugate of a mat2\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {mat2} a the source matrix\r\n * @returns {mat2} out\r\n */\r\nfunction adjoint(out, a) {\r\n  // Caching this value is nessecary if out == a\r\n  var a0 = a[0];\r\n  out[0] = a[3];\r\n  out[1] = -a[1];\r\n  out[2] = -a[2];\r\n  out[3] = a0;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the determinant of a mat2\r\n *\r\n * @param {mat2} a the source matrix\r\n * @returns {Number} determinant of a\r\n */\r\nfunction determinant(a) {\r\n  return a[0] * a[3] - a[2] * a[1];\r\n}\r\n\r\n/**\r\n * Multiplies two mat2's\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {mat2} a the first operand\r\n * @param {mat2} b the second operand\r\n * @returns {mat2} out\r\n */\r\nfunction multiply(out, a, b) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3];\r\n  var b0 = b[0],\r\n      b1 = b[1],\r\n      b2 = b[2],\r\n      b3 = b[3];\r\n  out[0] = a0 * b0 + a2 * b1;\r\n  out[1] = a1 * b0 + a3 * b1;\r\n  out[2] = a0 * b2 + a2 * b3;\r\n  out[3] = a1 * b2 + a3 * b3;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a mat2 by the given angle\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {mat2} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat2} out\r\n */\r\nfunction rotate(out, a, rad) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3];\r\n  var s = Math.sin(rad);\r\n  var c = Math.cos(rad);\r\n  out[0] = a0 * c + a2 * s;\r\n  out[1] = a1 * c + a3 * s;\r\n  out[2] = a0 * -s + a2 * c;\r\n  out[3] = a1 * -s + a3 * c;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Scales the mat2 by the dimensions in the given vec2\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {mat2} a the matrix to rotate\r\n * @param {vec2} v the vec2 to scale the matrix by\r\n * @returns {mat2} out\r\n **/\r\nfunction scale(out, a, v) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3];\r\n  var v0 = v[0],\r\n      v1 = v[1];\r\n  out[0] = a0 * v0;\r\n  out[1] = a1 * v0;\r\n  out[2] = a2 * v1;\r\n  out[3] = a3 * v1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a given angle\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat2.identity(dest);\r\n *     mat2.rotate(dest, dest, rad);\r\n *\r\n * @param {mat2} out mat2 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat2} out\r\n */\r\nfunction fromRotation(out, rad) {\r\n  var s = Math.sin(rad);\r\n  var c = Math.cos(rad);\r\n  out[0] = c;\r\n  out[1] = s;\r\n  out[2] = -s;\r\n  out[3] = c;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a vector scaling\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat2.identity(dest);\r\n *     mat2.scale(dest, dest, vec);\r\n *\r\n * @param {mat2} out mat2 receiving operation result\r\n * @param {vec2} v Scaling vector\r\n * @returns {mat2} out\r\n */\r\nfunction fromScaling(out, v) {\r\n  out[0] = v[0];\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = v[1];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns a string representation of a mat2\r\n *\r\n * @param {mat2} a matrix to represent as a string\r\n * @returns {String} string representation of the matrix\r\n */\r\nfunction str(a) {\r\n  return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';\r\n}\r\n\r\n/**\r\n * Returns Frobenius norm of a mat2\r\n *\r\n * @param {mat2} a the matrix to calculate Frobenius norm of\r\n * @returns {Number} Frobenius norm\r\n */\r\nfunction frob(a) {\r\n  return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2));\r\n}\r\n\r\n/**\r\n * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix\r\n * @param {mat2} L the lower triangular matrix\r\n * @param {mat2} D the diagonal matrix\r\n * @param {mat2} U the upper triangular matrix\r\n * @param {mat2} a the input matrix to factorize\r\n */\r\n\r\nfunction LDU(L, D, U, a) {\r\n  L[2] = a[2] / a[0];\r\n  U[0] = a[0];\r\n  U[1] = a[1];\r\n  U[3] = a[3] - L[2] * U[1];\r\n  return [L, D, U];\r\n}\r\n\r\n/**\r\n * Adds two mat2's\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {mat2} a the first operand\r\n * @param {mat2} b the second operand\r\n * @returns {mat2} out\r\n */\r\nfunction add(out, a, b) {\r\n  out[0] = a[0] + b[0];\r\n  out[1] = a[1] + b[1];\r\n  out[2] = a[2] + b[2];\r\n  out[3] = a[3] + b[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Subtracts matrix b from matrix a\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {mat2} a the first operand\r\n * @param {mat2} b the second operand\r\n * @returns {mat2} out\r\n */\r\nfunction subtract(out, a, b) {\r\n  out[0] = a[0] - b[0];\r\n  out[1] = a[1] - b[1];\r\n  out[2] = a[2] - b[2];\r\n  out[3] = a[3] - b[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {mat2} a The first matrix.\r\n * @param {mat2} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\r\nfunction exactEquals(a, b) {\r\n  return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];\r\n}\r\n\r\n/**\r\n * Returns whether or not the matrices have approximately the same elements in the same position.\r\n *\r\n * @param {mat2} a The first matrix.\r\n * @param {mat2} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\r\nfunction equals(a, b) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3];\r\n  var b0 = b[0],\r\n      b1 = b[1],\r\n      b2 = b[2],\r\n      b3 = b[3];\r\n  return Math.abs(a0 - b0) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a3), Math.abs(b3));\r\n}\r\n\r\n/**\r\n * Multiply each element of the matrix by a scalar.\r\n *\r\n * @param {mat2} out the receiving matrix\r\n * @param {mat2} a the matrix to scale\r\n * @param {Number} b amount to scale the matrix's elements by\r\n * @returns {mat2} out\r\n */\r\nfunction multiplyScalar(out, a, b) {\r\n  out[0] = a[0] * b;\r\n  out[1] = a[1] * b;\r\n  out[2] = a[2] * b;\r\n  out[3] = a[3] * b;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two mat2's after multiplying each element of the second operand by a scalar value.\r\n *\r\n * @param {mat2} out the receiving vector\r\n * @param {mat2} a the first operand\r\n * @param {mat2} b the second operand\r\n * @param {Number} scale the amount to scale b's elements by before adding\r\n * @returns {mat2} out\r\n */\r\nfunction multiplyScalarAndAdd(out, a, b, scale) {\r\n  out[0] = a[0] + b[0] * scale;\r\n  out[1] = a[1] + b[1] * scale;\r\n  out[2] = a[2] + b[2] * scale;\r\n  out[3] = a[3] + b[3] * scale;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Alias for {@link mat2.multiply}\r\n * @function\r\n */\r\nvar mul = multiply;\r\n\r\n/**\r\n * Alias for {@link mat2.subtract}\r\n * @function\r\n */\r\nvar sub = subtract;\n\n/***/ }),\n/* 9 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (immutable) */ __webpack_exports__[\"create\"] = create;\n/* harmony export (immutable) */ __webpack_exports__[\"clone\"] = clone;\n/* harmony export (immutable) */ __webpack_exports__[\"copy\"] = copy;\n/* harmony export (immutable) */ __webpack_exports__[\"identity\"] = identity;\n/* harmony export (immutable) */ __webpack_exports__[\"fromValues\"] = fromValues;\n/* harmony export (immutable) */ __webpack_exports__[\"set\"] = set;\n/* harmony export (immutable) */ __webpack_exports__[\"invert\"] = invert;\n/* harmony export (immutable) */ __webpack_exports__[\"determinant\"] = determinant;\n/* harmony export (immutable) */ __webpack_exports__[\"multiply\"] = multiply;\n/* harmony export (immutable) */ __webpack_exports__[\"rotate\"] = rotate;\n/* harmony export (immutable) */ __webpack_exports__[\"scale\"] = scale;\n/* harmony export (immutable) */ __webpack_exports__[\"translate\"] = translate;\n/* harmony export (immutable) */ __webpack_exports__[\"fromRotation\"] = fromRotation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromScaling\"] = fromScaling;\n/* harmony export (immutable) */ __webpack_exports__[\"fromTranslation\"] = fromTranslation;\n/* harmony export (immutable) */ __webpack_exports__[\"str\"] = str;\n/* harmony export (immutable) */ __webpack_exports__[\"frob\"] = frob;\n/* harmony export (immutable) */ __webpack_exports__[\"add\"] = add;\n/* harmony export (immutable) */ __webpack_exports__[\"subtract\"] = subtract;\n/* harmony export (immutable) */ __webpack_exports__[\"multiplyScalar\"] = multiplyScalar;\n/* harmony export (immutable) */ __webpack_exports__[\"multiplyScalarAndAdd\"] = multiplyScalarAndAdd;\n/* harmony export (immutable) */ __webpack_exports__[\"exactEquals\"] = exactEquals;\n/* harmony export (immutable) */ __webpack_exports__[\"equals\"] = equals;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mul\", function() { return mul; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sub\", function() { return sub; });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_js__ = __webpack_require__(0);\n\r\n\r\n/**\r\n * 2x3 Matrix\r\n * @module mat2d\r\n *\r\n * @description\r\n * A mat2d contains six elements defined as:\r\n * <pre>\r\n * [a, c, tx,\r\n *  b, d, ty]\r\n * </pre>\r\n * This is a short form for the 3x3 matrix:\r\n * <pre>\r\n * [a, c, tx,\r\n *  b, d, ty,\r\n *  0, 0, 1]\r\n * </pre>\r\n * The last row is ignored so the array is shorter and operations are faster.\r\n */\r\n\r\n/**\r\n * Creates a new identity mat2d\r\n *\r\n * @returns {mat2d} a new 2x3 matrix\r\n */\r\nfunction create() {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](6);\r\n  if (__WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"] != Float32Array) {\r\n    out[1] = 0;\r\n    out[2] = 0;\r\n    out[4] = 0;\r\n    out[5] = 0;\r\n  }\r\n  out[0] = 1;\r\n  out[3] = 1;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new mat2d initialized with values from an existing matrix\r\n *\r\n * @param {mat2d} a matrix to clone\r\n * @returns {mat2d} a new 2x3 matrix\r\n */\r\nfunction clone(a) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](6);\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  out[4] = a[4];\r\n  out[5] = a[5];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Copy the values from one mat2d to another\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @param {mat2d} a the source matrix\r\n * @returns {mat2d} out\r\n */\r\nfunction copy(out, a) {\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  out[4] = a[4];\r\n  out[5] = a[5];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set a mat2d to the identity matrix\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @returns {mat2d} out\r\n */\r\nfunction identity(out) {\r\n  out[0] = 1;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 1;\r\n  out[4] = 0;\r\n  out[5] = 0;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Create a new mat2d with the given values\r\n *\r\n * @param {Number} a Component A (index 0)\r\n * @param {Number} b Component B (index 1)\r\n * @param {Number} c Component C (index 2)\r\n * @param {Number} d Component D (index 3)\r\n * @param {Number} tx Component TX (index 4)\r\n * @param {Number} ty Component TY (index 5)\r\n * @returns {mat2d} A new mat2d\r\n */\r\nfunction fromValues(a, b, c, d, tx, ty) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](6);\r\n  out[0] = a;\r\n  out[1] = b;\r\n  out[2] = c;\r\n  out[3] = d;\r\n  out[4] = tx;\r\n  out[5] = ty;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set the components of a mat2d to the given values\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @param {Number} a Component A (index 0)\r\n * @param {Number} b Component B (index 1)\r\n * @param {Number} c Component C (index 2)\r\n * @param {Number} d Component D (index 3)\r\n * @param {Number} tx Component TX (index 4)\r\n * @param {Number} ty Component TY (index 5)\r\n * @returns {mat2d} out\r\n */\r\nfunction set(out, a, b, c, d, tx, ty) {\r\n  out[0] = a;\r\n  out[1] = b;\r\n  out[2] = c;\r\n  out[3] = d;\r\n  out[4] = tx;\r\n  out[5] = ty;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Inverts a mat2d\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @param {mat2d} a the source matrix\r\n * @returns {mat2d} out\r\n */\r\nfunction invert(out, a) {\r\n  var aa = a[0],\r\n      ab = a[1],\r\n      ac = a[2],\r\n      ad = a[3];\r\n  var atx = a[4],\r\n      aty = a[5];\r\n\r\n  var det = aa * ad - ab * ac;\r\n  if (!det) {\r\n    return null;\r\n  }\r\n  det = 1.0 / det;\r\n\r\n  out[0] = ad * det;\r\n  out[1] = -ab * det;\r\n  out[2] = -ac * det;\r\n  out[3] = aa * det;\r\n  out[4] = (ac * aty - ad * atx) * det;\r\n  out[5] = (ab * atx - aa * aty) * det;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the determinant of a mat2d\r\n *\r\n * @param {mat2d} a the source matrix\r\n * @returns {Number} determinant of a\r\n */\r\nfunction determinant(a) {\r\n  return a[0] * a[3] - a[1] * a[2];\r\n}\r\n\r\n/**\r\n * Multiplies two mat2d's\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @param {mat2d} a the first operand\r\n * @param {mat2d} b the second operand\r\n * @returns {mat2d} out\r\n */\r\nfunction multiply(out, a, b) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3],\r\n      a4 = a[4],\r\n      a5 = a[5];\r\n  var b0 = b[0],\r\n      b1 = b[1],\r\n      b2 = b[2],\r\n      b3 = b[3],\r\n      b4 = b[4],\r\n      b5 = b[5];\r\n  out[0] = a0 * b0 + a2 * b1;\r\n  out[1] = a1 * b0 + a3 * b1;\r\n  out[2] = a0 * b2 + a2 * b3;\r\n  out[3] = a1 * b2 + a3 * b3;\r\n  out[4] = a0 * b4 + a2 * b5 + a4;\r\n  out[5] = a1 * b4 + a3 * b5 + a5;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a mat2d by the given angle\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @param {mat2d} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat2d} out\r\n */\r\nfunction rotate(out, a, rad) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3],\r\n      a4 = a[4],\r\n      a5 = a[5];\r\n  var s = Math.sin(rad);\r\n  var c = Math.cos(rad);\r\n  out[0] = a0 * c + a2 * s;\r\n  out[1] = a1 * c + a3 * s;\r\n  out[2] = a0 * -s + a2 * c;\r\n  out[3] = a1 * -s + a3 * c;\r\n  out[4] = a4;\r\n  out[5] = a5;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Scales the mat2d by the dimensions in the given vec2\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @param {mat2d} a the matrix to translate\r\n * @param {vec2} v the vec2 to scale the matrix by\r\n * @returns {mat2d} out\r\n **/\r\nfunction scale(out, a, v) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3],\r\n      a4 = a[4],\r\n      a5 = a[5];\r\n  var v0 = v[0],\r\n      v1 = v[1];\r\n  out[0] = a0 * v0;\r\n  out[1] = a1 * v0;\r\n  out[2] = a2 * v1;\r\n  out[3] = a3 * v1;\r\n  out[4] = a4;\r\n  out[5] = a5;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Translates the mat2d by the dimensions in the given vec2\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @param {mat2d} a the matrix to translate\r\n * @param {vec2} v the vec2 to translate the matrix by\r\n * @returns {mat2d} out\r\n **/\r\nfunction translate(out, a, v) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3],\r\n      a4 = a[4],\r\n      a5 = a[5];\r\n  var v0 = v[0],\r\n      v1 = v[1];\r\n  out[0] = a0;\r\n  out[1] = a1;\r\n  out[2] = a2;\r\n  out[3] = a3;\r\n  out[4] = a0 * v0 + a2 * v1 + a4;\r\n  out[5] = a1 * v0 + a3 * v1 + a5;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a given angle\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat2d.identity(dest);\r\n *     mat2d.rotate(dest, dest, rad);\r\n *\r\n * @param {mat2d} out mat2d receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat2d} out\r\n */\r\nfunction fromRotation(out, rad) {\r\n  var s = Math.sin(rad),\r\n      c = Math.cos(rad);\r\n  out[0] = c;\r\n  out[1] = s;\r\n  out[2] = -s;\r\n  out[3] = c;\r\n  out[4] = 0;\r\n  out[5] = 0;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a vector scaling\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat2d.identity(dest);\r\n *     mat2d.scale(dest, dest, vec);\r\n *\r\n * @param {mat2d} out mat2d receiving operation result\r\n * @param {vec2} v Scaling vector\r\n * @returns {mat2d} out\r\n */\r\nfunction fromScaling(out, v) {\r\n  out[0] = v[0];\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = v[1];\r\n  out[4] = 0;\r\n  out[5] = 0;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a matrix from a vector translation\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat2d.identity(dest);\r\n *     mat2d.translate(dest, dest, vec);\r\n *\r\n * @param {mat2d} out mat2d receiving operation result\r\n * @param {vec2} v Translation vector\r\n * @returns {mat2d} out\r\n */\r\nfunction fromTranslation(out, v) {\r\n  out[0] = 1;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 1;\r\n  out[4] = v[0];\r\n  out[5] = v[1];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns a string representation of a mat2d\r\n *\r\n * @param {mat2d} a matrix to represent as a string\r\n * @returns {String} string representation of the matrix\r\n */\r\nfunction str(a) {\r\n  return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ')';\r\n}\r\n\r\n/**\r\n * Returns Frobenius norm of a mat2d\r\n *\r\n * @param {mat2d} a the matrix to calculate Frobenius norm of\r\n * @returns {Number} Frobenius norm\r\n */\r\nfunction frob(a) {\r\n  return Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1);\r\n}\r\n\r\n/**\r\n * Adds two mat2d's\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @param {mat2d} a the first operand\r\n * @param {mat2d} b the second operand\r\n * @returns {mat2d} out\r\n */\r\nfunction add(out, a, b) {\r\n  out[0] = a[0] + b[0];\r\n  out[1] = a[1] + b[1];\r\n  out[2] = a[2] + b[2];\r\n  out[3] = a[3] + b[3];\r\n  out[4] = a[4] + b[4];\r\n  out[5] = a[5] + b[5];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Subtracts matrix b from matrix a\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @param {mat2d} a the first operand\r\n * @param {mat2d} b the second operand\r\n * @returns {mat2d} out\r\n */\r\nfunction subtract(out, a, b) {\r\n  out[0] = a[0] - b[0];\r\n  out[1] = a[1] - b[1];\r\n  out[2] = a[2] - b[2];\r\n  out[3] = a[3] - b[3];\r\n  out[4] = a[4] - b[4];\r\n  out[5] = a[5] - b[5];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Multiply each element of the matrix by a scalar.\r\n *\r\n * @param {mat2d} out the receiving matrix\r\n * @param {mat2d} a the matrix to scale\r\n * @param {Number} b amount to scale the matrix's elements by\r\n * @returns {mat2d} out\r\n */\r\nfunction multiplyScalar(out, a, b) {\r\n  out[0] = a[0] * b;\r\n  out[1] = a[1] * b;\r\n  out[2] = a[2] * b;\r\n  out[3] = a[3] * b;\r\n  out[4] = a[4] * b;\r\n  out[5] = a[5] * b;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two mat2d's after multiplying each element of the second operand by a scalar value.\r\n *\r\n * @param {mat2d} out the receiving vector\r\n * @param {mat2d} a the first operand\r\n * @param {mat2d} b the second operand\r\n * @param {Number} scale the amount to scale b's elements by before adding\r\n * @returns {mat2d} out\r\n */\r\nfunction multiplyScalarAndAdd(out, a, b, scale) {\r\n  out[0] = a[0] + b[0] * scale;\r\n  out[1] = a[1] + b[1] * scale;\r\n  out[2] = a[2] + b[2] * scale;\r\n  out[3] = a[3] + b[3] * scale;\r\n  out[4] = a[4] + b[4] * scale;\r\n  out[5] = a[5] + b[5] * scale;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {mat2d} a The first matrix.\r\n * @param {mat2d} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\r\nfunction exactEquals(a, b) {\r\n  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];\r\n}\r\n\r\n/**\r\n * Returns whether or not the matrices have approximately the same elements in the same position.\r\n *\r\n * @param {mat2d} a The first matrix.\r\n * @param {mat2d} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\r\nfunction equals(a, b) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3],\r\n      a4 = a[4],\r\n      a5 = a[5];\r\n  var b0 = b[0],\r\n      b1 = b[1],\r\n      b2 = b[2],\r\n      b3 = b[3],\r\n      b4 = b[4],\r\n      b5 = b[5];\r\n  return Math.abs(a0 - b0) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a5), Math.abs(b5));\r\n}\r\n\r\n/**\r\n * Alias for {@link mat2d.multiply}\r\n * @function\r\n */\r\nvar mul = multiply;\r\n\r\n/**\r\n * Alias for {@link mat2d.subtract}\r\n * @function\r\n */\r\nvar sub = subtract;\n\n/***/ }),\n/* 10 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (immutable) */ __webpack_exports__[\"create\"] = create;\n/* harmony export (immutable) */ __webpack_exports__[\"clone\"] = clone;\n/* harmony export (immutable) */ __webpack_exports__[\"fromValues\"] = fromValues;\n/* harmony export (immutable) */ __webpack_exports__[\"fromRotationTranslationValues\"] = fromRotationTranslationValues;\n/* harmony export (immutable) */ __webpack_exports__[\"fromRotationTranslation\"] = fromRotationTranslation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromTranslation\"] = fromTranslation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromRotation\"] = fromRotation;\n/* harmony export (immutable) */ __webpack_exports__[\"fromMat4\"] = fromMat4;\n/* harmony export (immutable) */ __webpack_exports__[\"copy\"] = copy;\n/* harmony export (immutable) */ __webpack_exports__[\"identity\"] = identity;\n/* harmony export (immutable) */ __webpack_exports__[\"set\"] = set;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getReal\", function() { return getReal; });\n/* harmony export (immutable) */ __webpack_exports__[\"getDual\"] = getDual;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"setReal\", function() { return setReal; });\n/* harmony export (immutable) */ __webpack_exports__[\"setDual\"] = setDual;\n/* harmony export (immutable) */ __webpack_exports__[\"getTranslation\"] = getTranslation;\n/* harmony export (immutable) */ __webpack_exports__[\"translate\"] = translate;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateX\"] = rotateX;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateY\"] = rotateY;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateZ\"] = rotateZ;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateByQuatAppend\"] = rotateByQuatAppend;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateByQuatPrepend\"] = rotateByQuatPrepend;\n/* harmony export (immutable) */ __webpack_exports__[\"rotateAroundAxis\"] = rotateAroundAxis;\n/* harmony export (immutable) */ __webpack_exports__[\"add\"] = add;\n/* harmony export (immutable) */ __webpack_exports__[\"multiply\"] = multiply;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mul\", function() { return mul; });\n/* harmony export (immutable) */ __webpack_exports__[\"scale\"] = scale;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"dot\", function() { return dot; });\n/* harmony export (immutable) */ __webpack_exports__[\"lerp\"] = lerp;\n/* harmony export (immutable) */ __webpack_exports__[\"invert\"] = invert;\n/* harmony export (immutable) */ __webpack_exports__[\"conjugate\"] = conjugate;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"length\", function() { return length; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"len\", function() { return len; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"squaredLength\", function() { return squaredLength; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sqrLen\", function() { return sqrLen; });\n/* harmony export (immutable) */ __webpack_exports__[\"normalize\"] = normalize;\n/* harmony export (immutable) */ __webpack_exports__[\"str\"] = str;\n/* harmony export (immutable) */ __webpack_exports__[\"exactEquals\"] = exactEquals;\n/* harmony export (immutable) */ __webpack_exports__[\"equals\"] = equals;\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_js__ = __webpack_require__(0);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__quat_js__ = __webpack_require__(4);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__mat4_js__ = __webpack_require__(3);\n\r\n\r\n\r\n\r\n/**\r\n * Dual Quaternion<br>\r\n * Format: [real, dual]<br>\r\n * Quaternion format: XYZW<br>\r\n * Make sure to have normalized dual quaternions, otherwise the functions may not work as intended.<br>\r\n * @module quat2\r\n */\r\n\r\n/**\r\n * Creates a new identity dual quat\r\n *\r\n * @returns {quat2} a new dual quaternion [real -> rotation, dual -> translation]\r\n */\r\nfunction create() {\r\n  var dq = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](8);\r\n  if (__WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"] != Float32Array) {\r\n    dq[0] = 0;\r\n    dq[1] = 0;\r\n    dq[2] = 0;\r\n    dq[4] = 0;\r\n    dq[5] = 0;\r\n    dq[6] = 0;\r\n    dq[7] = 0;\r\n  }\r\n  dq[3] = 1;\r\n  return dq;\r\n}\r\n\r\n/**\r\n * Creates a new quat initialized with values from an existing quaternion\r\n *\r\n * @param {quat2} a dual quaternion to clone\r\n * @returns {quat2} new dual quaternion\r\n * @function\r\n */\r\nfunction clone(a) {\r\n  var dq = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](8);\r\n  dq[0] = a[0];\r\n  dq[1] = a[1];\r\n  dq[2] = a[2];\r\n  dq[3] = a[3];\r\n  dq[4] = a[4];\r\n  dq[5] = a[5];\r\n  dq[6] = a[6];\r\n  dq[7] = a[7];\r\n  return dq;\r\n}\r\n\r\n/**\r\n * Creates a new dual quat initialized with the given values\r\n *\r\n * @param {Number} x1 X component\r\n * @param {Number} y1 Y component\r\n * @param {Number} z1 Z component\r\n * @param {Number} w1 W component\r\n * @param {Number} x2 X component\r\n * @param {Number} y2 Y component\r\n * @param {Number} z2 Z component\r\n * @param {Number} w2 W component\r\n * @returns {quat2} new dual quaternion\r\n * @function\r\n */\r\nfunction fromValues(x1, y1, z1, w1, x2, y2, z2, w2) {\r\n  var dq = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](8);\r\n  dq[0] = x1;\r\n  dq[1] = y1;\r\n  dq[2] = z1;\r\n  dq[3] = w1;\r\n  dq[4] = x2;\r\n  dq[5] = y2;\r\n  dq[6] = z2;\r\n  dq[7] = w2;\r\n  return dq;\r\n}\r\n\r\n/**\r\n * Creates a new dual quat from the given values (quat and translation)\r\n *\r\n * @param {Number} x1 X component\r\n * @param {Number} y1 Y component\r\n * @param {Number} z1 Z component\r\n * @param {Number} w1 W component\r\n * @param {Number} x2 X component (translation)\r\n * @param {Number} y2 Y component (translation)\r\n * @param {Number} z2 Z component (translation)\r\n * @returns {quat2} new dual quaternion\r\n * @function\r\n */\r\nfunction fromRotationTranslationValues(x1, y1, z1, w1, x2, y2, z2) {\r\n  var dq = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](8);\r\n  dq[0] = x1;\r\n  dq[1] = y1;\r\n  dq[2] = z1;\r\n  dq[3] = w1;\r\n  var ax = x2 * 0.5,\r\n      ay = y2 * 0.5,\r\n      az = z2 * 0.5;\r\n  dq[4] = ax * w1 + ay * z1 - az * y1;\r\n  dq[5] = ay * w1 + az * x1 - ax * z1;\r\n  dq[6] = az * w1 + ax * y1 - ay * x1;\r\n  dq[7] = -ax * x1 - ay * y1 - az * z1;\r\n  return dq;\r\n}\r\n\r\n/**\r\n * Creates a dual quat from a quaternion and a translation\r\n *\r\n * @param {quat2} dual quaternion receiving operation result\r\n * @param {quat} q quaternion\r\n * @param {vec3} t tranlation vector\r\n * @returns {quat2} dual quaternion receiving operation result\r\n * @function\r\n */\r\nfunction fromRotationTranslation(out, q, t) {\r\n  var ax = t[0] * 0.5,\r\n      ay = t[1] * 0.5,\r\n      az = t[2] * 0.5,\r\n      bx = q[0],\r\n      by = q[1],\r\n      bz = q[2],\r\n      bw = q[3];\r\n  out[0] = bx;\r\n  out[1] = by;\r\n  out[2] = bz;\r\n  out[3] = bw;\r\n  out[4] = ax * bw + ay * bz - az * by;\r\n  out[5] = ay * bw + az * bx - ax * bz;\r\n  out[6] = az * bw + ax * by - ay * bx;\r\n  out[7] = -ax * bx - ay * by - az * bz;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a dual quat from a translation\r\n *\r\n * @param {quat2} dual quaternion receiving operation result\r\n * @param {vec3} t translation vector\r\n * @returns {quat2} dual quaternion receiving operation result\r\n * @function\r\n */\r\nfunction fromTranslation(out, t) {\r\n  out[0] = 0;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 1;\r\n  out[4] = t[0] * 0.5;\r\n  out[5] = t[1] * 0.5;\r\n  out[6] = t[2] * 0.5;\r\n  out[7] = 0;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a dual quat from a quaternion\r\n *\r\n * @param {quat2} dual quaternion receiving operation result\r\n * @param {quat} q the quaternion\r\n * @returns {quat2} dual quaternion receiving operation result\r\n * @function\r\n */\r\nfunction fromRotation(out, q) {\r\n  out[0] = q[0];\r\n  out[1] = q[1];\r\n  out[2] = q[2];\r\n  out[3] = q[3];\r\n  out[4] = 0;\r\n  out[5] = 0;\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new dual quat from a matrix (4x4)\r\n *\r\n * @param {quat2} out the dual quaternion\r\n * @param {mat4} a the matrix\r\n * @returns {quat2} dual quat receiving operation result\r\n * @function\r\n */\r\nfunction fromMat4(out, a) {\r\n  //TODO Optimize this\r\n  var outer = __WEBPACK_IMPORTED_MODULE_1__quat_js__[\"create\"]();\r\n  __WEBPACK_IMPORTED_MODULE_2__mat4_js__[\"getRotation\"](outer, a);\r\n  var t = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](3);\r\n  __WEBPACK_IMPORTED_MODULE_2__mat4_js__[\"getTranslation\"](t, a);\r\n  fromRotationTranslation(out, outer, t);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Copy the values from one dual quat to another\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a the source dual quaternion\r\n * @returns {quat2} out\r\n * @function\r\n */\r\nfunction copy(out, a) {\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  out[2] = a[2];\r\n  out[3] = a[3];\r\n  out[4] = a[4];\r\n  out[5] = a[5];\r\n  out[6] = a[6];\r\n  out[7] = a[7];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set a dual quat to the identity dual quaternion\r\n *\r\n * @param {quat2} out the receiving quaternion\r\n * @returns {quat2} out\r\n */\r\nfunction identity(out) {\r\n  out[0] = 0;\r\n  out[1] = 0;\r\n  out[2] = 0;\r\n  out[3] = 1;\r\n  out[4] = 0;\r\n  out[5] = 0;\r\n  out[6] = 0;\r\n  out[7] = 0;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set the components of a dual quat to the given values\r\n *\r\n * @param {quat2} out the receiving quaternion\r\n * @param {Number} x1 X component\r\n * @param {Number} y1 Y component\r\n * @param {Number} z1 Z component\r\n * @param {Number} w1 W component\r\n * @param {Number} x2 X component\r\n * @param {Number} y2 Y component\r\n * @param {Number} z2 Z component\r\n * @param {Number} w2 W component\r\n * @returns {quat2} out\r\n * @function\r\n */\r\nfunction set(out, x1, y1, z1, w1, x2, y2, z2, w2) {\r\n  out[0] = x1;\r\n  out[1] = y1;\r\n  out[2] = z1;\r\n  out[3] = w1;\r\n\r\n  out[4] = x2;\r\n  out[5] = y2;\r\n  out[6] = z2;\r\n  out[7] = w2;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Gets the real part of a dual quat\r\n * @param  {quat} out real part\r\n * @param  {quat2} a Dual Quaternion\r\n * @return {quat} real part\r\n */\r\nvar getReal = __WEBPACK_IMPORTED_MODULE_1__quat_js__[\"copy\"];\r\n\r\n/**\r\n * Gets the dual part of a dual quat\r\n * @param  {quat} out dual part\r\n * @param  {quat2} a Dual Quaternion\r\n * @return {quat} dual part\r\n */\r\nfunction getDual(out, a) {\r\n  out[0] = a[4];\r\n  out[1] = a[5];\r\n  out[2] = a[6];\r\n  out[3] = a[7];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set the real component of a dual quat to the given quaternion\r\n *\r\n * @param {quat2} out the receiving quaternion\r\n * @param {quat} q a quaternion representing the real part\r\n * @returns {quat2} out\r\n * @function\r\n */\r\nvar setReal = __WEBPACK_IMPORTED_MODULE_1__quat_js__[\"copy\"];\r\n\r\n/**\r\n * Set the dual component of a dual quat to the given quaternion\r\n *\r\n * @param {quat2} out the receiving quaternion\r\n * @param {quat} q a quaternion representing the dual part\r\n * @returns {quat2} out\r\n * @function\r\n */\r\nfunction setDual(out, q) {\r\n  out[4] = q[0];\r\n  out[5] = q[1];\r\n  out[6] = q[2];\r\n  out[7] = q[3];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Gets the translation of a normalized dual quat\r\n * @param  {vec3} out translation\r\n * @param  {quat2} a Dual Quaternion to be decomposed\r\n * @return {vec3} translation\r\n */\r\nfunction getTranslation(out, a) {\r\n  var ax = a[4],\r\n      ay = a[5],\r\n      az = a[6],\r\n      aw = a[7],\r\n      bx = -a[0],\r\n      by = -a[1],\r\n      bz = -a[2],\r\n      bw = a[3];\r\n  out[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;\r\n  out[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;\r\n  out[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Translates a dual quat by the given vector\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a the dual quaternion to translate\r\n * @param {vec3} v vector to translate by\r\n * @returns {quat2} out\r\n */\r\nfunction translate(out, a, v) {\r\n  var ax1 = a[0],\r\n      ay1 = a[1],\r\n      az1 = a[2],\r\n      aw1 = a[3],\r\n      bx1 = v[0] * 0.5,\r\n      by1 = v[1] * 0.5,\r\n      bz1 = v[2] * 0.5,\r\n      ax2 = a[4],\r\n      ay2 = a[5],\r\n      az2 = a[6],\r\n      aw2 = a[7];\r\n  out[0] = ax1;\r\n  out[1] = ay1;\r\n  out[2] = az1;\r\n  out[3] = aw1;\r\n  out[4] = aw1 * bx1 + ay1 * bz1 - az1 * by1 + ax2;\r\n  out[5] = aw1 * by1 + az1 * bx1 - ax1 * bz1 + ay2;\r\n  out[6] = aw1 * bz1 + ax1 * by1 - ay1 * bx1 + az2;\r\n  out[7] = -ax1 * bx1 - ay1 * by1 - az1 * bz1 + aw2;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a dual quat around the X axis\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a the dual quaternion to rotate\r\n * @param {number} rad how far should the rotation be\r\n * @returns {quat2} out\r\n */\r\nfunction rotateX(out, a, rad) {\r\n  var bx = -a[0],\r\n      by = -a[1],\r\n      bz = -a[2],\r\n      bw = a[3],\r\n      ax = a[4],\r\n      ay = a[5],\r\n      az = a[6],\r\n      aw = a[7],\r\n      ax1 = ax * bw + aw * bx + ay * bz - az * by,\r\n      ay1 = ay * bw + aw * by + az * bx - ax * bz,\r\n      az1 = az * bw + aw * bz + ax * by - ay * bx,\r\n      aw1 = aw * bw - ax * bx - ay * by - az * bz;\r\n  __WEBPACK_IMPORTED_MODULE_1__quat_js__[\"rotateX\"](out, a, rad);\r\n  bx = out[0];\r\n  by = out[1];\r\n  bz = out[2];\r\n  bw = out[3];\r\n  out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;\r\n  out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;\r\n  out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;\r\n  out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a dual quat around the Y axis\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a the dual quaternion to rotate\r\n * @param {number} rad how far should the rotation be\r\n * @returns {quat2} out\r\n */\r\nfunction rotateY(out, a, rad) {\r\n  var bx = -a[0],\r\n      by = -a[1],\r\n      bz = -a[2],\r\n      bw = a[3],\r\n      ax = a[4],\r\n      ay = a[5],\r\n      az = a[6],\r\n      aw = a[7],\r\n      ax1 = ax * bw + aw * bx + ay * bz - az * by,\r\n      ay1 = ay * bw + aw * by + az * bx - ax * bz,\r\n      az1 = az * bw + aw * bz + ax * by - ay * bx,\r\n      aw1 = aw * bw - ax * bx - ay * by - az * bz;\r\n  __WEBPACK_IMPORTED_MODULE_1__quat_js__[\"rotateY\"](out, a, rad);\r\n  bx = out[0];\r\n  by = out[1];\r\n  bz = out[2];\r\n  bw = out[3];\r\n  out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;\r\n  out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;\r\n  out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;\r\n  out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a dual quat around the Z axis\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a the dual quaternion to rotate\r\n * @param {number} rad how far should the rotation be\r\n * @returns {quat2} out\r\n */\r\nfunction rotateZ(out, a, rad) {\r\n  var bx = -a[0],\r\n      by = -a[1],\r\n      bz = -a[2],\r\n      bw = a[3],\r\n      ax = a[4],\r\n      ay = a[5],\r\n      az = a[6],\r\n      aw = a[7],\r\n      ax1 = ax * bw + aw * bx + ay * bz - az * by,\r\n      ay1 = ay * bw + aw * by + az * bx - ax * bz,\r\n      az1 = az * bw + aw * bz + ax * by - ay * bx,\r\n      aw1 = aw * bw - ax * bx - ay * by - az * bz;\r\n  __WEBPACK_IMPORTED_MODULE_1__quat_js__[\"rotateZ\"](out, a, rad);\r\n  bx = out[0];\r\n  by = out[1];\r\n  bz = out[2];\r\n  bw = out[3];\r\n  out[4] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;\r\n  out[5] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;\r\n  out[6] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;\r\n  out[7] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a dual quat by a given quaternion (a * q)\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a the dual quaternion to rotate\r\n * @param {quat} q quaternion to rotate by\r\n * @returns {quat2} out\r\n */\r\nfunction rotateByQuatAppend(out, a, q) {\r\n  var qx = q[0],\r\n      qy = q[1],\r\n      qz = q[2],\r\n      qw = q[3],\r\n      ax = a[0],\r\n      ay = a[1],\r\n      az = a[2],\r\n      aw = a[3];\r\n\r\n  out[0] = ax * qw + aw * qx + ay * qz - az * qy;\r\n  out[1] = ay * qw + aw * qy + az * qx - ax * qz;\r\n  out[2] = az * qw + aw * qz + ax * qy - ay * qx;\r\n  out[3] = aw * qw - ax * qx - ay * qy - az * qz;\r\n  ax = a[4];\r\n  ay = a[5];\r\n  az = a[6];\r\n  aw = a[7];\r\n  out[4] = ax * qw + aw * qx + ay * qz - az * qy;\r\n  out[5] = ay * qw + aw * qy + az * qx - ax * qz;\r\n  out[6] = az * qw + aw * qz + ax * qy - ay * qx;\r\n  out[7] = aw * qw - ax * qx - ay * qy - az * qz;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a dual quat by a given quaternion (q * a)\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat} q quaternion to rotate by\r\n * @param {quat2} a the dual quaternion to rotate\r\n * @returns {quat2} out\r\n */\r\nfunction rotateByQuatPrepend(out, q, a) {\r\n  var qx = q[0],\r\n      qy = q[1],\r\n      qz = q[2],\r\n      qw = q[3],\r\n      bx = a[0],\r\n      by = a[1],\r\n      bz = a[2],\r\n      bw = a[3];\r\n\r\n  out[0] = qx * bw + qw * bx + qy * bz - qz * by;\r\n  out[1] = qy * bw + qw * by + qz * bx - qx * bz;\r\n  out[2] = qz * bw + qw * bz + qx * by - qy * bx;\r\n  out[3] = qw * bw - qx * bx - qy * by - qz * bz;\r\n  bx = a[4];\r\n  by = a[5];\r\n  bz = a[6];\r\n  bw = a[7];\r\n  out[4] = qx * bw + qw * bx + qy * bz - qz * by;\r\n  out[5] = qy * bw + qw * by + qz * bx - qx * bz;\r\n  out[6] = qz * bw + qw * bz + qx * by - qy * bx;\r\n  out[7] = qw * bw - qx * bx - qy * by - qz * bz;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotates a dual quat around a given axis. Does the normalisation automatically\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a the dual quaternion to rotate\r\n * @param {vec3} axis the axis to rotate around\r\n * @param {Number} rad how far the rotation should be\r\n * @returns {quat2} out\r\n */\r\nfunction rotateAroundAxis(out, a, axis, rad) {\r\n  //Special case for rad = 0\r\n  if (Math.abs(rad) < __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"]) {\r\n    return copy(out, a);\r\n  }\r\n  var axisLength = Math.sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);\r\n\r\n  rad = rad * 0.5;\r\n  var s = Math.sin(rad);\r\n  var bx = s * axis[0] / axisLength;\r\n  var by = s * axis[1] / axisLength;\r\n  var bz = s * axis[2] / axisLength;\r\n  var bw = Math.cos(rad);\r\n\r\n  var ax1 = a[0],\r\n      ay1 = a[1],\r\n      az1 = a[2],\r\n      aw1 = a[3];\r\n  out[0] = ax1 * bw + aw1 * bx + ay1 * bz - az1 * by;\r\n  out[1] = ay1 * bw + aw1 * by + az1 * bx - ax1 * bz;\r\n  out[2] = az1 * bw + aw1 * bz + ax1 * by - ay1 * bx;\r\n  out[3] = aw1 * bw - ax1 * bx - ay1 * by - az1 * bz;\r\n\r\n  var ax = a[4],\r\n      ay = a[5],\r\n      az = a[6],\r\n      aw = a[7];\r\n  out[4] = ax * bw + aw * bx + ay * bz - az * by;\r\n  out[5] = ay * bw + aw * by + az * bx - ax * bz;\r\n  out[6] = az * bw + aw * bz + ax * by - ay * bx;\r\n  out[7] = aw * bw - ax * bx - ay * by - az * bz;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two dual quat's\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a the first operand\r\n * @param {quat2} b the second operand\r\n * @returns {quat2} out\r\n * @function\r\n */\r\nfunction add(out, a, b) {\r\n  out[0] = a[0] + b[0];\r\n  out[1] = a[1] + b[1];\r\n  out[2] = a[2] + b[2];\r\n  out[3] = a[3] + b[3];\r\n  out[4] = a[4] + b[4];\r\n  out[5] = a[5] + b[5];\r\n  out[6] = a[6] + b[6];\r\n  out[7] = a[7] + b[7];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Multiplies two dual quat's\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a the first operand\r\n * @param {quat2} b the second operand\r\n * @returns {quat2} out\r\n */\r\nfunction multiply(out, a, b) {\r\n  var ax0 = a[0],\r\n      ay0 = a[1],\r\n      az0 = a[2],\r\n      aw0 = a[3],\r\n      bx1 = b[4],\r\n      by1 = b[5],\r\n      bz1 = b[6],\r\n      bw1 = b[7],\r\n      ax1 = a[4],\r\n      ay1 = a[5],\r\n      az1 = a[6],\r\n      aw1 = a[7],\r\n      bx0 = b[0],\r\n      by0 = b[1],\r\n      bz0 = b[2],\r\n      bw0 = b[3];\r\n  out[0] = ax0 * bw0 + aw0 * bx0 + ay0 * bz0 - az0 * by0;\r\n  out[1] = ay0 * bw0 + aw0 * by0 + az0 * bx0 - ax0 * bz0;\r\n  out[2] = az0 * bw0 + aw0 * bz0 + ax0 * by0 - ay0 * bx0;\r\n  out[3] = aw0 * bw0 - ax0 * bx0 - ay0 * by0 - az0 * bz0;\r\n  out[4] = ax0 * bw1 + aw0 * bx1 + ay0 * bz1 - az0 * by1 + ax1 * bw0 + aw1 * bx0 + ay1 * bz0 - az1 * by0;\r\n  out[5] = ay0 * bw1 + aw0 * by1 + az0 * bx1 - ax0 * bz1 + ay1 * bw0 + aw1 * by0 + az1 * bx0 - ax1 * bz0;\r\n  out[6] = az0 * bw1 + aw0 * bz1 + ax0 * by1 - ay0 * bx1 + az1 * bw0 + aw1 * bz0 + ax1 * by0 - ay1 * bx0;\r\n  out[7] = aw0 * bw1 - ax0 * bx1 - ay0 * by1 - az0 * bz1 + aw1 * bw0 - ax1 * bx0 - ay1 * by0 - az1 * bz0;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Alias for {@link quat2.multiply}\r\n * @function\r\n */\r\nvar mul = multiply;\r\n\r\n/**\r\n * Scales a dual quat by a scalar number\r\n *\r\n * @param {quat2} out the receiving dual quat\r\n * @param {quat2} a the dual quat to scale\r\n * @param {Number} b amount to scale the dual quat by\r\n * @returns {quat2} out\r\n * @function\r\n */\r\nfunction scale(out, a, b) {\r\n  out[0] = a[0] * b;\r\n  out[1] = a[1] * b;\r\n  out[2] = a[2] * b;\r\n  out[3] = a[3] * b;\r\n  out[4] = a[4] * b;\r\n  out[5] = a[5] * b;\r\n  out[6] = a[6] * b;\r\n  out[7] = a[7] * b;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the dot product of two dual quat's (The dot product of the real parts)\r\n *\r\n * @param {quat2} a the first operand\r\n * @param {quat2} b the second operand\r\n * @returns {Number} dot product of a and b\r\n * @function\r\n */\r\nvar dot = __WEBPACK_IMPORTED_MODULE_1__quat_js__[\"dot\"];\r\n\r\n/**\r\n * Performs a linear interpolation between two dual quats's\r\n * NOTE: The resulting dual quaternions won't always be normalized (The error is most noticeable when t = 0.5)\r\n *\r\n * @param {quat2} out the receiving dual quat\r\n * @param {quat2} a the first operand\r\n * @param {quat2} b the second operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {quat2} out\r\n */\r\nfunction lerp(out, a, b, t) {\r\n  var mt = 1 - t;\r\n  if (dot(a, b) < 0) t = -t;\r\n\r\n  out[0] = a[0] * mt + b[0] * t;\r\n  out[1] = a[1] * mt + b[1] * t;\r\n  out[2] = a[2] * mt + b[2] * t;\r\n  out[3] = a[3] * mt + b[3] * t;\r\n  out[4] = a[4] * mt + b[4] * t;\r\n  out[5] = a[5] * mt + b[5] * t;\r\n  out[6] = a[6] * mt + b[6] * t;\r\n  out[7] = a[7] * mt + b[7] * t;\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the inverse of a dual quat. If they are normalized, conjugate is cheaper\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a dual quat to calculate inverse of\r\n * @returns {quat2} out\r\n */\r\nfunction invert(out, a) {\r\n  var sqlen = squaredLength(a);\r\n  out[0] = -a[0] / sqlen;\r\n  out[1] = -a[1] / sqlen;\r\n  out[2] = -a[2] / sqlen;\r\n  out[3] = a[3] / sqlen;\r\n  out[4] = -a[4] / sqlen;\r\n  out[5] = -a[5] / sqlen;\r\n  out[6] = -a[6] / sqlen;\r\n  out[7] = a[7] / sqlen;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the conjugate of a dual quat\r\n * If the dual quaternion is normalized, this function is faster than quat2.inverse and produces the same result.\r\n *\r\n * @param {quat2} out the receiving quaternion\r\n * @param {quat2} a quat to calculate conjugate of\r\n * @returns {quat2} out\r\n */\r\nfunction conjugate(out, a) {\r\n  out[0] = -a[0];\r\n  out[1] = -a[1];\r\n  out[2] = -a[2];\r\n  out[3] = a[3];\r\n  out[4] = -a[4];\r\n  out[5] = -a[5];\r\n  out[6] = -a[6];\r\n  out[7] = a[7];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the length of a dual quat\r\n *\r\n * @param {quat2} a dual quat to calculate length of\r\n * @returns {Number} length of a\r\n * @function\r\n */\r\nvar length = __WEBPACK_IMPORTED_MODULE_1__quat_js__[\"length\"];\r\n\r\n/**\r\n * Alias for {@link quat2.length}\r\n * @function\r\n */\r\nvar len = length;\r\n\r\n/**\r\n * Calculates the squared length of a dual quat\r\n *\r\n * @param {quat2} a dual quat to calculate squared length of\r\n * @returns {Number} squared length of a\r\n * @function\r\n */\r\nvar squaredLength = __WEBPACK_IMPORTED_MODULE_1__quat_js__[\"squaredLength\"];\r\n\r\n/**\r\n * Alias for {@link quat2.squaredLength}\r\n * @function\r\n */\r\nvar sqrLen = squaredLength;\r\n\r\n/**\r\n * Normalize a dual quat\r\n *\r\n * @param {quat2} out the receiving dual quaternion\r\n * @param {quat2} a dual quaternion to normalize\r\n * @returns {quat2} out\r\n * @function\r\n */\r\nfunction normalize(out, a) {\r\n  var magnitude = squaredLength(a);\r\n  if (magnitude > 0) {\r\n    magnitude = Math.sqrt(magnitude);\r\n\r\n    var a0 = a[0] / magnitude;\r\n    var a1 = a[1] / magnitude;\r\n    var a2 = a[2] / magnitude;\r\n    var a3 = a[3] / magnitude;\r\n\r\n    var b0 = a[4];\r\n    var b1 = a[5];\r\n    var b2 = a[6];\r\n    var b3 = a[7];\r\n\r\n    var a_dot_b = a0 * b0 + a1 * b1 + a2 * b2 + a3 * b3;\r\n\r\n    out[0] = a0;\r\n    out[1] = a1;\r\n    out[2] = a2;\r\n    out[3] = a3;\r\n\r\n    out[4] = (b0 - a0 * a_dot_b) / magnitude;\r\n    out[5] = (b1 - a1 * a_dot_b) / magnitude;\r\n    out[6] = (b2 - a2 * a_dot_b) / magnitude;\r\n    out[7] = (b3 - a3 * a_dot_b) / magnitude;\r\n  }\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns a string representation of a dual quatenion\r\n *\r\n * @param {quat2} a dual quaternion to represent as a string\r\n * @returns {String} string representation of the dual quat\r\n */\r\nfunction str(a) {\r\n  return 'quat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ')';\r\n}\r\n\r\n/**\r\n * Returns whether or not the dual quaternions have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {quat2} a the first dual quaternion.\r\n * @param {quat2} b the second dual quaternion.\r\n * @returns {Boolean} true if the dual quaternions are equal, false otherwise.\r\n */\r\nfunction exactEquals(a, b) {\r\n  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];\r\n}\r\n\r\n/**\r\n * Returns whether or not the dual quaternions have approximately the same elements in the same position.\r\n *\r\n * @param {quat2} a the first dual quat.\r\n * @param {quat2} b the second dual quat.\r\n * @returns {Boolean} true if the dual quats are equal, false otherwise.\r\n */\r\nfunction equals(a, b) {\r\n  var a0 = a[0],\r\n      a1 = a[1],\r\n      a2 = a[2],\r\n      a3 = a[3],\r\n      a4 = a[4],\r\n      a5 = a[5],\r\n      a6 = a[6],\r\n      a7 = a[7];\r\n  var b0 = b[0],\r\n      b1 = b[1],\r\n      b2 = b[2],\r\n      b3 = b[3],\r\n      b4 = b[4],\r\n      b5 = b[5],\r\n      b6 = b[6],\r\n      b7 = b[7];\r\n  return Math.abs(a0 - b0) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a7), Math.abs(b7));\r\n}\n\n/***/ }),\n/* 11 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (immutable) */ __webpack_exports__[\"create\"] = create;\n/* harmony export (immutable) */ __webpack_exports__[\"clone\"] = clone;\n/* harmony export (immutable) */ __webpack_exports__[\"fromValues\"] = fromValues;\n/* harmony export (immutable) */ __webpack_exports__[\"copy\"] = copy;\n/* harmony export (immutable) */ __webpack_exports__[\"set\"] = set;\n/* harmony export (immutable) */ __webpack_exports__[\"add\"] = add;\n/* harmony export (immutable) */ __webpack_exports__[\"subtract\"] = subtract;\n/* harmony export (immutable) */ __webpack_exports__[\"multiply\"] = multiply;\n/* harmony export (immutable) */ __webpack_exports__[\"divide\"] = divide;\n/* harmony export (immutable) */ __webpack_exports__[\"ceil\"] = ceil;\n/* harmony export (immutable) */ __webpack_exports__[\"floor\"] = floor;\n/* harmony export (immutable) */ __webpack_exports__[\"min\"] = min;\n/* harmony export (immutable) */ __webpack_exports__[\"max\"] = max;\n/* harmony export (immutable) */ __webpack_exports__[\"round\"] = round;\n/* harmony export (immutable) */ __webpack_exports__[\"scale\"] = scale;\n/* harmony export (immutable) */ __webpack_exports__[\"scaleAndAdd\"] = scaleAndAdd;\n/* harmony export (immutable) */ __webpack_exports__[\"distance\"] = distance;\n/* harmony export (immutable) */ __webpack_exports__[\"squaredDistance\"] = squaredDistance;\n/* harmony export (immutable) */ __webpack_exports__[\"length\"] = length;\n/* harmony export (immutable) */ __webpack_exports__[\"squaredLength\"] = squaredLength;\n/* harmony export (immutable) */ __webpack_exports__[\"negate\"] = negate;\n/* harmony export (immutable) */ __webpack_exports__[\"inverse\"] = inverse;\n/* harmony export (immutable) */ __webpack_exports__[\"normalize\"] = normalize;\n/* harmony export (immutable) */ __webpack_exports__[\"dot\"] = dot;\n/* harmony export (immutable) */ __webpack_exports__[\"cross\"] = cross;\n/* harmony export (immutable) */ __webpack_exports__[\"lerp\"] = lerp;\n/* harmony export (immutable) */ __webpack_exports__[\"random\"] = random;\n/* harmony export (immutable) */ __webpack_exports__[\"transformMat2\"] = transformMat2;\n/* harmony export (immutable) */ __webpack_exports__[\"transformMat2d\"] = transformMat2d;\n/* harmony export (immutable) */ __webpack_exports__[\"transformMat3\"] = transformMat3;\n/* harmony export (immutable) */ __webpack_exports__[\"transformMat4\"] = transformMat4;\n/* harmony export (immutable) */ __webpack_exports__[\"rotate\"] = rotate;\n/* harmony export (immutable) */ __webpack_exports__[\"angle\"] = angle;\n/* harmony export (immutable) */ __webpack_exports__[\"str\"] = str;\n/* harmony export (immutable) */ __webpack_exports__[\"exactEquals\"] = exactEquals;\n/* harmony export (immutable) */ __webpack_exports__[\"equals\"] = equals;\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"len\", function() { return len; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sub\", function() { return sub; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mul\", function() { return mul; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"div\", function() { return div; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"dist\", function() { return dist; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sqrDist\", function() { return sqrDist; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"sqrLen\", function() { return sqrLen; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"forEach\", function() { return forEach; });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__common_js__ = __webpack_require__(0);\n\r\n\r\n/**\r\n * 2 Dimensional Vector\r\n * @module vec2\r\n */\r\n\r\n/**\r\n * Creates a new, empty vec2\r\n *\r\n * @returns {vec2} a new 2D vector\r\n */\r\nfunction create() {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](2);\r\n  if (__WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"] != Float32Array) {\r\n    out[0] = 0;\r\n    out[1] = 0;\r\n  }\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new vec2 initialized with values from an existing vector\r\n *\r\n * @param {vec2} a vector to clone\r\n * @returns {vec2} a new 2D vector\r\n */\r\nfunction clone(a) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](2);\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Creates a new vec2 initialized with the given values\r\n *\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @returns {vec2} a new 2D vector\r\n */\r\nfunction fromValues(x, y) {\r\n  var out = new __WEBPACK_IMPORTED_MODULE_0__common_js__[\"ARRAY_TYPE\"](2);\r\n  out[0] = x;\r\n  out[1] = y;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Copy the values from one vec2 to another\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the source vector\r\n * @returns {vec2} out\r\n */\r\nfunction copy(out, a) {\r\n  out[0] = a[0];\r\n  out[1] = a[1];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Set the components of a vec2 to the given values\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @returns {vec2} out\r\n */\r\nfunction set(out, x, y) {\r\n  out[0] = x;\r\n  out[1] = y;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two vec2's\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @returns {vec2} out\r\n */\r\nfunction add(out, a, b) {\r\n  out[0] = a[0] + b[0];\r\n  out[1] = a[1] + b[1];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Subtracts vector b from vector a\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @returns {vec2} out\r\n */\r\nfunction subtract(out, a, b) {\r\n  out[0] = a[0] - b[0];\r\n  out[1] = a[1] - b[1];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Multiplies two vec2's\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @returns {vec2} out\r\n */\r\nfunction multiply(out, a, b) {\r\n  out[0] = a[0] * b[0];\r\n  out[1] = a[1] * b[1];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Divides two vec2's\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @returns {vec2} out\r\n */\r\nfunction divide(out, a, b) {\r\n  out[0] = a[0] / b[0];\r\n  out[1] = a[1] / b[1];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Math.ceil the components of a vec2\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a vector to ceil\r\n * @returns {vec2} out\r\n */\r\nfunction ceil(out, a) {\r\n  out[0] = Math.ceil(a[0]);\r\n  out[1] = Math.ceil(a[1]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Math.floor the components of a vec2\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a vector to floor\r\n * @returns {vec2} out\r\n */\r\nfunction floor(out, a) {\r\n  out[0] = Math.floor(a[0]);\r\n  out[1] = Math.floor(a[1]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the minimum of two vec2's\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @returns {vec2} out\r\n */\r\nfunction min(out, a, b) {\r\n  out[0] = Math.min(a[0], b[0]);\r\n  out[1] = Math.min(a[1], b[1]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the maximum of two vec2's\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @returns {vec2} out\r\n */\r\nfunction max(out, a, b) {\r\n  out[0] = Math.max(a[0], b[0]);\r\n  out[1] = Math.max(a[1], b[1]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Math.round the components of a vec2\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a vector to round\r\n * @returns {vec2} out\r\n */\r\nfunction round(out, a) {\r\n  out[0] = Math.round(a[0]);\r\n  out[1] = Math.round(a[1]);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Scales a vec2 by a scalar number\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the vector to scale\r\n * @param {Number} b amount to scale the vector by\r\n * @returns {vec2} out\r\n */\r\nfunction scale(out, a, b) {\r\n  out[0] = a[0] * b;\r\n  out[1] = a[1] * b;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Adds two vec2's after scaling the second operand by a scalar value\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @param {Number} scale the amount to scale b by before adding\r\n * @returns {vec2} out\r\n */\r\nfunction scaleAndAdd(out, a, b, scale) {\r\n  out[0] = a[0] + b[0] * scale;\r\n  out[1] = a[1] + b[1] * scale;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the euclidian distance between two vec2's\r\n *\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @returns {Number} distance between a and b\r\n */\r\nfunction distance(a, b) {\r\n  var x = b[0] - a[0],\r\n      y = b[1] - a[1];\r\n  return Math.sqrt(x * x + y * y);\r\n}\r\n\r\n/**\r\n * Calculates the squared euclidian distance between two vec2's\r\n *\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @returns {Number} squared distance between a and b\r\n */\r\nfunction squaredDistance(a, b) {\r\n  var x = b[0] - a[0],\r\n      y = b[1] - a[1];\r\n  return x * x + y * y;\r\n}\r\n\r\n/**\r\n * Calculates the length of a vec2\r\n *\r\n * @param {vec2} a vector to calculate length of\r\n * @returns {Number} length of a\r\n */\r\nfunction length(a) {\r\n  var x = a[0],\r\n      y = a[1];\r\n  return Math.sqrt(x * x + y * y);\r\n}\r\n\r\n/**\r\n * Calculates the squared length of a vec2\r\n *\r\n * @param {vec2} a vector to calculate squared length of\r\n * @returns {Number} squared length of a\r\n */\r\nfunction squaredLength(a) {\r\n  var x = a[0],\r\n      y = a[1];\r\n  return x * x + y * y;\r\n}\r\n\r\n/**\r\n * Negates the components of a vec2\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a vector to negate\r\n * @returns {vec2} out\r\n */\r\nfunction negate(out, a) {\r\n  out[0] = -a[0];\r\n  out[1] = -a[1];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Returns the inverse of the components of a vec2\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a vector to invert\r\n * @returns {vec2} out\r\n */\r\nfunction inverse(out, a) {\r\n  out[0] = 1.0 / a[0];\r\n  out[1] = 1.0 / a[1];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Normalize a vec2\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a vector to normalize\r\n * @returns {vec2} out\r\n */\r\nfunction normalize(out, a) {\r\n  var x = a[0],\r\n      y = a[1];\r\n  var len = x * x + y * y;\r\n  if (len > 0) {\r\n    //TODO: evaluate use of glm_invsqrt here?\r\n    len = 1 / Math.sqrt(len);\r\n    out[0] = a[0] * len;\r\n    out[1] = a[1] * len;\r\n  }\r\n  return out;\r\n}\r\n\r\n/**\r\n * Calculates the dot product of two vec2's\r\n *\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @returns {Number} dot product of a and b\r\n */\r\nfunction dot(a, b) {\r\n  return a[0] * b[0] + a[1] * b[1];\r\n}\r\n\r\n/**\r\n * Computes the cross product of two vec2's\r\n * Note that the cross product must by definition produce a 3D vector\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @returns {vec3} out\r\n */\r\nfunction cross(out, a, b) {\r\n  var z = a[0] * b[1] - a[1] * b[0];\r\n  out[0] = out[1] = 0;\r\n  out[2] = z;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Performs a linear interpolation between two vec2's\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the first operand\r\n * @param {vec2} b the second operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {vec2} out\r\n */\r\nfunction lerp(out, a, b, t) {\r\n  var ax = a[0],\r\n      ay = a[1];\r\n  out[0] = ax + t * (b[0] - ax);\r\n  out[1] = ay + t * (b[1] - ay);\r\n  return out;\r\n}\r\n\r\n/**\r\n * Generates a random vector with the given scale\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned\r\n * @returns {vec2} out\r\n */\r\nfunction random(out, scale) {\r\n  scale = scale || 1.0;\r\n  var r = __WEBPACK_IMPORTED_MODULE_0__common_js__[\"RANDOM\"]() * 2.0 * Math.PI;\r\n  out[0] = Math.cos(r) * scale;\r\n  out[1] = Math.sin(r) * scale;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transforms the vec2 with a mat2\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the vector to transform\r\n * @param {mat2} m matrix to transform with\r\n * @returns {vec2} out\r\n */\r\nfunction transformMat2(out, a, m) {\r\n  var x = a[0],\r\n      y = a[1];\r\n  out[0] = m[0] * x + m[2] * y;\r\n  out[1] = m[1] * x + m[3] * y;\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transforms the vec2 with a mat2d\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the vector to transform\r\n * @param {mat2d} m matrix to transform with\r\n * @returns {vec2} out\r\n */\r\nfunction transformMat2d(out, a, m) {\r\n  var x = a[0],\r\n      y = a[1];\r\n  out[0] = m[0] * x + m[2] * y + m[4];\r\n  out[1] = m[1] * x + m[3] * y + m[5];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transforms the vec2 with a mat3\r\n * 3rd vector component is implicitly '1'\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the vector to transform\r\n * @param {mat3} m matrix to transform with\r\n * @returns {vec2} out\r\n */\r\nfunction transformMat3(out, a, m) {\r\n  var x = a[0],\r\n      y = a[1];\r\n  out[0] = m[0] * x + m[3] * y + m[6];\r\n  out[1] = m[1] * x + m[4] * y + m[7];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Transforms the vec2 with a mat4\r\n * 3rd vector component is implicitly '0'\r\n * 4th vector component is implicitly '1'\r\n *\r\n * @param {vec2} out the receiving vector\r\n * @param {vec2} a the vector to transform\r\n * @param {mat4} m matrix to transform with\r\n * @returns {vec2} out\r\n */\r\nfunction transformMat4(out, a, m) {\r\n  var x = a[0];\r\n  var y = a[1];\r\n  out[0] = m[0] * x + m[4] * y + m[12];\r\n  out[1] = m[1] * x + m[5] * y + m[13];\r\n  return out;\r\n}\r\n\r\n/**\r\n * Rotate a 2D vector\r\n * @param {vec2} out The receiving vec2\r\n * @param {vec2} a The vec2 point to rotate\r\n * @param {vec2} b The origin of the rotation\r\n * @param {Number} c The angle of rotation\r\n * @returns {vec2} out\r\n */\r\nfunction rotate(out, a, b, c) {\r\n  //Translate point to the origin\r\n  var p0 = a[0] - b[0],\r\n      p1 = a[1] - b[1],\r\n      sinC = Math.sin(c),\r\n      cosC = Math.cos(c);\r\n\r\n  //perform rotation and translate to correct position\r\n  out[0] = p0 * cosC - p1 * sinC + b[0];\r\n  out[1] = p0 * sinC + p1 * cosC + b[1];\r\n\r\n  return out;\r\n}\r\n\r\n/**\r\n * Get the angle between two 2D vectors\r\n * @param {vec2} a The first operand\r\n * @param {vec2} b The second operand\r\n * @returns {Number} The angle in radians\r\n */\r\nfunction angle(a, b) {\r\n  var x1 = a[0],\r\n      y1 = a[1],\r\n      x2 = b[0],\r\n      y2 = b[1];\r\n\r\n  var len1 = x1 * x1 + y1 * y1;\r\n  if (len1 > 0) {\r\n    //TODO: evaluate use of glm_invsqrt here?\r\n    len1 = 1 / Math.sqrt(len1);\r\n  }\r\n\r\n  var len2 = x2 * x2 + y2 * y2;\r\n  if (len2 > 0) {\r\n    //TODO: evaluate use of glm_invsqrt here?\r\n    len2 = 1 / Math.sqrt(len2);\r\n  }\r\n\r\n  var cosine = (x1 * x2 + y1 * y2) * len1 * len2;\r\n\r\n  if (cosine > 1.0) {\r\n    return 0;\r\n  } else if (cosine < -1.0) {\r\n    return Math.PI;\r\n  } else {\r\n    return Math.acos(cosine);\r\n  }\r\n}\r\n\r\n/**\r\n * Returns a string representation of a vector\r\n *\r\n * @param {vec2} a vector to represent as a string\r\n * @returns {String} string representation of the vector\r\n */\r\nfunction str(a) {\r\n  return 'vec2(' + a[0] + ', ' + a[1] + ')';\r\n}\r\n\r\n/**\r\n * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)\r\n *\r\n * @param {vec2} a The first vector.\r\n * @param {vec2} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\r\nfunction exactEquals(a, b) {\r\n  return a[0] === b[0] && a[1] === b[1];\r\n}\r\n\r\n/**\r\n * Returns whether or not the vectors have approximately the same elements in the same position.\r\n *\r\n * @param {vec2} a The first vector.\r\n * @param {vec2} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\r\nfunction equals(a, b) {\r\n  var a0 = a[0],\r\n      a1 = a[1];\r\n  var b0 = b[0],\r\n      b1 = b[1];\r\n  return Math.abs(a0 - b0) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= __WEBPACK_IMPORTED_MODULE_0__common_js__[\"EPSILON\"] * Math.max(1.0, Math.abs(a1), Math.abs(b1));\r\n}\r\n\r\n/**\r\n * Alias for {@link vec2.length}\r\n * @function\r\n */\r\nvar len = length;\r\n\r\n/**\r\n * Alias for {@link vec2.subtract}\r\n * @function\r\n */\r\nvar sub = subtract;\r\n\r\n/**\r\n * Alias for {@link vec2.multiply}\r\n * @function\r\n */\r\nvar mul = multiply;\r\n\r\n/**\r\n * Alias for {@link vec2.divide}\r\n * @function\r\n */\r\nvar div = divide;\r\n\r\n/**\r\n * Alias for {@link vec2.distance}\r\n * @function\r\n */\r\nvar dist = distance;\r\n\r\n/**\r\n * Alias for {@link vec2.squaredDistance}\r\n * @function\r\n */\r\nvar sqrDist = squaredDistance;\r\n\r\n/**\r\n * Alias for {@link vec2.squaredLength}\r\n * @function\r\n */\r\nvar sqrLen = squaredLength;\r\n\r\n/**\r\n * Perform some operation over an array of vec2s.\r\n *\r\n * @param {Array} a the array of vectors to iterate over\r\n * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed\r\n * @param {Number} offset Number of elements to skip at the beginning of the array\r\n * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array\r\n * @param {Function} fn Function to call for each vector in the array\r\n * @param {Object} [arg] additional argument to pass to fn\r\n * @returns {Array} a\r\n * @function\r\n */\r\nvar forEach = function () {\r\n  var vec = create();\r\n\r\n  return function (a, stride, offset, count, fn, arg) {\r\n    var i = void 0,\r\n        l = void 0;\r\n    if (!stride) {\r\n      stride = 2;\r\n    }\r\n\r\n    if (!offset) {\r\n      offset = 0;\r\n    }\r\n\r\n    if (count) {\r\n      l = Math.min(count * stride + offset, a.length);\r\n    } else {\r\n      l = a.length;\r\n    }\r\n\r\n    for (i = offset; i < l; i += stride) {\r\n      vec[0] = a[i];vec[1] = a[i + 1];\r\n      fn(vec, vec, arg);\r\n      a[i] = vec[0];a[i + 1] = vec[1];\r\n    }\r\n\r\n    return a;\r\n  };\r\n}();\n\n/***/ }),\n/* 12 */\n/***/ (function(module, exports, __webpack_require__) {\n\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(true)\n\t\tmodule.exports = factory(__webpack_require__(1));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"gl-matrix\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"MinimalGLTFLoader\"] = factory(require(\"gl-matrix\"));\n\telse\n\t\troot[\"MinimalGLTFLoader\"] = factory(root[undefined]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"glTFLoader\", function() { return glTFLoader; });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_gl_matrix__ = __webpack_require__(1);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_gl_matrix___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_gl_matrix__);\n\n\nvar MinimalGLTFLoader = MinimalGLTFLoader || {};\n\nvar globalUniformBlockID = 0;\n\nvar curLoader = null;       // @tmp, might be unsafe if loading multiple model at the same time\n\nvar NUM_MAX_JOINTS = 65;\n\n// Data classes\nvar Scene = MinimalGLTFLoader.Scene = function (gltf, s) {\n    this.name = s.name !== undefined ? s.name : null;\n    this.nodes = new Array(s.nodes.length);    // root node object of this scene\n    for (var i = 0, len = s.nodes.length; i < len; i++) {\n        this.nodes[i] = gltf.nodes[s.nodes[i]];\n    }\n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n\n    this.boundingBox = null;\n};\n\n/**\n * \n * @param {vec3} min\n * @param {vec3} max\n */\nvar BoundingBox = MinimalGLTFLoader.BoundingBox = function (min, max, isClone) {\n    // this.min = min;\n    // this.max = max;\n    min = min || __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);\n    max = max || __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);\n\n    if (isClone === undefined || isClone === true) {\n        this.min = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].clone(min);\n        this.max = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].clone(max);\n    } else {\n        this.min = min;\n        this.max = max;\n    }\n    \n\n    this.transform = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\n};\n\nBoundingBox.prototype.updateBoundingBox = function (bbox) {\n    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].min(this.min, this.min, bbox.min);\n    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].max(this.max, this.max, bbox.max);\n};\n\nBoundingBox.prototype.calculateTransform = function () {\n    // transform from a unit cube whose min = (0, 0, 0) and max = (1, 1, 1)\n\n    // scale\n    this.transform[0] = this.max[0] - this.min[0];\n    this.transform[5] = this.max[1] - this.min[1];\n    this.transform[10] = this.max[2] - this.min[2];\n    // translate\n    this.transform[12] = this.min[0];\n    this.transform[13] = this.min[1];\n    this.transform[14] = this.min[2];\n};\n\nBoundingBox.getAABBFromOBB = (function() {\n    var transformRight = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n    var transformUp = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n    var transformBackward = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n\n    var tmpVec3a = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n    var tmpVec3b = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n\n    return (function (obb, matrix) {\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].set(transformRight, matrix[0], matrix[1], matrix[2]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].set(transformUp, matrix[4], matrix[5], matrix[6]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].set(transformBackward, matrix[8], matrix[9], matrix[10]);\n\n        var min = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(matrix[12], matrix[13], matrix[14]);  // init with matrix translation\n        var max = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].clone(min);\n\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3a, transformRight, obb.min[0]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3b, transformRight, obb.max[0]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].min(transformRight, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(min, min, transformRight);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].max(transformRight, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(max, max, transformRight);\n\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3a, transformUp, obb.min[1]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3b, transformUp, obb.max[1]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].min(transformUp, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(min, min, transformUp);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].max(transformUp, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(max, max, transformUp);\n\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3a, transformBackward, obb.min[2]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3b, transformBackward, obb.max[2]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].min(transformBackward, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(min, min, transformBackward);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].max(transformBackward, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(max, max, transformBackward);\n\n        var bbox = new BoundingBox(min, max, false);\n        bbox.calculateTransform();\n        return bbox;\n    });\n})();\n\n\n\nvar Accessor = MinimalGLTFLoader.Accessor = function (a, bufferViewObject) {\n    this.bufferView = bufferViewObject;\n    this.componentType = a.componentType;   // required\n    this.byteOffset = a.byteOffset !== undefined ? a.byteOffset : 0;\n    this.byteStride = bufferViewObject.byteStride;\n    this.normalized = a.normalized !== undefined ? a.normalized : false;\n    this.count = a.count;   // required\n    this.type = a.type;     // required\n    this.size = Type2NumOfComponent[this.type];\n\n    this.min = a.min;   // @tmp assume required for now (for bbox)\n    this.max = a.max;   // @tmp assume required for now (for bbox)\n\n    this.extensions = a.extensions !== undefined ? a.extensions : null;\n    this.extras = a.extras !== undefined ? a.extras : null;\n};\n\nAccessor.prototype.prepareVertexAttrib = function(location, gl) {\n    gl.vertexAttribPointer(\n        location,\n        this.size,\n        this.componentType,\n        this.normalized,\n        this.byteStride,\n        this.byteOffset\n        );\n    gl.enableVertexAttribArray(location);\n};\n\nvar BufferView = MinimalGLTFLoader.BufferView = function(bf, bufferData) {\n    this.byteLength = bf.byteLength;    //required\n    this.byteOffset = bf.byteOffset !== undefined ? bf.byteOffset : 0;\n    this.byteStride = bf.byteStride !== undefined ? bf.byteStride : 0;\n    this.target = bf.target !== undefined ? bf.target : null;\n\n    this.data = bufferData.slice(this.byteOffset, this.byteOffset + this.byteLength);\n\n    this.extensions = bf.extensions !== undefined ? bf.extensions : null;\n    this.extras = bf.extras !== undefined ? bf.extras : null;\n\n    // runtime stuffs -------------\n    this.buffer = null;     // gl buffer\n};\n\nBufferView.prototype.createBuffer = function(gl) {\n    this.buffer = gl.createBuffer();\n};\n\nBufferView.prototype.bindData = function(gl) {\n    if (this.target) {\n        gl.bindBuffer(this.target, this.buffer);\n        gl.bufferData(this.target, this.data, gl.STATIC_DRAW);\n        gl.bindBuffer(this.target, null);\n        return true;\n    }\n    return false;\n};\n\n\nvar Camera = MinimalGLTFLoader.Camera = function(c) {\n    this.name = c.name !== undefined ? c.name : null;\n    this.type = c.type; // required\n\n    this.othographic = c.othographic === undefined ? null : c.othographic;  // every attribute inside is required (excluding extensions)\n    this.perspective = c.perspective === undefined ? null : {\n        yfov: c.perspective.yfov,\n        znear: c.perspective.znear,\n        zfar: c.perspective.zfar !== undefined ? c.perspective.zfar : null,\n        aspectRatio: c.perspective.aspectRatio !== undefined ? c.perspective.aspectRatio : null\n    };\n\n    this.extensions = c.extensions !== undefined ? c.extensions : null;\n    this.extras = c.extras !== undefined ? c.extras : null;\n};\n\n\n\nvar Node = MinimalGLTFLoader.Node = function (n, nodeID) {\n    this.name = n.name !== undefined ? n.name : null;\n    this.nodeID = nodeID;\n    // TODO: camera\n    this.camera = n.camera !== undefined ? n.camera : null;\n\n    this.matrix = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\n    if (n.hasOwnProperty('matrix')) {\n        for(var i = 0; i < 16; ++i) {\n            this.matrix[i] = n.matrix[i];\n        }\n\n        this.translation = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].getTranslation(this.translation, this.matrix);\n\n        this.rotation = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"quat\"].create();\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].getRotation(this.rotation, this.matrix);\n\n        this.scale = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].getScaling(this.scale, this.matrix);\n    } else {\n        // this.translation = null;\n        // this.rotation = null;\n        // this.scale = null;\n        this.getTransformMatrixFromTRS(n.translation, n.rotation, n.scale);\n    }\n    \n    \n    \n\n    this.children = n.children || [];  // init as id, then hook up to node object later\n    this.mesh = n.mesh !== undefined ? curLoader.glTF.meshes[n.mesh] : null;\n\n    this.skin = n.skin !== undefined ? n.skin : null;   // init as id, then hook up to skin object later\n\n    if (n.extensions !== undefined) {\n        if (n.extensions.gl_avatar !== undefined && curLoader.enableGLAvatar === true) {\n            var linkedSkinID = curLoader.skeletonGltf.json.extensions.gl_avatar.skins[ n.extensions.gl_avatar.skin.name ];\n            var linkedSkin = curLoader.skeletonGltf.skins[linkedSkinID];\n            this.skin = new SkinLink(curLoader.glTF, linkedSkin, n.extensions.gl_avatar.skin.inverseBindMatrices);\n        }\n    }\n    \n\n\n    // TODO: morph targets weights\n    this.weights = n.weights !== undefined ? n.weights : null;\n\n\n    this.extensions = n.extensions !== undefined ? n.extensions : null;\n    this.extras = n.extras !== undefined ? n.extras : null;\n\n    // runtime stuffs--------------\n\n    this.aabb = null;   // axis aligned bounding box, not need to apply node transform to aabb\n    this.bvh = new BoundingBox();\n};\n\nNode.prototype.traverse = function(parent, executeFunc) {\n    executeFunc(this, parent);\n    for (var i = 0, len = this.children.length; i < len; i++) {\n        this.children[i].traverse(this, executeFunc);\n    }\n};\n\nNode.prototype.traversePostOrder = function(parent, executeFunc) {\n    for (var i = 0, len = this.children.length; i < len; i++) {\n        this.children[i].traversePostOrder(this, executeFunc);\n    }\n    executeFunc(this, parent);\n};\n\nNode.prototype.traverseTwoExecFun = function(parent, execFunPre, execFunPos) {\n    execFunPre(this, parent);\n    for (var i = 0, len = this.children.length; i < len; i++) {\n        this.children[i].traverseTwoExecFun(this, execFunPre, execFunPos);\n    }\n    execFunPos(this, parent);\n};\n\nvar TRSMatrix = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\n\nNode.prototype.getTransformMatrixFromTRS = function(translation, rotation, scale) {\n\n    this.translation = translation !== undefined ? __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(translation[0], translation[1], translation[2]) : __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(0, 0, 0);\n    this.rotation = rotation !== undefined ? __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].fromValues(rotation[0], rotation[1], rotation[2], rotation[3]) : __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].fromValues(0, 0, 0, 1);\n    this.scale = scale !== undefined ? __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(scale[0], scale[1], scale[2]) : __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(1, 1, 1);\n\n    this.updateMatrixFromTRS();\n};\n\nNode.prototype.updateMatrixFromTRS = function() {\n    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].fromRotationTranslation(TRSMatrix, this.rotation, this.translation);\n    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].scale(this.matrix, TRSMatrix, this.scale);\n};\n\n\n\nvar Mesh = MinimalGLTFLoader.Mesh = function (m, meshID) {\n    this.meshID = meshID;\n    this.name = m.name !== undefined ? m.name : null;\n\n    this.primitives = [];   // required\n    \n\n\n    // bounding box (runtime stuff)\n    this.boundingBox = null;\n\n    var p, primitive, accessor;\n\n    for (var i = 0, len = m.primitives.length; i < len; ++i) {\n        p = m.primitives[i];\n        primitive = new Primitive(curLoader.glTF, p);\n        this.primitives.push(primitive);\n\n        // bounding box related\n        if (primitive.boundingBox) {\n            if (!this.boundingBox) {\n                this.boundingBox = new BoundingBox();\n            }\n            this.boundingBox.updateBoundingBox(primitive.boundingBox);\n        }\n    }\n\n    if (this.boundingBox) {\n        this.boundingBox.calculateTransform();\n    }\n\n\n    // TODO: weights for morph targets\n    this.weights = m.weights !== undefined ? m.weights : null;\n\n    this.extensions = m.extensions !== undefined ? m.extensions : null;\n    this.extras = m.extras !== undefined ? m.extras : null;\n    \n};\n\nvar Primitive = MinimalGLTFLoader.Primitive = function (gltf, p) {\n    // <attribute name, accessor id>, required\n    // get hook up with accessor object in _postprocessing\n    this.attributes = p.attributes;\n    this.indices = p.indices !== undefined ? p.indices : null;  // accessor id\n\n    var attname;\n    if (p.extensions !== undefined) {\n        if (p.extensions.gl_avatar !== undefined && curLoader.enableGLAvatar === true) {\n            if (p.extensions.gl_avatar.attributes) {\n                for ( attname in p.extensions.gl_avatar.attributes ) {\n                    this.attributes[attname] = p.extensions.gl_avatar.attributes[attname];\n                }\n            }\n        }\n    }\n\n    \n    if (this.indices !== null) {\n        this.indicesComponentType = gltf.json.accessors[this.indices].componentType;\n        this.indicesLength = gltf.json.accessors[this.indices].count;\n        this.indicesOffset = (gltf.json.accessors[this.indices].byteOffset || 0);\n    } else {\n        // assume 'POSITION' is there\n        this.drawArraysCount = gltf.json.accessors[this.attributes.POSITION].count;\n        this.drawArraysOffset = (gltf.json.accessors[this.attributes.POSITION].byteOffset || 0);\n    }\n\n    \n    // hook up accessor object\n    for ( attname in this.attributes ) {\n        this.attributes[attname] = gltf.accessors[ this.attributes[attname] ];\n    }\n\n\n    this.material = p.material !== undefined ? gltf.materials[p.material] : null;\n\n\n    this.mode = p.mode !== undefined ? p.mode : 4; // default: gl.TRIANGLES\n\n    \n\n    // morph related\n    this.targets = p.targets;\n\n\n    this.extensions = p.extensions !== undefined ? p.extensions : null;\n    this.extras = p.extras !== undefined ? p.extras : null;\n\n\n    // ----gl run time related\n    this.vertexArray = null;    //vao\n    \n    this.vertexBuffer = null;\n    this.indexBuffer = null;\n\n\n    this.shader = null;\n\n\n    this.boundingBox = null;\n    if (this.attributes.POSITION !== undefined) {\n        var accessor = this.attributes.POSITION;\n        if (accessor.max) {\n            // @todo: handle cases where no min max are provided\n\n            // assume vec3\n            if (accessor.type === 'VEC3') {\n                this.boundingBox = new BoundingBox(\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(accessor.min[0], accessor.min[1], accessor.min[2]),\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(accessor.max[0], accessor.max[1], accessor.max[2]),\n                    false\n                );\n                this.boundingBox.calculateTransform();\n                \n\n                \n            }\n            \n        }\n    }\n};\n\n\nvar Texture = MinimalGLTFLoader.Texture = function (t) {\n    this.name = t.name !== undefined ? t.name : null;\n    this.sampler = t.sampler !== undefined ? curLoader.glTF.samplers[t.sampler] : null;\n    this.source = t.source !== undefined ? curLoader.glTF.images[t.source] : null;\n\n    this.extensions = t.extensions !== undefined ? t.extensions : null;\n    this.extras = t.extras !== undefined ? t.extras : null;\n\n    // runtime\n    this.texture = null;\n};\n\nTexture.prototype.createTexture = function(gl) {\n    this.texture = gl.createTexture();\n    gl.bindTexture(gl.TEXTURE_2D, this.texture);\n    gl.texImage2D(\n        gl.TEXTURE_2D,  // assumed\n        0,        // Level of details\n        // gl.RGB, // Format\n        // gl.RGB,\n        gl.RGBA, // Format\n        gl.RGBA,\n        gl.UNSIGNED_BYTE, // Size of each channel\n        this.source\n    );\n    gl.generateMipmap(gl.TEXTURE_2D);\n    gl.bindTexture(gl.TEXTURE_2D, null);\n};\n\nvar Sampler = MinimalGLTFLoader.Sampler = function (s) {\n    this.name = s.name !== undefined ? s.name : null;\n    this.magFilter = s.magFilter !== undefined ? s.magFilter : null;\n    this.minFilter = s.minFilter !== undefined ? s.minFilter : null;\n    this.wrapS = s.wrapS !== undefined ? s.wrapS : 10497;\n    this.wrapT = s.wrapT !== undefined ? s.wrapT : 10497;\n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n    this.sampler = null;\n};\n\nSampler.prototype.createSampler = function(gl) {\n    this.sampler = gl.createSampler();\n    if (this.minFilter) {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MIN_FILTER, this.minFilter);\n    } else {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);\n    }\n    if (this.magFilter) {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MAG_FILTER, this.magFilter);\n    } else {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n    }\n    gl.samplerParameteri(this.sampler, gl.TEXTURE_WRAP_S, this.wrapS);\n    gl.samplerParameteri(this.sampler, gl.TEXTURE_WRAP_T, this.wrapT);\n};\n\n// Sampler.prototype.bindSampler = function(i, gl) {\n//     gl.bindSampler(i, this.sampler);\n// }\n\nvar TextureInfo = MinimalGLTFLoader.TextureInfo = function (json) {\n    this.index = json.index;\n    this.texCoord = json.texCoord !== undefined ? json.texCoord : 0 ;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar PbrMetallicRoughness = MinimalGLTFLoader.PbrMetallicRoughness = function (json) {\n    this.baseColorFactor = json.baseColorFactor !== undefined ? json.baseColorFactor : [1, 1, 1, 1];\n    this.baseColorTexture = json.baseColorTexture !== undefined ? new TextureInfo(json.baseColorTexture): null;\n    this.metallicFactor = json.metallicFactor !== undefined ? json.metallicFactor : 1 ;\n    this.roughnessFactor = json.roughnessFactor !== undefined ? json.roughnessFactor : 1 ;\n    this.metallicRoughnessTexture = json.metallicRoughnessTexture !== undefined ? new TextureInfo(json.metallicRoughnessTexture): null;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar NormalTextureInfo = MinimalGLTFLoader.NormalTextureInfo = function (json) {\n    this.index = json.index;\n    this.texCoord = json.texCoord !== undefined ? json.texCoord : 0 ;\n    this.scale = json.scale !== undefined ? json.scale : 1 ;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar OcclusionTextureInfo = MinimalGLTFLoader.OcclusionTextureInfo = function (json) {\n    this.index = json.index;\n    this.texCoord = json.texCoord !== undefined ? json.texCoord : 0 ;\n    this.strength = json.strength !== undefined ? json.strength : 1 ;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar Material = MinimalGLTFLoader.Material = function (m) {\n    this.name = m.name !== undefined ? m.name : null;\n    \n    this.pbrMetallicRoughness = m.pbrMetallicRoughness !== undefined ? new PbrMetallicRoughness( m.pbrMetallicRoughness ) : new PbrMetallicRoughness({\n        baseColorFactor: [1, 1, 1, 1],\n        metallicFactor: 1,\n        metallicRoughnessTexture: 1\n    });\n    // this.normalTexture = m.normalTexture !== undefined ? m.normalTexture : null;\n    this.normalTexture = m.normalTexture !== undefined ? new NormalTextureInfo(m.normalTexture) : null;\n    this.occlusionTexture = m.occlusionTexture !== undefined ? new OcclusionTextureInfo(m.occlusionTexture) : null;\n    this.emissiveTexture = m.emissiveTexture !== undefined ? new TextureInfo(m.emissiveTexture) : null;\n\n    this.emissiveFactor = m.emissiveFactor !== undefined ? m.emissiveFactor : [0, 0, 0];\n    this.alphaMode = m.alphaMode !== undefined ? m.alphaMode : \"OPAQUE\";\n    this.alphaCutoff = m.alphaCutoff !== undefined ? m.alphaCutoff : 0.5;\n    this.doubleSided = m.doubleSided || false;\n\n    this.extensions = m.extensions !== undefined ? m.extensions : null;\n    this.extras = m.extras !== undefined ? m.extras : null;\n};\n\n\nvar Skin = MinimalGLTFLoader.Skin = function (gltf, s, skinID) {\n    this.name = s.name !== undefined ? s.name : null;\n    this.skinID = skinID;\n\n    this.joints = new Array(s.joints.length);   // required\n    var i, len;\n    for (i = 0, len = this.joints.length; i < len; i++) {\n        this.joints[i] = gltf.nodes[s.joints[i]];\n    }\n\n    this.skeleton = s.skeleton !== undefined ? gltf.nodes[s.skeleton] : null;\n    this.inverseBindMatrices = s.inverseBindMatrices !== undefined ? gltf.accessors[s.inverseBindMatrices] : null;\n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n\n    // @tmp: runtime stuff should be taken care of renderer\n    // since glTF model should only store info\n    // runtime can have multiple instances of this glTF models\n    this.uniformBlockID = globalUniformBlockID++;\n\n    if (this.inverseBindMatrices) {\n        // should be a mat4\n        this.inverseBindMatricesData = _getAccessorData(this.inverseBindMatrices);\n        // this.inverseBindMatricesMat4 = mat4.fromValues(this.inverseBindMatricesData);\n\n        this.inverseBindMatrix = [];  // for calculation\n        this.jointMatrixUniformBuffer = null;\n        // this.jointMatrixUnidormBufferData = _arrayBuffer2TypedArray(\n        //     this.inverseBindMatricesData, \n        //     0, \n        //     this.inverseBindMatricesData.length, \n        //     this.inverseBindMatrices.componentType\n        // );      // for copy to UBO\n\n        // @tmp: fixed length to coordinate with shader, for copy to UBO\n        this.jointMatrixUnidormBufferData = new Float32Array(NUM_MAX_JOINTS * 16);\n\n        for (i = 0, len = this.inverseBindMatricesData.length; i < len; i += 16) {\n            this.inverseBindMatrix.push(__WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].fromValues(\n                this.inverseBindMatricesData[i],\n                this.inverseBindMatricesData[i + 1],\n                this.inverseBindMatricesData[i + 2],\n                this.inverseBindMatricesData[i + 3],\n                this.inverseBindMatricesData[i + 4],\n                this.inverseBindMatricesData[i + 5],\n                this.inverseBindMatricesData[i + 6],\n                this.inverseBindMatricesData[i + 7],\n                this.inverseBindMatricesData[i + 8],\n                this.inverseBindMatricesData[i + 9],\n                this.inverseBindMatricesData[i + 10],\n                this.inverseBindMatricesData[i + 11],\n                this.inverseBindMatricesData[i + 12],\n                this.inverseBindMatricesData[i + 13],\n                this.inverseBindMatricesData[i + 14],\n                this.inverseBindMatricesData[i + 15]\n            ));\n        }\n    }\n\n};\n\nvar SkinLink = MinimalGLTFLoader.SkinLink = function (gltf, linkedSkin, inverseBindMatricesAccessorID) {\n    this.isLink = true;\n\n    if (!gltf.skins) {\n        gltf.skins = [];\n    }\n    gltf.skins.push(this);\n\n    this.name = linkedSkin.name;\n    // this.skinID = linkedSkin.skinID;   // use this for uniformblock id\n    // this.skinID = gltf.skins.length - 1;\n    // this.skinID = curLoader.skeletonGltf.skins.length + gltf.skins.length - 1;\n    this.skinID = gltf.skins.length - 1;\n\n    this.joints = linkedSkin.joints;\n\n    this.skeleton = linkedSkin.skeleton;\n    this.inverseBindMatrices = inverseBindMatricesAccessorID !== undefined ? gltf.accessors[inverseBindMatricesAccessorID] : null;\n\n    // @tmp: runtime stuff should be taken care of renderer\n    // since glTF model should only store info\n    // runtime can have multiple instances of this glTF models\n    this.uniformBlockID = globalUniformBlockID++;\n    if (this.inverseBindMatrices) {\n        // should be a mat4\n        this.inverseBindMatricesData = _getAccessorData(this.inverseBindMatrices);\n        // this.inverseBindMatricesMat4 = mat4.fromValues(this.inverseBindMatricesData);\n\n        this.inverseBindMatrix = [];  // for calculation\n        this.jointMatrixUniformBuffer = null;\n        // this.jointMatrixUnidormBufferData = _arrayBuffer2TypedArray(\n        //     this.inverseBindMatricesData, \n        //     0, \n        //     this.inverseBindMatricesData.length, \n        //     this.inverseBindMatrices.componentType\n        // );      // for copy to UBO\n\n        // @tmp: fixed length to coordinate with shader, for copy to UBO\n        this.jointMatrixUnidormBufferData = new Float32Array(NUM_MAX_JOINTS * 16);\n\n        for (var i = 0, len = this.inverseBindMatricesData.length; i < len; i += 16) {\n            this.inverseBindMatrix.push(__WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].fromValues(\n                this.inverseBindMatricesData[i],\n                this.inverseBindMatricesData[i + 1],\n                this.inverseBindMatricesData[i + 2],\n                this.inverseBindMatricesData[i + 3],\n                this.inverseBindMatricesData[i + 4],\n                this.inverseBindMatricesData[i + 5],\n                this.inverseBindMatricesData[i + 6],\n                this.inverseBindMatricesData[i + 7],\n                this.inverseBindMatricesData[i + 8],\n                this.inverseBindMatricesData[i + 9],\n                this.inverseBindMatricesData[i + 10],\n                this.inverseBindMatricesData[i + 11],\n                this.inverseBindMatricesData[i + 12],\n                this.inverseBindMatricesData[i + 13],\n                this.inverseBindMatricesData[i + 14],\n                this.inverseBindMatricesData[i + 15]\n            ));\n        }\n    }\n\n    \n\n};\n\n\n\n\n// animation has no potential plan for progressive rendering I guess\n// so everything happens after all buffers are loaded\n\nvar Target = MinimalGLTFLoader.Target = function (t) {\n    this.nodeID = t.node !== undefined ? t.node : null ;  //id, to be hooked up to object later\n    this.path = t.path;     //required, string\n\n    this.extensions = t.extensions !== undefined ? t.extensions : null;\n    this.extras = t.extras !== undefined ? t.extras : null;\n};\n\nvar Channel = MinimalGLTFLoader.Channel = function (c, animation) {\n    this.sampler = animation.samplers[c.sampler];   //required\n    this.target = new Target(c.target);     //required\n\n    this.extensions = c.extensions !== undefined ? c.extensions : null;\n    this.extras = c.extras !== undefined ? c.extras : null;\n};\n\nvar AnimationSampler = MinimalGLTFLoader.AnimationSampler = function (gltf, s) {\n    this.input = gltf.accessors[s.input];   //required, accessor object\n    this.output = gltf.accessors[s.output]; //required, accessor object\n\n    this.inputTypedArray = _getAccessorData(this.input);\n    this.outputTypedArray = _getAccessorData(this.output);\n\n\n    // \"LINEAR\"\n    // \"STEP\"\n    // \"CATMULLROMSPLINE\"\n    // \"CUBICSPLINE\"\n    this.interpolation = s.interpolation !== undefined ? s.interpolation : 'LINEAR' ;\n    \n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n    // ------- extra runtime info -----------\n    // runtime status thing\n    this.curIdx = 0;\n    // this.curValue = 0;\n    this.curValue = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].create();\n    this.endT = this.inputTypedArray[this.inputTypedArray.length - 1];\n    this.inputMax = this.endT - this.inputTypedArray[0];\n};\n\nvar animationOutputValueVec4a = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].create();\nvar animationOutputValueVec4b = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].create();\n\nAnimationSampler.prototype.getValue = function (t) {\n    if (t > this.endT) {\n        t -= this.inputMax * Math.ceil((t - this.endT) / this.inputMax);\n        this.curIdx = 0;\n    }\n\n    var len = this.inputTypedArray.length;\n    while (this.curIdx <= len - 2 && t >= this.inputTypedArray[this.curIdx + 1]) {\n        this.curIdx++;\n    }\n\n\n    if (this.curIdx >= len - 1) {\n        // loop\n        t -= this.inputMax;\n        this.curIdx = 0;\n    }\n\n    // @tmp: assume no stride\n    var count = Type2NumOfComponent[this.output.type];\n    \n    var v4lerp = count === 4 ? __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"quat\"].slerp: __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].lerp;\n\n    var i = this.curIdx;\n    var o = i * count;\n    var on = o + count;\n\n    var u = Math.max( 0, t - this.inputTypedArray[i] ) / (this.inputTypedArray[i+1] - this.inputTypedArray[i]);\n\n    for (var j = 0; j < count; j++ ) {\n        animationOutputValueVec4a[j] = this.outputTypedArray[o + j];\n        animationOutputValueVec4b[j] = this.outputTypedArray[on + j];\n    }\n\n    switch(this.interpolation) {\n        case 'LINEAR': \n        v4lerp(this.curValue, animationOutputValueVec4a, animationOutputValueVec4b, u);\n        break;\n\n        default:\n        break;\n    }\n};\n\n\n\nvar Animation = MinimalGLTFLoader.Animation = function (gltf, a) {\n    this.name = a.name !== undefined ? a.name : null;\n\n    var i, len;\n\n    \n\n    this.samplers = []; // required, array of animation sampler\n    \n    for (i = 0, len = a.samplers.length; i < len; i++) {\n        this.samplers[i] = new AnimationSampler(gltf, a.samplers[i]);\n    }\n\n    this.channels = [];     //required, array of channel\n    \n    for (i = 0, len = a.channels.length; i < len; i++) {\n        this.channels[i] = new Channel(a.channels[i], this);\n    }\n\n    this.extensions = a.extensions !== undefined ? a.extensions : null;\n    this.extras = a.extras !== undefined ? a.extras : null;\n};\n\n\n/**\n * \n */\nvar glTFModel = MinimalGLTFLoader.glTFModel = function (gltf) {\n    this.json = gltf;\n    this.defaultScene = gltf.scene !== undefined ? gltf.scene : 0;\n\n    this.version = Number(gltf.asset.version);\n\n    if (gltf.accessors) {\n        this.accessors = new Array(gltf.accessors.length);\n    }\n\n    if (gltf.bufferViews) {\n        this.bufferViews = new Array(gltf.bufferViews.length);\n    }\n\n    if (gltf.scenes) {\n        this.scenes = new Array(gltf.scenes.length);   // store Scene object\n    }\n\n    if (gltf.nodes) {\n        this.nodes = new Array(gltf.nodes.length);    // store Node object\n    }\n\n    if (gltf.meshes) {\n        this.meshes = new Array(gltf.meshes.length);    // store mesh object\n    }\n\n    if (gltf.materials) {\n        this.materials = new Array(gltf.materials.length);  // store material object\n    }\n\n    if (gltf.textures) {\n        this.textures = new Array(gltf.textures.length);\n    }\n\n    if (gltf.samplers) {\n        this.samplers = new Array(gltf.samplers.length);\n    }\n\n    if (gltf.images) {\n        this.images = new Array(gltf.images.length);\n    }\n\n\n    if (gltf.skins) {\n        this.skins = new Array(gltf.skins.length);\n    }\n\n    if (gltf.animations) {\n        this.animations = new Array(gltf.animations.length);\n    }\n\n    if (gltf.cameras) {\n        this.cameras = new Array(gltf.cameras.length);\n    }\n\n    this.extensions = gltf.extensions !== undefined ? gltf.extensions : null;\n    this.extras = gltf.extras !== undefined ? gltf.extras : null;\n\n};\n\n\n\nvar gl;\n\nvar glTFLoader = MinimalGLTFLoader.glTFLoader = function (glContext) {\n    gl = glContext !== undefined ? glContext : null;\n    this._init();\n    this.glTF = null;\n\n    this.enableGLAvatar = false;\n    this.linkSkeletonGltf = null;\n};\n\nglTFLoader.prototype._init = function() {\n    this._loadDone = false;\n\n    this._bufferRequested = 0;\n    this._bufferLoaded = 0;\n    this._buffers = [];\n    this._bufferTasks = {};\n\n    this._shaderRequested = 0;\n    this._shaderLoaded = 0;\n\n    this._imageRequested = 0;\n    this._imageLoaded = 0;\n\n    this._pendingTasks = 0;\n    this._finishedPendingTasks = 0;\n\n    this.onload = null;\n\n    curLoader = this;\n};\n\n\nglTFLoader.prototype._checkComplete = function () {\n    if (this._bufferRequested == this._bufferLoaded && \n        // this._shaderRequested == this._shaderLoaded && \n        this._imageRequested == this._imageLoaded \n        // && other resources finish loading\n        ) {\n        this._loadDone = true;\n    }\n\n    if (this._loadDone && this._pendingTasks == this._finishedPendingTasks) {\n\n        this._postprocess();\n\n        this.onload(this.glTF);\n    }\n};\n\nglTFLoader.prototype.loadGLTF_GL_Avatar_Skin = function (uri, skeletonGltf, callback) {\n    this.enableGLAvatar = true;\n    this.skeletonGltf = skeletonGltf;\n\n    this.loadGLTF(uri, callback);\n};\n\n/**\n * load a glTF model\n * \n * @param {String} uri uri of the .glTF file. Other resources (bins, images) are assumed to be in the same base path\n * @param {Function} callback the onload callback function\n */\nglTFLoader.prototype.loadGLTF = function (uri, callback) {\n\n    this._init();\n\n    this.onload = callback || function(glTF) {\n        console.log('glTF model loaded.');\n        console.log(glTF);\n    };\n    \n\n    this.baseUri = _getBaseUri(uri);\n\n    var loader = this;\n\n    _loadJSON(uri, function (response) {\n        // Parse JSON string into object\n        var json = JSON.parse(response);\n\n        loader.glTF = new glTFModel(json);\n\n        var bid;\n\n        var loadArrayBufferCallback = function (resource) {\n            \n            loader._buffers[bid] = resource;\n            loader._bufferLoaded++;\n            if (loader._bufferTasks[bid]) {\n                var i,len;\n                for (i = 0, len = loader._bufferTasks[bid].length; i < len; ++i) {\n                    (loader._bufferTasks[bid][i])(resource);\n                }\n            }\n            loader._checkComplete();\n\n        };\n\n        // Launch loading resources task: buffers, etc.\n        if (json.buffers) {\n            for (bid in json.buffers) {\n\n                loader._bufferRequested++;\n\n                _loadArrayBuffer(loader.baseUri + json.buffers[bid].uri, loadArrayBufferCallback);\n\n            }\n        }\n\n        // load images\n        var loadImageCallback = function (img, iid) {\n            loader._imageLoaded++;\n            loader.glTF.images[iid] = img;\n            loader._checkComplete();\n        };\n\n        var iid;\n\n        if (json.images) {\n            for (iid in json.images) {\n                loader._imageRequested++;\n                _loadImage(loader.baseUri + json.images[iid].uri, iid, loadImageCallback);\n            }\n        }\n\n        loader._checkComplete();\n    });\n};\n\n\nglTFLoader.prototype._postprocess = function () {\n    // if there's no plan for progressive loading (streaming)\n    // than simply everything should be placed here\n    \n    // console.log('finish loading all assets, do a second pass postprocess');\n    \n    curLoader = this;\n\n    var i, leni, j, lenj;\n\n    var scene, s;\n    var node;\n    var mesh, primitive, accessor;\n\n    // cameras\n    if (this.glTF.cameras) {\n        for (i = 0, leni = this.glTF.cameras.length; i < leni; i++) {\n            this.glTF.cameras[i] = new Camera(this.glTF.json.cameras[i]);\n        }\n    }\n\n    // bufferviews\n    if (this.glTF.bufferViews) {\n        for (i = 0, leni = this.glTF.bufferViews.length; i < leni; i++) {\n            this.glTF.bufferViews[i] = new BufferView(this.glTF.json.bufferViews[i], this._buffers[ this.glTF.json.bufferViews[i].buffer ]);\n        }\n    }\n\n    // accessors\n    if (this.glTF.accessors) {\n        for (i = 0, leni = this.glTF.accessors.length; i < leni; i++) {\n            this.glTF.accessors[i] = new Accessor(this.glTF.json.accessors[i], this.glTF.bufferViews[ this.glTF.json.accessors[i].bufferView ]);\n        }\n    }\n\n    // load all materials\n    if (this.glTF.materials) {\n        for (i = 0, leni = this.glTF.materials.length; i < leni; i++) {\n            this.glTF.materials[i] = new Material(this.glTF.json.materials[i]);\n        }\n    }\n\n    // load all samplers \n    if (this.glTF.samplers) {\n        for (i = 0, leni = this.glTF.samplers.length; i < leni; i++) {\n            this.glTF.samplers[i] = new Sampler(this.glTF.json.samplers[i]);\n        } \n    }\n\n    // load all textures\n    if (this.glTF.textures) {\n        for (i = 0, leni = this.glTF.textures.length; i < leni; i++) {\n            this.glTF.textures[i] = new Texture(this.glTF.json.textures[i]);\n        }\n    }\n\n    // mesh\n    for (i = 0, leni = this.glTF.meshes.length; i < leni; i++) {\n        this.glTF.meshes[i] = new Mesh(this.glTF.json.meshes[i], i);\n    }\n\n    // node\n    for (i = 0, leni = this.glTF.nodes.length; i < leni; i++) {\n        this.glTF.nodes[i] = new Node(this.glTF.json.nodes[i], i);\n    }\n\n    // node: hook up children\n    for (i = 0, leni = this.glTF.nodes.length; i < leni; i++) {\n        node = this.glTF.nodes[i];\n        for (j = 0, lenj = node.children.length; j < lenj; j++) {\n            node.children[j] = this.glTF.nodes[ node.children[j] ];\n        }\n    }\n\n    // scene Bounding box\n    var nodeMatrix = new Array(this.glTF.nodes.length);\n    for(i = 0, leni = nodeMatrix.length; i < leni; i++) {\n        nodeMatrix[i] = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\n    }\n\n    function execUpdateTransform(n, parent) {\n        var tmpMat4 = nodeMatrix[n.nodeID];\n\n        if (parent !== null) {\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(tmpMat4, nodeMatrix[parent.nodeID], n.matrix);\n        } else {\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].copy(tmpMat4, n.matrix);\n        }\n    }\n\n    function execUpdateBBox(n, parent){\n        var tmpMat4 = nodeMatrix[n.nodeID];\n        var parentBVH;\n\n        if (parent !== null) {\n            parentBVH = parent.bvh;\n        } else {\n            parentBVH = scene.boundingBox;\n        }\n\n        if (n.mesh) {\n            mesh = n.mesh;\n            if (mesh.boundingBox) {\n\n                n.aabb = BoundingBox.getAABBFromOBB(mesh.boundingBox, tmpMat4);\n\n                if (n.children.length === 0) {\n                    // n.bvh = n.aabb;\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].copy(n.bvh.min, n.aabb.min);\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].copy(n.bvh.max, n.aabb.max);\n                }\n            }\n        }\n\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].min(parentBVH.min, parentBVH.min, n.bvh.min);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].max(parentBVH.max, parentBVH.max, n.bvh.max);\n    }\n\n\n    for (i = 0, leni = this.glTF.scenes.length; i < leni; i++) {\n        scene = this.glTF.scenes[i] = new Scene(this.glTF, this.glTF.json.scenes[i]);\n\n        scene.boundingBox = new BoundingBox();\n\n\n        for (j = 0, lenj = scene.nodes.length; j < lenj; j++) {\n            node = scene.nodes[j];\n            // node.traverse(null, execUpdateBBox);\n            node.traverseTwoExecFun(null, execUpdateTransform, execUpdateBBox);\n        }\n\n        scene.boundingBox.calculateTransform();\n    }\n\n\n    for (j = 0, lenj = this.glTF.nodes.length; j < lenj; j++) {\n        node = this.glTF.nodes[j];\n        if (node.bvh !== null) {\n            node.bvh.calculateTransform();\n        }\n    }\n\n\n\n    // load animations (when all accessors are loaded correctly)\n    if (this.glTF.animations) {\n        for (i = 0, leni = this.glTF.animations.length; i < leni; i++) {\n            this.glTF.animations[i] = new Animation(this.glTF, this.glTF.json.animations[i]);\n        }\n    }\n\n    var joints;\n    // if (this.glTF.skins) {\n    if (this.glTF.json.skins) {\n        for (i = 0, leni = this.glTF.skins.length; i < leni; i++) {\n            this.glTF.skins[i] = new Skin(this.glTF, this.glTF.json.skins[i], i);\n            \n\n            joints = this.glTF.skins[i].joints;\n            for (j = 0, lenj = joints.length; j < lenj; j++) {\n                // this.glTF.nodes[ joints[j] ].jointID = j;\n                joints[j].jointID = j;\n            }\n        } \n    }\n\n    for (i = 0, leni = this.glTF.nodes.length; i < leni; i++) {\n        node = this.glTF.nodes[i];\n        if (node.skin !== null) {\n            if (typeof node.skin == 'number') {\n                // usual skin, hook up\n                node.skin = this.glTF.skins[ node.skin ];\n            } else {\n                // assume gl_avatar is in use\n                // do nothing\n            }\n            \n        }\n    } \n    \n\n};\n\n\n// TODO: get from gl context\nvar ComponentType2ByteSize = {\n    5120: 1, // BYTE\n    5121: 1, // UNSIGNED_BYTE\n    5122: 2, // SHORT\n    5123: 2, // UNSIGNED_SHORT\n    5126: 4  // FLOAT\n};\n\nvar Type2NumOfComponent = {\n    'SCALAR': 1,\n    'VEC2': 2,\n    'VEC3': 3,\n    'VEC4': 4,\n    'MAT2': 4,\n    'MAT3': 9,\n    'MAT4': 16\n};\n\n\n// ------ Scope limited private util functions---------------\n\n\n// for animation use\nfunction _arrayBuffer2TypedArray(buffer, byteOffset, countOfComponentType, componentType) {\n    switch(componentType) {\n        // @todo: finish\n        case 5122: return new Int16Array(buffer, byteOffset, countOfComponentType);\n        case 5123: return new Uint16Array(buffer, byteOffset, countOfComponentType);\n        case 5124: return new Int32Array(buffer, byteOffset, countOfComponentType);\n        case 5125: return new Uint32Array(buffer, byteOffset, countOfComponentType);\n        case 5126: return new Float32Array(buffer, byteOffset, countOfComponentType);\n        default: return null; \n    }\n}\n\nfunction _getAccessorData(accessor) {\n    return _arrayBuffer2TypedArray(\n        accessor.bufferView.data, \n        accessor.byteOffset, \n        accessor.count * Type2NumOfComponent[accessor.type],\n        accessor.componentType\n        );\n}\n\nfunction _getBaseUri(uri) {\n    \n    // https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Core/getBaseUri.js\n    \n    var basePath = '';\n    var i = uri.lastIndexOf('/');\n    if(i !== -1) {\n        basePath = uri.substring(0, i + 1);\n    }\n    \n    return basePath;\n}\n\nfunction _loadJSON(src, callback) {\n\n    // native json loading technique from @KryptoniteDove:\n    // http://codepen.io/KryptoniteDove/post/load-json-file-locally-using-pure-javascript\n\n    var xobj = new XMLHttpRequest();\n    xobj.overrideMimeType(\"application/json\");\n    xobj.open('GET', src, true);\n    xobj.onreadystatechange = function () {\n        if (xobj.readyState == 4 && // Request finished, response ready\n            xobj.status == \"200\") { // Status OK\n            callback(xobj.responseText, this);\n        }\n    };\n    xobj.send(null);\n}\n\nfunction _loadArrayBuffer(url, callback) {\n    var xobj = new XMLHttpRequest();\n    xobj.responseType = 'arraybuffer';\n    xobj.open('GET', url, true);\n    xobj.onreadystatechange = function () {\n        if (xobj.readyState == 4 && // Request finished, response ready\n            xobj.status == \"200\") { // Status OK\n            var arrayBuffer = xobj.response;\n            if (arrayBuffer && callback) {\n                callback(arrayBuffer);\n            }\n        }\n    };\n    xobj.send(null);\n}\n\nfunction _loadImage(url, iid, onload) {\n    var img = new Image();\n    img.crossOrigin = \"Anonymous\";\n    img.src = url;\n    img.onload = function() {\n        onload(img, iid);\n    };\n}\n\n// export { MinimalGLTFLoader };\n\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports) {\n\nmodule.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n/***/ })\n/******/ ]);\n});\n\n/***/ }),\n/* 13 */\n/***/ (function(module, exports, __webpack_require__) {\n\n// style-loader: Adds some css to the DOM by adding a <style> tag\n\n// load the styles\nvar content = __webpack_require__(14);\nif(typeof content === 'string') content = [[module.i, content, '']];\n// Prepare cssTransformation\nvar transform;\n\nvar options = {}\noptions.transform = transform\n// add the styles to the DOM\nvar update = __webpack_require__(16)(content, options);\nif(content.locals) module.exports = content.locals;\n// Hot Module Replacement\nif(false) {\n\t// When the styles change, update the <style> tags\n\tif(!content.locals) {\n\t\tmodule.hot.accept(\"!!../node_modules/css-loader/index.js!./style.css\", function() {\n\t\t\tvar newContent = require(\"!!../node_modules/css-loader/index.js!./style.css\");\n\t\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\t\t\tupdate(newContent);\n\t\t});\n\t}\n\t// When the module is disposed, remove the <style> tags\n\tmodule.hot.dispose(function() { update(); });\n}\n\n/***/ }),\n/* 14 */\n/***/ (function(module, exports, __webpack_require__) {\n\nexports = module.exports = __webpack_require__(15)(false);\n// imports\n\n\n// module\nexports.push([module.i, \"body {\\r\\n    color: #cccccc;\\r\\n    font-family: Monospace;\\r\\n    font-size: 13px;\\r\\n    text-align: center;\\r\\n    background-color: #050505;\\r\\n    margin: 0px;\\r\\n    overflow: hidden;\\r\\n}\\r\\n\\r\\n#info {\\r\\n    position: absolute;\\r\\n    top: 0px;\\r\\n    width: 100%;\\r\\n    padding: 5px;\\r\\n}\\r\\n\\r\\n#description {\\r\\n    position: absolute;\\r\\n    top: 20px;\\r\\n    width: 100%;\\r\\n    padding: 5px;\\r\\n}\\r\\n\\r\\n.float {\\r\\n    float: left;\\r\\n    top: 10px;\\r\\n}\\r\\n\\r\\na {\\r\\n    color: #0080ff;\\r\\n}\\r\\n\", \"\"]);\n\n// exports\n\n\n/***/ }),\n/* 15 */\n/***/ (function(module, exports) {\n\n/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\nmodule.exports = function(useSourceMap) {\n\tvar list = [];\n\n\t// return the list of modules as css string\n\tlist.toString = function toString() {\n\t\treturn this.map(function (item) {\n\t\t\tvar content = cssWithMappingToString(item, useSourceMap);\n\t\t\tif(item[2]) {\n\t\t\t\treturn \"@media \" + item[2] + \"{\" + content + \"}\";\n\t\t\t} else {\n\t\t\t\treturn content;\n\t\t\t}\n\t\t}).join(\"\");\n\t};\n\n\t// import a list of modules into the list\n\tlist.i = function(modules, mediaQuery) {\n\t\tif(typeof modules === \"string\")\n\t\t\tmodules = [[null, modules, \"\"]];\n\t\tvar alreadyImportedModules = {};\n\t\tfor(var i = 0; i < this.length; i++) {\n\t\t\tvar id = this[i][0];\n\t\t\tif(typeof id === \"number\")\n\t\t\t\talreadyImportedModules[id] = true;\n\t\t}\n\t\tfor(i = 0; i < modules.length; i++) {\n\t\t\tvar item = modules[i];\n\t\t\t// skip already imported module\n\t\t\t// this implementation is not 100% perfect for weird media query combinations\n\t\t\t//  when a module is imported multiple times with different media queries.\n\t\t\t//  I hope this will never occur (Hey this way we have smaller bundles)\n\t\t\tif(typeof item[0] !== \"number\" || !alreadyImportedModules[item[0]]) {\n\t\t\t\tif(mediaQuery && !item[2]) {\n\t\t\t\t\titem[2] = mediaQuery;\n\t\t\t\t} else if(mediaQuery) {\n\t\t\t\t\titem[2] = \"(\" + item[2] + \") and (\" + mediaQuery + \")\";\n\t\t\t\t}\n\t\t\t\tlist.push(item);\n\t\t\t}\n\t\t}\n\t};\n\treturn list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n\tvar content = item[1] || '';\n\tvar cssMapping = item[3];\n\tif (!cssMapping) {\n\t\treturn content;\n\t}\n\n\tif (useSourceMap && typeof btoa === 'function') {\n\t\tvar sourceMapping = toComment(cssMapping);\n\t\tvar sourceURLs = cssMapping.sources.map(function (source) {\n\t\t\treturn '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'\n\t\t});\n\n\t\treturn [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n\t}\n\n\treturn [content].join('\\n');\n}\n\n// Adapted from convert-source-map (MIT)\nfunction toComment(sourceMap) {\n\t// eslint-disable-next-line no-undef\n\tvar base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n\tvar data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;\n\n\treturn '/*# ' + data + ' */';\n}\n\n\n/***/ }),\n/* 16 */\n/***/ (function(module, exports, __webpack_require__) {\n\n/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n\nvar stylesInDom = {};\n\nvar\tmemoize = function (fn) {\n\tvar memo;\n\n\treturn function () {\n\t\tif (typeof memo === \"undefined\") memo = fn.apply(this, arguments);\n\t\treturn memo;\n\t};\n};\n\nvar isOldIE = memoize(function () {\n\t// Test for IE <= 9 as proposed by Browserhacks\n\t// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805\n\t// Tests for existence of standard globals is to allow style-loader\n\t// to operate correctly into non-standard environments\n\t// @see https://github.com/webpack-contrib/style-loader/issues/177\n\treturn window && document && document.all && !window.atob;\n});\n\nvar getElement = (function (fn) {\n\tvar memo = {};\n\n\treturn function(selector) {\n\t\tif (typeof memo[selector] === \"undefined\") {\n\t\t\tmemo[selector] = fn.call(this, selector);\n\t\t}\n\n\t\treturn memo[selector]\n\t};\n})(function (target) {\n\treturn document.querySelector(target)\n});\n\nvar singleton = null;\nvar\tsingletonCounter = 0;\nvar\tstylesInsertedAtTop = [];\n\nvar\tfixUrls = __webpack_require__(17);\n\nmodule.exports = function(list, options) {\n\tif (typeof DEBUG !== \"undefined\" && DEBUG) {\n\t\tif (typeof document !== \"object\") throw new Error(\"The style-loader cannot be used in a non-browser environment\");\n\t}\n\n\toptions = options || {};\n\n\toptions.attrs = typeof options.attrs === \"object\" ? options.attrs : {};\n\n\t// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>\n\t// tags it will allow on a page\n\tif (!options.singleton) options.singleton = isOldIE();\n\n\t// By default, add <style> tags to the <head> element\n\tif (!options.insertInto) options.insertInto = \"head\";\n\n\t// By default, add <style> tags to the bottom of the target\n\tif (!options.insertAt) options.insertAt = \"bottom\";\n\n\tvar styles = listToStyles(list, options);\n\n\taddStylesToDom(styles, options);\n\n\treturn function update (newList) {\n\t\tvar mayRemove = [];\n\n\t\tfor (var i = 0; i < styles.length; i++) {\n\t\t\tvar item = styles[i];\n\t\t\tvar domStyle = stylesInDom[item.id];\n\n\t\t\tdomStyle.refs--;\n\t\t\tmayRemove.push(domStyle);\n\t\t}\n\n\t\tif(newList) {\n\t\t\tvar newStyles = listToStyles(newList, options);\n\t\t\taddStylesToDom(newStyles, options);\n\t\t}\n\n\t\tfor (var i = 0; i < mayRemove.length; i++) {\n\t\t\tvar domStyle = mayRemove[i];\n\n\t\t\tif(domStyle.refs === 0) {\n\t\t\t\tfor (var j = 0; j < domStyle.parts.length; j++) domStyle.parts[j]();\n\n\t\t\t\tdelete stylesInDom[domStyle.id];\n\t\t\t}\n\t\t}\n\t};\n};\n\nfunction addStylesToDom (styles, options) {\n\tfor (var i = 0; i < styles.length; i++) {\n\t\tvar item = styles[i];\n\t\tvar domStyle = stylesInDom[item.id];\n\n\t\tif(domStyle) {\n\t\t\tdomStyle.refs++;\n\n\t\t\tfor(var j = 0; j < domStyle.parts.length; j++) {\n\t\t\t\tdomStyle.parts[j](item.parts[j]);\n\t\t\t}\n\n\t\t\tfor(; j < item.parts.length; j++) {\n\t\t\t\tdomStyle.parts.push(addStyle(item.parts[j], options));\n\t\t\t}\n\t\t} else {\n\t\t\tvar parts = [];\n\n\t\t\tfor(var j = 0; j < item.parts.length; j++) {\n\t\t\t\tparts.push(addStyle(item.parts[j], options));\n\t\t\t}\n\n\t\t\tstylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};\n\t\t}\n\t}\n}\n\nfunction listToStyles (list, options) {\n\tvar styles = [];\n\tvar newStyles = {};\n\n\tfor (var i = 0; i < list.length; i++) {\n\t\tvar item = list[i];\n\t\tvar id = options.base ? item[0] + options.base : item[0];\n\t\tvar css = item[1];\n\t\tvar media = item[2];\n\t\tvar sourceMap = item[3];\n\t\tvar part = {css: css, media: media, sourceMap: sourceMap};\n\n\t\tif(!newStyles[id]) styles.push(newStyles[id] = {id: id, parts: [part]});\n\t\telse newStyles[id].parts.push(part);\n\t}\n\n\treturn styles;\n}\n\nfunction insertStyleElement (options, style) {\n\tvar target = getElement(options.insertInto)\n\n\tif (!target) {\n\t\tthrow new Error(\"Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.\");\n\t}\n\n\tvar lastStyleElementInsertedAtTop = stylesInsertedAtTop[stylesInsertedAtTop.length - 1];\n\n\tif (options.insertAt === \"top\") {\n\t\tif (!lastStyleElementInsertedAtTop) {\n\t\t\ttarget.insertBefore(style, target.firstChild);\n\t\t} else if (lastStyleElementInsertedAtTop.nextSibling) {\n\t\t\ttarget.insertBefore(style, lastStyleElementInsertedAtTop.nextSibling);\n\t\t} else {\n\t\t\ttarget.appendChild(style);\n\t\t}\n\t\tstylesInsertedAtTop.push(style);\n\t} else if (options.insertAt === \"bottom\") {\n\t\ttarget.appendChild(style);\n\t} else {\n\t\tthrow new Error(\"Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.\");\n\t}\n}\n\nfunction removeStyleElement (style) {\n\tif (style.parentNode === null) return false;\n\tstyle.parentNode.removeChild(style);\n\n\tvar idx = stylesInsertedAtTop.indexOf(style);\n\tif(idx >= 0) {\n\t\tstylesInsertedAtTop.splice(idx, 1);\n\t}\n}\n\nfunction createStyleElement (options) {\n\tvar style = document.createElement(\"style\");\n\n\toptions.attrs.type = \"text/css\";\n\n\taddAttrs(style, options.attrs);\n\tinsertStyleElement(options, style);\n\n\treturn style;\n}\n\nfunction createLinkElement (options) {\n\tvar link = document.createElement(\"link\");\n\n\toptions.attrs.type = \"text/css\";\n\toptions.attrs.rel = \"stylesheet\";\n\n\taddAttrs(link, options.attrs);\n\tinsertStyleElement(options, link);\n\n\treturn link;\n}\n\nfunction addAttrs (el, attrs) {\n\tObject.keys(attrs).forEach(function (key) {\n\t\tel.setAttribute(key, attrs[key]);\n\t});\n}\n\nfunction addStyle (obj, options) {\n\tvar style, update, remove, result;\n\n\t// If a transform function was defined, run it on the css\n\tif (options.transform && obj.css) {\n\t    result = options.transform(obj.css);\n\n\t    if (result) {\n\t    \t// If transform returns a value, use that instead of the original css.\n\t    \t// This allows running runtime transformations on the css.\n\t    \tobj.css = result;\n\t    } else {\n\t    \t// If the transform function returns a falsy value, don't add this css.\n\t    \t// This allows conditional loading of css\n\t    \treturn function() {\n\t    \t\t// noop\n\t    \t};\n\t    }\n\t}\n\n\tif (options.singleton) {\n\t\tvar styleIndex = singletonCounter++;\n\n\t\tstyle = singleton || (singleton = createStyleElement(options));\n\n\t\tupdate = applyToSingletonTag.bind(null, style, styleIndex, false);\n\t\tremove = applyToSingletonTag.bind(null, style, styleIndex, true);\n\n\t} else if (\n\t\tobj.sourceMap &&\n\t\ttypeof URL === \"function\" &&\n\t\ttypeof URL.createObjectURL === \"function\" &&\n\t\ttypeof URL.revokeObjectURL === \"function\" &&\n\t\ttypeof Blob === \"function\" &&\n\t\ttypeof btoa === \"function\"\n\t) {\n\t\tstyle = createLinkElement(options);\n\t\tupdate = updateLink.bind(null, style, options);\n\t\tremove = function () {\n\t\t\tremoveStyleElement(style);\n\n\t\t\tif(style.href) URL.revokeObjectURL(style.href);\n\t\t};\n\t} else {\n\t\tstyle = createStyleElement(options);\n\t\tupdate = applyToTag.bind(null, style);\n\t\tremove = function () {\n\t\t\tremoveStyleElement(style);\n\t\t};\n\t}\n\n\tupdate(obj);\n\n\treturn function updateStyle (newObj) {\n\t\tif (newObj) {\n\t\t\tif (\n\t\t\t\tnewObj.css === obj.css &&\n\t\t\t\tnewObj.media === obj.media &&\n\t\t\t\tnewObj.sourceMap === obj.sourceMap\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tupdate(obj = newObj);\n\t\t} else {\n\t\t\tremove();\n\t\t}\n\t};\n}\n\nvar replaceText = (function () {\n\tvar textStore = [];\n\n\treturn function (index, replacement) {\n\t\ttextStore[index] = replacement;\n\n\t\treturn textStore.filter(Boolean).join('\\n');\n\t};\n})();\n\nfunction applyToSingletonTag (style, index, remove, obj) {\n\tvar css = remove ? \"\" : obj.css;\n\n\tif (style.styleSheet) {\n\t\tstyle.styleSheet.cssText = replaceText(index, css);\n\t} else {\n\t\tvar cssNode = document.createTextNode(css);\n\t\tvar childNodes = style.childNodes;\n\n\t\tif (childNodes[index]) style.removeChild(childNodes[index]);\n\n\t\tif (childNodes.length) {\n\t\t\tstyle.insertBefore(cssNode, childNodes[index]);\n\t\t} else {\n\t\t\tstyle.appendChild(cssNode);\n\t\t}\n\t}\n}\n\nfunction applyToTag (style, obj) {\n\tvar css = obj.css;\n\tvar media = obj.media;\n\n\tif(media) {\n\t\tstyle.setAttribute(\"media\", media)\n\t}\n\n\tif(style.styleSheet) {\n\t\tstyle.styleSheet.cssText = css;\n\t} else {\n\t\twhile(style.firstChild) {\n\t\t\tstyle.removeChild(style.firstChild);\n\t\t}\n\n\t\tstyle.appendChild(document.createTextNode(css));\n\t}\n}\n\nfunction updateLink (link, options, obj) {\n\tvar css = obj.css;\n\tvar sourceMap = obj.sourceMap;\n\n\t/*\n\t\tIf convertToAbsoluteUrls isn't defined, but sourcemaps are enabled\n\t\tand there is no publicPath defined then lets turn convertToAbsoluteUrls\n\t\ton by default.  Otherwise default to the convertToAbsoluteUrls option\n\t\tdirectly\n\t*/\n\tvar autoFixUrls = options.convertToAbsoluteUrls === undefined && sourceMap;\n\n\tif (options.convertToAbsoluteUrls || autoFixUrls) {\n\t\tcss = fixUrls(css);\n\t}\n\n\tif (sourceMap) {\n\t\t// http://stackoverflow.com/a/26603875\n\t\tcss += \"\\n/*# sourceMappingURL=data:application/json;base64,\" + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + \" */\";\n\t}\n\n\tvar blob = new Blob([css], { type: \"text/css\" });\n\n\tvar oldSrc = link.href;\n\n\tlink.href = URL.createObjectURL(blob);\n\n\tif(oldSrc) URL.revokeObjectURL(oldSrc);\n}\n\n\n/***/ }),\n/* 17 */\n/***/ (function(module, exports) {\n\n\n/**\n * When source maps are enabled, `style-loader` uses a link element with a data-uri to\n * embed the css on the page. This breaks all relative urls because now they are relative to a\n * bundle instead of the current page.\n *\n * One solution is to only use full urls, but that may be impossible.\n *\n * Instead, this function \"fixes\" the relative urls to be absolute according to the current page location.\n *\n * A rudimentary test suite is located at `test/fixUrls.js` and can be run via the `npm test` command.\n *\n */\n\nmodule.exports = function (css) {\n  // get current location\n  var location = typeof window !== \"undefined\" && window.location;\n\n  if (!location) {\n    throw new Error(\"fixUrls requires window.location\");\n  }\n\n\t// blank or null?\n\tif (!css || typeof css !== \"string\") {\n\t  return css;\n  }\n\n  var baseUrl = location.protocol + \"//\" + location.host;\n  var currentDir = baseUrl + location.pathname.replace(/\\/[^\\/]*$/, \"/\");\n\n\t// convert each url(...)\n\t/*\n\tThis regular expression is just a way to recursively match brackets within\n\ta string.\n\n\t /url\\s*\\(  = Match on the word \"url\" with any whitespace after it and then a parens\n\t   (  = Start a capturing group\n\t     (?:  = Start a non-capturing group\n\t         [^)(]  = Match anything that isn't a parentheses\n\t         |  = OR\n\t         \\(  = Match a start parentheses\n\t             (?:  = Start another non-capturing groups\n\t                 [^)(]+  = Match anything that isn't a parentheses\n\t                 |  = OR\n\t                 \\(  = Match a start parentheses\n\t                     [^)(]*  = Match anything that isn't a parentheses\n\t                 \\)  = Match a end parentheses\n\t             )  = End Group\n              *\\) = Match anything and then a close parens\n          )  = Close non-capturing group\n          *  = Match anything\n       )  = Close capturing group\n\t \\)  = Match a close parens\n\n\t /gi  = Get all matches, not the first.  Be case insensitive.\n\t */\n\tvar fixedCss = css.replace(/url\\s*\\(((?:[^)(]|\\((?:[^)(]+|\\([^)(]*\\))*\\))*)\\)/gi, function(fullMatch, origUrl) {\n\t\t// strip quotes (if they exist)\n\t\tvar unquotedOrigUrl = origUrl\n\t\t\t.trim()\n\t\t\t.replace(/^\"(.*)\"$/, function(o, $1){ return $1; })\n\t\t\t.replace(/^'(.*)'$/, function(o, $1){ return $1; });\n\n\t\t// already a full url? no change\n\t\tif (/^(#|data:|http:\\/\\/|https:\\/\\/|file:\\/\\/\\/)/i.test(unquotedOrigUrl)) {\n\t\t  return fullMatch;\n\t\t}\n\n\t\t// convert the url to a full url\n\t\tvar newUrl;\n\n\t\tif (unquotedOrigUrl.indexOf(\"//\") === 0) {\n\t\t  \t//TODO: should we add protocol?\n\t\t\tnewUrl = unquotedOrigUrl;\n\t\t} else if (unquotedOrigUrl.indexOf(\"/\") === 0) {\n\t\t\t// path should be relative to the base url\n\t\t\tnewUrl = baseUrl + unquotedOrigUrl; // already starts with '/'\n\t\t} else {\n\t\t\t// path should be relative to current directory\n\t\t\tnewUrl = currentDir + unquotedOrigUrl.replace(/^\\.\\//, \"\"); // Strip leading './'\n\t\t}\n\n\t\t// send back the fixed url(...)\n\t\treturn \"url(\" + JSON.stringify(newUrl) + \")\";\n\t});\n\n\t// send back the fixed css\n\treturn fixedCss;\n};\n\n\n/***/ }),\n/* 18 */\n/***/ (function(module, exports) {\n\nmodule.exports = \"#version 300 es\\n#define POSITION_LOCATION 0\\n\\nprecision highp float;\\nprecision highp int;\\n\\nuniform mat4 u_MVP;\\n\\nlayout(location = POSITION_LOCATION) in vec3 position;\\n\\nvoid main()\\n{\\n    gl_Position = u_MVP * vec4(position, 1.0) ;\\n}\"\n\n/***/ }),\n/* 19 */\n/***/ (function(module, exports) {\n\nmodule.exports = \"#version 300 es\\n#define FRAG_COLOR_LOCATION 0\\n\\nprecision highp float;\\nprecision highp int;\\n\\nlayout(location = FRAG_COLOR_LOCATION) out vec4 color;\\n\\nvoid main()\\n{\\n    color = vec4(1.0, 0.0, 0.0, 1.0);\\n}\"\n\n/***/ }),\n/* 20 */\n/***/ (function(module, exports) {\n\nmodule.exports = \"#version 300 es\\nprecision highp float;\\nprecision highp int;\\n\\nuniform mat4 u_MVP;\\n\\nlayout(location = 0) in vec3 position;\\n\\nout vec3 texcoord;\\n\\nvoid main()\\n{\\n    vec4 pos = u_MVP * vec4(position, 1.0);\\n    gl_Position = pos.xyww;\\n    texcoord = position;\\n}\"\n\n/***/ }),\n/* 21 */\n/***/ (function(module, exports) {\n\nmodule.exports = \"#version 300 es\\nprecision highp float;\\nprecision highp int;\\n\\nuniform samplerCube u_environment;\\n\\nin vec3 texcoord;\\n\\nout vec4 color;\\n\\nvoid main()\\n{\\n    color = texture(u_environment, texcoord);\\n}\"\n\n/***/ }),\n/* 22 */\n/***/ (function(module, exports) {\n\nmodule.exports = \"#define POSITION_LOCATION 0\\r\\n#define NORMAL_LOCATION 1\\r\\n#define TEXCOORD_0_LOCATION 2\\r\\n#define JOINTS_0_LOCATION 3\\r\\n#define JOINTS_1_LOCATION 5\\r\\n#define WEIGHTS_0_LOCATION 4\\r\\n#define WEIGHTS_1_LOCATION 6\\r\\n#define TANGENT_LOCATION 7\\r\\n\\r\\nprecision highp float;\\r\\nprecision highp int;\\r\\n\\r\\nuniform mat4 u_MVP;\\r\\nuniform mat4 u_MV;\\r\\nuniform mat4 u_MVNormal;\\r\\n\\r\\n#ifdef HAS_SKIN\\r\\nuniform JointMatrix\\r\\n{\\r\\n    mat4 matrix[65];\\r\\n} u_jointMatrix;\\r\\n#endif\\r\\n\\r\\nlayout(location = POSITION_LOCATION) in vec3 position;\\r\\nlayout(location = NORMAL_LOCATION) in vec3 normal;\\r\\nlayout(location = TEXCOORD_0_LOCATION) in vec2 uv;\\r\\n\\r\\n#ifdef HAS_SKIN\\r\\nlayout(location = JOINTS_0_LOCATION) in vec4 joint0;\\r\\nlayout(location = WEIGHTS_0_LOCATION) in vec4 weight0;\\r\\n#ifdef SKIN_VEC8\\r\\nlayout(location = JOINTS_1_LOCATION) in vec4 joint1;\\r\\nlayout(location = WEIGHTS_1_LOCATION) in vec4 weight1;\\r\\n#endif\\r\\n#endif\\r\\n\\r\\n\\r\\n// #ifdef HAS_TANGENTS\\r\\n// layout(location = TANGENT_LOCATION) in vec4 tangent;\\r\\n\\r\\n// out vec3 v_tangentW;\\r\\n// out vec3 v_bitangentW;\\r\\n// #endif\\r\\n\\r\\n\\r\\nout vec3 v_position;\\r\\nout vec3 v_normal;\\r\\nout vec2 v_uv;\\r\\n\\r\\nvoid main()\\r\\n{\\r\\n\\r\\n#ifdef HAS_SKIN\\r\\n    mat4 skinMatrix = \\r\\n        weight0.x * u_jointMatrix.matrix[int(joint0.x)] +\\r\\n        weight0.y * u_jointMatrix.matrix[int(joint0.y)] +\\r\\n        weight0.z * u_jointMatrix.matrix[int(joint0.z)] +\\r\\n        weight0.w * u_jointMatrix.matrix[int(joint0.w)];\\r\\n#ifdef SKIN_VEC8\\r\\n    skinMatrix +=\\r\\n        weight1.x * u_jointMatrix.matrix[int(joint1.x)] +\\r\\n        weight1.y * u_jointMatrix.matrix[int(joint1.y)] +\\r\\n        weight1.z * u_jointMatrix.matrix[int(joint1.z)] +\\r\\n        weight1.w * u_jointMatrix.matrix[int(joint1.w)];\\r\\n#endif\\r\\n#endif\\r\\n\\r\\n    v_uv = uv;\\r\\n\\r\\n#ifdef HAS_SKIN\\r\\n    v_normal = normalize(( u_MVNormal * transpose(inverse(skinMatrix)) * vec4(normal, 0)).xyz);\\r\\n    vec4 pos = u_MV * skinMatrix * vec4(position, 1.0);\\r\\n    gl_Position = u_MVP * skinMatrix * vec4(position, 1.0);\\r\\n#else\\r\\n    v_normal = normalize((u_MVNormal * vec4(normal, 0)).xyz);\\r\\n    vec4 pos = u_MV * vec4(position, 1.0);\\r\\n    gl_Position = u_MVP * vec4(position, 1.0);\\r\\n#endif\\r\\n\\r\\n    v_position = vec3(pos.xyz) / pos.w;\\r\\n    \\r\\n    \\r\\n}\"\n\n/***/ }),\n/* 23 */\n/***/ (function(module, exports) {\n\nmodule.exports = \"#define FRAG_COLOR_LOCATION 0\\r\\n\\r\\n// reference: https://github.com/KhronosGroup/glTF-WebGL-PBR/blob/master/shaders/pbr-frag.glsl\\r\\n\\r\\nprecision highp float;\\r\\nprecision highp int;\\r\\n\\r\\n// IBL\\r\\nuniform samplerCube u_DiffuseEnvSampler;\\r\\nuniform samplerCube u_SpecularEnvSampler;\\r\\nuniform sampler2D u_brdfLUT;\\r\\n\\r\\n// Metallic-roughness material\\r\\n\\r\\n// base color\\r\\nuniform vec4 u_baseColorFactor;\\r\\n#ifdef HAS_BASECOLORMAP\\r\\nuniform sampler2D u_baseColorTexture;\\r\\n#endif\\r\\n\\r\\n// normal map\\r\\n#ifdef HAS_NORMALMAP\\r\\nuniform sampler2D u_normalTexture;\\r\\nuniform float u_normalTextureScale;\\r\\n#endif\\r\\n\\r\\n// emmisve map\\r\\n#ifdef HAS_EMISSIVEMAP\\r\\nuniform sampler2D u_emissiveTexture;\\r\\nuniform vec3 u_emissiveFactor;\\r\\n#endif\\r\\n\\r\\n// metal roughness\\r\\n#ifdef HAS_METALROUGHNESSMAP\\r\\nuniform sampler2D u_metallicRoughnessTexture;\\r\\n#endif\\r\\nuniform float u_metallicFactor;\\r\\nuniform float u_roughnessFactor;\\r\\n\\r\\n// occlusion texture\\r\\n#ifdef HAS_OCCLUSIONMAP\\r\\nuniform sampler2D u_occlusionTexture;\\r\\nuniform float u_occlusionStrength;\\r\\n#endif\\r\\n\\r\\nin vec3 v_position;\\r\\nin vec3 v_normal;\\r\\nin vec2 v_uv;\\r\\n\\r\\nlayout(location = FRAG_COLOR_LOCATION) out vec4 frag_color;\\r\\n\\r\\nstruct PBRInfo\\r\\n{\\r\\n    float NdotL;                  // cos angle between normal and light direction\\r\\n    float NdotV;                  // cos angle between normal and view direction\\r\\n    float NdotH;                  // cos angle between normal and half vector\\r\\n    float LdotH;                  // cos angle between light direction and half vector\\r\\n    float VdotH;                  // cos angle between view direction and half vector\\r\\n    float perceptualRoughness;    // roughness value, as authored by the model creator (input to shader)\\r\\n    float metalness;              // metallic value at the surface\\r\\n    vec3 reflectance0;            // full reflectance color (normal incidence angle)\\r\\n    vec3 reflectance90;           // reflectance color at grazing angle\\r\\n    float alphaRoughness;         // roughness mapped to a more linear change in the roughness (proposed by [2])\\r\\n    vec3 diffuseColor;            // color contribution from diffuse lighting\\r\\n    vec3 specularColor;           // color contribution from specular lighting\\r\\n};\\r\\n\\r\\n\\r\\n// vec3 applyNormalMap(vec3 geomnor, vec3 normap) {\\r\\n//     normap = normap * 2.0 - 1.0;\\r\\n//     vec3 up = normalize(vec3(0.01, 1, 0.01));\\r\\n//     vec3 surftan = normalize(cross(geomnor, up));\\r\\n//     vec3 surfbinor = cross(geomnor, surftan);\\r\\n//     return normap.y * surftan * u_normalTextureScale + normap.x * surfbinor * u_normalTextureScale + normap.z * geomnor;\\r\\n// }\\r\\n\\r\\nconst float M_PI = 3.141592653589793;\\r\\nconst float c_MinRoughness = 0.04;\\r\\n\\r\\n\\r\\n// vec3 getNormal()\\r\\n// {\\r\\n\\r\\n// #ifdef HAS_NORMALMAP\\r\\n// #ifdef HAS_TANGENTS\\r\\n//     vec3 n = texture(u_normalTexture, v_uv).rgb;\\r\\n//     n = normalize(v_TBN * (2.0 * n - 1.0) - vec3(u_normalTextureScale, u_normalTextureScale, 1.0));\\r\\n// #else\\r\\n//     vec3 n = applyNormalMap( v_normal, texture(u_normalTexture, v_uv).rgb );\\r\\n// #endif\\r\\n// #else\\r\\n//     vec3 n = v_normal;\\r\\n// #endif\\r\\n//     return n;\\r\\n\\r\\n// #endif\\r\\n// }\\r\\n\\r\\n// Find the normal for this fragment, pulling either from a predefined normal map\\r\\n// or from the interpolated mesh normal and tangent attributes.\\r\\nvec3 getNormal()\\r\\n{\\r\\n\\r\\n// #ifdef HAS_NORMALMAP\\r\\n//     vec3 n = applyNormalMap( v_normal, texture(u_normalTexture, v_uv).rgb );\\r\\n// #else\\r\\n//     vec3 n = v_normal;\\r\\n// #endif\\r\\n//     return n;\\r\\n\\r\\n\\r\\n    // Retrieve the tangent space matrix\\r\\n// #ifndef HAS_TANGENTS\\r\\n    vec3 pos_dx = dFdx(v_position);\\r\\n    vec3 pos_dy = dFdy(v_position);\\r\\n    vec3 tex_dx = dFdx(vec3(v_uv, 0.0));\\r\\n    vec3 tex_dy = dFdy(vec3(v_uv, 0.0));\\r\\n    vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);\\r\\n\\r\\n    vec3 ng = v_normal;\\r\\n// #ifdef HAS_NORMALS\\r\\n//     vec3 ng = normalize(v_normal);\\r\\n// #else\\r\\n//     vec3 ng = cross(pos_dx, pos_dy);\\r\\n// #endif\\r\\n\\r\\n    t = normalize(t - ng * dot(ng, t));\\r\\n    vec3 b = normalize(cross(ng, t));\\r\\n    mat3 tbn = mat3(t, b, ng);\\r\\n// #else // HAS_TANGENTS\\r\\n    // mat3 tbn = v_TBN;\\r\\n// #endif\\r\\n\\r\\n// TODO: TANGENTS\\r\\n\\r\\n#ifdef HAS_NORMALMAP\\r\\n    vec3 n = texture(u_normalTexture, v_uv).rgb;\\r\\n    n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_normalTextureScale, u_normalTextureScale, 1.0)));\\r\\n#else\\r\\n    vec3 n = tbn[2].xyz;\\r\\n#endif\\r\\n\\r\\n    return n;\\r\\n}\\r\\n\\r\\nvec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection)\\r\\n{\\r\\n    // float mipCount = 9.0; // resolution of 512x512\\r\\n    // float mipCount = 10.0; // resolution of 1024x1024\\r\\n    float mipCount = 10.0; // resolution of 256x256\\r\\n    float lod = (pbrInputs.perceptualRoughness * mipCount);\\r\\n    // retrieve a scale and bias to F0. See [1], Figure 3\\r\\n    vec3 brdf = texture(u_brdfLUT, vec2(pbrInputs.NdotV, 1.0 - pbrInputs.perceptualRoughness)).rgb;\\r\\n    vec3 diffuseLight = texture(u_DiffuseEnvSampler, n).rgb;\\r\\n\\r\\n// #ifdef USE_TEX_LOD\\r\\n    vec3 specularLight = texture(u_SpecularEnvSampler, reflection, lod).rgb;\\r\\n// #else\\r\\n    // vec3 specularLight = texture(u_SpecularEnvSampler, reflection).rgb;\\r\\n// #endif\\r\\n\\r\\n    vec3 diffuse = diffuseLight * pbrInputs.diffuseColor;\\r\\n    vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y);\\r\\n\\r\\n    // // For presentation, this allows us to disable IBL terms\\r\\n    // diffuse *= u_ScaleIBLAmbient.x;\\r\\n    // specular *= u_ScaleIBLAmbient.y;\\r\\n\\r\\n    return diffuse + specular;\\r\\n}\\r\\n\\r\\n// Basic Lambertian diffuse\\r\\n// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog\\r\\n// See also [1], Equation 1\\r\\nvec3 diffuse(PBRInfo pbrInputs)\\r\\n{\\r\\n    return pbrInputs.diffuseColor / M_PI;\\r\\n}\\r\\n\\r\\n\\r\\n// The following equation models the Fresnel reflectance term of the spec equation (aka F())\\r\\n// Implementation of fresnel from [4], Equation 15\\r\\nvec3 specularReflection(PBRInfo pbrInputs)\\r\\n{\\r\\n    return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);\\r\\n}\\r\\n\\r\\n\\r\\n// This calculates the specular geometric attenuation (aka G()),\\r\\n// where rougher material will reflect less light back to the viewer.\\r\\n// This implementation is based on [1] Equation 4, and we adopt their modifications to\\r\\n// alphaRoughness as input as originally proposed in [2].\\r\\nfloat geometricOcclusion(PBRInfo pbrInputs)\\r\\n{\\r\\n    float NdotL = pbrInputs.NdotL;\\r\\n    float NdotV = pbrInputs.NdotV;\\r\\n    float r = pbrInputs.alphaRoughness;\\r\\n\\r\\n    float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));\\r\\n    float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));\\r\\n    return attenuationL * attenuationV;\\r\\n}\\r\\n\\r\\n\\r\\n// The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D())\\r\\n// Implementation from \\\"Average Irregularity Representation of a Roughened Surface for Ray Reflection\\\" by T. S. Trowbridge, and K. P. Reitz\\r\\n// Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3.\\r\\nfloat microfacetDistribution(PBRInfo pbrInputs)\\r\\n{\\r\\n    float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;\\r\\n    float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;\\r\\n    return roughnessSq / (M_PI * f * f);\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\nvoid main()\\r\\n{\\r\\n    float perceptualRoughness = u_roughnessFactor;\\r\\n    float metallic = u_metallicFactor;\\r\\n\\r\\n#ifdef HAS_METALROUGHNESSMAP\\r\\n    // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.\\r\\n    // This layout intentionally reserves the 'r' channel for (optional) occlusion map data\\r\\n    vec4 mrSample = texture(u_metallicRoughnessTexture, v_uv);\\r\\n    perceptualRoughness = mrSample.g * perceptualRoughness;\\r\\n    metallic = mrSample.b * metallic;\\r\\n#endif\\r\\n    perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);\\r\\n    metallic = clamp(metallic, 0.0, 1.0);\\r\\n    // Roughness is authored as perceptual roughness; as is convention,\\r\\n    // convert to material roughness by squaring the perceptual roughness [2].\\r\\n    float alphaRoughness = perceptualRoughness * perceptualRoughness;\\r\\n\\r\\n\\r\\n    // The albedo may be defined from a base texture or a flat color\\r\\n#ifdef HAS_BASECOLORMAP\\r\\n    vec4 baseColor = texture(u_baseColorTexture, v_uv) * u_baseColorFactor;\\r\\n#else\\r\\n    vec4 baseColor = u_baseColorFactor;\\r\\n#endif\\r\\n\\r\\n\\r\\n\\r\\n    vec3 f0 = vec3(0.04);\\r\\n    vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);\\r\\n    diffuseColor *= 1.0 - metallic;\\r\\n    vec3 specularColor = mix(f0, baseColor.rgb, metallic);\\r\\n\\r\\n    // Compute reflectance.\\r\\n    float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\\r\\n\\r\\n\\r\\n    // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.\\r\\n    // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.\\r\\n    float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\\r\\n    vec3 specularEnvironmentR0 = specularColor.rgb;\\r\\n    vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;\\r\\n\\r\\n\\r\\n    vec3 n = getNormal();                             // normal at surface point\\r\\n    // vec3 v = vec3( 0.0, 0.0, 1.0 );        // Vector from surface point to camera\\r\\n    vec3 v = normalize(-v_position);                       // Vector from surface point to camera\\r\\n    // vec3 l = normalize(u_LightDirection);             // Vector from surface point to light\\r\\n    vec3 l = normalize(vec3( 1.0, 1.0, 1.0 ));             // Vector from surface point to light\\r\\n    // vec3 l = vec3( 0.0, 0.0, 1.0 );             // Vector from surface point to light\\r\\n    vec3 h = normalize(l+v);                          // Half vector between both l and v\\r\\n    vec3 reflection = -normalize(reflect(v, n));\\r\\n\\r\\n    float NdotL = clamp(dot(n, l), 0.001, 1.0);\\r\\n    float NdotV = abs(dot(n, v)) + 0.001;\\r\\n    float NdotH = clamp(dot(n, h), 0.0, 1.0);\\r\\n    float LdotH = clamp(dot(l, h), 0.0, 1.0);\\r\\n    float VdotH = clamp(dot(v, h), 0.0, 1.0);\\r\\n\\r\\n    PBRInfo pbrInputs = PBRInfo(\\r\\n        NdotL,\\r\\n        NdotV,\\r\\n        NdotH,\\r\\n        LdotH,\\r\\n        VdotH,\\r\\n        perceptualRoughness,\\r\\n        metallic,\\r\\n        specularEnvironmentR0,\\r\\n        specularEnvironmentR90,\\r\\n        alphaRoughness,\\r\\n        diffuseColor,\\r\\n        specularColor\\r\\n    );\\r\\n\\r\\n    // Calculate the shading terms for the microfacet specular shading model\\r\\n    vec3 F = specularReflection(pbrInputs);\\r\\n    float G = geometricOcclusion(pbrInputs);\\r\\n    float D = microfacetDistribution(pbrInputs);\\r\\n\\r\\n    // Calculation of analytical lighting contribution\\r\\n    vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs);\\r\\n    vec3 specContrib = max(vec3(0.0), F * G * D / (4.0 * NdotL * NdotV));\\r\\n    // vec3 color = NdotL * u_LightColor * (diffuseContrib + specContrib);\\r\\n    vec3 color = NdotL * (diffuseContrib + specContrib);    // assume light color vec3(1, 1, 1)\\r\\n\\r\\n    // Calculate lighting contribution from image based lighting source (IBL)\\r\\n// #ifdef USE_IBL\\r\\n    color += getIBLContribution(pbrInputs, n, reflection);\\r\\n// #endif\\r\\n\\r\\n\\r\\n    // Apply optional PBR terms for additional (optional) shading\\r\\n#ifdef HAS_OCCLUSIONMAP\\r\\n    float ao = texture(u_occlusionTexture, v_uv).r;\\r\\n    color = mix(color, color * ao, u_occlusionStrength);\\r\\n#endif\\r\\n\\r\\n#ifdef HAS_EMISSIVEMAP\\r\\n    vec3 emissive = texture(u_emissiveTexture, v_uv).rgb * u_emissiveFactor;\\r\\n    color += emissive;\\r\\n#endif\\r\\n\\r\\n    // // This section uses mix to override final color for reference app visualization\\r\\n    // // of various parameters in the lighting equation.\\r\\n    // color = mix(color, F, u_ScaleFGDSpec.x);\\r\\n    // color = mix(color, vec3(G), u_ScaleFGDSpec.y);\\r\\n    // color = mix(color, vec3(D), u_ScaleFGDSpec.z);\\r\\n    // color = mix(color, specContrib, u_ScaleFGDSpec.w);\\r\\n\\r\\n    // color = mix(color, diffuseContrib, u_ScaleDiffBaseMR.x);\\r\\n    // color = mix(color, baseColor.rgb, u_ScaleDiffBaseMR.y);\\r\\n    // color = mix(color, vec3(metallic), u_ScaleDiffBaseMR.z);\\r\\n    // color = mix(color, vec3(perceptualRoughness), u_ScaleDiffBaseMR.w);\\r\\n\\r\\n    frag_color = vec4(color, baseColor.a);\\r\\n}\"\n\n/***/ })\n/******/ ]);"
  },
  {
    "path": "build/minimal-gltf-loader.js",
    "content": "(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"gl-matrix\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"gl-matrix\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"MinimalGLTFLoader\"] = factory(require(\"gl-matrix\"));\n\telse\n\t\troot[\"MinimalGLTFLoader\"] = factory(root[undefined]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"glTFLoader\", function() { return glTFLoader; });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_gl_matrix__ = __webpack_require__(1);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_gl_matrix___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_gl_matrix__);\n\n\nvar MinimalGLTFLoader = MinimalGLTFLoader || {};\n\nvar globalUniformBlockID = 0;\n\nvar curLoader = null;       // @tmp, might be unsafe if loading multiple model at the same time\n\nvar NUM_MAX_JOINTS = 65;\n\n// Data classes\nvar Scene = MinimalGLTFLoader.Scene = function (gltf, s) {\n    this.name = s.name !== undefined ? s.name : null;\n    this.nodes = new Array(s.nodes.length);    // root node object of this scene\n    for (var i = 0, len = s.nodes.length; i < len; i++) {\n        this.nodes[i] = gltf.nodes[s.nodes[i]];\n    }\n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n\n    this.boundingBox = null;\n};\n\n/**\n * \n * @param {vec3} min\n * @param {vec3} max\n */\nvar BoundingBox = MinimalGLTFLoader.BoundingBox = function (min, max, isClone) {\n    // this.min = min;\n    // this.max = max;\n    min = min || __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);\n    max = max || __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);\n\n    if (isClone === undefined || isClone === true) {\n        this.min = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].clone(min);\n        this.max = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].clone(max);\n    } else {\n        this.min = min;\n        this.max = max;\n    }\n    \n\n    this.transform = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\n};\n\nBoundingBox.prototype.updateBoundingBox = function (bbox) {\n    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].min(this.min, this.min, bbox.min);\n    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].max(this.max, this.max, bbox.max);\n};\n\nBoundingBox.prototype.calculateTransform = function () {\n    // transform from a unit cube whose min = (0, 0, 0) and max = (1, 1, 1)\n\n    // scale\n    this.transform[0] = this.max[0] - this.min[0];\n    this.transform[5] = this.max[1] - this.min[1];\n    this.transform[10] = this.max[2] - this.min[2];\n    // translate\n    this.transform[12] = this.min[0];\n    this.transform[13] = this.min[1];\n    this.transform[14] = this.min[2];\n};\n\nBoundingBox.getAABBFromOBB = (function() {\n    var transformRight = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n    var transformUp = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n    var transformBackward = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n\n    var tmpVec3a = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n    var tmpVec3b = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n\n    return (function (obb, matrix) {\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].set(transformRight, matrix[0], matrix[1], matrix[2]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].set(transformUp, matrix[4], matrix[5], matrix[6]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].set(transformBackward, matrix[8], matrix[9], matrix[10]);\n\n        var min = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(matrix[12], matrix[13], matrix[14]);  // init with matrix translation\n        var max = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].clone(min);\n\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3a, transformRight, obb.min[0]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3b, transformRight, obb.max[0]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].min(transformRight, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(min, min, transformRight);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].max(transformRight, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(max, max, transformRight);\n\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3a, transformUp, obb.min[1]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3b, transformUp, obb.max[1]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].min(transformUp, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(min, min, transformUp);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].max(transformUp, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(max, max, transformUp);\n\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3a, transformBackward, obb.min[2]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].scale(tmpVec3b, transformBackward, obb.max[2]);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].min(transformBackward, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(min, min, transformBackward);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].max(transformBackward, tmpVec3a, tmpVec3b);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].add(max, max, transformBackward);\n\n        var bbox = new BoundingBox(min, max, false);\n        bbox.calculateTransform();\n        return bbox;\n    });\n})();\n\n\n\nvar Accessor = MinimalGLTFLoader.Accessor = function (a, bufferViewObject) {\n    this.bufferView = bufferViewObject;\n    this.componentType = a.componentType;   // required\n    this.byteOffset = a.byteOffset !== undefined ? a.byteOffset : 0;\n    this.byteStride = bufferViewObject.byteStride;\n    this.normalized = a.normalized !== undefined ? a.normalized : false;\n    this.count = a.count;   // required\n    this.type = a.type;     // required\n    this.size = Type2NumOfComponent[this.type];\n\n    this.min = a.min;   // @tmp assume required for now (for bbox)\n    this.max = a.max;   // @tmp assume required for now (for bbox)\n\n    this.extensions = a.extensions !== undefined ? a.extensions : null;\n    this.extras = a.extras !== undefined ? a.extras : null;\n};\n\nAccessor.prototype.prepareVertexAttrib = function(location, gl) {\n    gl.vertexAttribPointer(\n        location,\n        this.size,\n        this.componentType,\n        this.normalized,\n        this.byteStride,\n        this.byteOffset\n        );\n    gl.enableVertexAttribArray(location);\n};\n\nvar BufferView = MinimalGLTFLoader.BufferView = function(bf, bufferData) {\n    this.byteLength = bf.byteLength;    //required\n    this.byteOffset = bf.byteOffset !== undefined ? bf.byteOffset : 0;\n    this.byteStride = bf.byteStride !== undefined ? bf.byteStride : 0;\n    this.target = bf.target !== undefined ? bf.target : null;\n\n    this.data = bufferData.slice(this.byteOffset, this.byteOffset + this.byteLength);\n\n    this.extensions = bf.extensions !== undefined ? bf.extensions : null;\n    this.extras = bf.extras !== undefined ? bf.extras : null;\n\n    // runtime stuffs -------------\n    this.buffer = null;     // gl buffer\n};\n\nBufferView.prototype.createBuffer = function(gl) {\n    this.buffer = gl.createBuffer();\n};\n\nBufferView.prototype.bindData = function(gl) {\n    if (this.target) {\n        gl.bindBuffer(this.target, this.buffer);\n        gl.bufferData(this.target, this.data, gl.STATIC_DRAW);\n        gl.bindBuffer(this.target, null);\n        return true;\n    }\n    return false;\n};\n\n\nvar Camera = MinimalGLTFLoader.Camera = function(c) {\n    this.name = c.name !== undefined ? c.name : null;\n    this.type = c.type; // required\n\n    this.othographic = c.othographic === undefined ? null : c.othographic;  // every attribute inside is required (excluding extensions)\n    this.perspective = c.perspective === undefined ? null : {\n        yfov: c.perspective.yfov,\n        znear: c.perspective.znear,\n        zfar: c.perspective.zfar !== undefined ? c.perspective.zfar : null,\n        aspectRatio: c.perspective.aspectRatio !== undefined ? c.perspective.aspectRatio : null\n    };\n\n    this.extensions = c.extensions !== undefined ? c.extensions : null;\n    this.extras = c.extras !== undefined ? c.extras : null;\n};\n\n\n\nvar Node = MinimalGLTFLoader.Node = function (n, nodeID) {\n    this.name = n.name !== undefined ? n.name : null;\n    this.nodeID = nodeID;\n    // TODO: camera\n    this.camera = n.camera !== undefined ? n.camera : null;\n\n    this.matrix = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\n    if (n.hasOwnProperty('matrix')) {\n        for(var i = 0; i < 16; ++i) {\n            this.matrix[i] = n.matrix[i];\n        }\n\n        this.translation = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].getTranslation(this.translation, this.matrix);\n\n        this.rotation = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"quat\"].create();\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].getRotation(this.rotation, this.matrix);\n\n        this.scale = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].create();\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].getScaling(this.scale, this.matrix);\n    } else {\n        // this.translation = null;\n        // this.rotation = null;\n        // this.scale = null;\n        this.getTransformMatrixFromTRS(n.translation, n.rotation, n.scale);\n    }\n    \n    \n    \n\n    this.children = n.children || [];  // init as id, then hook up to node object later\n    this.mesh = n.mesh !== undefined ? curLoader.glTF.meshes[n.mesh] : null;\n\n    this.skin = n.skin !== undefined ? n.skin : null;   // init as id, then hook up to skin object later\n\n    if (n.extensions !== undefined) {\n        if (n.extensions.gl_avatar !== undefined && curLoader.enableGLAvatar === true) {\n            var linkedSkinID = curLoader.skeletonGltf.json.extensions.gl_avatar.skins[ n.extensions.gl_avatar.skin.name ];\n            var linkedSkin = curLoader.skeletonGltf.skins[linkedSkinID];\n            this.skin = new SkinLink(curLoader.glTF, linkedSkin, n.extensions.gl_avatar.skin.inverseBindMatrices);\n        }\n    }\n    \n\n\n    // TODO: morph targets weights\n    this.weights = n.weights !== undefined ? n.weights : null;\n\n\n    this.extensions = n.extensions !== undefined ? n.extensions : null;\n    this.extras = n.extras !== undefined ? n.extras : null;\n\n    // runtime stuffs--------------\n\n    this.aabb = null;   // axis aligned bounding box, not need to apply node transform to aabb\n    this.bvh = new BoundingBox();\n};\n\nNode.prototype.traverse = function(parent, executeFunc) {\n    executeFunc(this, parent);\n    for (var i = 0, len = this.children.length; i < len; i++) {\n        this.children[i].traverse(this, executeFunc);\n    }\n};\n\nNode.prototype.traversePostOrder = function(parent, executeFunc) {\n    for (var i = 0, len = this.children.length; i < len; i++) {\n        this.children[i].traversePostOrder(this, executeFunc);\n    }\n    executeFunc(this, parent);\n};\n\nNode.prototype.traverseTwoExecFun = function(parent, execFunPre, execFunPos) {\n    execFunPre(this, parent);\n    for (var i = 0, len = this.children.length; i < len; i++) {\n        this.children[i].traverseTwoExecFun(this, execFunPre, execFunPos);\n    }\n    execFunPos(this, parent);\n};\n\nvar TRSMatrix = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\n\nNode.prototype.getTransformMatrixFromTRS = function(translation, rotation, scale) {\n\n    this.translation = translation !== undefined ? __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(translation[0], translation[1], translation[2]) : __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(0, 0, 0);\n    this.rotation = rotation !== undefined ? __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].fromValues(rotation[0], rotation[1], rotation[2], rotation[3]) : __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].fromValues(0, 0, 0, 1);\n    this.scale = scale !== undefined ? __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(scale[0], scale[1], scale[2]) : __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(1, 1, 1);\n\n    this.updateMatrixFromTRS();\n};\n\nNode.prototype.updateMatrixFromTRS = function() {\n    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].fromRotationTranslation(TRSMatrix, this.rotation, this.translation);\n    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].scale(this.matrix, TRSMatrix, this.scale);\n};\n\n\n\nvar Mesh = MinimalGLTFLoader.Mesh = function (m, meshID) {\n    this.meshID = meshID;\n    this.name = m.name !== undefined ? m.name : null;\n\n    this.primitives = [];   // required\n    \n\n\n    // bounding box (runtime stuff)\n    this.boundingBox = null;\n\n    var p, primitive, accessor;\n\n    for (var i = 0, len = m.primitives.length; i < len; ++i) {\n        p = m.primitives[i];\n        primitive = new Primitive(curLoader.glTF, p);\n        this.primitives.push(primitive);\n\n        // bounding box related\n        if (primitive.boundingBox) {\n            if (!this.boundingBox) {\n                this.boundingBox = new BoundingBox();\n            }\n            this.boundingBox.updateBoundingBox(primitive.boundingBox);\n        }\n    }\n\n    if (this.boundingBox) {\n        this.boundingBox.calculateTransform();\n    }\n\n\n    // TODO: weights for morph targets\n    this.weights = m.weights !== undefined ? m.weights : null;\n\n    this.extensions = m.extensions !== undefined ? m.extensions : null;\n    this.extras = m.extras !== undefined ? m.extras : null;\n    \n};\n\nvar Primitive = MinimalGLTFLoader.Primitive = function (gltf, p) {\n    // <attribute name, accessor id>, required\n    // get hook up with accessor object in _postprocessing\n    this.attributes = p.attributes;\n    this.indices = p.indices !== undefined ? p.indices : null;  // accessor id\n\n    var attname;\n    if (p.extensions !== undefined) {\n        if (p.extensions.gl_avatar !== undefined && curLoader.enableGLAvatar === true) {\n            if (p.extensions.gl_avatar.attributes) {\n                for ( attname in p.extensions.gl_avatar.attributes ) {\n                    this.attributes[attname] = p.extensions.gl_avatar.attributes[attname];\n                }\n            }\n        }\n    }\n\n    \n    if (this.indices !== null) {\n        this.indicesComponentType = gltf.json.accessors[this.indices].componentType;\n        this.indicesLength = gltf.json.accessors[this.indices].count;\n        this.indicesOffset = (gltf.json.accessors[this.indices].byteOffset || 0);\n    } else {\n        // assume 'POSITION' is there\n        this.drawArraysCount = gltf.json.accessors[this.attributes.POSITION].count;\n        this.drawArraysOffset = (gltf.json.accessors[this.attributes.POSITION].byteOffset || 0);\n    }\n\n    \n    // hook up accessor object\n    for ( attname in this.attributes ) {\n        this.attributes[attname] = gltf.accessors[ this.attributes[attname] ];\n    }\n\n\n    this.material = p.material !== undefined ? gltf.materials[p.material] : null;\n\n\n    this.mode = p.mode !== undefined ? p.mode : 4; // default: gl.TRIANGLES\n\n    \n\n    // morph related\n    this.targets = p.targets;\n\n\n    this.extensions = p.extensions !== undefined ? p.extensions : null;\n    this.extras = p.extras !== undefined ? p.extras : null;\n\n\n    // ----gl run time related\n    this.vertexArray = null;    //vao\n    \n    this.vertexBuffer = null;\n    this.indexBuffer = null;\n\n\n    this.shader = null;\n\n\n    this.boundingBox = null;\n    if (this.attributes.POSITION !== undefined) {\n        var accessor = this.attributes.POSITION;\n        if (accessor.max) {\n            // @todo: handle cases where no min max are provided\n\n            // assume vec3\n            if (accessor.type === 'VEC3') {\n                this.boundingBox = new BoundingBox(\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(accessor.min[0], accessor.min[1], accessor.min[2]),\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].fromValues(accessor.max[0], accessor.max[1], accessor.max[2]),\n                    false\n                );\n                this.boundingBox.calculateTransform();\n                \n\n                \n            }\n            \n        }\n    }\n};\n\n\nvar Texture = MinimalGLTFLoader.Texture = function (t) {\n    this.name = t.name !== undefined ? t.name : null;\n    this.sampler = t.sampler !== undefined ? curLoader.glTF.samplers[t.sampler] : null;\n    this.source = t.source !== undefined ? curLoader.glTF.images[t.source] : null;\n\n    this.extensions = t.extensions !== undefined ? t.extensions : null;\n    this.extras = t.extras !== undefined ? t.extras : null;\n\n    // runtime\n    this.texture = null;\n};\n\nTexture.prototype.createTexture = function(gl) {\n    this.texture = gl.createTexture();\n    gl.bindTexture(gl.TEXTURE_2D, this.texture);\n    gl.texImage2D(\n        gl.TEXTURE_2D,  // assumed\n        0,        // Level of details\n        // gl.RGB, // Format\n        // gl.RGB,\n        gl.RGBA, // Format\n        gl.RGBA,\n        gl.UNSIGNED_BYTE, // Size of each channel\n        this.source\n    );\n    gl.generateMipmap(gl.TEXTURE_2D);\n    gl.bindTexture(gl.TEXTURE_2D, null);\n};\n\nvar Sampler = MinimalGLTFLoader.Sampler = function (s) {\n    this.name = s.name !== undefined ? s.name : null;\n    this.magFilter = s.magFilter !== undefined ? s.magFilter : null;\n    this.minFilter = s.minFilter !== undefined ? s.minFilter : null;\n    this.wrapS = s.wrapS !== undefined ? s.wrapS : 10497;\n    this.wrapT = s.wrapT !== undefined ? s.wrapT : 10497;\n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n    this.sampler = null;\n};\n\nSampler.prototype.createSampler = function(gl) {\n    this.sampler = gl.createSampler();\n    if (this.minFilter) {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MIN_FILTER, this.minFilter);\n    } else {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);\n    }\n    if (this.magFilter) {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MAG_FILTER, this.magFilter);\n    } else {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n    }\n    gl.samplerParameteri(this.sampler, gl.TEXTURE_WRAP_S, this.wrapS);\n    gl.samplerParameteri(this.sampler, gl.TEXTURE_WRAP_T, this.wrapT);\n};\n\n// Sampler.prototype.bindSampler = function(i, gl) {\n//     gl.bindSampler(i, this.sampler);\n// }\n\nvar TextureInfo = MinimalGLTFLoader.TextureInfo = function (json) {\n    this.index = json.index;\n    this.texCoord = json.texCoord !== undefined ? json.texCoord : 0 ;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar PbrMetallicRoughness = MinimalGLTFLoader.PbrMetallicRoughness = function (json) {\n    this.baseColorFactor = json.baseColorFactor !== undefined ? json.baseColorFactor : [1, 1, 1, 1];\n    this.baseColorTexture = json.baseColorTexture !== undefined ? new TextureInfo(json.baseColorTexture): null;\n    this.metallicFactor = json.metallicFactor !== undefined ? json.metallicFactor : 1 ;\n    this.roughnessFactor = json.roughnessFactor !== undefined ? json.roughnessFactor : 1 ;\n    this.metallicRoughnessTexture = json.metallicRoughnessTexture !== undefined ? new TextureInfo(json.metallicRoughnessTexture): null;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar NormalTextureInfo = MinimalGLTFLoader.NormalTextureInfo = function (json) {\n    this.index = json.index;\n    this.texCoord = json.texCoord !== undefined ? json.texCoord : 0 ;\n    this.scale = json.scale !== undefined ? json.scale : 1 ;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar OcclusionTextureInfo = MinimalGLTFLoader.OcclusionTextureInfo = function (json) {\n    this.index = json.index;\n    this.texCoord = json.texCoord !== undefined ? json.texCoord : 0 ;\n    this.strength = json.strength !== undefined ? json.strength : 1 ;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar Material = MinimalGLTFLoader.Material = function (m) {\n    this.name = m.name !== undefined ? m.name : null;\n    \n    this.pbrMetallicRoughness = m.pbrMetallicRoughness !== undefined ? new PbrMetallicRoughness( m.pbrMetallicRoughness ) : new PbrMetallicRoughness({\n        baseColorFactor: [1, 1, 1, 1],\n        metallicFactor: 1,\n        metallicRoughnessTexture: 1\n    });\n    // this.normalTexture = m.normalTexture !== undefined ? m.normalTexture : null;\n    this.normalTexture = m.normalTexture !== undefined ? new NormalTextureInfo(m.normalTexture) : null;\n    this.occlusionTexture = m.occlusionTexture !== undefined ? new OcclusionTextureInfo(m.occlusionTexture) : null;\n    this.emissiveTexture = m.emissiveTexture !== undefined ? new TextureInfo(m.emissiveTexture) : null;\n\n    this.emissiveFactor = m.emissiveFactor !== undefined ? m.emissiveFactor : [0, 0, 0];\n    this.alphaMode = m.alphaMode !== undefined ? m.alphaMode : \"OPAQUE\";\n    this.alphaCutoff = m.alphaCutoff !== undefined ? m.alphaCutoff : 0.5;\n    this.doubleSided = m.doubleSided || false;\n\n    this.extensions = m.extensions !== undefined ? m.extensions : null;\n    this.extras = m.extras !== undefined ? m.extras : null;\n};\n\n\nvar Skin = MinimalGLTFLoader.Skin = function (gltf, s, skinID) {\n    this.name = s.name !== undefined ? s.name : null;\n    this.skinID = skinID;\n\n    this.joints = new Array(s.joints.length);   // required\n    var i, len;\n    for (i = 0, len = this.joints.length; i < len; i++) {\n        this.joints[i] = gltf.nodes[s.joints[i]];\n    }\n\n    this.skeleton = s.skeleton !== undefined ? gltf.nodes[s.skeleton] : null;\n    this.inverseBindMatrices = s.inverseBindMatrices !== undefined ? gltf.accessors[s.inverseBindMatrices] : null;\n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n\n    // @tmp: runtime stuff should be taken care of renderer\n    // since glTF model should only store info\n    // runtime can have multiple instances of this glTF models\n    this.uniformBlockID = globalUniformBlockID++;\n\n    if (this.inverseBindMatrices) {\n        // should be a mat4\n        this.inverseBindMatricesData = _getAccessorData(this.inverseBindMatrices);\n        // this.inverseBindMatricesMat4 = mat4.fromValues(this.inverseBindMatricesData);\n\n        this.inverseBindMatrix = [];  // for calculation\n        this.jointMatrixUniformBuffer = null;\n        // this.jointMatrixUnidormBufferData = _arrayBuffer2TypedArray(\n        //     this.inverseBindMatricesData, \n        //     0, \n        //     this.inverseBindMatricesData.length, \n        //     this.inverseBindMatrices.componentType\n        // );      // for copy to UBO\n\n        // @tmp: fixed length to coordinate with shader, for copy to UBO\n        this.jointMatrixUnidormBufferData = new Float32Array(NUM_MAX_JOINTS * 16);\n\n        for (i = 0, len = this.inverseBindMatricesData.length; i < len; i += 16) {\n            this.inverseBindMatrix.push(__WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].fromValues(\n                this.inverseBindMatricesData[i],\n                this.inverseBindMatricesData[i + 1],\n                this.inverseBindMatricesData[i + 2],\n                this.inverseBindMatricesData[i + 3],\n                this.inverseBindMatricesData[i + 4],\n                this.inverseBindMatricesData[i + 5],\n                this.inverseBindMatricesData[i + 6],\n                this.inverseBindMatricesData[i + 7],\n                this.inverseBindMatricesData[i + 8],\n                this.inverseBindMatricesData[i + 9],\n                this.inverseBindMatricesData[i + 10],\n                this.inverseBindMatricesData[i + 11],\n                this.inverseBindMatricesData[i + 12],\n                this.inverseBindMatricesData[i + 13],\n                this.inverseBindMatricesData[i + 14],\n                this.inverseBindMatricesData[i + 15]\n            ));\n        }\n    }\n\n};\n\nvar SkinLink = MinimalGLTFLoader.SkinLink = function (gltf, linkedSkin, inverseBindMatricesAccessorID) {\n    this.isLink = true;\n\n    if (!gltf.skins) {\n        gltf.skins = [];\n    }\n    gltf.skins.push(this);\n\n    this.name = linkedSkin.name;\n    // this.skinID = linkedSkin.skinID;   // use this for uniformblock id\n    // this.skinID = gltf.skins.length - 1;\n    // this.skinID = curLoader.skeletonGltf.skins.length + gltf.skins.length - 1;\n    this.skinID = gltf.skins.length - 1;\n\n    this.joints = linkedSkin.joints;\n\n    this.skeleton = linkedSkin.skeleton;\n    this.inverseBindMatrices = inverseBindMatricesAccessorID !== undefined ? gltf.accessors[inverseBindMatricesAccessorID] : null;\n\n    // @tmp: runtime stuff should be taken care of renderer\n    // since glTF model should only store info\n    // runtime can have multiple instances of this glTF models\n    this.uniformBlockID = globalUniformBlockID++;\n    if (this.inverseBindMatrices) {\n        // should be a mat4\n        this.inverseBindMatricesData = _getAccessorData(this.inverseBindMatrices);\n        // this.inverseBindMatricesMat4 = mat4.fromValues(this.inverseBindMatricesData);\n\n        this.inverseBindMatrix = [];  // for calculation\n        this.jointMatrixUniformBuffer = null;\n        // this.jointMatrixUnidormBufferData = _arrayBuffer2TypedArray(\n        //     this.inverseBindMatricesData, \n        //     0, \n        //     this.inverseBindMatricesData.length, \n        //     this.inverseBindMatrices.componentType\n        // );      // for copy to UBO\n\n        // @tmp: fixed length to coordinate with shader, for copy to UBO\n        this.jointMatrixUnidormBufferData = new Float32Array(NUM_MAX_JOINTS * 16);\n\n        for (var i = 0, len = this.inverseBindMatricesData.length; i < len; i += 16) {\n            this.inverseBindMatrix.push(__WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].fromValues(\n                this.inverseBindMatricesData[i],\n                this.inverseBindMatricesData[i + 1],\n                this.inverseBindMatricesData[i + 2],\n                this.inverseBindMatricesData[i + 3],\n                this.inverseBindMatricesData[i + 4],\n                this.inverseBindMatricesData[i + 5],\n                this.inverseBindMatricesData[i + 6],\n                this.inverseBindMatricesData[i + 7],\n                this.inverseBindMatricesData[i + 8],\n                this.inverseBindMatricesData[i + 9],\n                this.inverseBindMatricesData[i + 10],\n                this.inverseBindMatricesData[i + 11],\n                this.inverseBindMatricesData[i + 12],\n                this.inverseBindMatricesData[i + 13],\n                this.inverseBindMatricesData[i + 14],\n                this.inverseBindMatricesData[i + 15]\n            ));\n        }\n    }\n\n    \n\n};\n\n\n\n\n// animation has no potential plan for progressive rendering I guess\n// so everything happens after all buffers are loaded\n\nvar Target = MinimalGLTFLoader.Target = function (t) {\n    this.nodeID = t.node !== undefined ? t.node : null ;  //id, to be hooked up to object later\n    this.path = t.path;     //required, string\n\n    this.extensions = t.extensions !== undefined ? t.extensions : null;\n    this.extras = t.extras !== undefined ? t.extras : null;\n};\n\nvar Channel = MinimalGLTFLoader.Channel = function (c, animation) {\n    this.sampler = animation.samplers[c.sampler];   //required\n    this.target = new Target(c.target);     //required\n\n    this.extensions = c.extensions !== undefined ? c.extensions : null;\n    this.extras = c.extras !== undefined ? c.extras : null;\n};\n\nvar AnimationSampler = MinimalGLTFLoader.AnimationSampler = function (gltf, s) {\n    this.input = gltf.accessors[s.input];   //required, accessor object\n    this.output = gltf.accessors[s.output]; //required, accessor object\n\n    this.inputTypedArray = _getAccessorData(this.input);\n    this.outputTypedArray = _getAccessorData(this.output);\n\n\n    // \"LINEAR\"\n    // \"STEP\"\n    // \"CATMULLROMSPLINE\"\n    // \"CUBICSPLINE\"\n    this.interpolation = s.interpolation !== undefined ? s.interpolation : 'LINEAR' ;\n    \n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n    // ------- extra runtime info -----------\n    // runtime status thing\n    this.curIdx = 0;\n    // this.curValue = 0;\n    this.curValue = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].create();\n    this.endT = this.inputTypedArray[this.inputTypedArray.length - 1];\n    this.inputMax = this.endT - this.inputTypedArray[0];\n};\n\nvar animationOutputValueVec4a = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].create();\nvar animationOutputValueVec4b = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].create();\n\nAnimationSampler.prototype.getValue = function (t) {\n    if (t > this.endT) {\n        t -= this.inputMax * Math.ceil((t - this.endT) / this.inputMax);\n        this.curIdx = 0;\n    }\n\n    var len = this.inputTypedArray.length;\n    while (this.curIdx <= len - 2 && t >= this.inputTypedArray[this.curIdx + 1]) {\n        this.curIdx++;\n    }\n\n\n    if (this.curIdx >= len - 1) {\n        // loop\n        t -= this.inputMax;\n        this.curIdx = 0;\n    }\n\n    // @tmp: assume no stride\n    var count = Type2NumOfComponent[this.output.type];\n    \n    var v4lerp = count === 4 ? __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"quat\"].slerp: __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec4\"].lerp;\n\n    var i = this.curIdx;\n    var o = i * count;\n    var on = o + count;\n\n    var u = Math.max( 0, t - this.inputTypedArray[i] ) / (this.inputTypedArray[i+1] - this.inputTypedArray[i]);\n\n    for (var j = 0; j < count; j++ ) {\n        animationOutputValueVec4a[j] = this.outputTypedArray[o + j];\n        animationOutputValueVec4b[j] = this.outputTypedArray[on + j];\n    }\n\n    switch(this.interpolation) {\n        case 'LINEAR': \n        v4lerp(this.curValue, animationOutputValueVec4a, animationOutputValueVec4b, u);\n        break;\n\n        default:\n        break;\n    }\n};\n\n\n\nvar Animation = MinimalGLTFLoader.Animation = function (gltf, a) {\n    this.name = a.name !== undefined ? a.name : null;\n\n    var i, len;\n\n    \n\n    this.samplers = []; // required, array of animation sampler\n    \n    for (i = 0, len = a.samplers.length; i < len; i++) {\n        this.samplers[i] = new AnimationSampler(gltf, a.samplers[i]);\n    }\n\n    this.channels = [];     //required, array of channel\n    \n    for (i = 0, len = a.channels.length; i < len; i++) {\n        this.channels[i] = new Channel(a.channels[i], this);\n    }\n\n    this.extensions = a.extensions !== undefined ? a.extensions : null;\n    this.extras = a.extras !== undefined ? a.extras : null;\n};\n\n\n/**\n * \n */\nvar glTFModel = MinimalGLTFLoader.glTFModel = function (gltf) {\n    this.json = gltf;\n    this.defaultScene = gltf.scene !== undefined ? gltf.scene : 0;\n\n    this.version = Number(gltf.asset.version);\n\n    if (gltf.accessors) {\n        this.accessors = new Array(gltf.accessors.length);\n    }\n\n    if (gltf.bufferViews) {\n        this.bufferViews = new Array(gltf.bufferViews.length);\n    }\n\n    if (gltf.scenes) {\n        this.scenes = new Array(gltf.scenes.length);   // store Scene object\n    }\n\n    if (gltf.nodes) {\n        this.nodes = new Array(gltf.nodes.length);    // store Node object\n    }\n\n    if (gltf.meshes) {\n        this.meshes = new Array(gltf.meshes.length);    // store mesh object\n    }\n\n    if (gltf.materials) {\n        this.materials = new Array(gltf.materials.length);  // store material object\n    }\n\n    if (gltf.textures) {\n        this.textures = new Array(gltf.textures.length);\n    }\n\n    if (gltf.samplers) {\n        this.samplers = new Array(gltf.samplers.length);\n    }\n\n    if (gltf.images) {\n        this.images = new Array(gltf.images.length);\n    }\n\n\n    if (gltf.skins) {\n        this.skins = new Array(gltf.skins.length);\n    }\n\n    if (gltf.animations) {\n        this.animations = new Array(gltf.animations.length);\n    }\n\n    if (gltf.cameras) {\n        this.cameras = new Array(gltf.cameras.length);\n    }\n\n    this.extensions = gltf.extensions !== undefined ? gltf.extensions : null;\n    this.extras = gltf.extras !== undefined ? gltf.extras : null;\n\n};\n\n\n\nvar gl;\n\nvar glTFLoader = MinimalGLTFLoader.glTFLoader = function (glContext) {\n    gl = glContext !== undefined ? glContext : null;\n    this._init();\n    this.glTF = null;\n\n    this.enableGLAvatar = false;\n    this.linkSkeletonGltf = null;\n};\n\nglTFLoader.prototype._init = function() {\n    this._loadDone = false;\n\n    this._bufferRequested = 0;\n    this._bufferLoaded = 0;\n    this._buffers = [];\n    this._bufferTasks = {};\n\n    this._shaderRequested = 0;\n    this._shaderLoaded = 0;\n\n    this._imageRequested = 0;\n    this._imageLoaded = 0;\n\n    this._pendingTasks = 0;\n    this._finishedPendingTasks = 0;\n\n    this.onload = null;\n\n    curLoader = this;\n};\n\n\nglTFLoader.prototype._checkComplete = function () {\n    if (this._bufferRequested == this._bufferLoaded && \n        // this._shaderRequested == this._shaderLoaded && \n        this._imageRequested == this._imageLoaded \n        // && other resources finish loading\n        ) {\n        this._loadDone = true;\n    }\n\n    if (this._loadDone && this._pendingTasks == this._finishedPendingTasks) {\n\n        this._postprocess();\n\n        this.onload(this.glTF);\n    }\n};\n\nglTFLoader.prototype.loadGLTF_GL_Avatar_Skin = function (uri, skeletonGltf, callback) {\n    this.enableGLAvatar = true;\n    this.skeletonGltf = skeletonGltf;\n\n    this.loadGLTF(uri, callback);\n};\n\n/**\n * load a glTF model\n * \n * @param {String} uri uri of the .glTF file. Other resources (bins, images) are assumed to be in the same base path\n * @param {Function} callback the onload callback function\n */\nglTFLoader.prototype.loadGLTF = function (uri, callback) {\n\n    this._init();\n\n    this.onload = callback || function(glTF) {\n        console.log('glTF model loaded.');\n        console.log(glTF);\n    };\n    \n\n    this.baseUri = _getBaseUri(uri);\n\n    var loader = this;\n\n    _loadJSON(uri, function (response) {\n        // Parse JSON string into object\n        var json = JSON.parse(response);\n\n        loader.glTF = new glTFModel(json);\n\n        var bid;\n\n        var loadArrayBufferCallback = function (resource) {\n            \n            loader._buffers[bid] = resource;\n            loader._bufferLoaded++;\n            if (loader._bufferTasks[bid]) {\n                var i,len;\n                for (i = 0, len = loader._bufferTasks[bid].length; i < len; ++i) {\n                    (loader._bufferTasks[bid][i])(resource);\n                }\n            }\n            loader._checkComplete();\n\n        };\n\n        // Launch loading resources task: buffers, etc.\n        if (json.buffers) {\n            for (bid in json.buffers) {\n\n                loader._bufferRequested++;\n\n                _loadArrayBuffer(loader.baseUri + json.buffers[bid].uri, loadArrayBufferCallback);\n\n            }\n        }\n\n        // load images\n        var loadImageCallback = function (img, iid) {\n            loader._imageLoaded++;\n            loader.glTF.images[iid] = img;\n            loader._checkComplete();\n        };\n\n        var iid;\n\n        if (json.images) {\n            for (iid in json.images) {\n                loader._imageRequested++;\n                _loadImage(loader.baseUri + json.images[iid].uri, iid, loadImageCallback);\n            }\n        }\n\n        loader._checkComplete();\n    });\n};\n\n\nglTFLoader.prototype._postprocess = function () {\n    // if there's no plan for progressive loading (streaming)\n    // than simply everything should be placed here\n    \n    // console.log('finish loading all assets, do a second pass postprocess');\n    \n    curLoader = this;\n\n    var i, leni, j, lenj;\n\n    var scene, s;\n    var node;\n    var mesh, primitive, accessor;\n\n    // cameras\n    if (this.glTF.cameras) {\n        for (i = 0, leni = this.glTF.cameras.length; i < leni; i++) {\n            this.glTF.cameras[i] = new Camera(this.glTF.json.cameras[i]);\n        }\n    }\n\n    // bufferviews\n    if (this.glTF.bufferViews) {\n        for (i = 0, leni = this.glTF.bufferViews.length; i < leni; i++) {\n            this.glTF.bufferViews[i] = new BufferView(this.glTF.json.bufferViews[i], this._buffers[ this.glTF.json.bufferViews[i].buffer ]);\n        }\n    }\n\n    // accessors\n    if (this.glTF.accessors) {\n        for (i = 0, leni = this.glTF.accessors.length; i < leni; i++) {\n            this.glTF.accessors[i] = new Accessor(this.glTF.json.accessors[i], this.glTF.bufferViews[ this.glTF.json.accessors[i].bufferView ]);\n        }\n    }\n\n    // load all materials\n    if (this.glTF.materials) {\n        for (i = 0, leni = this.glTF.materials.length; i < leni; i++) {\n            this.glTF.materials[i] = new Material(this.glTF.json.materials[i]);\n        }\n    }\n\n    // load all samplers \n    if (this.glTF.samplers) {\n        for (i = 0, leni = this.glTF.samplers.length; i < leni; i++) {\n            this.glTF.samplers[i] = new Sampler(this.glTF.json.samplers[i]);\n        } \n    }\n\n    // load all textures\n    if (this.glTF.textures) {\n        for (i = 0, leni = this.glTF.textures.length; i < leni; i++) {\n            this.glTF.textures[i] = new Texture(this.glTF.json.textures[i]);\n        }\n    }\n\n    // mesh\n    for (i = 0, leni = this.glTF.meshes.length; i < leni; i++) {\n        this.glTF.meshes[i] = new Mesh(this.glTF.json.meshes[i], i);\n    }\n\n    // node\n    for (i = 0, leni = this.glTF.nodes.length; i < leni; i++) {\n        this.glTF.nodes[i] = new Node(this.glTF.json.nodes[i], i);\n    }\n\n    // node: hook up children\n    for (i = 0, leni = this.glTF.nodes.length; i < leni; i++) {\n        node = this.glTF.nodes[i];\n        for (j = 0, lenj = node.children.length; j < lenj; j++) {\n            node.children[j] = this.glTF.nodes[ node.children[j] ];\n        }\n    }\n\n    // scene Bounding box\n    var nodeMatrix = new Array(this.glTF.nodes.length);\n    for(i = 0, leni = nodeMatrix.length; i < leni; i++) {\n        nodeMatrix[i] = __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].create();\n    }\n\n    function execUpdateTransform(n, parent) {\n        var tmpMat4 = nodeMatrix[n.nodeID];\n\n        if (parent !== null) {\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].mul(tmpMat4, nodeMatrix[parent.nodeID], n.matrix);\n        } else {\n            __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"mat4\"].copy(tmpMat4, n.matrix);\n        }\n    }\n\n    function execUpdateBBox(n, parent){\n        var tmpMat4 = nodeMatrix[n.nodeID];\n        var parentBVH;\n\n        if (parent !== null) {\n            parentBVH = parent.bvh;\n        } else {\n            parentBVH = scene.boundingBox;\n        }\n\n        if (n.mesh) {\n            mesh = n.mesh;\n            if (mesh.boundingBox) {\n\n                n.aabb = BoundingBox.getAABBFromOBB(mesh.boundingBox, tmpMat4);\n\n                if (n.children.length === 0) {\n                    // n.bvh = n.aabb;\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].copy(n.bvh.min, n.aabb.min);\n                    __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].copy(n.bvh.max, n.aabb.max);\n                }\n            }\n        }\n\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].min(parentBVH.min, parentBVH.min, n.bvh.min);\n        __WEBPACK_IMPORTED_MODULE_0_gl_matrix__[\"vec3\"].max(parentBVH.max, parentBVH.max, n.bvh.max);\n    }\n\n\n    for (i = 0, leni = this.glTF.scenes.length; i < leni; i++) {\n        scene = this.glTF.scenes[i] = new Scene(this.glTF, this.glTF.json.scenes[i]);\n\n        scene.boundingBox = new BoundingBox();\n\n\n        for (j = 0, lenj = scene.nodes.length; j < lenj; j++) {\n            node = scene.nodes[j];\n            // node.traverse(null, execUpdateBBox);\n            node.traverseTwoExecFun(null, execUpdateTransform, execUpdateBBox);\n        }\n\n        scene.boundingBox.calculateTransform();\n    }\n\n\n    for (j = 0, lenj = this.glTF.nodes.length; j < lenj; j++) {\n        node = this.glTF.nodes[j];\n        if (node.bvh !== null) {\n            node.bvh.calculateTransform();\n        }\n    }\n\n\n\n    // load animations (when all accessors are loaded correctly)\n    if (this.glTF.animations) {\n        for (i = 0, leni = this.glTF.animations.length; i < leni; i++) {\n            this.glTF.animations[i] = new Animation(this.glTF, this.glTF.json.animations[i]);\n        }\n    }\n\n    var joints;\n    // if (this.glTF.skins) {\n    if (this.glTF.json.skins) {\n        for (i = 0, leni = this.glTF.skins.length; i < leni; i++) {\n            this.glTF.skins[i] = new Skin(this.glTF, this.glTF.json.skins[i], i);\n            \n\n            joints = this.glTF.skins[i].joints;\n            for (j = 0, lenj = joints.length; j < lenj; j++) {\n                // this.glTF.nodes[ joints[j] ].jointID = j;\n                joints[j].jointID = j;\n            }\n        } \n    }\n\n    for (i = 0, leni = this.glTF.nodes.length; i < leni; i++) {\n        node = this.glTF.nodes[i];\n        if (node.skin !== null) {\n            if (typeof node.skin == 'number') {\n                // usual skin, hook up\n                node.skin = this.glTF.skins[ node.skin ];\n            } else {\n                // assume gl_avatar is in use\n                // do nothing\n            }\n            \n        }\n    } \n    \n\n};\n\n\n// TODO: get from gl context\nvar ComponentType2ByteSize = {\n    5120: 1, // BYTE\n    5121: 1, // UNSIGNED_BYTE\n    5122: 2, // SHORT\n    5123: 2, // UNSIGNED_SHORT\n    5126: 4  // FLOAT\n};\n\nvar Type2NumOfComponent = {\n    'SCALAR': 1,\n    'VEC2': 2,\n    'VEC3': 3,\n    'VEC4': 4,\n    'MAT2': 4,\n    'MAT3': 9,\n    'MAT4': 16\n};\n\n\n// ------ Scope limited private util functions---------------\n\n\n// for animation use\nfunction _arrayBuffer2TypedArray(buffer, byteOffset, countOfComponentType, componentType) {\n    switch(componentType) {\n        // @todo: finish\n        case 5122: return new Int16Array(buffer, byteOffset, countOfComponentType);\n        case 5123: return new Uint16Array(buffer, byteOffset, countOfComponentType);\n        case 5124: return new Int32Array(buffer, byteOffset, countOfComponentType);\n        case 5125: return new Uint32Array(buffer, byteOffset, countOfComponentType);\n        case 5126: return new Float32Array(buffer, byteOffset, countOfComponentType);\n        default: return null; \n    }\n}\n\nfunction _getAccessorData(accessor) {\n    return _arrayBuffer2TypedArray(\n        accessor.bufferView.data, \n        accessor.byteOffset, \n        accessor.count * Type2NumOfComponent[accessor.type],\n        accessor.componentType\n        );\n}\n\nfunction _getBaseUri(uri) {\n    \n    // https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Core/getBaseUri.js\n    \n    var basePath = '';\n    var i = uri.lastIndexOf('/');\n    if(i !== -1) {\n        basePath = uri.substring(0, i + 1);\n    }\n    \n    return basePath;\n}\n\nfunction _loadJSON(src, callback) {\n\n    // native json loading technique from @KryptoniteDove:\n    // http://codepen.io/KryptoniteDove/post/load-json-file-locally-using-pure-javascript\n\n    var xobj = new XMLHttpRequest();\n    xobj.overrideMimeType(\"application/json\");\n    xobj.open('GET', src, true);\n    xobj.onreadystatechange = function () {\n        if (xobj.readyState == 4 && // Request finished, response ready\n            xobj.status == \"200\") { // Status OK\n            callback(xobj.responseText, this);\n        }\n    };\n    xobj.send(null);\n}\n\nfunction _loadArrayBuffer(url, callback) {\n    var xobj = new XMLHttpRequest();\n    xobj.responseType = 'arraybuffer';\n    xobj.open('GET', url, true);\n    xobj.onreadystatechange = function () {\n        if (xobj.readyState == 4 && // Request finished, response ready\n            xobj.status == \"200\") { // Status OK\n            var arrayBuffer = xobj.response;\n            if (arrayBuffer && callback) {\n                callback(arrayBuffer);\n            }\n        }\n    };\n    xobj.send(null);\n}\n\nfunction _loadImage(url, iid, onload) {\n    var img = new Image();\n    img.crossOrigin = \"Anonymous\";\n    img.src = url;\n    img.onload = function() {\n        onload(img, iid);\n    };\n}\n\n// export { MinimalGLTFLoader };\n\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports) {\n\nmodule.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n/***/ })\n/******/ ]);\n});"
  },
  {
    "path": "css/style.css",
    "content": "body {\r\n    color: #cccccc;\r\n    font-family: Monospace;\r\n    font-size: 13px;\r\n    text-align: center;\r\n    background-color: #050505;\r\n    margin: 0px;\r\n    overflow: hidden;\r\n}\r\n\r\n#info {\r\n    position: absolute;\r\n    top: 0px;\r\n    width: 100%;\r\n    padding: 5px;\r\n}\r\n\r\n#description {\r\n    position: absolute;\r\n    top: 20px;\r\n    width: 100%;\r\n    padding: 5px;\r\n}\r\n\r\n.float {\r\n    float: left;\r\n    top: 10px;\r\n}\r\n\r\na {\r\n    color: #0080ff;\r\n}\r\n"
  },
  {
    "path": "examples/occlusion-culling-demo.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <title>Occlusion culling with hierarchy demo</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <script src=\"../src/third-party/gl-matrix-min.js\"></script>\n    <script src=\"../src/minimal-gltf-loader.js\"></script>\n    <script src=\"utility.js\"></script>\n    <style>\n        #controls {\n            position: absolute;\n            bottom: 20px;\n            right: 20px;\n            color: white;\n        }\n    </style>\n</head>\n\n<body>\n    <div id=\"info\">Occlusion culling with hierarchy demo</div>\n    <p id=\"description\">\n        https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter06.html\n    </p>\n    <div id=\"controls\">\n        Draw Bounding Box: <input id=\"bbox-toggle\" type=\"checkbox\" checked><br>\n        Bounding Box type: <select id=\"bbox-type\">\n            <option value=\"aabb\">AABB</option>\n            <option value=\"obb\">OBB</option>\n            <option value=\"bvh\">BVH</option>\n        </select>\n    </div>\n\n    <script id=\"vs-bbox\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n\n        void main()\n        {\n            gl_Position = u_MVP * vec4(position, 1.0) ;\n        }\n    </script>\n\n    <script id=\"fs-bbox\" type=\"x-shader/x-fragment\">\n        #version 300 es\n        #define FRAG_COLOR_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        layout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\n        void main()\n        {\n            color = vec4(1.0, 0.0, 0.0, 1.0);\n        }\n    </script>\n\n    <script id=\"vs-normal\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n        #define NORMAL_LOCATION 1\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n        uniform mat4 u_MVNormal;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n        layout(location = NORMAL_LOCATION) in vec3 normal;\n\n        out vec3 v_normal;\n\n        void main()\n        {\n            v_normal = normalize((u_MVNormal * vec4(normal, 0)).xyz);\n            gl_Position = u_MVP * vec4(position, 1.0) ;\n        }\n    </script>\n\n    <script id=\"fs-normal\" type=\"x-shader/x-fragment\">\n        #version 300 es\n        #define FRAG_COLOR_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        in vec3 v_normal;\n\n        layout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\n        void main()\n        {\n            color = vec4(v_normal, 1.0);\n            //color = vec4(1.0, 1.0, 1.0, 1.0);\n        }\n    </script>\n\n    <script id=\"fs-base-color\" type=\"x-shader/x-fragment\">\n        #version 300 es\n        #define FRAG_COLOR_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        uniform vec4 u_baseColorFactor;\n\n        in vec3 v_normal;\n\n        layout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\n        void main()\n        {\n            float intensity = dot(v_normal, vec3(0.0, 0.0, 1.0));\n            color = u_baseColorFactor * intensity; \n        }\n    </script>\n\n    <script id=\"vs-texture\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n        #define NORMAL_LOCATION 1\n        #define UV_LOCATION 2\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n        uniform mat4 u_MVNormal;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n        layout(location = NORMAL_LOCATION) in vec3 normal;\n        layout(location = UV_LOCATION) in vec2 uv;\n\n        out vec3 v_normal;\n        out vec2 v_uv;\n\n        void main()\n        {\n            v_normal = normalize((u_MVNormal * vec4(normal, 0)).xyz);\n            v_uv = uv;\n            gl_Position = u_MVP * vec4(position, 1.0) ;\n        }\n    </script>\n\n    <script id=\"fs-texture\" type=\"x-shader/x-fragment\">\n        #version 300 es\n        #define FRAG_COLOR_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        uniform vec4 u_baseColorFactor;\n        uniform sampler2D u_baseColorTexture;\n\n        in vec3 v_normal;\n        in vec2 v_uv;\n\n        layout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\n        void main()\n        {\n            float intensity = dot(v_normal, vec3(0.0, 0.0, 1.0));\n            color = u_baseColorFactor * texture(u_baseColorTexture, v_uv) * intensity; \n        }\n    </script>\n\n\n    <script>\n    // var testNodeId = 0;\n    (function()  {\n        'use strict';\n\n        var drawBoundingBox = true;\n        var boundingBoxType = 'aabb';    // false: obb\n\n        document.getElementById(\"bbox-toggle\").addEventListener(\"change\", function() {\n            drawBoundingBox = this.checked;\n        });\n\n        document.getElementById(\"bbox-type\").addEventListener(\"change\", function() {\n            boundingBoxType = this.value;\n        });\n\n        var canvas = document.createElement('canvas');\n        // canvas.width = Math.min(window.innerWidth, window.innerHeight);\n        // canvas.height = canvas.width;\n        canvas.width = window.innerWidth;\n        canvas.height = window.innerHeight;\n        document.body.appendChild(canvas);\n\n        var gl = canvas.getContext( 'webgl2', { antialias: true } );\n        var isWebGL2 = !!gl;\n        if(!isWebGL2) {\n            document.getElementById('info').innerHTML = 'WebGL 2 is not available.  See <a href=\"https://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation\">How to get a WebGL 2 implementation</a>';\n            return;\n        }\n\n\n        // Scene object for runtime renderer\n        var Scene = function(glTFScene, glTF) {\n            this.glTFScene = glTFScene;\n\n            // runtime renderer context\n            this.rootTransform = mat4.create();\n            // @temp, assume every node is in current scene\n            this.nodeMatrix = new Array(glTF.nodes.length);\n            for(var i = 0, len = this.nodeMatrix.length; i < len; i++) {\n                this.nodeMatrix[i] = mat4.create();\n            }\n        };\n\n        var BOUNDING_BOX = {\n            vertexData: new Float32Array([\n                0.0, 0.0, 0.0,\n                1.0, 0.0, 0.0,\n                0.0, 0.0, 0.0,\n                0.0, 1.0, 0.0,\n                0.0, 0.0, 0.0,\n                0.0, 0.0, 1.0,\n\n                0.0, 1.0, 1.0,\n                1.0, 1.0, 1.0,\n                0.0, 1.0, 1.0,\n                0.0, 1.0, 0.0,\n                0.0, 1.0, 1.0,\n                0.0, 0.0, 1.0,\n\n                1.0, 1.0, 0.0,\n                1.0, 1.0, 1.0,\n                1.0, 1.0, 0.0,\n                0.0, 1.0, 0.0,\n                1.0, 1.0, 0.0,\n                1.0, 0.0, 0.0,\n\n                1.0, 0.0, 1.0,\n                1.0, 0.0, 0.0,\n                1.0, 0.0, 1.0,\n                1.0, 1.0, 1.0,\n                1.0, 0.0, 1.0,\n                0.0, 0.0, 1.0\n            ]),\n\n            vertexArray: gl.createVertexArray(),\n            vertexBuffer: gl.createBuffer(),\n\n            program: createProgram(gl, getShaderSource('vs-bbox'), getShaderSource('fs-bbox')),\n            positionLocation: 0,\n            uniformMvpLocation: 0, \n\n            \n            draw: (function() {\n                var MVP = mat4.create();\n                return (function(bbox, nodeTransform, V, P) {\n                    gl.useProgram(this.program);\n\n                    mat4.mul(MVP, nodeTransform, bbox.transform);\n                    mat4.mul(MVP, V, MVP);\n                    mat4.mul(MVP, P, MVP);\n\n                    gl.uniformMatrix4fv(this.uniformMvpLocation, false, MVP);\n                    gl.bindVertexArray(this.vertexArray);\n                    gl.drawArrays(gl.LINES, 0, 24);\n                    gl.bindVertexArray(null);\n                });\n            })()\n        };\n\n        \n\n        var defaultSampler = gl.createSampler();\n        gl.samplerParameteri(defaultSampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);\n        gl.samplerParameteri(defaultSampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n        gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_S, gl.REPEAT);\n        gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_T, gl.REPEAT);\n        // gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_R, gl.REPEAT);\n        // gl.samplerParameterf(defaultSampler, gl.TEXTURE_MIN_LOD, -1000.0);\n        // gl.samplerParameterf(defaultSampler, gl.TEXTURE_MAX_LOD, 1000.0);\n        // gl.samplerParameteri(defaultSampler, gl.TEXTURE_COMPARE_MODE, gl.NONE);\n        // gl.samplerParameteri(defaultSampler, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);\n\n        BOUNDING_BOX.uniformMvpLocation = gl.getUniformLocation(BOUNDING_BOX.program, \"u_MVP\");\n\n        gl.bindVertexArray(BOUNDING_BOX.vertexArray);\n\n        gl.bindBuffer(gl.ARRAY_BUFFER, BOUNDING_BOX.vertexBuffer);\n        gl.bufferData(gl.ARRAY_BUFFER, BOUNDING_BOX.vertexData, gl.STATIC_DRAW);\n        gl.vertexAttribPointer(BOUNDING_BOX.positionLocation, 3, gl.FLOAT, false, 0, 0);\n        gl.enableVertexAttribArray(BOUNDING_BOX.positionLocation);\n\n        gl.bindVertexArray(null);\n\n\n\n        // // -- Initialize program\n        // var program = createProgram(gl, getShaderSource('vs-normal'), getShaderSource('fs-normal'));\n        // var uniformMvpLocation = gl.getUniformLocation(program, \"u_MVP\");\n        // var uniformMvNormalLocation = gl.getUniformLocation(program, \"u_MVNormal\");\n\n        // var program = createProgram(gl, getShaderSource('vs-normal'), getShaderSource('fs-base-color'));\n        // var uniformMvpLocation = gl.getUniformLocation(program, \"u_MVP\");\n        // var uniformMvNormalLocation = gl.getUniformLocation(program, \"u_MVNormal\");\n        // var uniformBaseColorFactorLocation = gl.getUniformLocation(program, \"u_baseColorFactor\");\n\n        var program = createProgram(gl, getShaderSource('vs-normal'), getShaderSource('fs-base-color'));\n        var programBaseColor = {\n            program: program,\n            uniformMvpLocation: gl.getUniformLocation(program, \"u_MVP\"),\n            uniformMvNormalLocation: gl.getUniformLocation(program, \"u_MVNormal\"),\n            uniformBaseColorFactorLocation: gl.getUniformLocation(program, \"u_baseColorFactor\")\n        };\n\n        program = createProgram(gl, getShaderSource('vs-texture'), getShaderSource('fs-texture'));\n        var programBaseTexture = {\n            program: program,\n            uniformMvpLocation: gl.getUniformLocation(program, \"u_MVP\"),\n            uniformMvNormalLocation: gl.getUniformLocation(program, \"u_MVNormal\"),\n            uniformBaseColorFactorLocation: gl.getUniformLocation(program, \"u_baseColorFactor\"),\n            uniformBaseColorTextureLocation: gl.getUniformLocation(program, \"u_baseColorTexture\"),\n        };\n\n        \n        // -- Mouse Behaviour\n        var s = 1;\n        // var s = 1;\n        // var t = -100;\n        var translate = vec3.create();\n        // var t = -5;\n        var modelMatrix = mat4.create();\n        var mouseDown = false;\n        var lastMouseY = 0;\n        var identityQ = quat.create();\n        window.onmousedown = function(event) {\n            mouseDown = true;\n            lastMouseY = event.clientY;\n        };\n        window.onmouseup = function(event) {\n            mouseDown = false;  \n        };\n        window.onmousemove = function(event) {\n            if(!mouseDown) {\n                return;\n            }\n            var newY = event.clientY;\n            \n            var deltaY = newY - lastMouseY;\n            \n            // s += deltaY / 1000;\n            s *= (1 + deltaY / 1000);\n            \n            lastMouseY = newY;\n        };\n        window.onwheel = function(event) {\n            translate[2] += -event.deltaY * 0.01;\n            // translate[2] *= 1 + (-event.deltaY * 0.01);\n        };\n\n        \n        // 2.0\n        // var gltfUrl = '../glTFs/glTF_version_2/Duck/glTF/Duck.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/2CylinderEngine/glTF/2CylinderEngine.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/GearboxAssy/glTF/GearboxAssy.gltf';\n        var gltfUrl = '../glTFs/glTF_version_2/Buggy/glTF/Buggy.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/DamagedHelmet/glTF/DamagedHelmet.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/Avocado/glTF/Avocado.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/BoomBox/glTF/BoomBox.gltf';\n\n        var glTFLoader = new MinimalGLTFLoader.glTFLoader(gl);\n\n        var glTFModelCount = 3;\n        var scenes = [];\n\n        glTFLoader.loadGLTF(gltfUrl, function(glTF) {\n\n            var curScene = glTF.scenes[glTF.defaultScene];\n\n            // // draw multiple copies of the glTF scene\n            // // to build a relative complex scene for octree and occlusion query test\n            // var sceneRootTransforms = [mat4.create(), mat4.create()];\n            // var sceneDeltaTranslate = vec3.fromValues(curScene.boundingBox.transform[0] * 1.2, 0, 0);\n            // mat4.fromTranslation(sceneRootTransforms[1], sceneDeltaTranslate);\n\n            var sceneDeltaTranslate = vec3.fromValues(curScene.boundingBox.transform[0] * 1.2, 0, 0);\n            var tmpVec3Translate = vec3.create();\n\n            for (i = 0, len = glTFModelCount; i < len; i++) {\n                scenes.push(new Scene(curScene, glTF));\n                vec3.scale(tmpVec3Translate, sceneDeltaTranslate, i);\n                mat4.fromTranslation(scenes[i].rootTransform, tmpVec3Translate);\n            }\n            \n            \n            \n\n\n            // center\n            s = 1.0 / Math.max( curScene.boundingBox.transform[0], Math.max(curScene.boundingBox.transform[5], curScene.boundingBox.transform[10]) );\n            mat4.getTranslation(translate, curScene.boundingBox.transform);\n            vec3.scale(translate, translate, -1);\n            translate[0] += - 0.5 * curScene.boundingBox.transform[0];\n            translate[1] += - 0.5 * curScene.boundingBox.transform[5];\n            translate[2] += - 0.5 * curScene.boundingBox.transform[10];\n\n            modelMatrix[0] = s;\n            modelMatrix[5] = s;\n            modelMatrix[10] = s;\n            mat4.translate(modelMatrix, modelMatrix, translate);\n\n            vec3.set(translate, 0, 0, -1.5);\n            s = 1;\n\n\n\n            // -- Initialize vertex array\n            var POSITION_LOCATION = 0; // set with GLSL layout qualifier\n            var NORMAL_LOCATION = 1; // set with GLSL layout qualifier\n            var TEXCOORD_0_LOCATION = 2; // set with GLSL layout qualifier\n\n            // var vertexArrayMaps = {};\n            // var vertexArrayMaps = [];\n\n            // var in loop\n            var mesh;\n            var primitive;\n            var vertexBuffer;\n            var indexBuffer;\n            var vertexArray;\n\n            var nid, lenNodes;\n            var mid, lenMeshes;\n            var i, len;\n            var attribute;\n\n            var image, texture, sampler;\n\n            var accessor, bufferView;\n\n            program = programBaseColor;\n\n            // create buffers\n            for (i = 0, len = glTF.bufferViews.length; i < len; i++) {\n                bufferView = glTF.bufferViews[i];\n                // bufferView.buffer = gl.createBuffer();\n                // if (bufferView.target) {\n                //     gl.bindBuffer(bufferView.target, bufferView.buffer);\n                //     gl.bufferData(bufferView.target, bufferView.data, gl.STATIC_DRAW);\n                //     gl.bindBuffer(bufferView.target, null);\n                // }\n                bufferView.createBuffer(gl);\n                bufferView.bindData(gl);\n            }\n\n            \n            // create textures\n            if (this.glTF.textures) {\n                for (i = 0, len = glTF.textures.length; i < len; i++) {\n                    texture = glTF.textures[i];\n                    // texture.texture = gl.createTexture();\n                    // gl.bindTexture(gl.TEXTURE_2D, texture.texture);\n                    // gl.texImage2D(\n                    //     gl.TEXTURE_2D,  // assumed\n                    //     0,        // Level of details\n                    //     gl.RGBA, // Format\n                    //     gl.RGBA,\n                    //     gl.UNSIGNED_BYTE, // Size of each channel\n                    //     texture.source\n                    // );\n                    texture.createTexture(i, gl);\n                }\n            }\n\n            // create samplers\n            if (this.glTF.samplers) {\n                for (i = 0, len = glTF.samplers.length; i < len; i++) {\n                    sampler = glTF.samplers[i];\n                    \n                    sampler.createSampler(gl);\n                }\n            }\n\n            // create vaos\n            for (mid = 0, lenMeshes = glTF.meshes.length; mid < lenMeshes; mid++) {\n                mesh = glTF.meshes[mid];\n                // vertexArrayMaps[mid] = [];\n\n                for (i = 0, len = mesh.primitives.length; i < len; ++i) {\n                    primitive = mesh.primitives[i];\n                    // WebGL2: create vertexArray\n                    primitive.vertexArray = vertexArray = gl.createVertexArray();\n                    gl.bindVertexArray(vertexArray);\n                    \n                    // attributes\n                    // for (attribute in primitive.attributes) {\n                    //     accessor = glTF.accessors[ primitive.attributes[attribute] ];\n                    // }\n                    accessor = glTF.accessors[ primitive.attributes.POSITION ];\n                    bufferView = accessor.bufferView;\n                    if (bufferView.target === null) {\n                        // bufferView.target = gl.ARRAY_BUFFER;\n                        gl.bindBuffer(gl.ARRAY_BUFFER, bufferView.buffer);\n                        gl.bufferData(gl.ARRAY_BUFFER, bufferView.data, gl.STATIC_DRAW);\n                    } else {\n                        gl.bindBuffer(bufferView.target, bufferView.buffer);\n                    }\n                    \n                    gl.vertexAttribPointer(\n                        POSITION_LOCATION,\n                        accessor.size,\n                        accessor.componentType,\n                        accessor.normalized,\n                        accessor.byteStride,\n                        accessor.byteOffset\n                        );\n                    gl.enableVertexAttribArray(POSITION_LOCATION);\n\n                    accessor = glTF.accessors[ primitive.attributes.NORMAL ];\n                    bufferView = accessor.bufferView;\n                    if (bufferView.target === null) {\n                        // bufferView.target = gl.ARRAY_BUFFER;\n                        gl.bindBuffer(gl.ARRAY_BUFFER, bufferView.buffer);\n                        gl.bufferData(gl.ARRAY_BUFFER, bufferView.data, gl.STATIC_DRAW);\n                    } else {\n                        gl.bindBuffer(bufferView.target, bufferView.buffer);\n                    }\n                    \n                    gl.vertexAttribPointer(\n                        NORMAL_LOCATION,\n                        accessor.size,\n                        accessor.componentType,\n                        accessor.normalized,\n                        accessor.byteStride,\n                        accessor.byteOffset\n                        );\n                    gl.enableVertexAttribArray(NORMAL_LOCATION);\n\n                    // @tmp, should consider together with material\n                    if (primitive.attributes.TEXCOORD_0 !== undefined) {\n                        accessor = glTF.accessors[ primitive.attributes.TEXCOORD_0 ];\n                        bufferView = accessor.bufferView;\n                        if (bufferView.target === null) {\n                            // bufferView.target = gl.ARRAY_BUFFER;\n                            gl.bindBuffer(gl.ARRAY_BUFFER, bufferView.buffer);\n                            gl.bufferData(gl.ARRAY_BUFFER, bufferView.data, gl.STATIC_DRAW);\n                        } else {\n                            gl.bindBuffer(bufferView.target, bufferView.buffer);\n                        }\n                        \n                        gl.vertexAttribPointer(\n                            TEXCOORD_0_LOCATION,\n                            accessor.size,\n                            accessor.componentType,\n                            accessor.normalized,\n                            accessor.byteStride,\n                            accessor.byteOffset\n                            );\n                        gl.enableVertexAttribArray(TEXCOORD_0_LOCATION);\n                    }\n                    \n\n                    // indices ( assume use indices )\n                    accessor = glTF.accessors[ primitive.indices ];\n                    bufferView = accessor.bufferView;\n                    if (bufferView.target === null) {\n                        // bufferView.target = gl.ARRAY_BUFFER;\n                        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferView.buffer);\n                        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, bufferView.data, gl.STATIC_DRAW);\n                    } else {\n                        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferView.buffer);\n                    }\n                    \n\n                    gl.bindVertexArray(null);\n\n                    gl.bindBuffer(gl.ARRAY_BUFFER, null);\n                    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n                }\n                \n            }\n            \n\n\n            // -- Render preparation\n            gl.enable(gl.DEPTH_TEST);\n            gl.depthFunc(gl.LEQUAL);\n\n            \n            var scale = vec3.create();\n            \n            var r = 0.0;\n            var rotationSpeedY= 0.01;\n\n            var perspective = mat4.create();\n            mat4.perspective(perspective, 0.785, canvas.width / canvas.height, 0.1, 100);\n\n            var modelView = mat4.create();\n\n            var localMV = mat4.create();\n            var localMVP = mat4.create();\n            var localMVNormal = mat4.create();\n\n            var VP = mat4.create();\n\n            // var nodeMatrix = new Array(glTF.nodes.length);\n            // for(i = 0, len = nodeMatrix.length; i < len; i++) {\n            //     nodeMatrix[i] = mat4.create();\n            // }\n\n            var defaultColor = [1.0, 1.0, 1.0, 1.0];\n            function drawPrimitive(primitive, matrix) {\n                mat4.multiply(localMV, modelView, matrix);\n                mat4.multiply(localMVP, perspective, localMV);\n                // mat4.multiply(localMVP, VP, matrix);\n\n                mat4.invert(localMVNormal, localMV);\n                mat4.transpose(localMVNormal, localMVNormal);\n\n\n                // @tmp: material\n                var baseColor = defaultColor;\n                if (primitive.material) {\n                    if (primitive.material.pbrMetallicRoughness !== undefined) {\n                        if ( primitive.material.pbrMetallicRoughness.baseColorFactor ) {\n                            baseColor = primitive.material.pbrMetallicRoughness.baseColorFactor;\n                            if (program != programBaseColor) {\n                                gl.useProgram(programBaseColor.program);\n                                program = programBaseColor;\n                            }\n                        }\n\n                        if ( primitive.material.pbrMetallicRoughness.baseColorTexture ) {\n                            if (program != programBaseTexture) {\n                                gl.useProgram(programBaseTexture.program);\n                                program = programBaseTexture;\n                            }\n                            gl.activeTexture(gl.TEXTURE0 + primitive.material.pbrMetallicRoughness.baseColorTexture.index);\n                            // gl.activeTexture(gl.TEXTURE1);\n                            var texture = glTF.textures[ primitive.material.pbrMetallicRoughness.baseColorTexture.index ];\n                            gl.bindTexture(gl.TEXTURE_2D, texture.texture);\n                            var sampler;\n                            if (texture.sampler) {\n                                sampler = texture.sampler.sampler;\n                            } else {\n                                sampler = defaultSampler;\n                            }\n\n                            gl.bindSampler(primitive.material.pbrMetallicRoughness.baseColorTexture.index, sampler);\n                        }\n\n                        \n\n                    }\n                }\n\n                gl.uniform4fv(program.uniformBaseColorFactorLocation, baseColor);\n\n                gl.uniformMatrix4fv(program.uniformMvpLocation, false, localMVP);\n                gl.uniformMatrix4fv(program.uniformMvNormalLocation, false, localMVNormal);\n\n                gl.bindVertexArray(primitive.vertexArray);\n\n                // TODO: when no indices, do drawArrays\n                gl.drawElements(primitive.mode, primitive.indicesLength, primitive.indicesComponentType, primitive.indicesOffset);\n                // gl.drawElements(primitive.mode, 3, primitive.indicesComponentType, primitive.indicesOffset);\n\n                gl.bindVertexArray(null);\n\n            }\n\n            // function drawMesh(mesh, matrix) {\n            // }\n            \n            function drawNode(node, nodeID, nodeMatrix, parentModelMatrix) {\n                var matrix = nodeMatrix[nodeID];\n                \n                if (parentModelMatrix !== undefined) {\n                    mat4.mul(matrix, parentModelMatrix, node.matrix);\n                } else {\n                    // from scene root, parent is identity\n                    mat4.copy(matrix, node.matrix);\n                }\n                // mat4.mul(matrix, parentModelMatrix, node.matrix);\n\n                var i, len;\n\n                // draw cur node's mesh\n                if (node.mesh !== null) {\n                    // drawMesh(glTF.meshes[node.mesh], matrix);\n\n                    // var mesh = glTF.meshes[node.mesh];\n                    var mesh = node.mesh;\n                    for (i = 0, len = mesh.primitives.length; i < len; i++) {\n                        // draw primitive\n                        drawPrimitive(mesh.primitives[i], matrix);\n                    }\n\n                    // BOUNDING_BOX.draw(mesh.boundingBox, matrix, modelView, perspective);\n                    // gl.useProgram(program);\n                }\n                \n\n                // draw children\n                \n                var childNodeID;\n                for (i = 0, len = node.children.length; i < len; i++) {\n                    // childNodeID = node.children[i];\n                    // drawNode(glTF.nodes[childNodeID], childNodeID, matrix);\n                    drawNode(node.children[i], node.children[i].nodeID, nodeMatrix, matrix);\n                }\n            }\n\n\n            function drawScene(scene) {\n                // for (var i = 0, len = scene.nodes.length; i < len; i++) {\n                //     drawNode( scene.nodes[i], scene.nodes[i].nodeID, rootTransform );\n                // }\n                for (var i = 0, len = scene.glTFScene.nodes.length; i < len; i++) {\n                    drawNode( scene.glTFScene.nodes[i], scene.glTFScene.nodes[i].nodeID, scene.nodeMatrix, scene.rootTransform );\n                }\n            }\n\n            function drawSceneBBox(glTF, scene, bboxType) {\n                var node, mesh, bbox;\n                // @temp: assume all nodes are in cur scene\n                // @potential fix: can label each node's scene at the setup\n                for (i = 0, len = scene.nodeMatrix.length; i < len; i++) {\n                    node = glTF.nodes[i];\n\n                    if (bboxType == 'bvh') {\n                        // bvh\n                        mat4.mul(localMVP, scene.rootTransform, node.bvh.transform);\n                        mat4.mul(localMVP, VP, localMVP);\n                        gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\n                        gl.drawArrays(gl.LINES, 0, 24);\n                    }\n                    else if (node.mesh !== null) {\n                        // mesh = glTF.meshes[node.mesh];\n                        mesh = node.mesh;\n\n                        if (bboxType == 'aabb') {\n                            // aabb\n                            mat4.mul(localMVP, scene.rootTransform, node.aabb.transform);\n                            mat4.mul(localMVP, VP, localMVP);\n                        } else {\n                            // obb (assume object node is static)\n                            mat4.mul(localMVP, scene.nodeMatrix[i], mesh.boundingBox.transform);\n                            mat4.mul(localMVP, VP, localMVP);\n                        }\n\n                        gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\n                            \n                        gl.drawArrays(gl.LINES, 0, 24);\n\n                    }   \n                }\n\n                // scene bounding box\n                mat4.mul(localMVP, scene.rootTransform, scene.glTFScene.boundingBox.transform);\n                mat4.mul(localMVP, VP, localMVP);\n                gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\n                gl.drawArrays(gl.LINES, 0, 24);\n            }\n            \n\n            // -- Render loop\n            (function render() {\n                gl.clearColor(0.0, 0.0, 0.0, 1.0);\n                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\n\n                vec3.set(scale, s, s, s);\n                // mat4.identity(modelView);\n                // mat4.translate(modelView, modelView, translate);\n                // mat4.scale(modelView, modelView, scale);\n                // mat4.fromRotationTranslationScale(modelView, identityQ, translate, scale);\n                // mat4.mul(modelView, modelView, modelMatrix);\n                mat4.identity(modelView);\n                mat4.translate(modelView, modelView, translate);\n                r += rotationSpeedY;\n                mat4.rotateY(modelView, modelView, r);\n                mat4.scale(modelView, modelView, scale);\n                mat4.mul(modelView, modelView, modelMatrix);\n\n                // mat4.perspective(perspective, 0.785, canvas.width / canvas.height, 0.1, translate[2] + curScene.boundingBox.transform[10]);\n\n                \n\n                mat4.mul(VP, perspective, modelView);\n\n                gl.useProgram(program.program);\n\n                for (var i = 0, len = scenes.length; i < len; i++) {\n                    drawScene(scenes[i]);\n                }\n\n                // drawScene(curScene);\n                // drawScene(curScene, sceneRootTransforms[1]);\n\n                if (drawBoundingBox) {\n                    gl.useProgram(BOUNDING_BOX.program);\n                    gl.bindVertexArray(BOUNDING_BOX.vertexArray);\n\n                    for (i = 0, len = scenes.length; i < len; i++) {\n                        drawSceneBBox(glTF, scenes[i], boundingBoxType);\n                    }\n\n\n                    gl.bindVertexArray(null);\n                    gl.useProgram(program.program);\n                }\n\n                requestAnimationFrame(render);\n            })();\n\n\n        });\n    })();\n    </script>\n\n</body>\n\n</html>\n"
  },
  {
    "path": "examples/style.css",
    "content": "body {\n    color: #cccccc;\n    font-family: Monospace;\n    font-size: 13px;\n    text-align: center;\n    background-color: #050505;\n    margin: 0px;\n    overflow: hidden;\n}\n\n#info {\n    position: absolute;\n    top: 0px;\n    width: 100%;\n    padding: 5px;\n}\n\n#description {\n    position: absolute;\n    top: 20px;\n    width: 100%;\n    padding: 5px;\n}\n\n.float {\n    float: left;\n    top: 10px;\n}\n\na {\n    color: #0080ff;\n}\n"
  },
  {
    "path": "examples/utility.js",
    "content": "(function () {\n    'use strict';\n\n    window.getShaderSource = function(id) {\n        return document.getElementById(id).textContent.replace(/^\\s+|\\s+$/g, '');\n    };\n\n    function createShader(gl, source, type) {\n        var shader = gl.createShader(type);\n        gl.shaderSource(shader, source);\n        gl.compileShader(shader);\n        return shader;\n    }\n\n    window.createProgram = function(gl, vertexShaderSource, fragmentShaderSource) {\n        var program = gl.createProgram();\n        var vshader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER);\n        var fshader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);\n        gl.attachShader(program, vshader);\n        gl.deleteShader(vshader);\n        gl.attachShader(program, fshader);\n        gl.deleteShader(fshader);\n        gl.linkProgram(program);\n\n        var log = gl.getProgramInfoLog(program);\n        if (log) {\n            console.log(log);\n        }\n\n        log = gl.getShaderInfoLog(vshader);\n        if (log) {\n            console.log(log);\n        }\n\n        log = gl.getShaderInfoLog(fshader);\n        if (log) {\n            console.log(log);\n        }\n\n        return program;\n    };\n\n    window.loadImage = function(url, onload) {\n        var img = new Image();\n        img.src = url;\n        img.onload = function() {\n            onload(img);\n        };\n        return img;\n    };\n\n    window.loadImages = function(urls, onload) {\n        var imgs = [];\n        var imgsToLoad = urls.length;\n\n        function onImgLoad() {\n            if (--imgsToLoad <= 0) {\n                onload(imgs);\n            }\n        }\n\n        for (var i = 0; i < imgsToLoad; ++i) {\n            imgs.push(loadImage(urls[i], onImgLoad));\n        }\n    };\n\n    window.loadObj = function(url, onload) {\n        var xhr = new XMLHttpRequest();\n        xhr.open('GET', url, true);\n        xhr.responseType = 'text';\n        xhr.onload = function(e) {\n            var mesh = new OBJ.Mesh(this.response);\n            onload(mesh);\n        };\n        xhr.send();\n    };\n})();\n"
  },
  {
    "path": "examples/webgl2-renderer-old.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <title>WebGL 2 Renderer Example</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <script src=\"../src/third-party/gl-matrix-min.js\"></script>\n    <script src=\"../src/minimal-gltf-loader.js\"></script>\n    <script src=\"utility.js\"></script>\n    <style>\n        #controls {\n            position: absolute;\n            bottom: 20px;\n            right: 20px;\n            color: white;\n        }\n\n        canvas {\n            background-color: #000\n        }\n    </style>\n</head>\n\n<body>\n    <div id=\"info\">WebGL 2 Renderer Example</div>\n    <p id=\"description\">\n        An example viewer of the model loaded by Minimal-glTF-Loader\n    </p>\n    <div id=\"controls\">\n        Draw Bounding Box: <input id=\"bbox-toggle\" type=\"checkbox\" ><br>\n        Bounding Box type: <select id=\"bbox-type\">\n            <option value=\"obb\">OBB</option>\n            <option value=\"aabb\">AABB(static)</option>\n            <option value=\"bvh\">BVH(static)</option>\n        </select>\n    </div>\n\n    <script id=\"vs-bbox\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n\n        void main()\n        {\n            gl_Position = u_MVP * vec4(position, 1.0) ;\n        }\n    </script>\n\n    <script id=\"fs-bbox\" type=\"x-shader/x-fragment\">\n        #version 300 es\n        #define FRAG_COLOR_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        layout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\n        void main()\n        {\n            color = vec4(1.0, 0.0, 0.0, 1.0);\n        }\n    </script>\n\n    <!-- totally temp -->\n    <script id=\"vs-plain\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n\n        void main()\n        {\n            gl_Position = u_MVP * vec4(position, 1.0) ;\n        }\n    </script>\n\n    <script id=\"fs-plain\" type=\"x-shader/x-fragment\">\n        #version 300 es\n        #define FRAG_COLOR_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        uniform vec4 u_baseColorFactor;\n\n        layout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\n        void main()\n        {\n            color = u_baseColorFactor;\n        }\n    </script>\n\n    <script id=\"vs-normal\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n        #define NORMAL_LOCATION 1\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n        uniform mat4 u_MVNormal;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n        layout(location = NORMAL_LOCATION) in vec3 normal;\n\n        out vec3 v_normal;\n\n        void main()\n        {\n            v_normal = normalize((u_MVNormal * vec4(normal, 0)).xyz);\n            gl_Position = u_MVP * vec4(position, 1.0) ;\n        }\n    </script>\n\n    <script id=\"fs-normal\" type=\"x-shader/x-fragment\">\n        #version 300 es\n        #define FRAG_COLOR_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        in vec3 v_normal;\n\n        layout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\n        void main()\n        {\n            color = vec4(gl_FrontFacing ? v_normal : -v_normal, 1.0);\n        }\n    </script>\n\n    <script id=\"fs-base-color\" type=\"x-shader/x-fragment\">\n        #version 300 es\n        #define FRAG_COLOR_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        uniform vec4 u_baseColorFactor;\n\n        in vec3 v_normal;\n\n        layout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\n        void main()\n        {\n            float intensity = dot(gl_FrontFacing ? v_normal : -v_normal, vec3(0.0, 0.0, 1.0));\n            color = u_baseColorFactor * intensity;\n            color.a = 1.0;\n        }\n    </script>\n\n    <script id=\"vs-texture\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n        #define NORMAL_LOCATION 1\n        #define TEXCOORD_0_LOCATION 2\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n        uniform mat4 u_MVNormal;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n        layout(location = NORMAL_LOCATION) in vec3 normal;\n        layout(location = TEXCOORD_0_LOCATION) in vec2 uv;\n\n        out vec3 v_normal;\n        out vec2 v_uv;\n\n        void main()\n        {\n            v_normal = normalize((u_MVNormal * vec4(normal, 0)).xyz);\n            v_uv = uv;\n            gl_Position = u_MVP * vec4(position, 1.0) ;\n        }\n    </script>\n\n    <script id=\"vs-skin-normal\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n        #define NORMAL_LOCATION 1\n        #define TEXCOORD_0_LOCATION 2\n        #define JOINTS_0_LOCATION 3\n        #define WEIGHTS_0_LOCATION 4\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n        uniform mat4 u_MVNormal;\n\n        uniform JointMatrix\n        {\n            mat4 matrix[32];\n        } u_jointMatrix;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n        layout(location = NORMAL_LOCATION) in vec3 normal;\n        layout(location = JOINTS_0_LOCATION) in vec4 joint;\n        layout(location = WEIGHTS_0_LOCATION) in vec4 weight;\n\n        out vec3 v_normal;\n\n        void main()\n        {\n            mat4 skinMatrix = \n                weight.x * u_jointMatrix.matrix[int(joint.x)] +\n                weight.y * u_jointMatrix.matrix[int(joint.y)] +\n                weight.z * u_jointMatrix.matrix[int(joint.z)] +\n                weight.w * u_jointMatrix.matrix[int(joint.w)];\n\n            v_normal = normalize(( u_MVNormal * transpose(inverse(skinMatrix)) * vec4(normal, 0)).xyz);\n            gl_Position = u_MVP * skinMatrix * vec4(position, 1.0) ;\n        }\n    </script>\n\n    <script id=\"vs-skin-normal-8\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n        #define NORMAL_LOCATION 1\n        #define TEXCOORD_0_LOCATION 2\n        #define JOINTS_0_LOCATION 3\n        #define JOINTS_1_LOCATION 5\n        #define WEIGHTS_0_LOCATION 4\n        #define WEIGHTS_1_LOCATION 6\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n        uniform mat4 u_MVNormal;\n\n        uniform JointMatrix\n        {\n            mat4 matrix[32];\n        } u_jointMatrix;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n        layout(location = NORMAL_LOCATION) in vec3 normal;\n        layout(location = JOINTS_0_LOCATION) in vec4 joint0;\n        layout(location = JOINTS_1_LOCATION) in vec4 joint1;\n        layout(location = WEIGHTS_0_LOCATION) in vec4 weight0;\n        layout(location = WEIGHTS_1_LOCATION) in vec4 weight1;\n\n        out vec3 v_normal;\n\n        void main()\n        {\n            mat4 skinMatrix = \n                weight0.x * u_jointMatrix.matrix[int(joint0.x)] +\n                weight0.y * u_jointMatrix.matrix[int(joint0.y)] +\n                weight0.z * u_jointMatrix.matrix[int(joint0.z)] +\n                weight0.w * u_jointMatrix.matrix[int(joint0.w)] +\n                weight1.x * u_jointMatrix.matrix[int(joint1.x)] +\n                weight1.y * u_jointMatrix.matrix[int(joint1.y)] +\n                weight1.z * u_jointMatrix.matrix[int(joint1.z)] +\n                weight1.w * u_jointMatrix.matrix[int(joint1.w)];\n            //mat4 skinMatrix = 1.0 * u_jointMatrix.matrix[int(joint0.x)] + 0.0 *weight0.x * weight1.x* u_jointMatrix.matrix[int(joint1.x)];\n            \n            /*skinMatrix[0][0] = 1.0;\n            skinMatrix[1][1] = 1.0;\n            skinMatrix[2][2] = 1.0;\n            skinMatrix[3][3] = 1.0;*/\n\n\n            //v_normal = normalize(( u_MVNormal * vec4(normal, 0)).xyz);\n            v_normal = normalize(( u_MVNormal * transpose(inverse(skinMatrix)) * vec4(normal, 0)).xyz);\n            gl_Position = u_MVP * skinMatrix * vec4(position, 1.0) ;\n            //gl_Position = u_MVP * vec4(position, 1.0) + skinMatrix * vec4(10.0, 10.0, 10.0, 1.0);\n        }\n    </script>\n\n    <script id=\"vs-skin-texture\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n        #define NORMAL_LOCATION 1\n        #define TEXCOORD_0_LOCATION 2\n        #define JOINTS_0_LOCATION 3\n        #define WEIGHTS_0_LOCATION 4\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n        uniform mat4 u_MVNormal;\n\n        uniform JointMatrix\n        {\n            mat4 matrix[32];\n        } u_jointMatrix;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n        layout(location = NORMAL_LOCATION) in vec3 normal;\n        layout(location = TEXCOORD_0_LOCATION) in vec2 uv;\n        layout(location = JOINTS_0_LOCATION) in vec4 joint;\n        layout(location = WEIGHTS_0_LOCATION) in vec4 weight;\n\n        out vec3 v_normal;\n        out vec2 v_uv;\n\n        void main()\n        {\n            mat4 skinMatrix = \n                weight.x * u_jointMatrix.matrix[int(joint.x)] +\n                weight.y * u_jointMatrix.matrix[int(joint.y)] +\n                weight.z * u_jointMatrix.matrix[int(joint.z)] +\n                weight.w * u_jointMatrix.matrix[int(joint.w)];\n\n            v_normal = normalize(( u_MVNormal * transpose(inverse(skinMatrix)) * vec4(normal, 0)).xyz);\n            v_uv = uv;\n            gl_Position = u_MVP * skinMatrix * vec4(position, 1.0) ;\n        }\n    </script>\n\n    <script id=\"vs-skin-texture-8\" type=\"x-shader/x-vertex\">\n        #version 300 es\n        #define POSITION_LOCATION 0\n        #define NORMAL_LOCATION 1\n        #define TEXCOORD_0_LOCATION 2\n        #define JOINTS_0_LOCATION 3\n        #define JOINTS_1_LOCATION 5\n        #define WEIGHTS_0_LOCATION 4\n        #define WEIGHTS_1_LOCATION 6\n\n        precision highp float;\n        precision highp int;\n\n        uniform mat4 u_MVP;\n        uniform mat4 u_MVNormal;\n\n        uniform JointMatrix\n        {\n            mat4 matrix[32];\n        } u_jointMatrix;\n\n        layout(location = POSITION_LOCATION) in vec3 position;\n        layout(location = NORMAL_LOCATION) in vec3 normal;\n        layout(location = TEXCOORD_0_LOCATION) in vec2 uv;\n        layout(location = JOINTS_0_LOCATION) in vec4 joint0;\n        layout(location = JOINTS_1_LOCATION) in vec4 joint1;\n        layout(location = WEIGHTS_0_LOCATION) in vec4 weight0;\n        layout(location = WEIGHTS_1_LOCATION) in vec4 weight1;\n\n        out vec3 v_normal;\n        out vec2 v_uv;\n\n        void main()\n        {\n            mat4 skinMatrix = \n                weight0.x * u_jointMatrix.matrix[int(joint0.x)] +\n                weight0.y * u_jointMatrix.matrix[int(joint0.y)] +\n                weight0.z * u_jointMatrix.matrix[int(joint0.z)] +\n                weight0.w * u_jointMatrix.matrix[int(joint0.w)] +\n                weight1.x * u_jointMatrix.matrix[int(joint1.x)] +\n                weight1.y * u_jointMatrix.matrix[int(joint1.y)] +\n                weight1.z * u_jointMatrix.matrix[int(joint1.z)] +\n                weight1.w * u_jointMatrix.matrix[int(joint1.w)];\n            \n            \n            v_normal = normalize(( u_MVNormal * transpose(inverse(skinMatrix)) * vec4(normal, 0)).xyz);\n            v_uv = uv;\n            gl_Position = u_MVP * skinMatrix * vec4(position, 1.0) ;\n        }\n    </script>\n\n    <script id=\"fs-texture\" type=\"x-shader/x-fragment\">\n        #version 300 es\n        #define FRAG_COLOR_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        uniform vec4 u_baseColorFactor;\n        uniform sampler2D u_baseColorTexture;\n\n        in vec3 v_normal;\n        in vec2 v_uv;\n\n        layout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\n        void main()\n        {\n            float intensity = dot(gl_FrontFacing ? v_normal : -v_normal, vec3(0.0, 0.0, 1.0));\n            color = u_baseColorFactor * texture(u_baseColorTexture, v_uv) * intensity; \n            color.a = 1.0;\n        }\n    </script>\n\n    <script id=\"fs-texture-normal-map\" type=\"x-shader/x-fragment\">\n        #version 300 es\n        #define FRAG_COLOR_LOCATION 0\n\n        precision highp float;\n        precision highp int;\n\n        uniform vec4 u_baseColorFactor;\n        uniform sampler2D u_baseColorTexture;\n        uniform sampler2D u_normalTexture;\n\n        in vec3 v_normal;\n        in vec2 v_uv;\n\n        layout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\n\n        vec3 applyNormalMap(vec3 geomnor, vec3 normap) {\n            normap = normap * 2.0 - 1.0;\n            vec3 up = normalize(vec3(0.001, 1, 0.001));\n            vec3 surftan = normalize(cross(geomnor, up));\n            vec3 surfbinor = cross(geomnor, surftan);\n            return normap.y * surftan + normap.x * surfbinor + normap.z * geomnor;\n        }\n\n        void main()\n        {\n            vec3 normal = applyNormalMap( v_normal, texture(u_normalTexture, v_uv).rgb );\n            normal = gl_FrontFacing ? normal : -normal;\n\n            float intensity = dot(normal, vec3(0.0, 0.0, 1.0));\n            color = u_baseColorFactor * texture(u_baseColorTexture, v_uv) * intensity;\n            color.a = 1.0;\n        }\n    </script>\n\n\n    <script>\n    // var testNodeId = 0;\n    (function()  {\n        'use strict';\n\n        var drawBoundingBox = false;\n        var boundingBoxType = 'obb';\n\n        document.getElementById(\"bbox-toggle\").addEventListener(\"change\", function() {\n            drawBoundingBox = this.checked;\n        });\n\n        document.getElementById(\"bbox-type\").addEventListener(\"change\", function() {\n            boundingBoxType = this.value;\n        });\n\n        var canvas = document.createElement('canvas');\n        // canvas.width = Math.min(window.innerWidth, window.innerHeight);\n        // canvas.height = canvas.width;\n        canvas.width = window.innerWidth;\n        canvas.height = window.innerHeight;\n        document.body.appendChild(canvas);\n\n        var gl = canvas.getContext( 'webgl2', { antialias: true } );\n        var isWebGL2 = !!gl;\n        if(!isWebGL2) {\n            document.getElementById('info').innerHTML = 'WebGL 2 is not available.  See <a href=\"https://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation\">How to get a WebGL 2 implementation</a>';\n            return;\n        }\n\n        canvas.oncontextmenu = function (e) {\n            e.preventDefault();\n        };\n\n        // Scene object for runtime renderer\n        var Scene = function(glTFScene, glTF) {\n            this.glTFScene = glTFScene;\n\n            // runtime renderer context\n            this.rootTransform = mat4.create();\n            // @temp, assume every node is in current scene\n            this.nodeMatrix = new Array(glTF.nodes.length);\n            var i, len;\n            for(i = 0, len = this.nodeMatrix.length; i < len; i++) {\n                this.nodeMatrix[i] = mat4.create();\n            }\n\n\n            // if (glTF.skins) {\n            //     this.inverseSkeletonRootMatrix = new Array(glTF.skins.length);\n            //     this.inverseSkeletonRootMatrixReady = new Array(glTF.skins.length);\n            //     for(i = 0, len = this.inverseSkeletonRootMatrix.length; i < len; i++) {\n            //         if (glTF.skins[i].skeleton) {\n            //             this.inverseSkeletonRootMatrix[i] = mat4.create();\n            //             this.inverseSkeletonRootMatrixReady[i] = false;\n            //         } else {\n            //             this.inverseSkeletonRootMatrix[i] = null;\n            //         }\n            //     }\n            // }\n        };\n\n        var BOUNDING_BOX = {\n            vertexData: new Float32Array([\n                0.0, 0.0, 0.0,\n                1.0, 0.0, 0.0,\n                0.0, 0.0, 0.0,\n                0.0, 1.0, 0.0,\n                0.0, 0.0, 0.0,\n                0.0, 0.0, 1.0,\n\n                0.0, 1.0, 1.0,\n                1.0, 1.0, 1.0,\n                0.0, 1.0, 1.0,\n                0.0, 1.0, 0.0,\n                0.0, 1.0, 1.0,\n                0.0, 0.0, 1.0,\n\n                1.0, 1.0, 0.0,\n                1.0, 1.0, 1.0,\n                1.0, 1.0, 0.0,\n                0.0, 1.0, 0.0,\n                1.0, 1.0, 0.0,\n                1.0, 0.0, 0.0,\n\n                1.0, 0.0, 1.0,\n                1.0, 0.0, 0.0,\n                1.0, 0.0, 1.0,\n                1.0, 1.0, 1.0,\n                1.0, 0.0, 1.0,\n                0.0, 0.0, 1.0\n            ]),\n\n            vertexArray: gl.createVertexArray(),\n            vertexBuffer: gl.createBuffer(),\n\n            program: createProgram(gl, getShaderSource('vs-bbox'), getShaderSource('fs-bbox')),\n            positionLocation: 0,\n            uniformMvpLocation: 0, \n\n            \n            draw: (function() {\n                var MVP = mat4.create();\n                return (function(bbox, nodeTransform, V, P) {\n                    gl.useProgram(this.program);\n\n                    mat4.mul(MVP, nodeTransform, bbox.transform);\n                    mat4.mul(MVP, V, MVP);\n                    mat4.mul(MVP, P, MVP);\n\n                    gl.uniformMatrix4fv(this.uniformMvpLocation, false, MVP);\n                    gl.bindVertexArray(this.vertexArray);\n                    gl.drawArrays(gl.LINES, 0, 24);\n                    gl.bindVertexArray(null);\n                });\n            })()\n        };\n\n        \n\n        var defaultSampler = gl.createSampler();\n        gl.samplerParameteri(defaultSampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);\n        gl.samplerParameteri(defaultSampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n        gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_S, gl.REPEAT);\n        gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_T, gl.REPEAT);\n        // gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_R, gl.REPEAT);\n        // gl.samplerParameterf(defaultSampler, gl.TEXTURE_MIN_LOD, -1000.0);\n        // gl.samplerParameterf(defaultSampler, gl.TEXTURE_MAX_LOD, 1000.0);\n        // gl.samplerParameteri(defaultSampler, gl.TEXTURE_COMPARE_MODE, gl.NONE);\n        // gl.samplerParameteri(defaultSampler, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);\n\n        BOUNDING_BOX.uniformMvpLocation = gl.getUniformLocation(BOUNDING_BOX.program, \"u_MVP\");\n\n        gl.bindVertexArray(BOUNDING_BOX.vertexArray);\n\n        gl.bindBuffer(gl.ARRAY_BUFFER, BOUNDING_BOX.vertexBuffer);\n        gl.bufferData(gl.ARRAY_BUFFER, BOUNDING_BOX.vertexData, gl.STATIC_DRAW);\n        gl.vertexAttribPointer(BOUNDING_BOX.positionLocation, 3, gl.FLOAT, false, 0, 0);\n        gl.enableVertexAttribArray(BOUNDING_BOX.positionLocation);\n\n        gl.bindVertexArray(null);\n\n\n\n        // // -- Initialize program\n        // var program = createProgram(gl, getShaderSource('vs-normal'), getShaderSource('fs-normal'));\n        // var uniformMvpLocation = gl.getUniformLocation(program, \"u_MVP\");\n        // var uniformMvNormalLocation = gl.getUniformLocation(program, \"u_MVNormal\");\n\n        // var program = createProgram(gl, getShaderSource('vs-normal'), getShaderSource('fs-base-color'));\n        // var uniformMvpLocation = gl.getUniformLocation(program, \"u_MVP\");\n        // var uniformMvNormalLocation = gl.getUniformLocation(program, \"u_MVNormal\");\n        // var uniformBaseColorFactorLocation = gl.getUniformLocation(program, \"u_baseColorFactor\");\n\n        var program = createProgram(gl, getShaderSource('vs-normal'), getShaderSource('fs-base-color'));\n        var programBaseColor = {\n            program: program,\n            uniformMvpLocation: gl.getUniformLocation(program, \"u_MVP\"),\n            uniformMvNormalLocation: gl.getUniformLocation(program, \"u_MVNormal\"),\n            uniformBaseColorFactorLocation: gl.getUniformLocation(program, \"u_baseColorFactor\")\n        };\n\n        program = createProgram(gl, getShaderSource('vs-plain'), getShaderSource('fs-plain'));\n        var programPlain = {\n            program: program,\n            uniformMvpLocation: gl.getUniformLocation(program, \"u_MVP\"),\n            uniformBaseColorFactorLocation: gl.getUniformLocation(program, \"u_baseColorFactor\")\n        };\n\n        program = createProgram(gl, getShaderSource('vs-texture'), getShaderSource('fs-texture'));\n        var programBaseTexture = {\n            program: program,\n            uniformMvpLocation: gl.getUniformLocation(program, \"u_MVP\"),\n            uniformMvNormalLocation: gl.getUniformLocation(program, \"u_MVNormal\"),\n            uniformBaseColorFactorLocation: gl.getUniformLocation(program, \"u_baseColorFactor\"),\n            uniformBaseColorTextureLocation: gl.getUniformLocation(program, \"u_baseColorTexture\")\n        };\n\n        // @temp test\n        program = createProgram(gl, getShaderSource('vs-texture'), getShaderSource('fs-texture-normal-map'));\n        var programBaseTextureNormalMap = {\n            program: program,\n            uniformMvpLocation: gl.getUniformLocation(program, \"u_MVP\"),\n            uniformMvNormalLocation: gl.getUniformLocation(program, \"u_MVNormal\"),\n            uniformBaseColorFactorLocation: gl.getUniformLocation(program, \"u_baseColorFactor\"),\n            uniformBaseColorTextureLocation: gl.getUniformLocation(program, \"u_baseColorTexture\"),\n            // uniformNormalTextureScaleLocation: gl.getUniformLocation(program, \"u_normalTextureScale\"),\n            uniformNormalTextureLocation: gl.getUniformLocation(program, \"u_normalTexture\")\n        };\n\n        program = createProgram(gl, getShaderSource('vs-skin-normal'), getShaderSource('fs-base-color'));\n        var programSkinBaseColor = {\n            program: program,\n            uniformMvpLocation: gl.getUniformLocation(program, \"u_MVP\"),\n            uniformMvNormalLocation: gl.getUniformLocation(program, \"u_MVNormal\"),\n            uniformBaseColorFactorLocation: gl.getUniformLocation(program, \"u_baseColorFactor\"),\n            uniformBlockIndexJointMatrix: gl.getUniformBlockIndex(program, \"JointMatrix\")\n        };\n\n        program = createProgram(gl, getShaderSource('vs-skin-normal-8'), getShaderSource('fs-base-color'));\n        var programSkinBaseColorVec8 = {\n            program: program,\n            uniformMvpLocation: gl.getUniformLocation(program, \"u_MVP\"),\n            uniformMvNormalLocation: gl.getUniformLocation(program, \"u_MVNormal\"),\n            uniformBaseColorFactorLocation: gl.getUniformLocation(program, \"u_baseColorFactor\"),\n            uniformBlockIndexJointMatrix: gl.getUniformBlockIndex(program, \"JointMatrix\")\n        };\n\n        // temp\n        program = createProgram(gl, getShaderSource('vs-skin-texture'), getShaderSource('fs-texture'));\n        var programSkinBaseTexture = {\n            program: program,\n            uniformMvpLocation: gl.getUniformLocation(program, \"u_MVP\"),\n            uniformMvNormalLocation: gl.getUniformLocation(program, \"u_MVNormal\"),\n            uniformBaseColorFactorLocation: gl.getUniformLocation(program, \"u_baseColorFactor\"),\n            uniformBaseColorTextureLocation: gl.getUniformLocation(program, \"u_baseColorTexture\"),\n            uniformBlockIndexJointMatrix: gl.getUniformBlockIndex(program, \"JointMatrix\")\n        };\n\n        program = createProgram(gl, getShaderSource('vs-skin-texture-8'), getShaderSource('fs-texture'));\n        var programSkinBaseTextureVec8 = {\n            program: program,\n            uniformMvpLocation: gl.getUniformLocation(program, \"u_MVP\"),\n            uniformMvNormalLocation: gl.getUniformLocation(program, \"u_MVNormal\"),\n            uniformBaseColorFactorLocation: gl.getUniformLocation(program, \"u_baseColorFactor\"),\n            uniformBaseColorTextureLocation: gl.getUniformLocation(program, \"u_baseColorTexture\"),\n            uniformBlockIndexJointMatrix: gl.getUniformBlockIndex(program, \"JointMatrix\")\n        };\n\n        \n        // -- Mouse Behaviour\n        var isDisplayRotation = true;\n        var s = 1;\n        var eulerX = 0;\n        var eulerY = 0;\n        // var s = 1;\n        // var t = -100;\n        var translate = vec3.create();\n        // var t = -5;\n        var modelMatrix = mat4.create();\n        var mouseDown = false;\n        var mouseButtonId = 0;\n        var lastMouseY = 0;\n        var lastMouseX = 0;\n        var identityQ = quat.create();\n        window.onmousedown = function(event) {\n            mouseDown = true;\n            mouseButtonId = event.which;\n            lastMouseY = event.clientY;\n            lastMouseX = event.clientX;\n            if (mouseButtonId === 1) {\n                isDisplayRotation = false;\n            }\n        };\n        window.onmouseup = function(event) {\n            mouseDown = false;\n            isDisplayRotation = true;\n        };\n        window.onmousemove = function(event) {\n            if(!mouseDown) {\n                return;\n            }\n            var newY = event.clientY;\n            var newX = event.clientX;\n            \n            var deltaY = newY - lastMouseY;\n            var deltaX = newX - lastMouseX;\n            \n            // s *= (1 + deltaY / 1000);\n\n            switch(mouseButtonId) {\n                case 1:\n                // left: rotation\n                eulerX += -deltaY * 0.01;\n                eulerY += deltaX * 0.01;\n                break;\n                case 3:\n                // right\n                translate[0] += deltaX * 0.001;\n                translate[1] += -deltaY * 0.001;\n                break;\n            }\n            \n            \n            lastMouseY = newY;\n            lastMouseX = newX;\n        };\n        window.onwheel = function(event) {\n            translate[2] += -event.deltaY * 0.001;\n            // translate[2] *= 1 + (-event.deltaY * 0.01);\n        };\n\n        \n        // 2.0\n        // var gltfUrl = '../glTFs/glTF_version_2/Duck/glTF/Duck.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/2CylinderEngine/glTF/2CylinderEngine.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/GearboxAssy/glTF/GearboxAssy.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/Buggy/glTF/Buggy.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/DamagedHelmet/glTF/DamagedHelmet.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/Avocado/glTF/Avocado.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/BoomBox/glTF/BoomBox.gltf';\n\n        // var gltfUrl = '../glTFs/glTF_version_2/BoxAnimated/glTF/BoxAnimated.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/CesiumMilkTruck/glTF/CesiumMilkTruck.gltf';\n\n        // var gltfUrl = '../glTFs/glTF_version_2/RiggedSimple/glTF/RiggedSimple.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/RiggedFigure/glTF/RiggedFigure.gltf';\n        var gltfUrl = '../glTFs/glTF_version_2/BrainStem/glTF/BrainStem.gltf';\n        // var gltfUrl = '../glTFs/glTF_version_2/CesiumMan/glTF/CesiumMan.gltf';\n\n        // var gltfUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Monster/glTF/Monster.gltf';\n        // var gltfUrl = 'https://raw.githubusercontent.com/mrdoob/rome-gltf/master/files/models/black_soup/quadruped_wolf.gltf';\n        // var gltfUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/VC/glTF/VC.gltf';\n        // var gltfUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/TextureSettingsTest/glTF/TextureSettingsTest.gltf';\n        // var gltfUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/TwoSidedPlane/glTF/TwoSidedPlane.gltf';\n        // var gltfUrl = 'https://raw.githubusercontent.com/pjcozzi/pjcozzi.github.io/master/img/models/patrick.gltf';\n\n        // var gltfUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Triangle/glTF/Triangle.gltf';\n        // var gltfUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/TriangleWithoutIndices/glTF/TriangleWithoutIndices.gltf';\n        // var gltfUrl = 'https://raw.githubusercontent.com/cx20/gltf-test/master/tutorialModels/AnimatedTriangle/glTF/AnimatedTriangle.gltf';\n        // var gltfUrl = 'https://raw.githubusercontent.com/cx20/gltf-test/master/tutorialModels/SimpleMeshes/glTF/SimpleMeshes.gltf';\n\n        var glTFLoader = new MinimalGLTFLoader.glTFLoader(gl);\n\n        var glTFModelCount = 1;\n        var scenes = [];\n\n        gl.enable(gl.CULL_FACE);\n        gl.cullFace(gl.BACK);\n        gl.frontFace(gl.CCW);\n        var isFaceCulling = true;\n\n        glTFLoader.loadGLTF(gltfUrl, function(glTF) {\n\n            var curGltfScene = glTF.scenes[glTF.defaultScene];\n\n            // // draw multiple copies of the glTF scene\n            // // to build a relative complex scene for octree and occlusion query test\n            // var sceneRootTransforms = [mat4.create(), mat4.create()];\n            // var sceneDeltaTranslate = vec3.fromValues(curGltfScene.boundingBox.transform[0] * 1.2, 0, 0);\n            // mat4.fromTranslation(sceneRootTransforms[1], sceneDeltaTranslate);\n\n\n            var sceneDeltaTranslate = vec3.fromValues(curGltfScene.boundingBox.transform[0] * 1.2, 0, 0);\n            var tmpVec3Translate = vec3.create();\n\n            for (i = 0, len = glTFModelCount; i < len; i++) {\n                scenes.push(new Scene(curGltfScene, glTF));\n                vec3.scale(tmpVec3Translate, sceneDeltaTranslate, i);\n                mat4.fromTranslation(scenes[i].rootTransform, tmpVec3Translate);\n            }\n            \n\n            // center\n            s = 1.0 / Math.max( curGltfScene.boundingBox.transform[0], Math.max(curGltfScene.boundingBox.transform[5], curGltfScene.boundingBox.transform[10]) );\n            mat4.getTranslation(translate, curGltfScene.boundingBox.transform);\n            vec3.scale(translate, translate, -1);\n            translate[0] += - 0.5 * curGltfScene.boundingBox.transform[0];\n            translate[1] += - 0.5 * curGltfScene.boundingBox.transform[5];\n            translate[2] += - 0.5 * curGltfScene.boundingBox.transform[10];\n\n            s *= 0.5;\n\n            modelMatrix[0] = s;\n            modelMatrix[5] = s;\n            modelMatrix[10] = s;\n            mat4.translate(modelMatrix, modelMatrix, translate);\n\n            vec3.set(translate, 0, 0, -1.5);\n            s = 1;\n\n\n\n            // -- Initialize vertex array\n            var POSITION_LOCATION = 0; // set with GLSL layout qualifier\n            var NORMAL_LOCATION = 1; // set with GLSL layout qualifier\n            var TEXCOORD_0_LOCATION = 2; // set with GLSL layout qualifier\n            var JOINTS_0_LOCATION = 3; // set with GLSL layout qualifier\n            var JOINTS_1_LOCATION = 5; // set with GLSL layout qualifier\n            var WEIGHTS_0_LOCATION = 4; // set with GLSL layout qualifier\n            var WEIGHTS_1_LOCATION = 6; // set with GLSL layout qualifier\n\n            // var vertexArrayMaps = {};\n            // var vertexArrayMaps = [];\n\n            // var in loop\n            var mesh;\n            var primitive;\n            var vertexBuffer;\n            var indexBuffer;\n            var vertexArray;\n\n            var nid, lenNodes;\n            var mid, lenMeshes;\n            var i, len;\n            var attribute;\n\n            var image, texture, sampler;\n\n            var accessor, bufferView;\n\n            var animation, animationSampler, channel;\n\n            var skin;\n\n            var curScene;   // runtime scene object (not gltf scene object)\n\n            program = programBaseColor;\n\n\n\n            // // animations typed array\n            // for (i = 0, len = glTF.animations.length; i < len; i++) {\n            //     animation = glTF.animations[i];\n\n                \n            // }\n\n            \n\n\n            // create buffers\n            for (i = 0, len = glTF.bufferViews.length; i < len; i++) {\n                bufferView = glTF.bufferViews[i];\n                // bufferView.buffer = gl.createBuffer();\n                // if (bufferView.target) {\n                //     gl.bindBuffer(bufferView.target, bufferView.buffer);\n                //     gl.bufferData(bufferView.target, bufferView.data, gl.STATIC_DRAW);\n                //     gl.bindBuffer(bufferView.target, null);\n                // }\n                bufferView.createBuffer(gl);\n                bufferView.bindData(gl);\n            }\n\n            \n            // create textures\n            if (this.glTF.textures) {\n                for (i = 0, len = glTF.textures.length; i < len; i++) {\n                    texture = glTF.textures[i];\n                    // texture.texture = gl.createTexture();\n                    // gl.bindTexture(gl.TEXTURE_2D, texture.texture);\n                    // gl.texImage2D(\n                    //     gl.TEXTURE_2D,  // assumed\n                    //     0,        // Level of details\n                    //     gl.RGBA, // Format\n                    //     gl.RGBA,\n                    //     gl.UNSIGNED_BYTE, // Size of each channel\n                    //     texture.source\n                    // );\n                    texture.createTexture(i, gl);\n                }\n            }\n\n            // create samplers\n            if (this.glTF.samplers) {\n                for (i = 0, len = glTF.samplers.length; i < len; i++) {\n                    sampler = glTF.samplers[i];\n                    \n                    sampler.createSampler(gl);\n                }\n            }\n\n            if (glTF.skins) {\n                // gl.useProgram(programSkinBaseColor.program);\n                // gl.uniformBlockBinding(programSkinBaseColor.program, programSkinBaseColor.uniformBlockIndexJointMatrix, 0);\n                // gl.useProgram(null);\n                for (i = 0, len = glTF.skins.length; i < len; i++) {\n                    skin = glTF.skins[i];\n                    \n                    skin.jointMatrixUniformBuffer = gl.createBuffer();\n\n                    gl.bindBufferBase(gl.UNIFORM_BUFFER, i, skin.jointMatrixUniformBuffer);\n\n                    gl.bindBuffer(gl.UNIFORM_BUFFER, skin.jointMatrixUniformBuffer);\n                    gl.bufferData(gl.UNIFORM_BUFFER, skin.jointMatrixUnidormBufferData, gl.DYNAMIC_DRAW);\n                    gl.bufferSubData(gl.UNIFORM_BUFFER, 0, skin.jointMatrixUnidormBufferData);\n                    gl.bindBuffer(gl.UNIFORM_BUFFER, null);\n                }\n            }\n\n\n\n            function setupAttribuite(attrib, location) {\n                if (attrib !== undefined) {\n                    var accessor = glTF.accessors[ attrib ];\n                    var bufferView = accessor.bufferView;\n                    if (bufferView.target === null) {\n                        // console.log('WARNING: the bufferview of this accessor should have a target, or it should represent non buffer data (like animation)');\n                        gl.bindBuffer(gl.ARRAY_BUFFER, bufferView.buffer);\n                        gl.bufferData(gl.ARRAY_BUFFER, bufferView.data, gl.STATIC_DRAW);\n                    } else {\n                        gl.bindBuffer(bufferView.target, bufferView.buffer);\n                    }\n                    accessor.prepareVertexAttrib(location, gl);\n                }\n            }\n\n            // create vaos\n            for (mid = 0, lenMeshes = glTF.meshes.length; mid < lenMeshes; mid++) {\n                mesh = glTF.meshes[mid];\n                // vertexArrayMaps[mid] = [];\n\n                for (i = 0, len = mesh.primitives.length; i < len; ++i) {\n                    primitive = mesh.primitives[i];\n                    // WebGL2: create vertexArray\n                    primitive.vertexArray = vertexArray = gl.createVertexArray();\n                    gl.bindVertexArray(vertexArray);\n                    \n                    \n                    setupAttribuite(primitive.attributes.POSITION, POSITION_LOCATION);\n                    setupAttribuite(primitive.attributes.NORMAL, NORMAL_LOCATION);\n\n                    // @tmp, should consider together with material\n                    setupAttribuite(primitive.attributes.TEXCOORD_0, TEXCOORD_0_LOCATION);\n                    \n\n                    setupAttribuite(primitive.attributes.JOINTS_0, JOINTS_0_LOCATION);\n                    setupAttribuite(primitive.attributes.WEIGHTS_0, WEIGHTS_0_LOCATION);\n\n                    setupAttribuite(primitive.attributes.JOINTS_1, JOINTS_1_LOCATION);\n                    setupAttribuite(primitive.attributes.WEIGHTS_1, WEIGHTS_1_LOCATION);\n\n                    \n\n                    // indices ( assume use indices )\n                    if (primitive.indices !== null) {\n                        accessor = glTF.accessors[ primitive.indices ];\n                        bufferView = accessor.bufferView;\n                        if (bufferView.target === null) {\n                            // console.log('WARNING: the bufferview of this accessor should have a target, or it should represent non buffer data (like animation)');\n                            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferView.buffer);\n                            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, bufferView.data, gl.STATIC_DRAW);\n                        } else {\n                            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferView.buffer);\n                        }\n                    }\n                    \n                    \n\n                    gl.bindVertexArray(null);\n\n                    gl.bindBuffer(gl.ARRAY_BUFFER, null);\n                    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n                }\n                \n            }\n            \n\n\n            // -- Render preparation\n            gl.enable(gl.DEPTH_TEST);\n            gl.depthFunc(gl.LEQUAL);\n\n            \n            var scale = vec3.create();\n            \n            var r = 0.0;\n            var rotationSpeedY= 0.01;\n            // var rotationSpeedY= 0.0;\n\n            var perspective = mat4.create();\n            mat4.perspective(perspective, 0.785, canvas.width / canvas.height, 0.01, 100);\n\n            var modelView = mat4.create();\n\n            var localMV = mat4.create();\n            var localMVP = mat4.create();\n            var localMVNormal = mat4.create();\n\n            var VP = mat4.create();\n\n            var hasIndices = true;\n\n            var hasSkin = false;\n            var skinID;     // same for uniform block binding id\n\n            // var nodeMatrix = new Array(glTF.nodes.length);\n            // for(i = 0, len = nodeMatrix.length; i < len; i++) {\n            //     nodeMatrix[i] = mat4.create();\n            // }\n\n            var defaultColor = [1.0, 1.0, 1.0, 1.0];\n            var defaultMaterial = new MinimalGLTFLoader.Material({});\n\n            var hasNormal = true;\n\n            function drawPrimitive(primitive, matrix) {\n                mat4.multiply(localMV, modelView, matrix);\n                mat4.multiply(localMVP, perspective, localMV);\n                // mat4.multiply(localMVP, VP, matrix);\n\n                mat4.invert(localMVNormal, localMV);\n                mat4.transpose(localMVNormal, localMVNormal);\n\n                var material = primitive.material !== null ? primitive.material : defaultMaterial;\n\n                if (material !== null) {\n                    if (material.doubleSided === isFaceCulling) {\n                        isFaceCulling = !material.doubleSided;\n                        if (isFaceCulling) {\n                            gl.enable(gl.CULL_FACE);\n                        } else {\n                            gl.disable(gl.CULL_FACE);\n                        }\n                    }\n                }\n                \n                \n\n                // @tmp: program choice\n                // super ugly code\n\n                var baseColor = defaultColor;\n\n                if (primitive.attributes.NORMAL === undefined)\n                {\n                    if (program != programPlain) {\n                        gl.useProgram(programPlain.program);\n                        program = programPlain;\n                    }\n                    hasNormal = false;\n                } else {\n                    hasNormal = true;\n\n                        // hasSkin = false;\n                    if (hasSkin) {\n                        if (material !== null) {\n\n                            if (material.pbrMetallicRoughness !== null) {\n                                \n\n                                if ( material.pbrMetallicRoughness.baseColorTexture ) {\n\n                                    if (primitive.attributes.JOINTS_1 === undefined) {\n                                        if (program != programSkinBaseTexture) {\n                                            gl.useProgram(programSkinBaseTexture.program);\n                                            program = programSkinBaseTexture;\n                                        }\n                                    } else {\n                                        if (program != programSkinBaseTextureVec8) {\n                                            gl.useProgram(programSkinBaseTextureVec8.program);\n                                            program = programSkinBaseTextureVec8;\n                                        }\n                                    }\n\n                                    gl.uniform1i(program.uniformBaseColorTextureLocation, material.pbrMetallicRoughness.baseColorTexture.index);\n                                    gl.activeTexture(gl.TEXTURE0 + material.pbrMetallicRoughness.baseColorTexture.index);\n                                    // gl.activeTexture(gl.TEXTURE1);\n                                    texture = glTF.textures[ material.pbrMetallicRoughness.baseColorTexture.index ];\n                                    gl.bindTexture(gl.TEXTURE_2D, texture.texture);\n                                    if (texture.sampler) {\n                                        sampler = texture.sampler.sampler;\n                                    } else {\n                                        sampler = defaultSampler;\n                                    }\n\n                                    gl.bindSampler(material.pbrMetallicRoughness.baseColorTexture.index, sampler);\n\n                                    if (material.pbrMetallicRoughness.baseColorFactor) {\n                                        baseColor = material.pbrMetallicRoughness.baseColorFactor;\n                                    }\n                                } else if ( material.pbrMetallicRoughness.baseColorFactor ) {\n                                    baseColor = material.pbrMetallicRoughness.baseColorFactor;\n\n                                    if (primitive.attributes.JOINTS_1 === undefined) {\n                                        if (program != programSkinBaseColor) {\n                                            gl.useProgram(programSkinBaseColor.program);\n                                            program = programSkinBaseColor;\n                                        }\n                                    } else {\n                                        if (program != programSkinBaseColorVec8) {\n                                            gl.useProgram(programSkinBaseColorVec8.program);\n                                            program = programSkinBaseColorVec8;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n\n                        gl.uniformBlockBinding(program.program, program.uniformBlockIndexJointMatrix, skinID);\n                    } else {\n\n                        if (material !== null) {\n                            if (material.pbrMetallicRoughness !== null) {\n                                if ( material.pbrMetallicRoughness.baseColorFactor ) {\n                                    baseColor = material.pbrMetallicRoughness.baseColorFactor;\n                                    if (program != programBaseColor) {\n                                        gl.useProgram(programBaseColor.program);\n                                        program = programBaseColor;\n                                    }\n                                }\n\n                                if ( material.pbrMetallicRoughness.baseColorTexture ) {\n                                    if (material.normalTexture) {\n                                        if (program != programBaseTextureNormalMap) {\n                                            gl.useProgram(programBaseTextureNormalMap.program);\n                                            program = programBaseTextureNormalMap;\n                                        }\n\n                                        gl.uniform1i(program.uniformNormalTextureLocation, material.normalTexture.index);\n\n                                        gl.activeTexture(gl.TEXTURE0 + material.normalTexture.index);\n                                        texture = glTF.textures[ material.normalTexture.index ];\n                                        gl.bindTexture(gl.TEXTURE_2D, texture.texture);\n                                        if (texture.sampler) {\n                                            sampler = texture.sampler.sampler;\n                                        } else {\n                                            sampler = defaultSampler;\n                                        }\n\n                                        gl.bindSampler(material.normalTexture.index, sampler);\n                                    } else {\n                                        if (program != programBaseTexture) {\n                                            gl.useProgram(programBaseTexture.program);\n                                            program = programBaseTexture;\n                                        }\n                                    }\n\n\n                                    gl.uniform1i(program.uniformBaseColorTextureLocation, material.pbrMetallicRoughness.baseColorTexture.index);\n                                    gl.activeTexture(gl.TEXTURE0 + material.pbrMetallicRoughness.baseColorTexture.index);\n                                    // gl.activeTexture(gl.TEXTURE1);\n                                    texture = glTF.textures[ material.pbrMetallicRoughness.baseColorTexture.index ];\n                                    gl.bindTexture(gl.TEXTURE_2D, texture.texture);\n                                    if (texture.sampler) {\n                                        sampler = texture.sampler.sampler;\n                                    } else {\n                                        sampler = defaultSampler;\n                                    }\n\n                                    gl.bindSampler(material.pbrMetallicRoughness.baseColorTexture.index, sampler);\n                                }\n\n                                \n\n                            }\n                        }\n\n                    }\n                }\n                \n                \n\n                gl.uniform4fv(program.uniformBaseColorFactorLocation, baseColor);\n\n                gl.uniformMatrix4fv(program.uniformMvpLocation, false, localMVP);\n                if (hasNormal) {\n                    gl.uniformMatrix4fv(program.uniformMvNormalLocation, false, localMVNormal);\n                }\n                \n\n                gl.bindVertexArray(primitive.vertexArray);\n\n                // TODO: when no indices, do drawArrays\n                if (primitive.indices !== null) {\n                    gl.drawElements(primitive.mode, primitive.indicesLength, primitive.indicesComponentType, primitive.indicesOffset);\n                } else {\n                    gl.drawArrays(primitive.mode, primitive.drawArraysOffset, primitive.drawArraysCount);\n                }\n\n                gl.bindVertexArray(null);\n\n            }\n\n            // function drawMesh(mesh, matrix) {\n            // }\n            var tmpMat4 = mat4.create();\n            var inverseTransformMat4 = mat4.create();\n            var inverseSkeletonRootMat4 = null;\n            \n            // @todo: \n            // in a real engine, it is better to simply parse the node tree stucture\n            // to compute transform matrices,\n            // then sort node array by material and render use a for loop\n            // to minimize context switch\n            function drawNode(node, nodeID, nodeMatrix, parentModelMatrix) {\n                var matrix = nodeMatrix[nodeID];\n                \n                if (parentModelMatrix !== undefined) {\n                    mat4.mul(matrix, parentModelMatrix, node.matrix);\n                } else {\n                    // from scene root, parent is identity\n                    mat4.copy(matrix, node.matrix);\n                }\n                // mat4.mul(matrix, parentModelMatrix, node.matrix);\n\n                hasSkin = false;\n                if (node.skin !== null) {\n                    // mesh node with skin\n                    hasSkin = true;\n                    var skin = node.skin;\n                    skinID = skin.skinID;\n                    var joints = node.skin.joints;\n                    var jointNode;\n\n                    mat4.invert(inverseTransformMat4, matrix);\n                    // if (skin.skeleton !== null) {\n                    //     // if (curScene.inverseSkeletonRootMatrixReady[skin.skinID] === false) {\n                    //     //     curScene.inverseSkeletonRootMatrixReady[skin.skinID] = true;\n                    //     //     mat4.invert(curScene.inverseSkeletonRootMatrix[skin.skinID], nodeMatrix[skin.skeleton.nodeID]);\n                    //     // }\n                    //     // inverseSkeletonRootMat4 = curScene.inverseSkeletonRootMatrix[skin.skinID];\n\n                    //     mat4.mul(inverseTransformMat4, inverseTransformMat4, nodeMatrix[skin.skeleton.nodeID]);\n                    // }\n\n                    // @tmp: assume joint nodes are always in the front of the scene node list\n                    // so that their matrices are ready to use\n                    for (i = 0, len = joints.length; i < len; i++) {\n                        jointNode = joints[i];\n                        mat4.mul(tmpMat4, nodeMatrix[jointNode.nodeID], skin.inverseBindMatrix[i]);\n                        \n                        mat4.mul(tmpMat4, inverseTransformMat4, tmpMat4);\n\n                        // if (skin.skeleton !== null) {\n                        //     mat4.mul(tmpMat4, inverseSkeletonRootMat4, tmpMat4);\n                        // }\n\n                        skin.jointMatrixUnidormBufferData.set(tmpMat4, i * 16);\n                    }\n\n                    gl.bindBuffer(gl.UNIFORM_BUFFER, skin.jointMatrixUniformBuffer);\n                    // gl.bufferSubData(gl.UNIFORM_BUFFER, 0, skin.jointMatrixUnidormBufferData);\n                    gl.bufferSubData(gl.UNIFORM_BUFFER, 0, skin.jointMatrixUnidormBufferData, 0, skin.jointMatrixUnidormBufferData.length);\n\n                    // if (program != programSkinBaseColor) {\n                    //     gl.useProgram(programSkinBaseColor.program);\n                    //     program = programSkinBaseColor;\n\n                    //     // @todo: uniform bind\n                    //     gl.uniformBlockBinding(program.program, program.uniformBlockIndexJointMatrix, 0);\n                    // }\n                    \n                }\n\n\n                var i, len;\n\n                // draw cur node's mesh\n                if (node.mesh !== null) {\n                    // drawMesh(glTF.meshes[node.mesh], matrix);\n\n                    // var mesh = glTF.meshes[node.mesh];\n                    var mesh = node.mesh;\n                    for (i = 0, len = mesh.primitives.length; i < len; i++) {\n                        // draw primitive\n                        drawPrimitive(mesh.primitives[i], matrix);\n                    }\n\n                    // BOUNDING_BOX.draw(mesh.boundingBox, matrix, modelView, perspective);\n                    // gl.useProgram(program);\n                }\n                \n                if (node.skin !== null) {\n                    gl.bindBuffer(gl.UNIFORM_BUFFER, null);\n                }\n                \n\n                // draw children\n                \n                var childNodeID;\n                for (i = 0, len = node.children.length; i < len; i++) {\n                    // childNodeID = node.children[i];\n                    // drawNode(glTF.nodes[childNodeID], childNodeID, matrix);\n                    drawNode(node.children[i], node.children[i].nodeID, nodeMatrix, matrix);\n                }\n            }\n\n\n            function drawScene(scene) {\n                // for (var i = 0, len = scene.nodes.length; i < len; i++) {\n                //     drawNode( scene.nodes[i], scene.nodes[i].nodeID, rootTransform );\n                // }\n                for (var i = 0, len = scene.glTFScene.nodes.length; i < len; i++) {\n                    drawNode( scene.glTFScene.nodes[i], scene.glTFScene.nodes[i].nodeID, scene.nodeMatrix, scene.rootTransform );\n                }\n            }\n\n            function drawSceneBBox(glTF, scene, bboxType) {\n                var node, mesh, bbox;\n                // @temp: assume all nodes are in cur scene\n                // @potential fix: can label each node's scene at the setup\n                for (i = 0, len = scene.nodeMatrix.length; i < len; i++) {\n                    node = glTF.nodes[i];\n\n                    if (bboxType == 'bvh') {\n                        // bvh\n                        mat4.mul(localMVP, scene.rootTransform, node.bvh.transform);\n                        mat4.mul(localMVP, VP, localMVP);\n                        gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\n                        gl.drawArrays(gl.LINES, 0, 24);\n                    }\n                    else if (node.mesh !== null) {\n                        // mesh = glTF.meshes[node.mesh];\n                        mesh = node.mesh;\n\n                        if (bboxType == 'aabb') {\n                            // aabb\n                            mat4.mul(localMVP, scene.rootTransform, node.aabb.transform);\n                            mat4.mul(localMVP, VP, localMVP);\n                        } else {\n                            // obb (assume object node is static)\n                            mat4.mul(localMVP, scene.nodeMatrix[i], mesh.boundingBox.transform);\n                            mat4.mul(localMVP, VP, localMVP);\n                        }\n\n                        gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\n                            \n                        gl.drawArrays(gl.LINES, 0, 24);\n\n                    }   \n                }\n\n                // scene bounding box\n                mat4.mul(localMVP, scene.rootTransform, scene.glTFScene.boundingBox.transform);\n                mat4.mul(localMVP, VP, localMVP);\n                gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\n                gl.drawArrays(gl.LINES, 0, 24);\n            }\n            \n\n            var timeParameter = 0;\n\n            // -- Render loop\n            (function render() {\n                var i, len;\n                var j, lenj;\n                var node;\n\n                // animation\n                if (glTF.animations) {\n                    for (i = 0, len = glTF.animations.length; i < len; i++) {\n                        animation = glTF.animations[i];\n                        for (j = 0, lenj = animation.samplers.length; j < lenj; j++) {\n                            animation.samplers[j].getValue(timeParameter);\n                        }\n\n                        for (j = 0, lenj = animation.channels.length; j < lenj; j++) {\n                            channel = animation.channels[j];\n                            animationSampler = channel.sampler;\n                            node = glTF.nodes[channel.target.nodeID];\n\n                            switch (channel.target.path) {\n                                case 'rotation':\n                                vec4.copy(node.rotation, animationSampler.curValue);\n                                break;\n\n                                case 'translation':\n                                vec3.copy(node.translation, animationSampler.curValue);\n                                break;\n\n                                case 'scale':\n                                vec3.copy(node.scale, animationSampler.curValue);\n                                break;\n                            }\n                            // switch (channel.target.path) {\n                            //     case 'rotation':\n                            //     vec4.copy(node.rotation, animationSampler.curValue);\n                            //     break;\n\n                            //     case 'translation':\n                            //     vec3.copy(node.translation, animationSampler.curValue);\n                            //     break;\n\n                            //     case 'scale':\n                            //     vec3.copy(node.scale, animationSampler.curValue);\n                            //     break;\n                            // }\n\n                            node.updateMatrixFromTRS();\n                            \n                        }\n                    }\n                }\n\n\n\n\n                // // skins\n                // if (glTF.skins) {\n                //     var skin, joints, M;\n                //     for (i = 0, len = glTF.skins.length; i < len; i++) {\n                //         skin = glTF.skins[i];\n                //         joints = skin.joints;\n                //         for (j = 0, lenj = joints.length; j < lenj; j++) {\n                //             M = skin.inverseBindMatrix[j];\n                //         }\n                //     }\n                // }\n\n                \n\n\n\n\n                gl.clearColor(0.0, 0.0, 0.0, 1.0);\n                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\n\n                vec3.set(scale, s, s, s);\n                // mat4.identity(modelView);\n                // mat4.translate(modelView, modelView, translate);\n                // mat4.scale(modelView, modelView, scale);\n                // mat4.fromRotationTranslationScale(modelView, identityQ, translate, scale);\n                // mat4.mul(modelView, modelView, modelMatrix);\n                mat4.identity(modelView);\n                mat4.translate(modelView, modelView, translate);\n                if (isDisplayRotation) {\n                    r += rotationSpeedY;\n                }\n                \n                \n                mat4.rotateX(modelView, modelView, eulerX);\n                mat4.rotateY(modelView, modelView, r);\n                \n                \n                mat4.scale(modelView, modelView, scale);\n\n\n                mat4.mul(modelView, modelView, modelMatrix);\n\n                mat4.rotateY(modelView, modelView, eulerY); \n                \n\n                mat4.mul(VP, perspective, modelView);\n\n                gl.useProgram(program.program);\n\n                for (i = 0, len = scenes.length; i < len; i++) {\n                    curScene = scenes[i];\n                    drawScene(scenes[i]);\n                }\n\n                if (drawBoundingBox) {\n                    gl.useProgram(BOUNDING_BOX.program);\n                    gl.bindVertexArray(BOUNDING_BOX.vertexArray);\n\n                    for (i = 0, len = scenes.length; i < len; i++) {\n                        drawSceneBBox(glTF, scenes[i], boundingBoxType);\n                    }\n\n\n                    gl.bindVertexArray(null);\n                    gl.useProgram(program.program);\n                }\n\n                requestAnimationFrame(render);\n                timeParameter += 0.01;\n            })();\n\n\n        });\n    })();\n    </script>\n\n</body>\n\n</html>\n"
  },
  {
    "path": "examples/webgl2-renderer.html",
    "content": "<!DOCTYPE html>\r\n<html lang=\"en\">\r\n\r\n<head>\r\n    <title>Minimal-glTF-Loader renderer example</title>\r\n    <meta charset=\"utf-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\r\n    <style>\r\n        #mycontrols {\r\n            position: absolute;\r\n            bottom: 20px;\r\n            right: 20px;\r\n            color: white;\r\n        }\r\n\r\n        canvas {\r\n            background-color: #000\r\n        }\r\n    </style>\r\n</head>\r\n\r\n<body>\r\n    <div id=\"info\">Minimal-glTF-Loader renderer example WebGL 2 Renderer Example</div>\r\n    <p id=\"description\">\r\n        An example viewer of the model loaded by Minimal-glTF-Loader\r\n    </p>\r\n    <div id=\"mycontrols\">\r\n        glTF Models: <select id=\"gltf-model\">\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/DamagedHelmet/glTF/DamagedHelmet.gltf\">DamagedHelmet</option>\r\n            <option value=\"https://raw.githubusercontent.com/shrekshao/minimal-gltf-loader/store-drone-model/glTFs/glTF_version_2/buster_drone/scene.gltf\">Drone</option>\r\n            <option value=\"https://raw.githubusercontent.com/shrekshao/glAvatar/master/demo/models/saber-mixamo-animation-test/saber-animation.gltf\">Mixamo-test</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BrainStem/glTF/BrainStem.gltf\">BrainStem</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Buggy/glTF/Buggy.gltf\">Buggy</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/2CylinderEngine/glTF/2CylinderEngine.gltf\">2CylinderEngine</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Avocado/glTF/Avocado.gltf\">Avocado</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BarramundiFish/glTF/BarramundiFish.gltf\">BarramundiFish</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BoomBox/glTF/BoomBox.gltf\">BoomBox</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/CesiumMan/glTF/CesiumMan.gltf\">CesiumMan</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/CesiumMilkTruck/glTF/CesiumMilkTruck.gltf\">CesiumMilkTruck</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Corset/glTF/Corset.gltf\">Corset</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Duck/glTF/Duck.gltf\">Duck</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/GearboxAssy/glTF/GearboxAssy.gltf\">GearboxAssy</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Lantern/glTF/Lantern.gltf\">Lantern</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/MetalRoughSpheres/glTF/MetalRoughSpheres.gltf\">MetalRoughSpheres</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/NormalTangentTest/glTF/NormalTangentTest.gltf\">NormalTangentTest</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/TextureCoordinateTest/glTF/TextureCoordinateTest.gltf\">TextureCoordinateTest</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/TextureSettingsTest/glTF/TextureSettingsTest.gltf\">TextureSettingsTest</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Triangle/glTF/Triangle.gltf\">Triangle</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/TriangleWithoutIndices/glTF/TriangleWithoutIndices.gltf\">TriangleWithoutIndices</option>\r\n            <option value=\"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/WaterBottle/glTF/WaterBottle.gltf\">WaterBottle</option>\r\n        </select> <br>\r\n        Animations: <select id=\"animations\"></select><br>\r\n        Play All Animations: <input id=\"play-all-animations\" type=\"checkbox\"><br>\r\n        Draw Bounding Box: <input id=\"bbox-toggle\" type=\"checkbox\" ><br>\r\n        Bounding Box type: <select id=\"bbox-type\">\r\n            <option value=\"obb\">OBB</option>\r\n            <option value=\"aabb\">AABB(static)</option>\r\n            <option value=\"bvh\">BVH(static)</option>\r\n        </select>\r\n    </div>\r\n\r\n\r\n    <script src='../build/app.js'></script>\r\n\r\n</body>\r\n\r\n</html>\r\n"
  },
  {
    "path": "examples/webpack.config.js",
    "content": "var path = require('path');\nvar webpack = require('webpack');\n// var HtmlWebpackPlugin = require('html-webpack-plugin');\nconst UglifyJSPlugin = require('uglifyjs-webpack-plugin');\n\nmodule.exports = {\n  entry: {\n    app: './src/index.js'\n  },\n  resolve: {\n      alias: {\n        // Lib: path.resolve(__dirname, 'demo/lib/'),\n        // Shaders: path.resolve(__dirname, 'demo/lib/src/shaders')\n      }\n  },\n  output: {\n    filename: '[name].js',\n    path: path.resolve(__dirname, '../build'),\n  },\n  module: {\n    rules: [\n        {\n            test: /\\.css$/,\n            use: [\n              'style-loader',\n              'css-loader'\n            ]\n        },\n        {\n            test: /\\.(png|jpg|gif)$/,\n            use: [\n                'file-loader'\n            ]\n        },\n        {\n            test: /\\.(glsl|vs|fs)$/,\n            use: [\n                'shader-loader'\n            ]\n        }\n    ],\n    // loaders: [\n    //   {\n    //     test: /\\.glsl$/,\n    //     loader: \"webpack-glsl\"\n    //   },\n    // ]\n  },\n  plugins: [\n        // new webpack.optimize.UglifyJsPlugin({\n        //     compress: {\n        //     warnings: false,\n        //     drop_console: false,\n        //     }\n        // })\n        // new UglifyJSPlugin()\n\n        // new HtmlWebpackPlugin({\n        //   title: \"glAvatar demo\"\n        // })\n    ],\n  devServer: {\n    contentBase: path.join(__dirname, \"demo\"),\n    port: 7777\n  }\n};"
  },
  {
    "path": "gulpfile.js",
    "content": "(function(){\n    'use strict';\n\n    var jshint = require('gulp-jshint');\n    var uglify = require('gulp-uglify');\n    var rename = require(\"gulp-rename\");\n    var gulp = require('gulp');\n\n    var jsHintFiles = [\n            '**/*.js', \n            '**/*.html', \n            '!node_modules/**', \n            '!src/third-party/**',\n            '!build/**'\n            ];\n\n    // gulp.task('default', function() {\n    //   // place code for your default task here\n    // });\n\n    gulp.task('default', ['jsHint']);\n\n    gulp.task('jsHint', function() {\n        return gulp.src(jsHintFiles)\n            .pipe(jshint.extract('auto'))\n            .pipe(jshint())\n            .pipe(jshint.reporter('jshint-stylish'))\n            .pipe(jshint.reporter('fail'));\n    });\n\n    gulp.task('jsHint-watch', function() {\n        gulp.watch(jsHintFiles).on('change', function(event) {\n            gulp.src(event.path)\n                .pipe(jshint.extract('auto'))\n                .pipe(jshint())\n                .pipe(jshint.reporter('jshint-stylish'));\n        });\n    });\n\n    gulp.task('compress', function() {\n    return gulp.src('src/minimal-gltf-loader.js')\n        .pipe(uglify())\n        .pipe(rename({suffix: '.min'}))\n        .pipe(gulp.dest('build'));\n    });\n})();\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"minimal-gltf-loader\",\n  \"version\": \"0.1.0\",\n  \"description\": \"A minimal JavaScript glTF Loader without need of 3D engines like Three.js.\",\n  \"main\": \"build/minimal-gltf-loader.js\",\n  \"directories\": {\n    \"example\": \"examples\"\n  },\n  \"scripts\": {\n    \"test\": \"gulp jsHint\",\n    \"build-examples\": \"webpack --config examples/webpack.config.js\",\n    \"build-examples-watch\": \"webpack --config examples/webpack.config.js --watch\",\n    \"build\": \"webpack\",\n    \"build-watch\": \"webpack --watch\",\n    \"dev-server\": \"node_modules/.bin/webpack-dev-server\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/shrekshao/minimal-gltf-loader.git\"\n  },\n  \"keywords\": [\n    \"glTF\",\n    \"WebGL\"\n  ],\n  \"author\": \"shrekshao\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/shrekshao/minimal-gltf-loader/issues\"\n  },\n  \"homepage\": \"https://github.com/shrekshao/minimal-gltf-loader#readme\",\n  \"devDependencies\": {\n    \"css-loader\": \"^0.28.7\",\n    \"file-loader\": \"^0.11.2\",\n    \"gulp\": \"^3.9.1\",\n    \"gulp-jshint\": \"^2.0.1\",\n    \"gulp-rename\": \"^1.2.2\",\n    \"gulp-uglify\": \"^1.5.3\",\n    \"jshint\": \"^2.9.2\",\n    \"jshint-stylish\": \"^2.2.0\",\n    \"shader-loader\": \"^1.3.1\",\n    \"style-loader\": \"^0.18.2\",\n    \"webpack\": \"^3.5.6\",\n    \"webpack-glsl-loader\": \"^1.0.1\"\n  },\n  \"dependencies\": {\n    \"gl-matrix\": \"^3.4.3\"\n  }\n}\n"
  },
  {
    "path": "src/glTFLoader.ts",
    "content": "import { vec3, mat4, quat } from \"gl-matrix\" \n\ntype GLTFID = number;\n\nenum MeshPrimitiveType {\n\tPOINTS\t\t\t\t\t\t\t= 0,\n\tLINES\t\t\t\t\t\t\t= 1,\n\tLINE_LOOP\t\t\t\t\t\t= 2,\n\tLINE_STRIP\t\t\t\t\t\t= 3,\n\tTRIANGLES\t\t\t\t\t\t= 4,\n\tTRIANGLE_STRIP\t\t\t\t\t= 5,\n\tTRIANGLE_FAN\t\t\t\t\t= 6\n}\n\nenum AccessorComponentType { \n\tGL_BYTE \t\t\t\t\t\t= 5120, \n\tGL_UNSIGNED_BYTE\t\t\t\t= 5121,\n\tGL_SHORT\t\t\t\t\t\t= 5122,\n\tGL_UNSIGNED_SHORT\t\t\t\t= 5123,\n\tGL_INT\t\t\t\t\t\t\t= 5124,\n\tGL_UNSIGNED_INT\t\t\t\t\t= 5125,\n\tGL_FLOAT\t\t\t\t\t\t= 5126\n};\n\nenum AccessorSparseIndicesComponentType {\n\tGL_UNSIGNED_BYTE\t\t\t\t= 5121,\n\tGL_UNSIGNED_SHORT\t\t\t\t= 5123,\n\tGL_UNSIGNED_INT\t\t\t\t\t= 5125\n}\n\nenum BufferViewTarget {\n\tARRAY_BUFFER\t\t\t\t\t= 34962,\n\tELEMENT_ARRAY_BUFFER\t\t\t= 34963\n}\n\nenum SamplerMagnificationFilter {\n\tNEAREST\t\t\t\t\t\t\t= 9728,\n\tLINEAR\t\t\t\t\t\t\t= 9729\n}\n\nenum SamplerMinificationFilter {\n\tNEAREST\t\t\t\t\t\t\t= 9728,\n\tLINEAR\t\t\t\t\t\t\t= 9729,\n\tNEAREST_MIPMAP_NEAREST\t\t\t= 9984,\n\tLINEAR_MIPMAP_NEAREST\t\t\t= 9985,\n\tNEAREST_MIPMAP_LINEAR\t\t\t= 9986,\n\tLINEAR_MIPMAP_LINEAR\t\t\t= 9987\n}\n\nenum SamplerWrappingMode {\n\tCLAMP_TO_EDGE\t\t\t\t\t= 33071,\n\tMIRRORED_REPEAT\t\t\t\t\t= 33648,\n\tREPEAT\t\t\t\t\t\t\t= 10497\n}\n\ninterface AssetBase {\n\tcopyright\t?: string;\n\tgenerator\t?: string;\n\tversion\t\t:  string;\n\tminVersion\t?: string;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface SceneBase {\n\tnodes\t\t:  GLTFID[];\n\tname\t\t?: string;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface NodeBase {\n\tcamera\t\t?: GLTFID;\n\tchildren\t?: GLTFID[];\n\tskin\t\t?: GLTFID;\n\tmatrix\t\t:  mat4;\n\tmesh\t\t?: GLTFID;\n\ttranslation\t?: vec3;\n\trotation\t?: quat;\n\tscale\t\t?: vec3;\n\tweights\t\t?: number[];\n\tname\t\t?: string;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface MeshBase {\n\tprimitives\t:  MeshPrimitiveBase[];\n\tweights\t\t?: number[];\n\tname\t\t?: string;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface MeshPrimitiveBase {\n\tattributes\t:  {POSITION ?: GLTFID, NORMAL ?: GLTFID, TEXCOORD_0 ?: GLTFID};\n\tindices\t\t?: GLTFID;\n\tmaterial\t?: GLTFID;\n\tmode\t\t?: MeshPrimitiveType;\n\ttargets\t\t?: {POSITION ?: GLTFID, NORMAL ?: GLTFID, TANGENT ?: GLTFID}[];\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface AccessorBase {\n\tbufferView\t\t?: GLTFID;\n\tbyteOffset\t\t?: number;\n\tcomponentType\t:  AccessorComponentType;\n\tnormalized\t\t?: boolean;\n\tcount\t\t\t:  number;\n\ttype\t\t\t:  \"SCALAR\" | \"VEC2\" | \"VEC3\" | \"VEC4\" | \"MAT2\" | \"MAT3\" | \"MAT4\";\n\tmax\t\t\t\t?: number[];\n\tmin\t\t\t\t?: number[];\n\tsparse\t\t\t?: AccessorSparseBase;\n\tname\t\t\t?: string;\n\textensions\t\t?: any;\n\textras\t\t\t?: any;\n}\ninterface AccessorSparseBase {\n\tcount\t\t\t:  number;\n\tindices\t\t\t:  AccessorSparseIndicesBase;\n\tvalues\t\t\t:  AccessorSparseValuesBase;\n\textensions\t\t?: any;\n\textras\t\t\t?: any;\n}\ninterface AccessorSparseIndicesBase {\n\tbufferView\t\t:  GLTFID;\n\tbyteOffset\t\t?: number;\n\tcomponentType\t:  AccessorSparseIndicesComponentType;\n\textensions\t\t?: any;\n\textras\t\t\t?: any;\n}\ninterface AccessorSparseValuesBase {\n\tbufferView\t\t:  GLTFID;\n\tbyteOffset\t\t?: number;\n\textensions\t\t?: any;\n\textras\t\t\t?: any;\n}\ninterface BufferViewBase {\n\tbuffer\t\t:  GLTFID;\n\tbyteOffset\t?: number;\n\tbyteLength\t:  number;\n\tbyteStride\t?: number;\n\ttarget\t\t?: BufferViewTarget;\n\tname\t\t?: string;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface BufferBase {\n\turi\t\t\t?: string;\n\tbyteLength\t:  number;\n\tname\t\t?: string;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface AnimationBase {\n\tchannels\t\t:  AnimationChannelBase[];\n\tsamplers\t\t:  AnimationSamplerBase[];\n\tname\t\t\t?: string;\n\textensions\t\t?: any;\n\textras\t\t\t?: any;\n}\ninterface AnimationChannelBase {\t\n\tsampler\t\t:  GLTFID;\n\ttarget\t\t:  AnimationChannelTargetBase;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface AnimationChannelTargetBase{\n\tnode\t\t?: GLTFID;\n\tpath\t\t:  \"translation\" | \"rotation\" | \"scale\" | \"weights\";\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface AnimationSamplerBase {\n\tinput\t\t\t:  GLTFID;\n\tinterpolation\t?: \"LINEAR\" | \"STEP\" | \"CUBICSPLINE\";\n\toutput\t\t\t:  GLTFID;\n\textensions\t\t?: any;\n\textras\t\t\t?: any;\n}\ninterface CameraBase{\n\torthographic\t?: CameraOrthographicBase;\n\tperspective\t\t?: CameraPerspectiveBase;\n\ttype\t\t\t:  \"perspective\" | \"orthographic\";\n\tname\t\t\t?: string;\n\textensions\t\t?: any;\n\textras\t\t\t?: any;\n}\ninterface CameraOrthographicBase {\n\txmag\t\t:  number;\n\tymag\t\t:  number;\n\tzfar\t\t:  number;\n\tznear\t\t:  number;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface CameraPerspectiveBase {\n\taspectRatio\t?: number;\n\tyfov\t\t:  number;\n\tzfar\t\t?: number;\n\tznear\t\t:  number;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface TextureBase {\n\tsampler\t\t?: GLTFID;\n\tsource\t\t?: GLTFID;\n\tname\t\t?: string;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface ImageBase {\n\turi\t\t\t?: string;\n\tmimeType\t?: \"image/jpeg\" | \"image/png\";\n\tbufferView\t?: GLTFID;\n\tname\t\t?: string;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface SamplerBase {\n\tmagFilter\t:  SamplerMagnificationFilter;\n\tminFilter\t:  SamplerMinificationFilter;\n\twrapS\t\t:  SamplerWrappingMode;\n\twrapT\t\t:  SamplerWrappingMode;\n\tname\t\t?: string;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface MaterialBase {\n\tname\t\t\t\t\t?: string;\n\textensions\t\t\t\t?: any;\n\textras\t\t\t\t\t?: any;\n\tpbrMetallicRoughness\t?: MaterialPbrMetallicRoughnessBase;\n\tnormalTexture\t\t\t?: MaterialNormalTextureInfoBase;\n\tocclusionTexture\t\t?: MaterialOcclusionTextureInfoBase;\n\temissiveTexture\t\t\t?: TextureInfoBase;\n\temissiveFactor\t\t\t?: number[];\n\talphaMode\t\t\t\t?: \"OPAQUE\" | \"MASK\" | \"BLEND\";\n\talphaCutoff\t\t\t\t?: number;\n\tdoubleSided\t\t\t\t?: boolean;\n}\ninterface MaterialPbrMetallicRoughnessBase {\n\tbaseColorFactor\t\t\t\t:  number[];\n\tbaseColorTexture\t\t\t:  TextureInfoBase;\n\tmetallicFactor\t\t\t\t:  number;\n\troughnessFactor\t\t\t\t:  number;\n\tmetallicRoughnessTexture\t:  TextureInfoBase;\n\textensions\t\t\t\t\t?: any;\n\textras\t\t\t\t\t\t?: any;\n}\ninterface MaterialNormalTextureInfoBase {\n\tindex\t\t?: any;\n\ttexCoord\t?: any;\n\tscale\t\t?: number;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface MaterialOcclusionTextureInfoBase {\n\tindex\t\t?: any;\n\ttexCoord\t?: any;\n\tstrength\t?: number;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface TextureInfoBase {\n\tindex\t\t:  GLTFID;\n\ttexCoord\t?: number;\n\textensions\t?: any;\n\textras\t\t?: any;\n}\ninterface SkinBase {\n\tinverseBindMatrices\t?: GLTFID;\n\tskeleton\t\t\t?: GLTFID;\n\tjoints\t\t\t\t:  GLTFID[];\n\tname\t\t\t\t?: string;\n\textensions\t\t\t?: any;\n\textras\t\t\t\t?: any;\n}\ninterface GLTFBase {\n\tasset\t\t\t\t:  AssetBase;\n\tscenes\t\t\t\t?: SceneBase[];\n\tscene\t\t\t\t?: GLTFID;\n\tnodes\t\t\t\t?: NodeBase[];\n\tmeshes\t\t\t\t?: MeshBase[];\n\taccessors\t\t\t?: AccessorBase[];\n\tbufferViews\t\t\t?: BufferViewBase[];\n\tbuffers\t\t\t\t?: BufferBase[];\n\tanimations\t\t\t?: AnimationBase[];\n\tcameras\t\t\t\t?: CameraBase[];\n\ttextures\t\t\t?: TextureBase[];\n\timages\t\t\t\t?: ImageBase[];\n\tsamplers\t\t\t?: SamplerBase[];\n\tmaterials\t\t\t?: MaterialBase[];\n\tskins\t\t\t\t?: SkinBase[];\n\textensions\t\t\t?: any;\n\textensionsRequired\t?: string[];\n\textensionsUsed\t\t?: string[];\n\textras\t\t\t\t?: any;\n}\ninterface BoundingBoxBase {\n\tmin\t\t\t:  vec3;\n\tmax\t\t\t:  vec3;\n\ttransform\t:  mat4;\n}\nclass Scene {\n\tnodes\t\t:  Node[];\n\tname\t\t:  string;\n\textensions\t:  any;\n\textras\t\t:  any;\n\tboundingBox\t:  BoundingBox;\n\tconstructor (sceneBase: SceneBase, gltf: GLTF) {\n\t\tconst length = sceneBase.nodes.length;\n\t\tthis.nodes = [];\n\t\tfor (let i = 0; i < length; i++) {\n\t\t\tthis.nodes.push(gltf.nodes[sceneBase.nodes[i]]);\n\t\t}\n\t\tthis.name\t\t\t= (sceneBase.name\t\t!== undefined) ? sceneBase.name\t\t\t: null;\n\t\tthis.extensions\t\t= (sceneBase.extensions\t!== undefined) ? sceneBase.extensions\t: null;\n\t\tthis.extras\t\t\t= (sceneBase.extras\t\t!== undefined) ? sceneBase.extras\t\t: null;\n\t\tthis.boundingBox\t=  null;\n\t};\n};\nexport class BoundingBox {\n\tmin\t\t\t:  vec3;\n\tmax\t\t\t:  vec3;\n\ttransform\t:  mat4;\n\tconstructor(min?: vec3, max?: vec3, isClone?: boolean) {\n\t\tmin = min || vec3.fromValues(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);\n\t\tmax = max || vec3.fromValues(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);\n\t\tif (isClone === undefined || isClone === true) {\n\t\t\tthis.min = vec3.clone(min);\n\t\t\tthis.max = vec3.clone(max);\n\t\t} else {\n\t\t\tthis.min = min;\n\t\t\tthis.max = max;\n\t\t}\n\t\tthis.transform = mat4.create();\n\t};\n\tupdateBoundingBox(boundingBoxBase: BoundingBoxBase): void {\n\t\tvec3.min(this.min, this.min, boundingBoxBase.min);\n\t\tvec3.max(this.max, this.max, boundingBoxBase.max);\n\t};\n\tcalculateTransform(): void {\n\t\t// transform from a unit cube whose min = (0, 0, 0) and max = (1, 1, 1)\n\t\t// scale\n\t\tthis.transform[0]\t= this.max[0] - this.min[0];\n\t\tthis.transform[5]\t= this.max[1] - this.min[1];\n\t\tthis.transform[10]\t= this.max[2] - this.min[2];\n\t\t// translate\n\t\tthis.transform[12]\t= this.min[0];\n\t\tthis.transform[13]\t= this.min[1];\n\t\tthis.transform[14]\t= this.min[2];\n\t};\n}\nclass Accessor {\n\tbufferView\t\t:  BufferView;\n\tbyteOffset\t\t:  number;\n\tcomponentType\t:  AccessorComponentType;\n\tnormalized\t\t:  boolean;\n\tcount\t\t\t:  number;\n\ttype\t\t\t:  \"SCALAR\" | \"VEC2\" | \"VEC3\" | \"VEC4\" | \"MAT2\" | \"MAT3\" | \"MAT4\";\n\tmax\t\t\t\t:  number[];\n\tmin\t\t\t\t:  number[];\n\tsparse\t\t\t:  AccessorSparseBase;\n\tname\t\t\t:  string;\n\textensions\t\t:  any;\n\textras\t\t\t:  any;\n\tconstructor(accessorBase: AccessorBase, bufferView: BufferView) {\n\t\tthis.bufferView \t=  bufferView;\n\t\tthis.byteOffset\t\t= (accessorBase.byteOffset\t!== undefined) ? accessorBase.byteOffset\t: 0;\n\t\tthis.componentType\t=  accessorBase.componentType;\n\t\tthis.normalized\t\t= (accessorBase.normalized\t!== undefined) ? accessorBase.normalized\t: false;\n\t\tthis.count\t\t\t=  accessorBase.count;\n\t\tthis.type\t\t\t=  accessorBase.type;\n\t\tthis.max\t\t\t=  accessorBase.max;\n\t\tthis.min\t\t\t=  accessorBase.min;\n\t\tthis.sparse\t\t\t= (accessorBase.sparse\t\t!== undefined) ? accessorBase.sparse\t\t: null;\n\t\tthis.name\t\t\t= (accessorBase.name\t\t!== undefined) ? accessorBase.name\t\t\t: null;\n\t\tthis.extensions\t\t= (accessorBase.extensions\t!== undefined) ? accessorBase.extensions\t: null;\n\t\tthis.extras\t\t\t= (accessorBase.extras\t\t!== undefined) ? accessorBase.extras\t\t: null;\n\t}\n\tprepareVertexAttribute(gl: WebGL2RenderingContext, location: number): void {\n\t\tgl.vertexAttribPointer(\n\t\t\tlocation,\n\t\t\tglTFLoaderBasic.accessorTypeToNumComponents(this.type),\n\t\t\tthis.componentType,\n\t\t\tthis.normalized,\n\t\t\tthis.bufferView.byteStride,\n\t\t\tthis.byteOffset\n\t\t)\n\t\tgl.enableVertexAttribArray(location)\n\t}\n}\nclass BufferView {\n\tbuffer\t\t:  WebGLBuffer;\n\tbyteOffset\t:  number;\n\tbyteLength\t:  number;\n\tbyteStride\t:  number;\n\ttarget\t\t:  BufferViewTarget;\n\tname\t\t:  string;\n\textensions\t:  any;\n\textras\t\t:  any;\n\tdata\t\t:  ArrayBuffer;\n\tconstructor(bufferViewBase: BufferViewBase, bufferData: ArrayBuffer) {\n\t\tthis.buffer\t\t=  null;\n\t\tthis.byteOffset = (bufferViewBase.byteOffset\t!== undefined) ? bufferViewBase.byteOffset\t: 0;\n\t\tthis.byteLength =  bufferViewBase.byteLength;\n\t\tthis.byteStride = (bufferViewBase.byteStride\t!== undefined) ? bufferViewBase.byteStride\t: 0;\n\t\tthis.target\t\t= (bufferViewBase.target\t\t!== undefined) ? bufferViewBase.target\t\t: 0;\n\t\tthis.name\t\t= (bufferViewBase.name\t\t\t!== undefined) ? bufferViewBase.name\t\t: null;\n\t\tthis.extensions\t= (bufferViewBase.extensions\t!== undefined) ? bufferViewBase.extensions\t: null;\n\t\tthis.extras\t\t= (bufferViewBase.extras\t\t!== undefined) ? bufferViewBase.extras\t\t: null;\n\t\tthis.data\t\t=  bufferData.slice(this.byteOffset, this.byteOffset + this.byteLength);\n\t}\n\tcreateBuffer(gl: WebGL2RenderingContext): void {\n\t\tthis.buffer = gl.createBuffer()\n\t}\n\tbindData(gl:WebGL2RenderingContext): void {\n\t\tconst target = this.target || BufferViewTarget.ARRAY_BUFFER\n\t\tgl.bindBuffer(target, this.buffer);\n\t\tgl.bufferData(target, this.data, gl.STATIC_DRAW);\n\t\tgl.bindBuffer(target, null);\n\t}\n}\nclass Camera {\n\torthographic\t:  CameraOrthographicBase;\n\tperspective\t\t:  CameraPerspectiveBase;\n\ttype\t\t\t:  \"perspective\" | \"orthographic\";\n\tname\t\t\t:  string;\n\textensions\t\t:  any;\n\textras\t\t\t:  any;\n\tconstructor(cameraBase: CameraBase) {\n\t\tthis.orthographic\t= (cameraBase.orthographic\t!== undefined) ? cameraBase.orthographic: null;\n\t\tthis.perspective\t= (cameraBase.perspective\t!== undefined) ? cameraBase.perspective\t: null;\n\t\tthis.type \t\t\t=  cameraBase.type;\n\t\tthis.name\t\t\t= (cameraBase.name\t\t\t!== undefined) ? cameraBase.name\t\t: null;\n\t\tthis.extensions\t\t= (cameraBase.extensions\t!== undefined) ? cameraBase.extensions\t: null;\n\t\tthis.extras\t\t\t= (cameraBase.extras\t\t!== undefined) ? cameraBase.extras\t\t: null;\n\t}\n}\nexport class Node {\n\tcamera\t\t:  GLTFID;\n\tchildren\t:  Node[];\n\tskin\t\t:  Skin;\n\ttranslation\t:  vec3;\n\trotation\t:  quat;\n\tscale\t\t:  vec3;\n\tmatrix\t\t:  mat4;\n\tmesh\t\t:  Mesh;\n\tweights\t\t:  number[];\n\tname\t\t:  string;\n\textensions\t:  any;\n\textras\t\t:  any;\n\tnodeID\t\t:  GLTFID;\n\tchildrenID\t:  GLTFID[];\n\tparent\t\t:  Node;\t\n\tskinLink\t:  SkinLink;\n\tmodelMatrix\t:  mat4;\n\tworldMatrix\t:  mat4;\n\taabb\t\t:  BoundingBox;\n\tbvh\t\t\t:  BoundingBox;\n\tconstructor(nodeBase: NodeBase, nodeID: GLTFID, currentLoader: GLTFLoader) {\n\t\tthis.camera\t\t\t= (nodeBase.camera\t\t!== undefined) ? nodeBase.camera\t\t: null;\n\t\tthis.children\t\t=  [];\n\t\tthis.skin\t\t\t=  null;\n\t\tthis.translation\t= (nodeBase.translation\t!== undefined) ? nodeBase.translation\t: vec3.create();\n\t\tthis.rotation\t\t= (nodeBase.rotation\t!== undefined) ? nodeBase.rotation\t\t: quat.create();\n\t\tthis.scale\t\t\t= (nodeBase.scale\t\t!== undefined) ? nodeBase.scale\t\t\t: vec3.fromValues(1.0, 1.0, 1.0);\n\t\tthis.matrix\t\t\t= (nodeBase.matrix\t\t!== undefined) ? mat4.clone(nodeBase.matrix) : mat4.fromRotationTranslationScale(mat4.create(), this.rotation, this.translation, this.scale);\n\t\tthis.mesh\t\t\t= (nodeBase.mesh\t\t!== undefined) ? currentLoader.glTF.meshes[nodeBase.mesh] : null;\n\t\tthis.weights\t\t= (nodeBase.weights\t\t!== undefined) ? nodeBase.weights\t\t: null;\n\t\tthis.name\t\t\t= (nodeBase.name\t\t!== undefined) ? nodeBase.name\t\t\t: null;\n\t\tthis.extensions\t\t= (nodeBase.extensions\t!== undefined) ? nodeBase.extensions\t: null;\n\t\tthis.extras\t\t\t= (nodeBase.extras\t\t!== undefined) ? nodeBase.extras\t\t: null;\n\t\tthis.nodeID\t\t\t=  nodeID;\n\t\tthis.childrenID\t\t= (nodeBase.children\t!== undefined) ? nodeBase.children\t\t: [];\n\t\tthis.parent\t\t\t=  null;\n\t\tthis.modelMatrix\t=  mat4.clone(this.matrix);\n\t\tthis.worldMatrix\t=  mat4.clone(this.matrix);\n\t\tif (nodeBase.extensions !== undefined) {\n\t\t\tif (nodeBase.extensions.gl_avatar !== undefined && currentLoader.enableGLAvatar === true) {\n\t\t\t\tconst linkedSkinID \t: number\t= currentLoader._glTF.extensions.gl_avatar.skins[nodeBase.extensions.gl_avatar.skin.name];\n\t\t\t\tconst linkedSkin\t: Skin\t\t= currentLoader.skeletonGLTF.skins[linkedSkinID];\n\t\t\t\tthis.skinLink = new SkinLink(linkedSkin, currentLoader.glTF, nodeBase.extensions.gl_avatar.skin.inverseBindMatrices);\n\t\t\t} else {\n\t\t\t\tthis.skinLink = null;\n\t\t\t}\n\t\t}\n\t\tthis.aabb\t\t\t= null;\n\t\tthis.bvh\t\t\t= new BoundingBox();\n\t};\n\ttraverse(traverseFunction: Function, parent?: Node): void {\n\t\tparent = (parent === undefined) ? null : parent;\n\t\ttraverseFunction(this, parent);\n\t\tfor (let i = 0, len = this.children.length; i < len; i++) {\n\t\t\tthis.children[i].traverse(traverseFunction, this);\n\t\t}\n\t};\n\ttraversePostOrder(traverseFunction: Function, parent: Node): void {\n\t\tparent = (parent === undefined) ? null : parent;\n\t\tfor (var i = 0, len = this.children.length; i < len; i++) {\n\t\t\tthis.children[i].traversePostOrder(traverseFunction, this);\n\t\t}\n\t\ttraverseFunction(this, parent);\n\t};\n\ttraverseTwoFunction(traverseFunctionPreOrder: Function, traverseFunctionPostOrder: Function, parent?: Node): void {\n\t\tparent = (parent === undefined) ? null : parent;\n\t\ttraverseFunctionPreOrder(this, parent);\n\t\tfor (let i = 0, len = this.children.length; i < len; i++) {\n\t\t\tthis.children[i].traverseTwoFunction(traverseFunctionPreOrder, traverseFunctionPostOrder, this);\n\t\t}\n\t\ttraverseFunctionPostOrder(this, parent);\n\t};\n}\nclass Mesh {\n\tprimitives\t:  MeshPrimitive[];\n\tweights\t\t:  number[];\n\tname\t\t:  string;\n\textensions\t:  any;\n\textras\t\t:  any;\n\tboundingBox\t:  BoundingBox;\n\tmeshID\t\t:  number;\n\tconstructor(meshBase: MeshBase, meshID: number, currentLoader: GLTFLoader) {\n\t\tthis.primitives\t\t=  [];\n\t\tthis.weights\t\t= (meshBase.weights\t\t!== undefined) ? meshBase.weights\t\t: null;\n\t\tthis.name\t\t\t= (meshBase.name\t\t!== undefined) ? meshBase.name\t\t\t: null;\n\t\tthis.extensions\t\t= (meshBase.extensions\t!== undefined) ? meshBase.extensions\t: null;\n\t\tthis.extras\t\t\t= (meshBase.extras\t\t!== undefined) ? meshBase.extras\t\t: null;\n\t\tthis.boundingBox\t=  null;\n\t\tlet  primitiveBase : MeshPrimitiveBase, primitive : MeshPrimitive;\n\t\tfor (let i = 0; i < meshBase.primitives.length; i++) {\n\t\t\tprimitiveBase = meshBase.primitives[i];\n\t\t\tprimitive = new MeshPrimitive(primitiveBase, currentLoader.glTF, currentLoader);\n\t\t\tthis.primitives.push(primitive);\n\t\t\tif (primitive.boundingBox) {\n\t\t\t\tif (!this.boundingBox) {\n\t\t\t\t\tthis.boundingBox = new BoundingBox()\n\t\t\t\t}\n\t\t\t\tthis.boundingBox.updateBoundingBox(primitive.boundingBox);\n\t\t\t}\n\t\t}\n\t\tif (this.boundingBox) {\n\t\t\tthis.boundingBox.calculateTransform();\n\t\t}\n\t\tthis.meshID\t\t\t=  meshID;\n\t}\n}\nexport class MeshPrimitive {\n\tattributesID\t\t\t: {POSITION ?: GLTFID , NORMAL ?: GLTFID, TEXCOORD_0 ?: GLTFID};\n\tattributes\t\t\t\t: {POSITION ?: Accessor , NORMAL ?: Accessor, TEXCOORD_0 ?: Accessor};\n\tindicesID\t\t\t\t:  GLTFID;\n\tindices\t\t\t\t\t:  Accessor;\n\tmaterial\t\t\t\t:  Material;\n\tmode\t\t\t\t\t:  MeshPrimitiveType;\n\ttargetsID\t\t\t\t: {POSITION ?: GLTFID, NORMAL ?: GLTFID, TANGENT ?: GLTFID}[];\n\ttargets\t\t\t\t\t: {POSITION ?: Accessor, NORMAL ?: Accessor, TANGENT ?: Accessor}[];\n\textensions\t\t\t\t:  any;\n\textras\t\t\t\t\t:  any;\n\tdrawIndices\t\t\t\t:  Accessor;\n\tvertexArray\t\t\t\t:  ArrayBuffer;\n\tvertexBuffer\t\t\t:  ArrayBuffer;\n\tshader\t\t\t\t\t:  WebGLShader;\n\tboundingBox\t\t\t\t:  BoundingBox;\n\tconstructor(primitiveBase: MeshPrimitiveBase, gltf: GLTF, currentLoader: GLTFLoader) {\n\t\tthis.attributesID =  primitiveBase.attributes;\n\t\tif (primitiveBase.extensions !== undefined) {\n\t\t\tif (primitiveBase.extensions.gl_avatar !== undefined && currentLoader.enableGLAvatar === true) {\n\t\t\t\tif (primitiveBase.extensions.gl_avatar.attributes) {\n\t\t\t\t\tfor (let attributeName in primitiveBase.extensions.gl_avatar.attributes) {\n\t\t\t\t\t\tthis.attributesID[attributeName] = primitiveBase.extensions.gl_avatar.attributeName[attributeName];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.attributes = {POSITION : null , NORMAL : null, TEXCOORD_0 : null};\n\t\tfor (let attributeName in this.attributesID) {\n\t\t\tthis.attributes[attributeName] = gltf.accessors[this.attributesID[attributeName]];\n\t\t}\n\t\tif (this.attributes.POSITION !== undefined) {\n\t\t\tlet accessor = this.attributes.POSITION;\n\t\t\tif (accessor.max) {\n\t\t\t\tif (accessor.type === \"VEC3\") {\n\t\t\t\t\tthis.boundingBox = new BoundingBox(\n\t\t\t\t\t\tvec3.fromValues(accessor.min[0], accessor.min[1], accessor.min[2]),\n\t\t\t\t\t\tvec3.fromValues(accessor.max[0], accessor.max[1], accessor.max[2]),\n\t\t\t\t\t\tfalse\n\t\t\t\t\t);\n\t\t\t\t\tthis.boundingBox.calculateTransform();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.indicesID\t= (primitiveBase.indices\t!== undefined) ? primitiveBase.indices\t\t: null;\n\t\tif (this.indicesID !== null) {\n\t\t\tthis.indices\t\t= gltf.accessors[this.indicesID];\n\t\t} else {\n\t\t\tthis.drawIndices\t= gltf.accessors[this.attributesID.POSITION];\n\t\t}\n\n\t\tthis.material\t= (primitiveBase.material\t!== undefined) ? gltf.materials[primitiveBase.material] : null;\n\t\tthis.mode\t\t= (primitiveBase.mode\t\t!== undefined) ? primitiveBase.mode\t\t\t: MeshPrimitiveType.TRIANGLES;\n\t\tthis.targetsID\t= (primitiveBase.targets\t!== undefined) ? primitiveBase.targets\t\t: null;\n\t\tfor (let targetID in this.targetsID) {\n\t\t\tconst currentTarget = {POSITION : null , NORMAL : null, TEXCOORD_0 : null};\n\t\t\t// for (let attributeName in targetID) {\n\t\t\t// \tthis.targets\n\t\t\t// }\n\t\t}\n\t\tthis.extensions\t= (primitiveBase.extensions\t!== undefined) ? primitiveBase.extensions\t: null;\n\t\tthis.extras\t\t= (primitiveBase.extras\t\t!== undefined) ? primitiveBase.extras\t\t: null;\n\n\n\t\tthis.vertexArray\t= null;\n\t\tthis.vertexBuffer\t= null;\n\t\tthis.shader\t\t\t= null;\n\t}\n}\nclass Texture {\n\tsampler\t\t:  Sampler;\n\tsource\t\t:  ImageBitmap | ImageData | HTMLImageElement;\n\tname\t\t:  string;\n\textensions\t:  any;\n\textras\t\t:  any;\n\ttexture\t\t:  WebGLTexture;\n\tconstructor(textureBase: TextureBase, currentLoader: GLTFLoader) {\n\t\tthis.sampler\t= (textureBase.sampler\t\t!== undefined) ? currentLoader.glTF.samplers[textureBase.sampler]\t: null;\n\t\tthis.source\t\t= (textureBase.sampler\t\t!== undefined) ? currentLoader.glTF.images[textureBase.source]\t\t: null;\n\t\tthis.name\t\t= (textureBase.name\t\t\t!== undefined) ? textureBase.name\t\t\t: null;\n\t\tthis.extensions\t= (textureBase.extensions\t!== undefined) ? textureBase.extensions\t\t: null;\n\t\tthis.extras\t\t= (textureBase.extras\t\t!== undefined) ? textureBase.extras\t\t\t: null;\n\t\tthis.texture\t= null;\n\t}\n\tcreateTexture(gl: WebGL2RenderingContext): void {\n\t\tthis.texture = gl.createTexture();\n\t\tgl.bindTexture(gl.TEXTURE_2D, this.texture);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\t\t// assumed\n\t\t\t0,\t\t\t\t\t// Level of details\n\t\t\tgl.RGBA,\t\t\t// Internalformat\n\t\t\tgl.RGBA,\t\t\t// Format\n\t\t\tgl.UNSIGNED_BYTE,\t// Size of each channel\n\t\t\tthis.source\n\t\t);\n\t\tgl.generateMipmap(gl.TEXTURE_2D);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t}\n}\nclass Sampler {\n\tmagFilter\t:  SamplerMagnificationFilter;\n\tminFilter\t:  SamplerMinificationFilter;\n\twrapS\t\t:  SamplerWrappingMode;\n\twrapT\t\t:  SamplerWrappingMode;\n\tname\t\t:  string;\n\textensions\t:  any;\n\textras\t\t:  any;\n\t// FIXME: \n\t// 当前版本typescipt不支持接口WebGLSampler 等待升级\n\t// sampler\t\t:  WebGLSampler;\n\tsampler\t\t:  any;\n\tconstructor(samplerBase: SamplerBase) {\n\t\tthis.magFilter\t= (samplerBase.magFilter\t!== undefined) ? samplerBase.magFilter\t: null;\n\t\tthis.minFilter\t= (samplerBase.minFilter\t!== undefined) ? samplerBase.minFilter\t: null;\n\t\tthis.wrapS\t\t= (samplerBase.wrapS\t\t!== undefined) ? samplerBase.wrapS\t\t: SamplerWrappingMode.REPEAT;\n\t\tthis.wrapT\t\t= (samplerBase.wrapT\t\t!== undefined) ? samplerBase.wrapT\t\t: SamplerWrappingMode.REPEAT;\n\t\tthis.name\t\t= (samplerBase.name\t\t\t!== undefined) ? samplerBase.name\t\t: null;\n\t\tthis.extensions\t= (samplerBase.extensions\t!== undefined) ? samplerBase.extensions\t: null;\n\t\tthis.extras\t\t= (samplerBase.extras\t\t!== undefined) ? samplerBase.extras\t\t: null;\n\t\tthis.sampler\t= null;\n\t}\n\tcreateSampler(gl: WebGL2RenderingContext) {\n\t\tthis.sampler = gl.createSampler();\n\t\tif (this.minFilter) {\n\t\t\tgl.samplerParameteri(this.sampler, gl.TEXTURE_MIN_FILTER, this.minFilter);\n\t\t} else {\n\t\t\tgl.samplerParameteri(this.sampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);\n\t\t}\n\t\tif (this.magFilter) {\n\t\t\tgl.samplerParameteri(this.sampler, gl.TEXTURE_MAG_FILTER, this.magFilter);\n\t\t} else {\n\t\t\tgl.samplerParameteri(this.sampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\t}\n\t\tgl.samplerParameteri(this.sampler, gl.TEXTURE_WRAP_S, this.wrapS);\n\t\tgl.samplerParameteri(this.sampler, gl.TEXTURE_WRAP_T, this.wrapT);\n\t}\n}\nclass TextureInfo {\n\tindex\t\t:  GLTFID;\n\ttexCoord\t:  number;\n\textensions\t:  any;\n\textras\t\t:  any;\n\tconstructor(textureInfoBase: TextureInfoBase) {\n\t\tthis.index\t\t= textureInfoBase.index;\n\t\tthis.texCoord\t= (textureInfoBase.texCoord\t\t!== undefined) ? textureInfoBase.texCoord\t: 0 ;\n\t\tthis.extensions\t= (textureInfoBase.extensions\t!== undefined) ? textureInfoBase.extensions\t: null;\n\t\tthis.extras\t\t= (textureInfoBase.extras\t\t!== undefined) ? textureInfoBase.extras\t\t: null;\n\t}\n}\nclass Material {\n\tname\t\t\t\t\t:  string;\n\textensions\t\t\t\t:  any;\n\textras\t\t\t\t\t:  any;\n\tpbrMetallicRoughness\t:  MaterialPbrMetallicRoughness;\n\tnormalTexture\t\t\t:  MaterialNormalTextureInfo;\n\tocclusionTexture\t\t:  MaterialOcclusionTextureInfo;\n\temissiveTexture\t\t\t:  TextureInfo;\n\temissiveFactor\t\t\t:  number[];\n\talphaMode\t\t\t\t:  \"OPAQUE\" | \"MASK\" | \"BLEND\";\n\talphaCutoff\t\t\t\t:  number;\n\tdoubleSided\t\t\t\t:  boolean;\n\tconstructor(materialBase: MaterialBase) {\n\t\tthis.name\t\t\t\t\t= (materialBase.name\t\t\t\t\t!== undefined) ? materialBase.name\t\t\t\t: null;\n\t\tthis.extensions\t\t\t\t= (materialBase.extensions\t\t\t\t!== undefined) ? materialBase.extensions\t\t: null;\n\t\tthis.extras\t\t\t\t\t= (materialBase.extras\t\t\t\t\t!== undefined) ? materialBase.extras\t\t\t: null;\n\t\tthis.pbrMetallicRoughness\t= (materialBase.pbrMetallicRoughness\t!== undefined) ? new MaterialPbrMetallicRoughness(materialBase.pbrMetallicRoughness) : new MaterialPbrMetallicRoughness({\n\t\t\tbaseColorFactor\t\t\t\t: [1, 1, 1, 1],\n\t\t\tbaseColorTexture\t\t\t: null,\n\t\t\tmetallicFactor\t\t\t\t: 1,\n\t\t\troughnessFactor\t\t\t\t: 1,\n\t\t\tmetallicRoughnessTexture\t: null,\n\t\t});\n\t\tthis.normalTexture\t\t\t= (materialBase.normalTexture\t\t\t!== undefined) ? new MaterialNormalTextureInfo(materialBase.normalTexture)\t\t: null;\n\t\tthis.occlusionTexture\t\t= (materialBase.occlusionTexture\t\t!== undefined) ? new MaterialOcclusionTextureInfo(materialBase.occlusionTexture)\t: null;\n\t\tthis.emissiveTexture\t\t= (materialBase.emissiveTexture\t\t\t!== undefined) ? new TextureInfo(materialBase.emissiveTexture)\t\t\t\t\t: null;\n\t\tthis.emissiveFactor\t\t\t= (materialBase.emissiveFactor\t\t\t!== undefined) ? materialBase.emissiveFactor\t: [0, 0, 0];\n\t\tthis.alphaMode\t\t\t\t= (materialBase.alphaMode\t\t\t\t!== undefined) ? materialBase.alphaMode\t\t\t: \"OPAQUE\";\n\t\tthis.alphaCutoff\t\t\t= (materialBase.alphaCutoff\t\t\t\t!== undefined) ? materialBase.alphaCutoff\t\t: 0.5;\n\t\tthis.doubleSided\t\t\t= !!materialBase.doubleSided;\n\t}\n}\nclass MaterialPbrMetallicRoughness {\n\tbaseColorFactor\t\t\t\t:  number[];\n\tbaseColorTexture\t\t\t:  TextureInfoBase;\n\tmetallicFactor\t\t\t\t:  number;\n\troughnessFactor\t\t\t\t:  number;\n\tmetallicRoughnessTexture\t:  TextureInfoBase;\n\textensions\t\t\t\t\t:  any;\n\textras\t\t\t\t\t\t:  any;\n\tconstructor(materialPbrMetallicRoughnessBase: MaterialPbrMetallicRoughnessBase) {\n\t\tthis.baseColorFactor\t\t\t= (materialPbrMetallicRoughnessBase.baseColorFactor\t\t\t\t!== undefined) ? materialPbrMetallicRoughnessBase.baseColorFactor\t: [1, 1, 1, 1];\n\t\tthis.baseColorTexture\t\t\t= (materialPbrMetallicRoughnessBase.baseColorTexture\t\t\t!== undefined) ? new TextureInfo(materialPbrMetallicRoughnessBase.baseColorTexture): null;\n\t\tthis.metallicFactor\t\t\t\t= (materialPbrMetallicRoughnessBase.metallicFactor\t\t\t\t!== undefined) ? materialPbrMetallicRoughnessBase.metallicFactor\t: 1;\n\t\tthis.roughnessFactor\t\t\t= (materialPbrMetallicRoughnessBase.roughnessFactor\t\t\t\t!== undefined) ? materialPbrMetallicRoughnessBase.roughnessFactor\t: 1;\n\t\tthis.metallicRoughnessTexture\t= (materialPbrMetallicRoughnessBase.metallicRoughnessTexture\t!== undefined) ? new TextureInfo(materialPbrMetallicRoughnessBase.metallicRoughnessTexture): null;\n\t\tthis.extensions\t\t\t\t\t= (materialPbrMetallicRoughnessBase.extensions\t\t\t\t\t!== undefined) ? materialPbrMetallicRoughnessBase.extensions\t\t: null;\n\t\tthis.extras\t\t\t\t\t\t= (materialPbrMetallicRoughnessBase.extras\t\t\t\t\t\t!== undefined) ? materialPbrMetallicRoughnessBase.extras\t\t\t: null;\n\t}\n}\nclass MaterialNormalTextureInfo {\n\tindex\t\t:  any;\n\ttexCoord\t:  any;\n\tscale\t\t:  number;\n\textensions\t:  any;\n\textras\t\t:  any;\n\tconstructor(materialNormalTextureInfoBase: MaterialNormalTextureInfoBase) {\n\t\tthis.index\t\t= (materialNormalTextureInfoBase.index\t\t!== undefined) ? materialNormalTextureInfoBase.index\t\t: 0;\n\t\tthis.texCoord\t= (materialNormalTextureInfoBase.texCoord\t!== undefined) ? materialNormalTextureInfoBase.texCoord\t\t: 0;\n\t\tthis.scale\t\t= (materialNormalTextureInfoBase.scale\t\t!== undefined) ? materialNormalTextureInfoBase.scale\t\t: 1;\n\t\tthis.extensions\t= (materialNormalTextureInfoBase.extensions\t!== undefined) ? materialNormalTextureInfoBase.extensions\t: null;\n\t\tthis.extras\t\t= (materialNormalTextureInfoBase.extras\t\t!== undefined) ? materialNormalTextureInfoBase.extras\t\t: null;\n\t}\n}\nclass MaterialOcclusionTextureInfo {\n\tindex\t\t:  any;\n\ttexCoord\t:  any;\n\tstrength\t:  number;\n\textensions\t:  any;\n\textras\t\t:  any;\n\tconstructor(materialOcclusionTextureInfoBase: MaterialOcclusionTextureInfoBase) {\n\t\tthis.index\t\t= (materialOcclusionTextureInfoBase.index\t\t!== undefined) ? materialOcclusionTextureInfoBase.index\t\t\t: 0;\n\t\tthis.texCoord\t= (materialOcclusionTextureInfoBase.texCoord\t!== undefined) ? materialOcclusionTextureInfoBase.texCoord\t\t: 0;\n\t\tthis.strength\t= (materialOcclusionTextureInfoBase.strength\t!== undefined) ? materialOcclusionTextureInfoBase.strength\t\t: 1;\n\t\tthis.extensions\t= (materialOcclusionTextureInfoBase.extensions\t!== undefined) ? materialOcclusionTextureInfoBase.extensions\t: null;\n\t\tthis.extras\t\t= (materialOcclusionTextureInfoBase.extras\t\t!== undefined) ? materialOcclusionTextureInfoBase.extras\t\t: null;\n\t}\n}\nclass Skin {\n\tinverseBindMatrices\t\t\t\t:  Accessor;\n\tskeleton\t\t\t\t\t\t:  Node;\n\tjoints\t\t\t\t\t\t\t:  Node[];\n\tname\t\t\t\t\t\t\t:  string;\n\textensions\t\t\t\t\t\t:  any;\n\textras\t\t\t\t\t\t\t:  any;\n\tisLink\t\t\t\t\t\t\t:  boolean;\n\tinverseBindMatricesData\t\t\t:  Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array;\n\tinverseBindMatrix\t\t\t\t:  mat4[];\n\tconstructor(skinBase: SkinBase, gltf: GLTF) {\n\t\tthis.inverseBindMatrices\t= (skinBase.inverseBindMatrices\t!== undefined) ? gltf.accessors[skinBase.inverseBindMatrices]\t: null;\n\t\tthis.skeleton\t\t\t\t= (skinBase.skeleton\t\t\t!== undefined) ? gltf.nodes[skinBase.skeleton]\t\t\t\t\t: null;\n\t\tthis.joints\t\t\t\t\t=  [];\n\t\tfor (let i = 0; i < skinBase.joints.length; i++) {\n\t\t\tthis.joints.push(gltf.nodes[skinBase.joints[i]]);\n\t\t}\t\t\n\t\tthis.name\t\t\t\t\t= (skinBase.name\t\t\t\t!== undefined) ? skinBase.name\t\t\t\t: null;\n\t\tthis.extensions\t\t\t\t= (skinBase.extensions\t\t\t!== undefined) ? skinBase.extensions\t\t: null;\n\t\tthis.extras\t\t\t\t\t= (skinBase.extras\t\t\t\t!== undefined) ? skinBase.extras\t\t\t: null;\n\t\tthis.isLink\t\t\t\t\t=  false;\n\t\tif (this.inverseBindMatrices) {\n\t\t\tthis.inverseBindMatricesData = glTFLoaderBasic.getAccessorData(this.inverseBindMatrices);\n\t\t\tthis.inverseBindMatrix = [];\n\t\t\tfor(let i = 0; i < this.inverseBindMatricesData.length; i += 16) {\n\t\t\t\tthis.inverseBindMatrix.push(\n\t\t\t\t\tmat4.fromValues(\n\t\t\t\t\t\tthis.inverseBindMatricesData[i],\t\tthis.inverseBindMatricesData[i + 1],\tthis.inverseBindMatricesData[i + 2],\tthis.inverseBindMatricesData[i + 3],\n\t\t\t\t\t\tthis.inverseBindMatricesData[i + 4],\tthis.inverseBindMatricesData[i + 5],\tthis.inverseBindMatricesData[i + 6],\tthis.inverseBindMatricesData[i + 7],\n\t\t\t\t\t\tthis.inverseBindMatricesData[i + 8],\tthis.inverseBindMatricesData[i + 9],\tthis.inverseBindMatricesData[i + 10],\tthis.inverseBindMatricesData[i + 11],\n\t\t\t\t\t\tthis.inverseBindMatricesData[i + 12],\tthis.inverseBindMatricesData[i + 13],\tthis.inverseBindMatricesData[i + 14],\tthis.inverseBindMatricesData[i + 15],\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\nclass SkinLink {\n\tinverseBindMatrices\t\t\t\t:  Accessor;\n\tskeleton\t\t\t\t\t\t:  Node;\n\tjoints\t\t\t\t\t\t\t:  Node[];\n\tname\t\t\t\t\t\t\t:  string;\n\textensions\t\t\t\t\t\t:  any;\n\textras\t\t\t\t\t\t\t:  any;\n\tisLink\t\t\t\t\t\t\t:  boolean\n\tinverseBindMatricesData\t\t\t:  Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array;\n\tinverseBindMatrix\t\t\t\t:  mat4[];\n\tconstructor(linkedSkin: Skin, gltf: GLTF, inverseBindMatricesAccessorID?: number) {\n\t\tif (!gltf.skins) {\n\t\t\tgltf.skins = [];\n\t\t}\n\t\tgltf.skins.push(this);\n\t\tthis.inverseBindMatrices\t= (inverseBindMatricesAccessorID\t!== undefined) ? gltf.accessors[inverseBindMatricesAccessorID]\t: null;\n\t\tthis.skeleton\t\t\t\t=  linkedSkin.skeleton;\n\t\tthis.joints\t\t\t\t\t=  linkedSkin.joints;\t\t\n\t\tthis.name\t\t\t\t\t=  linkedSkin.name;\n\t\tthis.extensions\t\t\t\t=  linkedSkin.extensions;\n\t\tthis.extras\t\t\t\t\t=  linkedSkin.extras;\n\t\tthis.isLink\t\t\t\t\t=  true;\n\t\tif (this.inverseBindMatrices) {\n\t\t\tthis.inverseBindMatricesData = glTFLoaderBasic.getAccessorData(this.inverseBindMatrices);\n\t\t\tthis.inverseBindMatrix = [];\n\t\t\tfor(let i = 0; i < this.inverseBindMatricesData.length; i += 16) {\n\t\t\t\tthis.inverseBindMatrix.push(\n\t\t\t\t\tmat4.fromValues(\n\t\t\t\t\t\tthis.inverseBindMatricesData[i],\t\tthis.inverseBindMatricesData[i + 1],\tthis.inverseBindMatricesData[i + 2],\tthis.inverseBindMatricesData[i + 3],\n\t\t\t\t\t\tthis.inverseBindMatricesData[i + 4],\tthis.inverseBindMatricesData[i + 5],\tthis.inverseBindMatricesData[i + 6],\tthis.inverseBindMatricesData[i + 7],\n\t\t\t\t\t\tthis.inverseBindMatricesData[i + 8],\tthis.inverseBindMatricesData[i + 9],\tthis.inverseBindMatricesData[i + 10],\tthis.inverseBindMatricesData[i + 11],\n\t\t\t\t\t\tthis.inverseBindMatricesData[i + 12],\tthis.inverseBindMatricesData[i + 13],\tthis.inverseBindMatricesData[i + 14],\tthis.inverseBindMatricesData[i + 15],\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\nexport class Animation {\n\tsamplers\t\t:  AnimationSampler[];\n\tchannels\t\t:  AnimationChannel[];\n\tname\t\t\t:  string;\n\textensions\t\t:  any;\n\textras\t\t\t:  any;\n\tconstructor(animationBase: AnimationBase, gltf: GLTF) {\n\t\tthis.samplers = [];\n\t\tfor (let i = 0; i < animationBase.samplers.length; i++) {\n\t\t\tthis.samplers.push(new AnimationSampler(animationBase.samplers[i], gltf));\n\t\t}\n\t\tthis.channels = [];\n\t\tfor (let i = 0; i < animationBase.channels.length; i++) {\n\t\t\tthis.channels.push(new AnimationChannel(animationBase.channels[i], this));\n\t\t}\n\t\tthis.name\t\t\t\t\t= (animationBase.name\t\t\t\t!== undefined) ? animationBase.name\t\t\t\t: null;\n\t\tthis.extensions\t\t\t\t= (animationBase.extensions\t\t\t!== undefined) ? animationBase.extensions\t\t: null;\n\t\tthis.extras\t\t\t\t\t= (animationBase.extras\t\t\t\t!== undefined) ? animationBase.extras\t\t\t: null;\n\t}\n}\nexport class AnimationChannel {\n\tsampler\t\t:  AnimationSampler;\n\ttarget\t\t:  AnimationChannelTarget;\n\textensions\t:  any;\n\textras\t\t:  any;\n\tconstructor(animationChannelBase: AnimationChannelBase, animation: Animation) {\n\t\tthis.sampler\t=  animation.samplers[animationChannelBase.sampler];\n\t\tthis.target\t\t=  new AnimationChannelTarget(animationChannelBase.target);\n\t\tthis.extensions\t= (animationChannelBase.extensions\t!== undefined) ? animationChannelBase.extensions\t: null;\n\t\tthis.extras\t\t= (animationChannelBase.extras\t\t!== undefined) ? animationChannelBase.extras\t\t: null;\n\t}\n}\nclass AnimationChannelTarget {\n\tnode\t\t:  Node;\n\tpath\t\t:  \"translation\" | \"rotation\" | \"scale\" | \"weights\";\n\textensions\t:  any;\n\textras\t\t:  any;\n\tnodeID\t\t:  GLTFID;\n\tconstructor(animationChannelTargetBase: AnimationChannelTargetBase) {\n\t\t//id, to be hooked up to object later\n\t\tthis.nodeID\t\t=  animationChannelTargetBase.node;\n\t\tthis.path\t\t=  animationChannelTargetBase.path;\n\t\tthis.extensions\t= (animationChannelTargetBase.extensions\t!== undefined) ? animationChannelTargetBase.extensions\t: null;\n\t\tthis.extras\t\t= (animationChannelTargetBase.extras\t\t!== undefined) ? animationChannelTargetBase.extras\t\t: null;\n\t}\n}\nexport class AnimationSampler {\n\tinput\t\t\t\t:  Accessor;\n\tinterpolation\t\t:  \"LINEAR\" | \"STEP\" | \"CUBICSPLINE\";\n\toutput\t\t\t\t:  Accessor;\n\textensions\t\t\t:  any;\n\textras\t\t\t\t:  any;\n\tkeyFrameIndices\t\t:  Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array;\n\tkeyFrameRaw\t\t\t:  Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array;\n\tkeyFrames\t\t\t:  {src: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array, dst: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array};\n\tcurrentIndex\t\t:  number;\n\tstartTime\t\t\t:  number;\n\tendTime\t\t\t\t:  number;\n\tduration\t\t\t:  number;\n\tconstructor(animationSamplerBase: AnimationSamplerBase, gltf: GLTF) {\n\t\tthis.input\t\t\t\t=  gltf.accessors[animationSamplerBase.input]; \n\t\tthis.interpolation\t\t= (animationSamplerBase.interpolation\t!== undefined) ? animationSamplerBase.interpolation : \"LINEAR\";\n\t\tthis.output\t\t\t\t=  gltf.accessors[animationSamplerBase.output];\n\t\tthis.extensions\t\t\t= (animationSamplerBase.extensions\t\t!== undefined) ? animationSamplerBase.extensions\t: null;\n\t\tthis.extras\t\t\t\t= (animationSamplerBase.extras\t\t\t!== undefined) ? animationSamplerBase.extras\t\t: null;\n\t\tthis.keyFrameIndices\t=  glTFLoaderBasic.getAccessorData(this.input);\n\t\tthis.keyFrameRaw\t\t=  glTFLoaderBasic.getAccessorData(this.output);\n\t\tthis.keyFrames\t\t\t= {src: null, dst: null};\n\t\tthis.currentIndex\t\t= 0;\n\t\tthis.startTime\t\t\t= this.keyFrameIndices[0];\n\t\tthis.endTime\t\t\t= this.keyFrameIndices[this.keyFrameIndices.length - 1];\n\t\tthis.duration\t\t\t= this.endTime - this.startTime;\n\t}\n\tupdateKeyFrames(time: number): void  {\n\t\twhile (this.currentIndex < this.keyFrameIndices.length - 2 && time >= this.keyFrameIndices[this.currentIndex + 1]) {\n\t\t\tthis.currentIndex++;\n\t\t}\n\t\tconst byteLength = glTFLoaderBasic.accessorTypeToNumComponents(this.output.type);\n\t\tthis.keyFrames.src = this.keyFrameRaw.slice(this.currentIndex * byteLength, (this.currentIndex + 1) * byteLength);\n\t\tthis.keyFrames.dst = this.keyFrameRaw.slice((this.currentIndex + 1) * byteLength, (this.currentIndex + 2) * byteLength);\n\t\tif (time >= this.endTime) {\n\t\t\tthis.currentIndex = 0;\n\t\t}\n\t}\n}\nexport class GLTF {\n\tasset\t\t\t\t:  AssetBase;\n\tscene\t\t\t\t?: Scene;\n\tscenes\t\t\t\t?: Scene[];\n\tnodes\t\t\t\t?: Node[];\n\tmeshes\t\t\t\t?: Mesh[];\n\taccessors\t\t\t?: Accessor[];\n\tbufferViews\t\t\t?: BufferView[];\n\tbuffers\t\t\t\t?: ArrayBuffer[];\n\tanimations\t\t\t?: Animation[];\n\tcameras\t\t\t\t?: Camera[];\n\ttextures\t\t\t?: Texture[];\n\timages\t\t\t\t?: (ImageBitmap | ImageData | HTMLImageElement)[];\n\tsamplers\t\t\t?: Sampler[];\n\tmaterials\t\t\t?: Material[];\n\tskins\t\t\t\t?: (Skin | SkinLink)[];\n\textensions\t\t\t?: any;\n\textensionsUsed\t\t?: string[];\n\textensionsRequired\t?: string[];\n\textras\t\t\t\t?: any;\n\tconstructor(glTFBase: GLTFBase) {\n\t\tthis.asset\t\t\t\t=  glTFBase.asset;\n\t\tthis.scene\t\t\t\t=  null;\n\t\tthis.scenes\t\t\t\t= (glTFBase.scenes\t\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.nodes\t\t\t\t= (glTFBase.nodes\t\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.meshes\t\t\t\t= (glTFBase.meshes\t\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.accessors\t\t\t= (glTFBase.accessors\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.bufferViews\t\t= (glTFBase.bufferViews\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.buffers\t\t\t= (glTFBase.buffers\t\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.animations\t\t\t= (glTFBase.animations\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.cameras\t\t\t= (glTFBase.cameras\t\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.textures\t\t\t= (glTFBase.textures\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.images\t\t\t\t= (glTFBase.images\t\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.samplers\t\t\t= (glTFBase.samplers\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.materials\t\t\t= (glTFBase.materials\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.skins\t\t\t\t= (glTFBase.skins\t\t\t\t!== undefined) ? []\t\t\t\t\t\t\t\t: null;\n\t\tthis.extensions\t\t\t= (glTFBase.extensions\t\t\t!== undefined) ? glTFBase.extensions\t\t\t: null;\n\t\tthis.extensionsUsed\t\t= (glTFBase.extensionsUsed\t\t!== undefined) ? glTFBase.extensionsUsed\t\t: null;\n\t\tthis.extensionsRequired\t= (glTFBase.extensionsRequired\t!== undefined) ? glTFBase.extensionsRequired\t: null;\n\t\tthis.extras\t\t\t\t= (glTFBase.extras\t\t\t\t!== undefined) ? glTFBase.extras\t\t\t\t: null;\n\t}\n}\n\nexport class GLTFLoader {\n\t_glTF\t\t\t\t\t:  GLTFBase;\n\tglTF\t\t\t\t\t:  GLTF;\n\tbaseUri\t\t\t\t\t:  string;\n\tenableGLAvatar\t\t\t:  boolean;\n\tskeletonGLTF\t\t\t:  GLTF;\n\tgl\t\t\t\t\t\t:  WebGL2RenderingContext;\n\n\tconstructor(gl: WebGL2RenderingContext) {\n\t\tthis.glTF\t\t\t\t= null;\n\t\tthis.enableGLAvatar\t\t= false;\n\t\tthis.skeletonGLTF\t\t= null;\n\t\tthis.gl\t\t\t\t\t= gl;\n\t}\n\t/**\n\t * Get base URL from the given URL\n\t * @param\t{url} string The original URL\n\t * @returns\t{string} The base URL\n\t */\n\tpublic getBaseUri(uri: string): string {\n\t\t// https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Core/getBaseUri.js\n\t\tlet basePath: string = \"\";\n\t\tif (uri.lastIndexOf('/') !== -1) {\n\t\t\tbasePath = uri.substring(0, uri.lastIndexOf('/') + 1);\n\t\t}\n\t\treturn basePath;\n\t}\n\t/**\n\t * infer attribute target for BufferView whether ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER\n\t * @param\t{glTF} GLTF The glTF need to be inferred\n\t * @returns\t{void}\n\t */\n\tprivate inferBufferViewTarget(): void {\n\t\tthis._glTF.meshes.forEach((mesh: MeshBase) => {\n\t\t\tmesh.primitives.forEach((primitive: MeshPrimitiveBase) => {\n\t\t\t\t// set bufferView.target for POSITION, NORMAL, and TEXCOORD_0\n\t\t\t\tfor (const [attributeName, accessorIndex] of Object.entries(primitive.attributes)) {\n\t\t\t\t\tif (attributeName === \"POSITION\" || attributeName === \"NORMAL\" || attributeName === \"TEXCOORD_0\") {\n\t\t\t\t\t\tthis._glTF.bufferViews[this._glTF.accessors[accessorIndex].bufferView].target = BufferViewTarget.ARRAY_BUFFER\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (primitive.indices !== undefined) {\n\t\t\t\t\tconst bufferView = this._glTF.bufferViews[this._glTF.accessors[primitive.indices].bufferView];\n\t\t\t\t\tif (bufferView.target !== undefined) {\n\t\t\t\t\t\tif (bufferView.target !== BufferViewTarget.ELEMENT_ARRAY_BUFFER)\n\t\t\t\t\t\t\tconsole.warn(\"BufferView \" + primitive.indices + \" should have a target equal to ELEMENT_ARRAY_BUFFER\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbufferView.target =  BufferViewTarget.ELEMENT_ARRAY_BUFFER;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n\tprivate postProcess():void {\n\t\tthis.inferBufferViewTarget();\n\t\t// 挂载 BufferView\n\t\tif (this._glTF.bufferViews !== undefined) {\n\t\t\tfor (let i = 0; i < this._glTF.bufferViews.length; i++) {\n\t\t\t\tconst bufferView = new BufferView(this._glTF.bufferViews[i], this.glTF.buffers[this._glTF.bufferViews[i].buffer]);\n\t\t\t\tbufferView.createBuffer(this.gl);\n\t\t\t\tbufferView.bindData(this.gl);\n\t\t\t\tthis.glTF.bufferViews.push(bufferView);\n\t\t\t}\n\t\t}\n\t\t// 挂载 Accessor\n\t\tif (this._glTF.accessors !== undefined) {\n\t\t\tfor (let i = 0; i < this._glTF.accessors.length; i++) {\n\t\t\t\tthis.glTF.accessors.push(new Accessor(this._glTF.accessors[i], this.glTF.bufferViews[this._glTF.accessors[i].bufferView]));\n\t\t\t}\n\t\t}\n\t\t// 挂载 Camera\n\t\tif (this._glTF.cameras !== undefined) {\n\t\t\tfor (let i = 0; i < this._glTF.cameras.length; i++) {\n\t\t\t\tthis.glTF.cameras.push(new Camera(this._glTF.cameras[i]))\n\t\t\t}\n\t\t}\n\t\t// 挂载 Material\n\t\tif (this._glTF.materials !== undefined) {\n\t\t\tfor (let i = 0; i < this._glTF.materials.length; i++) {\n\t\t\t\tthis.glTF.materials.push(new Material(this._glTF.materials[i]));\n\t\t\t}\n\t\t}\n\t\t// 挂载 Sampler\n\t\tif (this._glTF.samplers !== undefined) {\n\t\t\tfor (let i = 0; i < this._glTF.samplers.length; i++) {\n\t\t\t\tthis.glTF.samplers.push(new Sampler(this._glTF.samplers[i]));\n\t\t\t}\n\t\t}\n\t\t// 挂载 Texture\n\t\tif (this._glTF.textures !== undefined) {\n\t\t\tfor (let i = 0; i < this._glTF.textures.length; i++) {\n\t\t\t\tthis.glTF.textures.push(new Texture(this._glTF.textures[i], this));\n\t\t\t\tthis.glTF.textures[i].createTexture(this.gl);\n\t\t\t}\n\t\t}\n\t\t// 挂载 Mesh\n\t\tif (this._glTF.meshes !== undefined) {\n\t\t\tfor (let i = 0; i < this._glTF.meshes.length; i++) {\n\t\t\t\tthis.glTF.meshes.push(new Mesh(this._glTF.meshes[i], i, this));\n\t\t\t}\n\t\t}\n \t\t// 挂载 Node\n\t\tif (this._glTF.nodes !== undefined) {\n\t\t\tfor (let i = 0; i < this._glTF.nodes.length; i++) {\n\t\t\t\tthis.glTF.nodes.push(new Node(this._glTF.nodes[i], i, this));\n\t\t\t}\n\t\t\t// 为每个 Node 挂载 Node.children\n\t\t\tthis.glTF.nodes.forEach(currentNode => {\n\t\t\t\tfor (let i = 0; i < currentNode.childrenID.length; i++) {\n\t\t\t\t\tcurrentNode.children[i] = this.glTF.nodes[currentNode.childrenID[i]];\n\t\t\t\t\tcurrentNode.children[i].parent = currentNode;\n\t\t\t\t}\n\t\t\t});\n\t\t\t// 挂载 Scene\n\t\t\tif (this._glTF.scenes !== undefined) {\n\t\t\t\tfor (let i = 0; i < this._glTF.scenes.length; i++) {\n\t\t\t\t\tthis.glTF.scenes[i] = new Scene(this._glTF.scenes[i], this.glTF);\n\t\t\t\t\tthis.glTF.scenes[i].boundingBox = new BoundingBox();\n\t\t\t\t\tconst nodeMatrices : mat4[] = new Array(this.glTF.nodes.length);\n\t\t\t\t\tfor (let j = 0; j < this.glTF.scenes[i].nodes.length; j++) {\n\t\t\t\t\t\tthis.glTF.scenes[i].nodes[j].traverseTwoFunction(\n\t\t\t\t\t\t\t(node: Node, parent: Node) => {\n\t\t\t\t\t\t\t\tif (parent !== null) {\n\t\t\t\t\t\t\t\t\tmat4.multiply(nodeMatrices[node.nodeID], nodeMatrices[parent.nodeID], node.modelMatrix)\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnodeMatrices[node.nodeID] = mat4.clone(node.modelMatrix);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t(node: Node, parent: Node) => {\n\t\t\t\t\t\t\t\tif (node.mesh) {\n\t\t\t\t\t\t\t\t\tnode.worldMatrix = mat4.clone(nodeMatrices[node.nodeID]);\n\t\t\t\t\t\t\t\t\tif (node.mesh.boundingBox) {\n\t\t\t\t\t\t\t\t\t\tnode.aabb = getAABBFromOBB(node.mesh.boundingBox, nodeMatrices[node.nodeID]);\n\t\t\t\t\t\t\t\t\t\tif (node.children.length === 0) {\n\t\t\t\t\t\t\t\t\t\t\tnode.bvh.min = vec3.clone(node.aabb.min);\n\t\t\t\t\t\t\t\t\t\t\tnode.bvh.max = vec3.clone(node.aabb.max);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (parent !== null) {\n\t\t\t\t\t\t\t\t\tparent.bvh.min = vec3.min(parent.bvh.min, parent.bvh.min, node.bvh.min);\n\t\t\t\t\t\t\t\t\tparent.bvh.max = vec3.max(parent.bvh.max, parent.bvh.max, node.bvh.max);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tvec3.min(this.glTF.scenes[i].boundingBox.min, this.glTF.scenes[i].boundingBox.min, node.bvh.min);\n\t\t\t\t\t\t\t\t\tvec3.max(this.glTF.scenes[i].boundingBox.max, this.glTF.scenes[i].boundingBox.max, node.bvh.max);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tthis.glTF.scenes[i].boundingBox.calculateTransform();\n\t\t\t\t}\n\t\t\t\tif (this._glTF.scene !== undefined) {\n\t\t\t\t\tthis.glTF.scene = this.glTF.scenes[this._glTF.scene];\n\t\t\t\t} else {\n\t\t\t\t\tthis.glTF.scene = this.glTF.scenes[0];\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.glTF.nodes.length; i++) {\n\t\t\t\tif (this.glTF.nodes[i].bvh !== null) {\n\t\t\t\t\tthis.glTF.nodes[i].bvh.calculateTransform();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// 挂载 Animation\n\t\tif (this._glTF.animations) {\n\t\t\tfor (let i = 0; i < this._glTF.animations.length; i++) {\n\t\t\t\tthis.glTF.animations.push(new Animation(this._glTF.animations[i], this.glTF));\n\t\t\t\tthis.glTF.animations[i].channels.forEach((channel) => {\n\t\t\t\t\tchannel.target.node = this.glTF.nodes[channel.target.nodeID];\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\t// 挂载 Skin\n\t\tif (this._glTF.skins) {\n\t\t\tfor (let i = 0; i < this._glTF.skins.length; i++) {\n\t\t\t\tthis.glTF.skins.push(new Skin(this._glTF.skins[i], this.glTF));\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.glTF.nodes.length; i++) {\n\t\t\t\tif (this.glTF.nodes[i].skin !== null) {\n\t\t\t\t\tif (typeof this._glTF.nodes[this.glTF.nodes[i].nodeID].skin) {\n\t\t\t\t\t\t// usual skin, hook up\n\t\t\t\t\t\tthis.glTF.nodes[i].skin = this.glTF.skins[this._glTF.nodes[this.glTF.nodes[i].nodeID].skin];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// assume gl_avatar is in use then do nothing\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n \n\t}\n\tpublic async loadGLTF(uri: string): Promise<GLTF> {\n\t\tthis.baseUri = this.getBaseUri(uri);\n\t\ttry {\n\t\t\tconst glTFBase : GLTFBase = await fetch(new Request(uri)).then((response: Response) => {\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconsole.log(response)\n\t\t\t\t\treturn response.json();\n\t\t\t\t}\n\t\t\t\tthrow Error(\"LoadingError: Error occured in loading glTF JSON.\");\n\t\t\t});\n\t\t\tthis._glTF = glTFBase;\n\t\t\tthis.glTF = new GLTF(glTFBase);\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t}\n\t\tconst loadBuffer : Promise<boolean> = new Promise<boolean>(async (resolve) => {\n\t\t\tif (this._glTF.buffers) {\n\t\t\t\tconst bufferPromises : Promise<ArrayBuffer>[] = [];\n\t\t\t\tfor (const bufferInfo of this._glTF.buffers) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tbufferPromises.push(fetch (new Request(this.baseUri + bufferInfo.uri)\n\t\t\t\t\t\t).then((response: Response) => {\n\t\t\t\t\t\t\tif (response.ok) {\n\t\t\t\t\t\t\t\treturn response.arrayBuffer();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthrow Error(\"LoadingError: Error occured in loading buffers.\");\n\t\t\t\t\t\t}));\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconsole.error(error);\n\t\t\t\t\t}\t\n\t\t\t\t}\n\t\t\t\tfor (const [bufferID, buffer] of bufferPromises.entries()) {\n\t\t\t\t\tthis.glTF.buffers[bufferID] = await buffer;\n\t\t\t\t\tconsole.log(`image ${bufferID} complete`); \n\t\t\t\t}\n\t\t\t}\n\t\t\tresolve(true);\n\t\t});\n\t\tconst loadImage : Promise<boolean> = new Promise<boolean>(async (resolve) => {\n\t\t\tif (this._glTF.images) {\n\t\t\t\tconst imagePromises : Promise<ImageBitmap>[] = [];\n\t\t\t\tfor (const imageInfo of this._glTF.images) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\timagePromises.push(fetch (new Request(this.baseUri + imageInfo.uri)\n\t\t\t\t\t\t).then((response: Response) => {\n\t\t\t\t\t\t\tif (response.ok) {\n\t\t\t\t\t\t\t\treturn response.blob();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthrow Error(\"LoadingError: Error occured in loading images.\");\n\t\t\t\t\t\t}).then((imageBlob: Blob) => {\n\t\t\t\t\t\t\treturn createImageBitmap(imageBlob);\n\t\t\t\t\t\t}));\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconsole.error(error);\n\t\t\t\t\t}\t\n\t\t\t\t}\n\t\t\t\tfor (const [imageID, image] of imagePromises.entries()) {\n\t\t\t\t\tthis.glTF.images[imageID] = await image;\n\t\t\t\t\tconsole.log(`image ${imageID} complete`); \n\t\t\t\t}\n\t\t\t}\n\t\t\tresolve(true);\n\t\t});\n\t\tawait loadBuffer;\n\t\tawait loadImage;\n\t\tthis.postProcess();\n\t\treturn this.glTF;\n\t}\n}\n\nexport module glTFLoaderBasic {\n\t/**\n\t * Common utilities\n\t * @module loaderBasic\n\t */\n\t/**\n\t * Get the count of components from the given accessor\n\t * @param\t{type} string The type of the given accessor\n\t * @returns\t{number} The count of components\n\t */\n\texport function accessorTypeToNumComponents(type : string): number {\n\t\tconst accessorMap = new Map<string, number>([\n\t\t\t[\"SCALAR\",\t1],\n\t\t\t[\"VEC2\",\t2],\n\t\t\t[\"VEC3\",\t3],\n\t\t\t[\"VEC4\",\t4],\n\t\t\t[\"MAT2\",\t4],\n\t\t\t[\"MAT3\",\t9],\n\t\t\t[\"MAT4\",\t16]\n\t\t]);\n\t\tif (accessorMap.has(type)) {\n\t\t\treturn accessorMap.get(type);\n\t\t}\n\t\tthrow new Error(`NOKEY ERROR: no numComponents for accessorType ${type}`);\n\t}\n\t/**\n\t * Get the typed array of the given accessor's component\n\t * @param\t{type} string The component type of the given accessor\n\t * @returns\t{typedArrayConstructor} The constructor of the component's typed array\n\t */\n\texport function glTypeToTypedArray(type: AccessorComponentType) {\n\t\tconst typeMap = new Map<number, Int8ArrayConstructor | Uint8ArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Float32ArrayConstructor>([\n\t\t\t[5120, Int8Array],\t\t// gl.BYTE\n\t\t\t[5121, Uint8Array],\t\t// gl.UNSIGNED_BYTE\n\t\t\t[5122, Int16Array],\t\t// gl.SHORT\n\t\t\t[5123, Uint16Array],\t// gl.UNSIGNED_SHORT\n\t\t\t[5124, Int32Array],\t\t// gl.INT\n\t\t\t[5125, Uint32Array],\t// gl.UNSIGNED_INT\n\t\t\t[5126, Float32Array]\t// gl.FLOAT\n\t\t]);\n\t\tif (typeMap.has(type)) {\n\t\t\treturn typeMap.get(type);\n\t\t}\n\t\tthrow new Error(`NOKEY ERROR: no typedArray for glType ${type}`);\n\t}\n\t/**\n\t * Get the typed array of the given accessor's component\n\t * @param\t{type} string The component type of the given accessor\n\t * @returns\t{typedArrayConstructor} The constructor of the component's typed array\n\t */\n\texport function getAccessorData(accessor: Accessor): Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array {\n\t\tconst typedArray = glTFLoaderBasic.glTypeToTypedArray(accessor.componentType);\n\t\treturn new typedArray(\n\t\t\taccessor.bufferView.data, \n\t\t\taccessor.byteOffset, \n\t\t\taccessor.count * glTFLoaderBasic.accessorTypeToNumComponents(accessor.type)\n\t\t);\n\t}\n}\n\n// get Axis-Aligned Bounding Boxes from Oriented Bounding Boxes\nfunction getAABBFromOBB(obb: BoundingBox, matrix: mat4): BoundingBox{\n\tlet transformRight\t\t: vec3 = vec3.fromValues(matrix[0], matrix[1], matrix[2]);\n\tlet transformUp\t\t\t: vec3 = vec3.fromValues(matrix[4], matrix[5], matrix[6]);\n\tlet transformBackward\t: vec3 = vec3.fromValues(matrix[8], matrix[9], matrix[10]);\n\n\tlet tmpVec3a \t\t\t: vec3 = vec3.create();\n\tlet tmpVec3b \t\t\t: vec3 = vec3.create();\n\n\tlet min = vec3.fromValues(matrix[12], matrix[13], matrix[14]);  // init with matrix translation\n\tlet max = vec3.clone(min);\n\n\tvec3.scale(tmpVec3a, transformRight, obb.min[0]);\n\tvec3.scale(tmpVec3b, transformRight, obb.max[0]);\n\tvec3.min(transformRight, tmpVec3a, tmpVec3b);\n\tvec3.add(min, min, transformRight);\n\tvec3.max(transformRight, tmpVec3a, tmpVec3b);\n\tvec3.add(max, max, transformRight);\n\n\ttmpVec3a\t\t\t= vec3.scale(tmpVec3a, transformUp, obb.min[1]);\n\ttmpVec3b \t\t\t= vec3.scale(tmpVec3b, transformUp, obb.max[1]);\n\tvec3.min(transformUp, tmpVec3a, tmpVec3b);\n\tvec3.add(min, min, transformUp);\n\tvec3.max(transformUp, tmpVec3a, tmpVec3b);\n\tvec3.add(max, max, transformUp);\n\n\ttmpVec3a\t\t\t= vec3.scale(tmpVec3a, transformBackward, obb.min[2]);\n\ttmpVec3b \t\t\t= vec3.scale(tmpVec3b, transformBackward, obb.max[2]);\n\tvec3.min(transformBackward, tmpVec3a, tmpVec3b);\n\tvec3.add(min, min, transformBackward);\n\tvec3.max(transformBackward, tmpVec3a, tmpVec3b);\n\tvec3.add(max, max, transformBackward);\n\n\tlet axisAlignedBoundingBox = new BoundingBox(min, max, false);\n\taxisAlignedBoundingBox.calculateTransform();\n\treturn axisAlignedBoundingBox;\n}"
  },
  {
    "path": "src/index.js",
    "content": "import {vec3, vec4, quat, mat4} from 'gl-matrix';\r\nvar MinimalGLTFLoader = require('../build/minimal-gltf-loader.js');\r\n// require('./lib/minimal-gltf-loader.js');\r\nimport '../css/style.css';\r\n\r\n\r\n\r\n// utils\r\nvar Utils = Utils || {};\r\n(function () {\r\n    'use strict';\r\n\r\n    Utils.getShaderSource = function(id) {\r\n        return document.getElementById(id).textContent.replace(/^\\s+|\\s+$/g, '');\r\n    };\r\n\r\n    function createShader(gl, source, type) {\r\n        var shader = gl.createShader(type);\r\n        gl.shaderSource(shader, source);\r\n        gl.compileShader(shader);\r\n        return shader;\r\n    }\r\n\r\n    Utils.createProgram = function(gl, vertexShaderSource, fragmentShaderSource) {\r\n        var program = gl.createProgram();\r\n        var vshader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER);\r\n        var fshader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);\r\n        gl.attachShader(program, vshader);\r\n        gl.deleteShader(vshader);\r\n        gl.attachShader(program, fshader);\r\n        gl.deleteShader(fshader);\r\n        gl.linkProgram(program);\r\n\r\n        var log = gl.getProgramInfoLog(program);\r\n        if (log) {\r\n            console.log(log);\r\n        }\r\n\r\n        log = gl.getShaderInfoLog(vshader);\r\n        if (log) {\r\n            console.log(log);\r\n        }\r\n\r\n        log = gl.getShaderInfoLog(fshader);\r\n        if (log) {\r\n            console.log(log);\r\n        }\r\n\r\n        return program;\r\n    };\r\n\r\n    var loadImage = Utils.loadImage = function(url, onload) {\r\n        var img = new Image();\r\n        img.crossOrigin = \"Anonymous\";\r\n        img.src = url;\r\n        // img.onload = function() {\r\n        //     onload(img);\r\n        // };\r\n        img.onload = onload;\r\n        return img;\r\n    };\r\n\r\n    Utils.loadImages = function(urls, onload) {\r\n        var imgs = [];\r\n        var imgsToLoad = urls.length;\r\n\r\n        function onImgLoad() {\r\n            if (--imgsToLoad <= 0) {\r\n                onload(imgs);\r\n            }\r\n        }\r\n\r\n        for (var i = 0; i < imgsToLoad; ++i) {\r\n            imgs.push(loadImage(urls[i], onImgLoad));\r\n        }\r\n    };\r\n\r\n})();\r\n\r\n\r\n\r\n\r\n\r\n(function()  {\r\n    'use strict';\r\n\r\n    // var selectedGltfSampleModel = 'Drone';\r\n    var selectedGltfSampleModel = 'DamagedHelmet';\r\n\r\n    var drawBoundingBox = false;\r\n    var boundingBoxType = 'obb';\r\n\r\n    var curAnimationId = 0;\r\n    var playAllAnimationTogether = false;\r\n    var animationSelectionList = document.getElementById(\"animations\");\r\n\r\n    animationSelectionList.addEventListener(\"change\", function() {\r\n        curAnimationId = this.selectedIndex;\r\n    });\r\n\r\n    document.getElementById(\"gltf-model\").addEventListener(\"change\", function() {\r\n        // selectedGltfSampleModel = this.value;\r\n        var uri = this.value;\r\n        // if (selectedGltfSampleModel == 'Drone') {\r\n        //     uri = 'https://raw.githubusercontent.com/shrekshao/minimal-gltf-loader/store-drone-model/glTFs/glTF_version_2/buster_drone/scene.gltf';\r\n        // } else {\r\n        //     uri = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/'\r\n        //     + selectedGltfSampleModel\r\n        //     + '/glTF/'\r\n        //     + selectedGltfSampleModel\r\n        //     + '.gltf';\r\n        // }\r\n\r\n        glTFLoader.loadGLTF(uri, function(glTF) {\r\n            // var scene = scenes[0];\r\n            scenes = [];\r\n            // TODO: delete gl resources\r\n            // scene = null;\r\n\r\n            setupScene(glTF);\r\n        });\r\n\r\n    });\r\n\r\n    document.getElementById(\"bbox-toggle\").addEventListener(\"change\", function() {\r\n        drawBoundingBox = this.checked;\r\n    });\r\n\r\n    document.getElementById(\"play-all-animations\").addEventListener(\"change\", function() {\r\n        playAllAnimationTogether = this.checked;\r\n    });\r\n\r\n    document.getElementById(\"bbox-type\").addEventListener(\"change\", function() {\r\n        boundingBoxType = this.value;\r\n    });\r\n\r\n    var canvas = document.createElement('canvas');\r\n    // canvas.width = Math.min(window.innerWidth, window.innerHeight);\r\n    // canvas.height = canvas.width;\r\n    canvas.width = window.innerWidth;\r\n    canvas.height = window.innerHeight;\r\n    document.body.appendChild(canvas);\r\n\r\n    var gl = canvas.getContext( 'webgl2', { antialias: true } );\r\n    var isWebGL2 = !!gl;\r\n    if(!isWebGL2) {\r\n        document.getElementById('info').innerHTML = 'WebGL 2 is not available.  See <a href=\"https://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation\">How to get a WebGL 2 implementation</a>';\r\n        return;\r\n    }\r\n\r\n    canvas.oncontextmenu = function (e) {\r\n        e.preventDefault();\r\n    };\r\n\r\n    // Scene object for runtime renderer\r\n    var Scene = function(glTFScene, glTF, id) {\r\n        this.glTFScene = glTFScene;\r\n        this.glTF = glTF;\r\n        this.id = id;\r\n\r\n        // runtime renderer context\r\n        this.rootTransform = mat4.create();\r\n        // @temp, assume every node is in current scene\r\n        this.nodeMatrix = new Array(glTF.nodes.length);\r\n        var i, len;\r\n        for(i = 0, len = this.nodeMatrix.length; i < len; i++) {\r\n            this.nodeMatrix[i] = mat4.create();\r\n        }\r\n\r\n        // TODO: runtime joint matrix\r\n    };\r\n\r\n    var BOUNDING_BOX = {\r\n        vertexData: new Float32Array([\r\n            0.0, 0.0, 0.0,\r\n            1.0, 0.0, 0.0,\r\n            0.0, 0.0, 0.0,\r\n            0.0, 1.0, 0.0,\r\n            0.0, 0.0, 0.0,\r\n            0.0, 0.0, 1.0,\r\n\r\n            0.0, 1.0, 1.0,\r\n            1.0, 1.0, 1.0,\r\n            0.0, 1.0, 1.0,\r\n            0.0, 1.0, 0.0,\r\n            0.0, 1.0, 1.0,\r\n            0.0, 0.0, 1.0,\r\n\r\n            1.0, 1.0, 0.0,\r\n            1.0, 1.0, 1.0,\r\n            1.0, 1.0, 0.0,\r\n            0.0, 1.0, 0.0,\r\n            1.0, 1.0, 0.0,\r\n            1.0, 0.0, 0.0,\r\n\r\n            1.0, 0.0, 1.0,\r\n            1.0, 0.0, 0.0,\r\n            1.0, 0.0, 1.0,\r\n            1.0, 1.0, 1.0,\r\n            1.0, 0.0, 1.0,\r\n            0.0, 0.0, 1.0\r\n        ]),\r\n\r\n        vertexArray: gl.createVertexArray(),\r\n        vertexBuffer: gl.createBuffer(),\r\n\r\n        program: Utils.createProgram(gl, require('./shaders/vs-bbox.glsl'), require('./shaders/fs-bbox.glsl')),\r\n        positionLocation: 0,\r\n        uniformMvpLocation: 0, \r\n\r\n        \r\n        draw: (function() {\r\n            var MVP = mat4.create();\r\n            return (function(bbox, nodeTransform, V, P) {\r\n                // gl.useProgram(this.program);\r\n\r\n                mat4.mul(MVP, nodeTransform, bbox.transform);\r\n                mat4.mul(MVP, V, MVP);\r\n                mat4.mul(MVP, P, MVP);\r\n\r\n                gl.uniformMatrix4fv(this.uniformMvpLocation, false, MVP);\r\n                // gl.bindVertexArray(this.vertexArray);\r\n                gl.drawArrays(gl.LINES, 0, 24);\r\n                // gl.bindVertexArray(null);\r\n            });\r\n        })()\r\n    };\r\n\r\n    \r\n\r\n    var defaultSampler = gl.createSampler();\r\n    gl.samplerParameteri(defaultSampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);\r\n    gl.samplerParameteri(defaultSampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\r\n    gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_S, gl.REPEAT);\r\n    gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_T, gl.REPEAT);\r\n    // gl.samplerParameteri(defaultSampler, gl.TEXTURE_WRAP_R, gl.REPEAT);\r\n    // gl.samplerParameterf(defaultSampler, gl.TEXTURE_MIN_LOD, -1000.0);\r\n    // gl.samplerParameterf(defaultSampler, gl.TEXTURE_MAX_LOD, 1000.0);\r\n    // gl.samplerParameteri(defaultSampler, gl.TEXTURE_COMPARE_MODE, gl.NONE);\r\n    // gl.samplerParameteri(defaultSampler, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n    BOUNDING_BOX.uniformMvpLocation = gl.getUniformLocation(BOUNDING_BOX.program, \"u_MVP\");\r\n\r\n    gl.bindVertexArray(BOUNDING_BOX.vertexArray);\r\n\r\n    gl.bindBuffer(gl.ARRAY_BUFFER, BOUNDING_BOX.vertexBuffer);\r\n    gl.bufferData(gl.ARRAY_BUFFER, BOUNDING_BOX.vertexData, gl.STATIC_DRAW);\r\n    gl.vertexAttribPointer(BOUNDING_BOX.positionLocation, 3, gl.FLOAT, false, 0, 0);\r\n    gl.enableVertexAttribArray(BOUNDING_BOX.positionLocation);\r\n\r\n    gl.bindVertexArray(null);\r\n\r\n\r\n    var BRDF_LUT = {\r\n        texture: null,\r\n        textureIndex: 29,\r\n\r\n        createTexture: function (img) {\r\n            this.texture = gl.createTexture();\r\n            gl.bindTexture(gl.TEXTURE_2D, this.texture);\r\n            gl.texImage2D(\r\n                gl.TEXTURE_2D,  // assumed\r\n                0,        // Level of details\r\n                gl.RG16F, // Format\r\n                gl.RG,\r\n                // gl.RGBA, // Format\r\n                // gl.RGBA,\r\n                // gl.UNSIGNED_BYTE, // Size of each channel\r\n                gl.FLOAT,\r\n                img\r\n            );\r\n            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\r\n            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\r\n            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\r\n            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\r\n            gl.bindTexture(gl.TEXTURE_2D, null);\r\n        }\r\n    }\r\n\r\n\r\n    // Environment maps\r\n    var CUBE_MAP = {\r\n        textureIndex: 31,\r\n        texture: null,\r\n\r\n        // IBL\r\n        textureIBLDiffuseIndex: 30,\r\n        textureIBLDiffuse: null,\r\n\r\n        // loading asset --------------------\r\n        // TODO: use webpack to pack these\r\n        uris: [\r\n            '../textures/environment/px.jpg',\r\n            '../textures/environment/nx.jpg',\r\n            '../textures/environment/py.jpg',\r\n            '../textures/environment/ny.jpg',\r\n            '../textures/environment/pz.jpg',\r\n            '../textures/environment/nz.jpg',\r\n\r\n            // ibl diffuse\r\n            '../textures/environment/diffuse/bakedDiffuse_01.jpg',\r\n            '../textures/environment/diffuse/bakedDiffuse_02.jpg',\r\n            '../textures/environment/diffuse/bakedDiffuse_03.jpg',\r\n            '../textures/environment/diffuse/bakedDiffuse_04.jpg',\r\n            '../textures/environment/diffuse/bakedDiffuse_05.jpg',\r\n            '../textures/environment/diffuse/bakedDiffuse_06.jpg',\r\n\r\n            // '../textures/papermill/environment_right_0.jpg',\r\n            // '../textures/papermill/environment_left_0.jpg',\r\n            // '../textures/papermill/environment_top_0.jpg',\r\n            // '../textures/papermill/environment_bottom_0.jpg',\r\n            // '../textures/papermill/environment_front_0.jpg',\r\n            // '../textures/papermill/environment_back_0.jpg',\r\n\r\n            // '../textures/papermill/diffuse/diffuse_right_0.jpg',\r\n            // '../textures/papermill/diffuse/diffuse_left_0.jpg',\r\n            // '../textures/papermill/diffuse/diffuse_top_0.jpg',\r\n            // '../textures/papermill/diffuse/diffuse_bottom_0.jpg',\r\n            // '../textures/papermill/diffuse/diffuse_front_0.jpg',\r\n            // '../textures/papermill/diffuse/diffuse_back_0.jpg',\r\n\r\n            // @tmp, ugly, load brdfLUT here\r\n            '../textures/brdfLUT.png'\r\n        ],\r\n\r\n        images: null,\r\n\r\n        loadAll: function() {\r\n            Utils.loadImages(this.uris, this.onloadAll.bind(this));\r\n        },\r\n\r\n        onloadAll: function(imgs) {\r\n            this.images = imgs;\r\n            console.log('all cube maps loaded');\r\n\r\n            this.texture = gl.createTexture();\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.texture);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.NONE);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);\r\n\r\n            for (var i = 0; i < 6; i++) {\r\n                gl.texImage2D(\r\n                    gl.TEXTURE_CUBE_MAP_POSITIVE_X + i,\r\n                    0,\r\n                    gl.RGBA,\r\n                    gl.RGBA,\r\n                    gl.UNSIGNED_BYTE,\r\n                    this.images[i]\r\n                );\r\n            }\r\n            gl.generateMipmap(gl.TEXTURE_CUBE_MAP);\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);\r\n\r\n\r\n\r\n            this.textureIBLDiffuse = gl.createTexture();\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.textureIBLDiffuse);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.NONE);\r\n            gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);\r\n\r\n            for (var i = 0; i < 6; i++) {\r\n                gl.texImage2D(\r\n                    gl.TEXTURE_CUBE_MAP_POSITIVE_X + i,\r\n                    0,\r\n                    gl.RGBA,\r\n                    gl.RGBA,\r\n                    gl.UNSIGNED_BYTE,\r\n                    this.images[i + 6]\r\n                );\r\n            }\r\n\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);\r\n\r\n\r\n\r\n            // @tmp\r\n            BRDF_LUT.createTexture(this.images[this.images.length - 1]);\r\n\r\n            if (this.finishLoadingCallback) {\r\n                this.finishLoadingCallback();\r\n            }\r\n        },\r\n\r\n        finishLoadingCallback: null,\r\n\r\n\r\n        // runtime stuffs -------------------------\r\n        vertexData: new Float32Array([         \r\n            -1.0,  1.0, -1.0,\r\n            -1.0, -1.0, -1.0,\r\n            1.0, -1.0, -1.0,\r\n            1.0, -1.0, -1.0,\r\n            1.0,  1.0, -1.0,\r\n            -1.0,  1.0, -1.0,\r\n\r\n            -1.0, -1.0,  1.0,\r\n            -1.0, -1.0, -1.0,\r\n            -1.0,  1.0, -1.0,\r\n            -1.0,  1.0, -1.0,\r\n            -1.0,  1.0,  1.0,\r\n            -1.0, -1.0,  1.0,\r\n\r\n            1.0, -1.0, -1.0,\r\n            1.0, -1.0,  1.0,\r\n            1.0,  1.0,  1.0,\r\n            1.0,  1.0,  1.0,\r\n            1.0,  1.0, -1.0,\r\n            1.0, -1.0, -1.0,\r\n\r\n            -1.0, -1.0,  1.0,\r\n            -1.0,  1.0,  1.0,\r\n            1.0,  1.0,  1.0,\r\n            1.0,  1.0,  1.0,\r\n            1.0, -1.0,  1.0,\r\n            -1.0, -1.0,  1.0,\r\n\r\n            -1.0,  1.0, -1.0,\r\n            1.0,  1.0, -1.0,\r\n            1.0,  1.0,  1.0,\r\n            1.0,  1.0,  1.0,\r\n            -1.0,  1.0,  1.0,\r\n            -1.0,  1.0, -1.0,\r\n\r\n            -1.0, -1.0, -1.0,\r\n            -1.0, -1.0,  1.0,\r\n            1.0, -1.0, -1.0,\r\n            1.0, -1.0, -1.0,\r\n            -1.0, -1.0,  1.0,\r\n            1.0, -1.0,  1.0\r\n        ]),\r\n\r\n        \r\n        vertexArray: gl.createVertexArray(),\r\n        vertexBuffer: gl.createBuffer(),\r\n\r\n        program: Utils.createProgram(gl, require('./shaders/vs-cube-map.glsl'), require('./shaders/fs-cube-map.glsl')),\r\n        positionLocation: 0,\r\n        uniformMvpLocation: 0, \r\n        uniformEnvironmentLocation: 0,\r\n\r\n        \r\n        draw: (function() {\r\n            var MVP = mat4.create();\r\n            return (function(V, P) {\r\n                mat4.copy(MVP, V);\r\n                MVP[12] = 0.0;\r\n                MVP[13] = 0.0;\r\n                MVP[14] = 0.0;\r\n                MVP[15] = 1.0;\r\n                mat4.mul(MVP, P, MVP);\r\n\r\n                gl.useProgram(this.program);\r\n                gl.activeTexture(gl.TEXTURE0 + this.textureIndex);\r\n                gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.texture);\r\n                gl.uniformMatrix4fv(this.uniformMvpLocation, false, MVP);\r\n                gl.uniform1i(this.uniformEnvironmentLocation, this.textureIndex);\r\n                gl.bindVertexArray(this.vertexArray);\r\n                gl.drawArrays(gl.TRIANGLES, 0, 36);\r\n                gl.bindVertexArray(null);\r\n            });\r\n        })()\r\n    };\r\n\r\n    CUBE_MAP.uniformMvpLocation = gl.getUniformLocation(CUBE_MAP.program, \"u_MVP\");\r\n    CUBE_MAP.uniformEnvironmentLocation = gl.getUniformLocation(CUBE_MAP.program, \"u_environment\");\r\n\r\n    gl.bindVertexArray(CUBE_MAP.vertexArray);\r\n    \r\n    gl.bindBuffer(gl.ARRAY_BUFFER, CUBE_MAP.vertexBuffer);\r\n    gl.bufferData(gl.ARRAY_BUFFER, CUBE_MAP.vertexData, gl.STATIC_DRAW);\r\n    gl.vertexAttribPointer(CUBE_MAP.positionLocation, 3, gl.FLOAT, false, 0, 0);\r\n    gl.enableVertexAttribArray(CUBE_MAP.positionLocation);\r\n\r\n    gl.bindVertexArray(null);\r\n\r\n\r\n    \r\n    var Shader_Static = {\r\n        shaderVersionLine: '#version 300 es\\n',\r\n        \r\n        bitMasks: {\r\n            // vertex shader\r\n            HAS_SKIN: 1,\r\n            SKIN_VEC8: 2,\r\n\r\n            // fragment shader\r\n            HAS_BASECOLORMAP: 4,\r\n            HAS_NORMALMAP: 8,\r\n            HAS_METALROUGHNESSMAP: 16,\r\n            HAS_OCCLUSIONMAP: 32,\r\n            HAS_EMISSIVEMAP: 64\r\n        },\r\n\r\n        vsMasterCode: require('./shaders/vs-pbr-master.glsl'),\r\n        fsMasterCode: require('./shaders/fs-pbr-master.glsl'),\r\n\r\n        programObjects: {}    // < flags, Shader Object >\r\n    };\r\n\r\n    var Shader = function() {\r\n        this.flags = 0;\r\n        this.programObject = null;\r\n    };\r\n\r\n    Shader.prototype.hasSkin = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_SKIN;\r\n    };\r\n    Shader.prototype.hasBaseColorMap = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_BASECOLORMAP;\r\n    };\r\n    Shader.prototype.hasNormalMap = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_NORMALMAP;\r\n    };\r\n    Shader.prototype.hasMetalRoughnessMap = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_METALROUGHNESSMAP;\r\n    };\r\n    Shader.prototype.hasOcclusionMap = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_OCCLUSIONMAP;\r\n    };\r\n    Shader.prototype.hasEmissiveMap = function() {\r\n        return this.flags & Shader_Static.bitMasks.HAS_EMISSIVEMAP;\r\n    };\r\n\r\n\r\n    Shader.prototype.defineMacro = function(macro) {\r\n        if (Shader_Static.bitMasks[macro] !== undefined) {\r\n            this.flags = Shader_Static.bitMasks[macro] | this.flags;\r\n        } else {\r\n            console.log('WARNING: ' + macro + ' is not a valid macro');\r\n        }\r\n    };\r\n\r\n    Shader.prototype.compile = function() {\r\n        var existingProgramObject = Shader_Static.programObjects[this.flags];\r\n        if (existingProgramObject) {\r\n            this.programObject = existingProgramObject;\r\n            return;\r\n        }\r\n\r\n\r\n        // new program\r\n\r\n        var vsDefine = '';\r\n        var fsDefine = '';\r\n\r\n        // define macros\r\n\r\n        if (this.flags & Shader_Static.bitMasks.HAS_SKIN) {\r\n            vsDefine += '#define HAS_SKIN\\n';\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.SKIN_VEC8) {\r\n            vsDefine += '#define SKIN_VEC8\\n';\r\n        }\r\n\r\n        if (this.flags & Shader_Static.bitMasks.HAS_BASECOLORMAP) {\r\n            fsDefine += '#define HAS_BASECOLORMAP\\n';\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_NORMALMAP) {\r\n            fsDefine += '#define HAS_NORMALMAP\\n';\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_METALROUGHNESSMAP) {\r\n            fsDefine += '#define HAS_METALROUGHNESSMAP\\n';\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_OCCLUSIONMAP) {\r\n            fsDefine += '#define HAS_OCCLUSIONMAP\\n';\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_EMISSIVEMAP) {\r\n            fsDefine += '#define HAS_EMISSIVEMAP\\n';\r\n        }\r\n\r\n\r\n        // concat\r\n        var vertexShaderSource = \r\n            Shader_Static.shaderVersionLine +\r\n            vsDefine +\r\n            Shader_Static.vsMasterCode;\r\n        \r\n        var fragmentShaderSource = \r\n            Shader_Static.shaderVersionLine +\r\n            fsDefine +\r\n            Shader_Static.fsMasterCode;\r\n\r\n        // compile\r\n        var program = Utils.createProgram(gl, vertexShaderSource, fragmentShaderSource);\r\n        this.programObject = {\r\n            program: program,\r\n    \r\n            uniformLocations: {},\r\n\r\n            uniformBlockIndices: {}\r\n        };\r\n\r\n        // uniform block id\r\n        if (this.flags & Shader_Static.bitMasks.HAS_SKIN) {\r\n            this.programObject.uniformBlockIndices.JointMatrix = gl.getUniformBlockIndex(program, \"JointMatrix\");\r\n        }\r\n\r\n        // uniform locations\r\n        var us = this.programObject.uniformLocations;\r\n\r\n        us.MVP = gl.getUniformLocation(program, 'u_MVP');\r\n        us.MVNormal = gl.getUniformLocation(program, 'u_MVNormal');\r\n        us.MV = gl.getUniformLocation(program, 'u_MV');\r\n        us.baseColorFactor = gl.getUniformLocation(program, 'u_baseColorFactor');\r\n        us.metallicFactor = gl.getUniformLocation(program, 'u_metallicFactor');\r\n        us.roughnessFactor = gl.getUniformLocation(program, 'u_roughnessFactor');\r\n\r\n        if (this.flags & Shader_Static.bitMasks.HAS_BASECOLORMAP) {\r\n            us.baseColorTexture = gl.getUniformLocation(program, 'u_baseColorTexture');\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_NORMALMAP) {\r\n            us.normalTexture = gl.getUniformLocation(program, 'u_normalTexture');\r\n            us.normalTextureScale = gl.getUniformLocation(program, 'u_normalTextureScale');\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_METALROUGHNESSMAP) {\r\n            us.metallicRoughnessTexture = gl.getUniformLocation(program, 'u_metallicRoughnessTexture');\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_OCCLUSIONMAP) {\r\n            us.occlusionTexture = gl.getUniformLocation(program, 'u_occlusionTexture');\r\n            us.occlusionStrength = gl.getUniformLocation(program, 'u_occlusionStrength');\r\n        }\r\n        if (this.flags & Shader_Static.bitMasks.HAS_EMISSIVEMAP) {\r\n            us.emissiveTexture = gl.getUniformLocation(program, 'u_emissiveTexture');\r\n            us.emissiveFactor = gl.getUniformLocation(program, 'u_emissiveFactor');\r\n        }\r\n\r\n        us.diffuseEnvSampler = gl.getUniformLocation(program, 'u_DiffuseEnvSampler');\r\n        us.specularEnvSampler = gl.getUniformLocation(program, 'u_SpecularEnvSampler');\r\n        us.brdfLUT = gl.getUniformLocation(program, 'u_brdfLUT');\r\n\r\n        // set static uniform values in cubemap\r\n        gl.useProgram(program);\r\n        gl.uniform1i(us.brdfLUT, BRDF_LUT.textureIndex);\r\n        gl.uniform1i(us.specularEnvSampler, CUBE_MAP.textureIndex);\r\n        gl.uniform1i(us.diffuseEnvSampler, CUBE_MAP.textureIBLDiffuseIndex);\r\n        gl.useProgram(null);\r\n\r\n        Shader_Static.programObjects[this.flags] = this.programObject;\r\n    };\r\n\r\n    // -- Initialize vertex array\r\n    var POSITION_LOCATION = 0; // set with GLSL layout qualifier\r\n    var NORMAL_LOCATION = 1; // set with GLSL layout qualifier\r\n    var TEXCOORD_0_LOCATION = 2; // set with GLSL layout qualifier\r\n    var JOINTS_0_LOCATION = 3; // set with GLSL layout qualifier\r\n    var JOINTS_1_LOCATION = 5; // set with GLSL layout qualifier\r\n    var WEIGHTS_0_LOCATION = 4; // set with GLSL layout qualifier\r\n    var WEIGHTS_1_LOCATION = 6; // set with GLSL layout qualifier\r\n    \r\n    // -- Mouse Behaviour\r\n    var isDisplayRotation = true;\r\n    var s = 1;\r\n    var eulerX = 0;\r\n    var eulerY = 0;\r\n    // var s = 1;\r\n    // var t = -100;\r\n    var translate = vec3.create();\r\n    // var t = -5;\r\n    var modelMatrix = mat4.create();\r\n    var mouseDown = false;\r\n    var mouseButtonId = 0;\r\n    var lastMouseY = 0;\r\n    var lastMouseX = 0;\r\n    var identityQ = quat.create();\r\n    window.onmousedown = function(event) {\r\n        mouseDown = true;\r\n        mouseButtonId = event.which;\r\n        lastMouseY = event.clientY;\r\n        lastMouseX = event.clientX;\r\n        if (mouseButtonId === 1) {\r\n            isDisplayRotation = false;\r\n        }\r\n    };\r\n    window.onmouseup = function(event) {\r\n        mouseDown = false;\r\n        isDisplayRotation = true;\r\n    };\r\n    window.onmousemove = function(event) {\r\n        if(!mouseDown) {\r\n            return;\r\n        }\r\n        var newY = event.clientY;\r\n        var newX = event.clientX;\r\n        \r\n        var deltaY = newY - lastMouseY;\r\n        var deltaX = newX - lastMouseX;\r\n        \r\n        // s *= (1 + deltaY / 1000);\r\n\r\n        switch(mouseButtonId) {\r\n            case 1:\r\n            // left: rotation\r\n            eulerX += -deltaY * 0.01;\r\n            eulerY += deltaX * 0.01;\r\n            break;\r\n            case 3:\r\n            // right\r\n            translate[0] += deltaX * 0.001;\r\n            translate[1] += -deltaY * 0.001;\r\n            break;\r\n        }\r\n        \r\n        \r\n        lastMouseY = newY;\r\n        lastMouseX = newX;\r\n    };\r\n    window.onwheel = function(event) {\r\n        translate[2] += -event.deltaY * 0.001;\r\n        // translate[2] *= 1 + (-event.deltaY * 0.01);\r\n    };\r\n\r\n    \r\n    // 2.0\r\n    // var gltfUrl = '../glTFs/glTF_version_2/Duck/glTF/Duck.gltf';\r\n    var gltfUrl = 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/DamagedHelmet/glTF/DamagedHelmet.gltf';\r\n\r\n    var glTFLoader = new MinimalGLTFLoader.glTFLoader(gl);\r\n\r\n    var glTFModelCount = 1;\r\n    var scenes = [];\r\n\r\n    gl.enable(gl.CULL_FACE);\r\n    gl.cullFace(gl.BACK);\r\n    gl.frontFace(gl.CCW);\r\n    var isFaceCulling = true;\r\n\r\n\r\n    function setupScene(glTF, replaceScene) {\r\n        var i, len;\r\n\r\n        // update animation list\r\n        for(i = animationSelectionList.options.length - 1 ; i >= 0 ; i--) {\r\n            animationSelectionList.remove(i);\r\n        }\r\n        if (glTF.animations) {\r\n            var option;\r\n            for (i = 0, len = glTF.animations.length; i < len; i++) {\r\n                option = document.createElement(\"option\");\r\n                option.text = glTF.animations[i].name || i;\r\n                animationSelectionList.add(option);\r\n            }    \r\n        }\r\n        curAnimationId = 0;\r\n\r\n        // ----------------\r\n        \r\n        var curGltfScene = glTF.scenes[glTF.defaultScene];\r\n\r\n        var sceneDeltaTranslate = vec3.fromValues(curGltfScene.boundingBox.transform[0] * 1.2, 0, 0);\r\n        var tmpVec3Translate = vec3.create();\r\n\r\n        var newGltfRuntimeScene;\r\n        if (!replaceScene) {\r\n            newGltfRuntimeScene = new Scene(curGltfScene, glTF, scenes.length);\r\n            scenes.push(newGltfRuntimeScene);\r\n        } else {\r\n            newGltfRuntimeScene = scenes[replaceScene.id] = new Scene(curGltfScene, glTF, replaceScene.id);\r\n        }\r\n        \r\n        // for (i = 0, len = glTFModelCount; i < len; i++) {\r\n        //     scenes.push(new Scene(curGltfScene, glTF));\r\n        //     // vec3.scale(tmpVec3Translate, sceneDeltaTranslate, i);\r\n        //     // mat4.fromTranslation(scenes[i].rootTransform, tmpVec3Translate);\r\n        // }\r\n        \r\n\r\n        \r\n        if (scenes.length === 1) {\r\n            // first model, adjust camera\r\n            mat4.identity(modelMatrix);\r\n            \r\n            // center\r\n            s = 1.0 / Math.max( curGltfScene.boundingBox.transform[0], Math.max(curGltfScene.boundingBox.transform[5], curGltfScene.boundingBox.transform[10]) );\r\n            mat4.getTranslation(translate, curGltfScene.boundingBox.transform);\r\n            vec3.scale(translate, translate, -1);\r\n            translate[0] += - 0.5 * curGltfScene.boundingBox.transform[0];\r\n            translate[1] += - 0.5 * curGltfScene.boundingBox.transform[5];\r\n            translate[2] += - 0.5 * curGltfScene.boundingBox.transform[10];\r\n    \r\n            s *= 0.5;\r\n    \r\n            modelMatrix[0] = s;\r\n            modelMatrix[5] = s;\r\n            modelMatrix[10] = s;\r\n            mat4.translate(modelMatrix, modelMatrix, translate);\r\n    \r\n            vec3.set(translate, 0, 0, -1.5);\r\n            s = 1;\r\n        }\r\n        \r\n\r\n\r\n        // var in loop\r\n        var mesh;\r\n        var primitive;\r\n        var vertexBuffer;\r\n        var indexBuffer;\r\n        var vertexArray;\r\n\r\n        var nid, lenNodes;\r\n        var mid, lenMeshes;\r\n        \r\n        var attribute;\r\n        var material;\r\n\r\n        var image, texture, sampler;\r\n\r\n        var accessor, bufferView;\r\n\r\n        var animation, animationSampler, channel;\r\n\r\n        var skin;\r\n\r\n        // create buffers\r\n        for (i = 0, len = glTF.bufferViews.length; i < len; i++) {\r\n            bufferView = glTF.bufferViews[i];\r\n            bufferView.createBuffer(gl);\r\n            bufferView.bindData(gl);\r\n        }\r\n\r\n        \r\n        // create textures\r\n        if (glTF.textures) {\r\n            for (i = 0, len = glTF.textures.length; i < len; i++) {\r\n                texture = glTF.textures[i];\r\n                texture.createTexture(gl);\r\n            }\r\n        }\r\n\r\n        // create samplers\r\n        if (glTF.samplers) {\r\n            for (i = 0, len = glTF.samplers.length; i < len; i++) {\r\n                sampler = glTF.samplers[i];\r\n                \r\n                sampler.createSampler(gl);\r\n            }\r\n        }\r\n\r\n        if (glTF.skins) {\r\n            // gl.useProgram(programSkinBaseColor.program);\r\n            // gl.uniformBlockBinding(programSkinBaseColor.program, programSkinBaseColor.uniformBlockIndexJointMatrix, 0);\r\n            // gl.useProgram(null);\r\n            for (i = 0, len = glTF.skins.length; i < len; i++) {\r\n                skin = glTF.skins[i];\r\n                \r\n                skin.jointMatrixUniformBuffer = gl.createBuffer();\r\n\r\n                // gl.bindBufferBase(gl.UNIFORM_BUFFER, i, skin.jointMatrixUniformBuffer);\r\n                gl.bindBufferBase(gl.UNIFORM_BUFFER, skin.uniformBlockID, skin.jointMatrixUniformBuffer);\r\n\r\n                gl.bindBuffer(gl.UNIFORM_BUFFER, skin.jointMatrixUniformBuffer);\r\n                gl.bufferData(gl.UNIFORM_BUFFER, skin.jointMatrixUnidormBufferData, gl.DYNAMIC_DRAW);\r\n                gl.bufferSubData(gl.UNIFORM_BUFFER, 0, skin.jointMatrixUnidormBufferData);\r\n                gl.bindBuffer(gl.UNIFORM_BUFFER, null);\r\n            }\r\n        }\r\n\r\n\r\n\r\n        function setupAttribuite(attrib, location) {\r\n            if (attrib !== undefined) {\r\n                // var accessor = glTF.accessors[ attrib ];\r\n                var accessor = attrib;\r\n                var bufferView = accessor.bufferView;\r\n                if (bufferView.target === null) {\r\n                    // console.log('WARNING: the bufferview of this accessor should have a target, or it should represent non buffer data (like animation)');\r\n                    gl.bindBuffer(gl.ARRAY_BUFFER, bufferView.buffer);\r\n                    gl.bufferData(gl.ARRAY_BUFFER, bufferView.data, gl.STATIC_DRAW);\r\n                } else {\r\n                    gl.bindBuffer(bufferView.target, bufferView.buffer);\r\n                }\r\n                accessor.prepareVertexAttrib(location, gl);\r\n                return true;\r\n            }\r\n            return false;\r\n        }\r\n\r\n\r\n        // create vaos & materials shader source setup\r\n        for (mid = 0, lenMeshes = glTF.meshes.length; mid < lenMeshes; mid++) {\r\n            mesh = glTF.meshes[mid];\r\n            // vertexArrayMaps[mid] = [];\r\n\r\n            for (i = 0, len = mesh.primitives.length; i < len; ++i) {\r\n                primitive = mesh.primitives[i];\r\n                primitive.shader = new Shader();\r\n                // WebGL2: create vertexArray\r\n                primitive.vertexArray = vertexArray = gl.createVertexArray();\r\n                gl.bindVertexArray(vertexArray);\r\n                \r\n                \r\n                setupAttribuite(primitive.attributes.POSITION, POSITION_LOCATION);\r\n                setupAttribuite(primitive.attributes.NORMAL, NORMAL_LOCATION);\r\n\r\n                // @tmp, should consider together with material\r\n                setupAttribuite(primitive.attributes.TEXCOORD_0, TEXCOORD_0_LOCATION);\r\n                \r\n\r\n                if (\r\n                    setupAttribuite(primitive.attributes.JOINTS_0, JOINTS_0_LOCATION) &&\r\n                    setupAttribuite(primitive.attributes.WEIGHTS_0, WEIGHTS_0_LOCATION)\r\n                ) {\r\n                    // assume these two attributes always appear together\r\n                    primitive.shader.defineMacro('HAS_SKIN');\r\n                }\r\n                \r\n\r\n                if (\r\n                    setupAttribuite(primitive.attributes.JOINTS_1, JOINTS_1_LOCATION) &&\r\n                    setupAttribuite(primitive.attributes.WEIGHTS_1, WEIGHTS_1_LOCATION)\r\n                ) {\r\n                    // assume these two attributes always appear together\r\n                    primitive.shader.defineMacro('SKIN_VEC8');\r\n                }\r\n\r\n                // indices ( assume use indices )\r\n                if (primitive.indices !== null) {\r\n                    accessor = glTF.accessors[ primitive.indices ];\r\n                    bufferView = accessor.bufferView;\r\n                    if (bufferView.target === null) {\r\n                        // console.log('WARNING: the bufferview of this accessor should have a target, or it should represent non buffer data (like animation)');\r\n                        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferView.buffer);\r\n                        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, bufferView.data, gl.STATIC_DRAW);\r\n                    } else {\r\n                        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferView.buffer);\r\n                    }\r\n                }\r\n                \r\n                \r\n\r\n                gl.bindVertexArray(null);\r\n\r\n                gl.bindBuffer(gl.ARRAY_BUFFER, null);\r\n                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\r\n\r\n\r\n\r\n                // material shader setup\r\n                material = primitive.material;\r\n                if (material) {\r\n                    if (material.pbrMetallicRoughness.baseColorTexture) {\r\n                        primitive.shader.defineMacro('HAS_BASECOLORMAP');\r\n                    }\r\n                    if (material.pbrMetallicRoughness.metallicRoughnessTexture) {\r\n                        primitive.shader.defineMacro('HAS_METALROUGHNESSMAP');\r\n                    }\r\n                    if (material.normalTexture) {\r\n                        primitive.shader.defineMacro('HAS_NORMALMAP');\r\n                    }\r\n                    if (material.occlusionTexture) {\r\n                        primitive.shader.defineMacro('HAS_OCCLUSIONMAP');\r\n                    }\r\n                    if (material.emissiveTexture) {\r\n                        primitive.shader.defineMacro('HAS_EMISSIVEMAP');\r\n                    }\r\n                }\r\n                \r\n\r\n                primitive.shader.compile();\r\n\r\n            }\r\n            \r\n        }\r\n\r\n\r\n        return newGltfRuntimeScene;\r\n    }\r\n\r\n\r\n\r\n\r\n    // -- Render preparation\r\n    gl.enable(gl.DEPTH_TEST);\r\n    gl.depthFunc(gl.LEQUAL);\r\n\r\n\r\n\r\n    var Renderer = Renderer || {};\r\n\r\n    var program = null; // current program object\r\n\r\n    (function() {\r\n        'use strict';\r\n\r\n\r\n        var scale = vec3.create();\r\n        \r\n        var r = 0.0;\r\n        var rotationSpeedY= 0.01;\r\n        // var rotationSpeedY= 0.0;\r\n\r\n        var perspective = mat4.create();\r\n        mat4.perspective(perspective, 0.785, canvas.width / canvas.height, 0.01, 100);\r\n\r\n        var modelView = mat4.create();\r\n\r\n        var localMV = mat4.create();\r\n        var localMVP = mat4.create();\r\n        var localMVNormal = mat4.create();\r\n\r\n        var VP = mat4.create();\r\n\r\n        var hasIndices = true;\r\n\r\n        var hasSkin = false;\r\n        var uniformBlockID;     // same for uniform block binding id\r\n\r\n        var curScene;\r\n\r\n\r\n        function activeAndBindTexture(uniformLocation, textureInfo) {\r\n            gl.uniform1i(uniformLocation, textureInfo.index);\r\n            gl.activeTexture(gl.TEXTURE0 + textureInfo.index);\r\n            var texture = curScene.glTF.textures[ textureInfo.index ];\r\n            gl.bindTexture(gl.TEXTURE_2D, texture.texture);\r\n            var sampler;\r\n            if (texture.sampler) {\r\n                sampler = texture.sampler.sampler;\r\n            } else {\r\n                sampler = defaultSampler;\r\n            }\r\n\r\n            gl.bindSampler(textureInfo.index, sampler);\r\n        }\r\n        \r\n\r\n        var defaultColor = [1.0, 1.0, 1.0, 1.0];\r\n        var drawPrimitive = Renderer.drawPrimitive = function(primitive, matrix) {\r\n            mat4.multiply(localMV, modelView, matrix);\r\n            mat4.multiply(localMVP, perspective, localMV);\r\n            // mat4.multiply(localMVP, VP, matrix);\r\n\r\n            mat4.invert(localMVNormal, localMV);\r\n            mat4.transpose(localMVNormal, localMVNormal);\r\n\r\n\r\n            var texture, sampler;\r\n            var baseColor = defaultColor;\r\n\r\n            var shader = primitive.shader;\r\n            var material = primitive.material;\r\n            \r\n\r\n            if (material !== null) {\r\n                var pbrMetallicRoughness = material.pbrMetallicRoughness;\r\n                baseColor = pbrMetallicRoughness.baseColorFactor;\r\n                \r\n                if (primitive.material.doubleSided === isFaceCulling) {\r\n                    isFaceCulling = !primitive.material.doubleSided;\r\n                    if (isFaceCulling) {\r\n                        gl.enable(gl.CULL_FACE);\r\n                    } else {\r\n                        gl.disable(gl.CULL_FACE);\r\n                    }\r\n                }\r\n            }\r\n\r\n            \r\n            \r\n            if (program != primitive.shader.programObject) {\r\n                program = primitive.shader.programObject;\r\n                gl.useProgram(program.program);\r\n            }\r\n\r\n            if (material) {\r\n                // base color texture\r\n                if (shader.hasBaseColorMap()) {\r\n                    activeAndBindTexture(program.uniformLocations.baseColorTexture, pbrMetallicRoughness.baseColorTexture);\r\n                }\r\n\r\n                // normal texture\r\n                if (shader.hasNormalMap()) {\r\n                    activeAndBindTexture(program.uniformLocations.normalTexture, material.normalTexture);\r\n                    gl.uniform1f(program.uniformLocations.normalTextureScale, material.normalTexture.scale);\r\n                }\r\n\r\n                // metallic roughness texture\r\n                if (shader.hasMetalRoughnessMap()) {\r\n                    activeAndBindTexture(program.uniformLocations.metallicRoughnessTexture, pbrMetallicRoughness.metallicRoughnessTexture);\r\n                }\r\n                \r\n                gl.uniform1f(program.uniformLocations.metallicFactor, pbrMetallicRoughness.metallicFactor);\r\n                gl.uniform1f(program.uniformLocations.roughnessFactor, pbrMetallicRoughness.roughnessFactor);\r\n\r\n                // occlusion texture\r\n                if (shader.hasOcclusionMap()) {\r\n                    activeAndBindTexture(program.uniformLocations.occlusionTexture, material.occlusionTexture);\r\n                    gl.uniform1f(program.uniformLocations.occlusionStrength, material.occlusionTexture.strength);\r\n                }\r\n\r\n                // emissive texture\r\n                if (shader.hasEmissiveMap()) {\r\n                    activeAndBindTexture(program.uniformLocations.emissiveTexture, material.emissiveTexture);\r\n                    gl.uniform3fv(program.uniformLocations.emissiveFactor, material.emissiveFactor);\r\n                }\r\n            }\r\n            \r\n            \r\n            // TODO: skin JointMatrix uniform block\r\n            if (shader.hasSkin()) {\r\n                gl.uniformBlockBinding(program.program, program.uniformBlockIndices.JointMatrix, uniformBlockID);\r\n            }\r\n            \r\n\r\n            gl.activeTexture(gl.TEXTURE0 + BRDF_LUT.textureIndex);\r\n            gl.bindTexture(gl.TEXTURE_2D, BRDF_LUT.texture);\r\n\r\n            // console.log( (gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)).toString(16) );            \r\n\r\n            gl.activeTexture(gl.TEXTURE0 + CUBE_MAP.textureIndex);\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, CUBE_MAP.texture);\r\n\r\n            gl.activeTexture(gl.TEXTURE0 + CUBE_MAP.textureIBLDiffuseIndex);\r\n            gl.bindTexture(gl.TEXTURE_CUBE_MAP, CUBE_MAP.textureIBLDiffuse);\r\n\r\n            gl.uniform4fv(program.uniformLocations.baseColorFactor, baseColor);\r\n            \r\n            gl.uniformMatrix4fv(program.uniformLocations.MV, false, localMV);\r\n            gl.uniformMatrix4fv(program.uniformLocations.MVP, false, localMVP);\r\n            gl.uniformMatrix4fv(program.uniformLocations.MVNormal, false, localMVNormal);\r\n            \r\n\r\n            gl.bindVertexArray(primitive.vertexArray);\r\n\r\n            if (primitive.indices !== null) {\r\n                gl.drawElements(primitive.mode, primitive.indicesLength, primitive.indicesComponentType, primitive.indicesOffset);\r\n            } else {\r\n                gl.drawArrays(primitive.mode, primitive.drawArraysOffset, primitive.drawArraysCount);\r\n            }\r\n\r\n\r\n            gl.bindVertexArray(null);\r\n\r\n        }\r\n\r\n        \r\n\r\n        var tmpMat4 = mat4.create();\r\n        var inverseTransformMat4 = mat4.create();\r\n        \r\n        // @todo: \r\n        // in a real engine, it is better to simply parse the node tree stucture\r\n        // to compute transform matrices,\r\n        // then sort node array by material and render use a for loop\r\n        // to minimize context switch\r\n        var drawNode = Renderer.drawNode = function (node, nodeID, nodeMatrix, parentModelMatrix) {\r\n            var matrix = nodeMatrix[nodeID];\r\n            \r\n            if (parentModelMatrix !== undefined) {\r\n                mat4.mul(matrix, parentModelMatrix, node.matrix);\r\n            } else {\r\n                // from scene root, parent is identity\r\n                mat4.copy(matrix, node.matrix);\r\n            }\r\n            // mat4.mul(matrix, parentModelMatrix, node.matrix);\r\n\r\n            hasSkin = false;\r\n            if (node.skin !== null) {\r\n                // mesh node with skin\r\n                hasSkin = true;\r\n                var skin = node.skin;\r\n                uniformBlockID = skin.uniformBlockID;\r\n                var joints = node.skin.joints;\r\n                var jointNode;\r\n\r\n                mat4.invert(inverseTransformMat4, matrix);\r\n\r\n\r\n                // @tmp: assume joint nodes are always in the front of the scene node list\r\n                // so that their matrices are ready to use\r\n                for (i = 0, len = joints.length; i < len; i++) {\r\n                    jointNode = joints[i];\r\n                    mat4.mul(tmpMat4, nodeMatrix[jointNode.nodeID], skin.inverseBindMatrix[i]);\r\n                    mat4.mul(tmpMat4, inverseTransformMat4, tmpMat4);\r\n\r\n                    // if (skin.skeleton !== null) {\r\n                    //     mat4.mul(tmpMat4, inverseSkeletonRootMat4, tmpMat4);\r\n                    // }\r\n\r\n                    skin.jointMatrixUnidormBufferData.set(tmpMat4, i * 16);\r\n                }\r\n\r\n                gl.bindBuffer(gl.UNIFORM_BUFFER, skin.jointMatrixUniformBuffer);\r\n                gl.bufferSubData(gl.UNIFORM_BUFFER, 0, skin.jointMatrixUnidormBufferData, 0, skin.jointMatrixUnidormBufferData.length);\r\n            }\r\n\r\n\r\n            var i, len;\r\n\r\n            // draw cur node's mesh\r\n            if (node.mesh !== null) {\r\n                // drawMesh(glTF.meshes[node.mesh], matrix);\r\n\r\n                // var mesh = glTF.meshes[node.mesh];\r\n                var mesh = node.mesh;\r\n                for (i = 0, len = mesh.primitives.length; i < len; i++) {\r\n                    // draw primitive\r\n                    drawPrimitive(mesh.primitives[i], matrix);\r\n                }\r\n\r\n                // BOUNDING_BOX.draw(mesh.boundingBox, matrix, modelView, perspective);\r\n                // gl.useProgram(program);\r\n            }\r\n            \r\n            if (node.skin !== null) {\r\n                gl.bindBuffer(gl.UNIFORM_BUFFER, null);\r\n            }\r\n            \r\n\r\n            // draw children\r\n            \r\n            var childNodeID;\r\n            for (i = 0, len = node.children.length; i < len; i++) {\r\n                // childNodeID = node.children[i];\r\n                // drawNode(glTF.nodes[childNodeID], childNodeID, matrix);\r\n                drawNode(node.children[i], node.children[i].nodeID, nodeMatrix, matrix);\r\n            }\r\n        }\r\n\r\n\r\n        function applyAnimation(animation, glTF) {\r\n            var j, lenj;\r\n            var channel, animationSampler, node;\r\n\r\n            for (j = 0, lenj = animation.samplers.length; j < lenj; j++) {\r\n                animation.samplers[j].getValue(timeParameter);\r\n            }\r\n\r\n            for (j = 0, lenj = animation.channels.length; j < lenj; j++) {\r\n                channel = animation.channels[j];\r\n                animationSampler = channel.sampler;\r\n                node = glTF.nodes[channel.target.nodeID];\r\n\r\n                switch (channel.target.path) {\r\n                    case 'rotation':\r\n                    vec4.copy(node.rotation, animationSampler.curValue);\r\n                    break;\r\n\r\n                    case 'translation':\r\n                    vec3.copy(node.translation, animationSampler.curValue);\r\n                    break;\r\n\r\n                    case 'scale':\r\n                    vec3.copy(node.scale, animationSampler.curValue);\r\n                    break;\r\n                }\r\n\r\n                node.updateMatrixFromTRS();\r\n                \r\n            }\r\n        }\r\n\r\n        var drawScene = Renderer.drawScene = function (scene) {\r\n            // animation\r\n            var animation;\r\n            var i, len;\r\n\r\n            var glTF = scene.glTF;\r\n            if (glTF.animations) {\r\n                if (playAllAnimationTogether) {\r\n                    for (i = 0, len = glTF.animations.length; i < len; i++) {\r\n                        animation = glTF.animations[i];\r\n                        applyAnimation(animation, glTF);\r\n                    }\r\n                } else {\r\n                    animation = glTF.animations[curAnimationId];\r\n                    applyAnimation(animation, glTF);\r\n                }\r\n            }\r\n\r\n\r\n            for (var i = 0, len = scene.glTFScene.nodes.length; i < len; i++) {\r\n                drawNode( scene.glTFScene.nodes[i], scene.glTFScene.nodes[i].nodeID, scene.nodeMatrix, scene.rootTransform );\r\n            }\r\n        }\r\n\r\n        var drawSceneBBox = Renderer.drawSceneBBox = function (glTF, scene, bboxType) {\r\n            var node, mesh, bbox;\r\n            // @temp: assume all nodes are in cur scene\r\n            // @potential fix: can label each node's scene at the setup\r\n            var i, len;\r\n            for (i = 0, len = scene.nodeMatrix.length; i < len; i++) {\r\n                node = glTF.nodes[i];\r\n\r\n                if (bboxType == 'bvh') {\r\n                    // bvh\r\n                    mat4.mul(localMVP, scene.rootTransform, node.bvh.transform);\r\n                    mat4.mul(localMVP, VP, localMVP);\r\n                    gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\r\n                    gl.drawArrays(gl.LINES, 0, 24);\r\n                }\r\n                else if (node.mesh !== null) {\r\n                    // mesh = glTF.meshes[node.mesh];\r\n                    mesh = node.mesh;\r\n\r\n                    if (bboxType == 'aabb') {\r\n                        // aabb\r\n                        mat4.mul(localMVP, scene.rootTransform, node.aabb.transform);\r\n                        mat4.mul(localMVP, VP, localMVP);\r\n                    } else {\r\n                        // obb (assume object node is static)\r\n                        mat4.mul(localMVP, scene.nodeMatrix[i], mesh.boundingBox.transform);\r\n                        mat4.mul(localMVP, VP, localMVP);\r\n                    }\r\n\r\n                    gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\r\n                        \r\n                    gl.drawArrays(gl.LINES, 0, 24);\r\n\r\n                }   \r\n            }\r\n\r\n            // // scene bounding box\r\n            // mat4.mul(localMVP, scene.rootTransform, scene.glTFScene.boundingBox.transform);\r\n            // mat4.mul(localMVP, VP, localMVP);\r\n            // gl.uniformMatrix4fv(BOUNDING_BOX.uniformMvpLocation, false, localMVP);\r\n            // gl.drawArrays(gl.LINES, 0, 24);\r\n        }\r\n        \r\n\r\n        var timeStampZero = performance.now();\r\n        var timeParameter = 0;\r\n\r\n        // -- Render loop\r\n        // function render() {\r\n        var render = Renderer.render = function(timestamp) {\r\n            var i, len;\r\n            var j, lenj;\r\n            var node;\r\n\r\n\r\n            gl.clearColor(0.0, 0.0, 0.0, 1.0);\r\n            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\r\n\r\n            vec3.set(scale, s, s, s);\r\n            // mat4.identity(modelView);\r\n            // mat4.translate(modelView, modelView, translate);\r\n            // mat4.scale(modelView, modelView, scale);\r\n            // mat4.fromRotationTranslationScale(modelView, identityQ, translate, scale);\r\n            // mat4.mul(modelView, modelView, modelMatrix);\r\n            mat4.identity(modelView);\r\n            mat4.translate(modelView, modelView, translate);\r\n            if (isDisplayRotation) {\r\n                r += rotationSpeedY;\r\n            }\r\n            \r\n\r\n            mat4.rotateX(modelView, modelView, eulerX);\r\n            mat4.rotateY(modelView, modelView, r);\r\n            mat4.scale(modelView, modelView, scale);\r\n            \r\n            mat4.mul(modelView, modelView, modelMatrix);\r\n\r\n            mat4.rotateY(modelView, modelView, eulerY); \r\n\r\n            \r\n\r\n            mat4.mul(VP, perspective, modelView);\r\n\r\n\r\n            for (i = 0, len = scenes.length; i < len; i++) {\r\n                curScene = scenes[i];\r\n\r\n                drawScene(scenes[i]);\r\n            }\r\n\r\n            if (drawBoundingBox) {\r\n                gl.useProgram(BOUNDING_BOX.program);\r\n                gl.bindVertexArray(BOUNDING_BOX.vertexArray);\r\n\r\n                for (i = 0, len = scenes.length; i < len; i++) {\r\n                    drawSceneBBox(scenes[i].glTF, scenes[i], boundingBoxType);\r\n                }\r\n\r\n\r\n                gl.bindVertexArray(null);\r\n            }\r\n\r\n\r\n            // cube map\r\n\r\n            CUBE_MAP.draw(modelView, perspective);\r\n\r\n            program = null;\r\n\r\n            timeParameter = (timestamp - timeStampZero) * 0.001;\r\n            requestAnimationFrame(render);\r\n        }\r\n\r\n    })();\r\n\r\n\r\n    CUBE_MAP.finishLoadingCallback = function() {\r\n        glTFLoader.loadGLTF(gltfUrl, function(glTF) {\r\n            setupScene(glTF);\r\n            Renderer.render();\r\n        });\r\n    };\r\n\r\n    CUBE_MAP.loadAll();\r\n\r\n})();\r\n"
  },
  {
    "path": "src/minimal-gltf-loader.js",
    "content": "import {vec3, vec4, quat, mat4} from 'gl-matrix';\n\nvar MinimalGLTFLoader = MinimalGLTFLoader || {};\n\nvar globalUniformBlockID = 0;\n\nvar curLoader = null;       // @tmp, might be unsafe if loading multiple model at the same time\n\nvar NUM_MAX_JOINTS = 65;\n\n// Data classes\nvar Scene = MinimalGLTFLoader.Scene = function (gltf, s) {\n    this.name = s.name !== undefined ? s.name : null;\n    this.nodes = new Array(s.nodes.length);    // root node object of this scene\n    for (var i = 0, len = s.nodes.length; i < len; i++) {\n        this.nodes[i] = gltf.nodes[s.nodes[i]];\n    }\n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n\n    this.boundingBox = null;\n};\n\n/**\n * \n * @param {vec3} min\n * @param {vec3} max\n */\nvar BoundingBox = MinimalGLTFLoader.BoundingBox = function (min, max, isClone) {\n    // this.min = min;\n    // this.max = max;\n    min = min || vec3.fromValues(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);\n    max = max || vec3.fromValues(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY);\n\n    if (isClone === undefined || isClone === true) {\n        this.min = vec3.clone(min);\n        this.max = vec3.clone(max);\n    } else {\n        this.min = min;\n        this.max = max;\n    }\n    \n\n    this.transform = mat4.create();\n};\n\nBoundingBox.prototype.updateBoundingBox = function (bbox) {\n    vec3.min(this.min, this.min, bbox.min);\n    vec3.max(this.max, this.max, bbox.max);\n};\n\nBoundingBox.prototype.calculateTransform = function () {\n    // transform from a unit cube whose min = (0, 0, 0) and max = (1, 1, 1)\n\n    // scale\n    this.transform[0] = this.max[0] - this.min[0];\n    this.transform[5] = this.max[1] - this.min[1];\n    this.transform[10] = this.max[2] - this.min[2];\n    // translate\n    this.transform[12] = this.min[0];\n    this.transform[13] = this.min[1];\n    this.transform[14] = this.min[2];\n};\n\nBoundingBox.getAABBFromOBB = (function() {\n    var transformRight = vec3.create();\n    var transformUp = vec3.create();\n    var transformBackward = vec3.create();\n\n    var tmpVec3a = vec3.create();\n    var tmpVec3b = vec3.create();\n\n    return (function (obb, matrix) {\n        vec3.set(transformRight, matrix[0], matrix[1], matrix[2]);\n        vec3.set(transformUp, matrix[4], matrix[5], matrix[6]);\n        vec3.set(transformBackward, matrix[8], matrix[9], matrix[10]);\n\n        var min = vec3.fromValues(matrix[12], matrix[13], matrix[14]);  // init with matrix translation\n        var max = vec3.clone(min);\n\n        vec3.scale(tmpVec3a, transformRight, obb.min[0]);\n        vec3.scale(tmpVec3b, transformRight, obb.max[0]);\n        vec3.min(transformRight, tmpVec3a, tmpVec3b);\n        vec3.add(min, min, transformRight);\n        vec3.max(transformRight, tmpVec3a, tmpVec3b);\n        vec3.add(max, max, transformRight);\n\n        vec3.scale(tmpVec3a, transformUp, obb.min[1]);\n        vec3.scale(tmpVec3b, transformUp, obb.max[1]);\n        vec3.min(transformUp, tmpVec3a, tmpVec3b);\n        vec3.add(min, min, transformUp);\n        vec3.max(transformUp, tmpVec3a, tmpVec3b);\n        vec3.add(max, max, transformUp);\n\n        vec3.scale(tmpVec3a, transformBackward, obb.min[2]);\n        vec3.scale(tmpVec3b, transformBackward, obb.max[2]);\n        vec3.min(transformBackward, tmpVec3a, tmpVec3b);\n        vec3.add(min, min, transformBackward);\n        vec3.max(transformBackward, tmpVec3a, tmpVec3b);\n        vec3.add(max, max, transformBackward);\n\n        var bbox = new BoundingBox(min, max, false);\n        bbox.calculateTransform();\n        return bbox;\n    });\n})();\n\n\n\nvar Accessor = MinimalGLTFLoader.Accessor = function (a, bufferViewObject) {\n    this.bufferView = bufferViewObject;\n    this.componentType = a.componentType;   // required\n    this.byteOffset = a.byteOffset !== undefined ? a.byteOffset : 0;\n    this.byteStride = bufferViewObject.byteStride;\n    this.normalized = a.normalized !== undefined ? a.normalized : false;\n    this.count = a.count;   // required\n    this.type = a.type;     // required\n    this.size = Type2NumOfComponent[this.type];\n\n    this.min = a.min;   // @tmp assume required for now (for bbox)\n    this.max = a.max;   // @tmp assume required for now (for bbox)\n\n    this.extensions = a.extensions !== undefined ? a.extensions : null;\n    this.extras = a.extras !== undefined ? a.extras : null;\n};\n\nAccessor.prototype.prepareVertexAttrib = function(location, gl) {\n    gl.vertexAttribPointer(\n        location,\n        this.size,\n        this.componentType,\n        this.normalized,\n        this.byteStride,\n        this.byteOffset\n        );\n    gl.enableVertexAttribArray(location);\n};\n\nvar BufferView = MinimalGLTFLoader.BufferView = function(bf, bufferData) {\n    this.byteLength = bf.byteLength;    //required\n    this.byteOffset = bf.byteOffset !== undefined ? bf.byteOffset : 0;\n    this.byteStride = bf.byteStride !== undefined ? bf.byteStride : 0;\n    this.target = bf.target !== undefined ? bf.target : null;\n\n    this.data = bufferData.slice(this.byteOffset, this.byteOffset + this.byteLength);\n\n    this.extensions = bf.extensions !== undefined ? bf.extensions : null;\n    this.extras = bf.extras !== undefined ? bf.extras : null;\n\n    // runtime stuffs -------------\n    this.buffer = null;     // gl buffer\n};\n\nBufferView.prototype.createBuffer = function(gl) {\n    this.buffer = gl.createBuffer();\n};\n\nBufferView.prototype.bindData = function(gl) {\n    if (this.target) {\n        gl.bindBuffer(this.target, this.buffer);\n        gl.bufferData(this.target, this.data, gl.STATIC_DRAW);\n        gl.bindBuffer(this.target, null);\n        return true;\n    }\n    return false;\n};\n\n\nvar Camera = MinimalGLTFLoader.Camera = function(c) {\n    this.name = c.name !== undefined ? c.name : null;\n    this.type = c.type; // required\n\n    this.othographic = c.othographic === undefined ? null : c.othographic;  // every attribute inside is required (excluding extensions)\n    this.perspective = c.perspective === undefined ? null : {\n        yfov: c.perspective.yfov,\n        znear: c.perspective.znear,\n        zfar: c.perspective.zfar !== undefined ? c.perspective.zfar : null,\n        aspectRatio: c.perspective.aspectRatio !== undefined ? c.perspective.aspectRatio : null\n    };\n\n    this.extensions = c.extensions !== undefined ? c.extensions : null;\n    this.extras = c.extras !== undefined ? c.extras : null;\n};\n\n\n\nvar Node = MinimalGLTFLoader.Node = function (n, nodeID) {\n    this.name = n.name !== undefined ? n.name : null;\n    this.nodeID = nodeID;\n    // TODO: camera\n    this.camera = n.camera !== undefined ? n.camera : null;\n\n    this.matrix = mat4.create();\n    if (n.hasOwnProperty('matrix')) {\n        for(var i = 0; i < 16; ++i) {\n            this.matrix[i] = n.matrix[i];\n        }\n\n        this.translation = vec3.create();\n        mat4.getTranslation(this.translation, this.matrix);\n\n        this.rotation = quat.create();\n        mat4.getRotation(this.rotation, this.matrix);\n\n        this.scale = vec3.create();\n        mat4.getScaling(this.scale, this.matrix);\n    } else {\n        // this.translation = null;\n        // this.rotation = null;\n        // this.scale = null;\n        this.getTransformMatrixFromTRS(n.translation, n.rotation, n.scale);\n    }\n    \n    \n    \n\n    this.children = n.children || [];  // init as id, then hook up to node object later\n    this.mesh = n.mesh !== undefined ? curLoader.glTF.meshes[n.mesh] : null;\n\n    this.skin = n.skin !== undefined ? n.skin : null;   // init as id, then hook up to skin object later\n\n    if (n.extensions !== undefined) {\n        if (n.extensions.gl_avatar !== undefined && curLoader.enableGLAvatar === true) {\n            var linkedSkinID = curLoader.skeletonGltf.json.extensions.gl_avatar.skins[ n.extensions.gl_avatar.skin.name ];\n            var linkedSkin = curLoader.skeletonGltf.skins[linkedSkinID];\n            this.skin = new SkinLink(curLoader.glTF, linkedSkin, n.extensions.gl_avatar.skin.inverseBindMatrices);\n        }\n    }\n    \n\n\n    // TODO: morph targets weights\n    this.weights = n.weights !== undefined ? n.weights : null;\n\n\n    this.extensions = n.extensions !== undefined ? n.extensions : null;\n    this.extras = n.extras !== undefined ? n.extras : null;\n\n    // runtime stuffs--------------\n\n    this.aabb = null;   // axis aligned bounding box, not need to apply node transform to aabb\n    this.bvh = new BoundingBox();\n};\n\nNode.prototype.traverse = function(parent, executeFunc) {\n    executeFunc(this, parent);\n    for (var i = 0, len = this.children.length; i < len; i++) {\n        this.children[i].traverse(this, executeFunc);\n    }\n};\n\nNode.prototype.traversePostOrder = function(parent, executeFunc) {\n    for (var i = 0, len = this.children.length; i < len; i++) {\n        this.children[i].traversePostOrder(this, executeFunc);\n    }\n    executeFunc(this, parent);\n};\n\nNode.prototype.traverseTwoExecFun = function(parent, execFunPre, execFunPos) {\n    execFunPre(this, parent);\n    for (var i = 0, len = this.children.length; i < len; i++) {\n        this.children[i].traverseTwoExecFun(this, execFunPre, execFunPos);\n    }\n    execFunPos(this, parent);\n};\n\nvar TRSMatrix = mat4.create();\n\nNode.prototype.getTransformMatrixFromTRS = function(translation, rotation, scale) {\n\n    this.translation = translation !== undefined ? vec3.fromValues(translation[0], translation[1], translation[2]) : vec3.fromValues(0, 0, 0);\n    this.rotation = rotation !== undefined ? vec4.fromValues(rotation[0], rotation[1], rotation[2], rotation[3]) : vec4.fromValues(0, 0, 0, 1);\n    this.scale = scale !== undefined ? vec3.fromValues(scale[0], scale[1], scale[2]) : vec3.fromValues(1, 1, 1);\n\n    this.updateMatrixFromTRS();\n};\n\nNode.prototype.updateMatrixFromTRS = function() {\n    mat4.fromRotationTranslation(TRSMatrix, this.rotation, this.translation);\n    mat4.scale(this.matrix, TRSMatrix, this.scale);\n};\n\n\n\nvar Mesh = MinimalGLTFLoader.Mesh = function (m, meshID) {\n    this.meshID = meshID;\n    this.name = m.name !== undefined ? m.name : null;\n\n    this.primitives = [];   // required\n    \n\n\n    // bounding box (runtime stuff)\n    this.boundingBox = null;\n\n    var p, primitive, accessor;\n\n    for (var i = 0, len = m.primitives.length; i < len; ++i) {\n        p = m.primitives[i];\n        primitive = new Primitive(curLoader.glTF, p);\n        this.primitives.push(primitive);\n\n        // bounding box related\n        if (primitive.boundingBox) {\n            if (!this.boundingBox) {\n                this.boundingBox = new BoundingBox();\n            }\n            this.boundingBox.updateBoundingBox(primitive.boundingBox);\n        }\n    }\n\n    if (this.boundingBox) {\n        this.boundingBox.calculateTransform();\n    }\n\n\n    // TODO: weights for morph targets\n    this.weights = m.weights !== undefined ? m.weights : null;\n\n    this.extensions = m.extensions !== undefined ? m.extensions : null;\n    this.extras = m.extras !== undefined ? m.extras : null;\n    \n};\n\nvar Primitive = MinimalGLTFLoader.Primitive = function (gltf, p) {\n    // <attribute name, accessor id>, required\n    // get hook up with accessor object in _postprocessing\n    this.attributes = p.attributes;\n    this.indices = p.indices !== undefined ? p.indices : null;  // accessor id\n\n    var attname;\n    if (p.extensions !== undefined) {\n        if (p.extensions.gl_avatar !== undefined && curLoader.enableGLAvatar === true) {\n            if (p.extensions.gl_avatar.attributes) {\n                for ( attname in p.extensions.gl_avatar.attributes ) {\n                    this.attributes[attname] = p.extensions.gl_avatar.attributes[attname];\n                }\n            }\n        }\n    }\n\n    \n    if (this.indices !== null) {\n        this.indicesComponentType = gltf.json.accessors[this.indices].componentType;\n        this.indicesLength = gltf.json.accessors[this.indices].count;\n        this.indicesOffset = (gltf.json.accessors[this.indices].byteOffset || 0);\n    } else {\n        // assume 'POSITION' is there\n        this.drawArraysCount = gltf.json.accessors[this.attributes.POSITION].count;\n        this.drawArraysOffset = (gltf.json.accessors[this.attributes.POSITION].byteOffset || 0);\n    }\n\n    \n    // hook up accessor object\n    for ( attname in this.attributes ) {\n        this.attributes[attname] = gltf.accessors[ this.attributes[attname] ];\n    }\n\n\n    this.material = p.material !== undefined ? gltf.materials[p.material] : null;\n\n\n    this.mode = p.mode !== undefined ? p.mode : 4; // default: gl.TRIANGLES\n\n    \n\n    // morph related\n    this.targets = p.targets;\n\n\n    this.extensions = p.extensions !== undefined ? p.extensions : null;\n    this.extras = p.extras !== undefined ? p.extras : null;\n\n\n    // ----gl run time related\n    this.vertexArray = null;    //vao\n    \n    this.vertexBuffer = null;\n    this.indexBuffer = null;\n\n\n    this.shader = null;\n\n\n    this.boundingBox = null;\n    if (this.attributes.POSITION !== undefined) {\n        var accessor = this.attributes.POSITION;\n        if (accessor.max) {\n            // @todo: handle cases where no min max are provided\n\n            // assume vec3\n            if (accessor.type === 'VEC3') {\n                this.boundingBox = new BoundingBox(\n                    vec3.fromValues(accessor.min[0], accessor.min[1], accessor.min[2]),\n                    vec3.fromValues(accessor.max[0], accessor.max[1], accessor.max[2]),\n                    false\n                );\n                this.boundingBox.calculateTransform();\n                \n\n                \n            }\n            \n        }\n    }\n};\n\n\nvar Texture = MinimalGLTFLoader.Texture = function (t) {\n    this.name = t.name !== undefined ? t.name : null;\n    this.sampler = t.sampler !== undefined ? curLoader.glTF.samplers[t.sampler] : null;\n    this.source = t.source !== undefined ? curLoader.glTF.images[t.source] : null;\n\n    this.extensions = t.extensions !== undefined ? t.extensions : null;\n    this.extras = t.extras !== undefined ? t.extras : null;\n\n    // runtime\n    this.texture = null;\n};\n\nTexture.prototype.createTexture = function(gl) {\n    this.texture = gl.createTexture();\n    gl.bindTexture(gl.TEXTURE_2D, this.texture);\n    gl.texImage2D(\n        gl.TEXTURE_2D,  // assumed\n        0,        // Level of details\n        // gl.RGB, // Format\n        // gl.RGB,\n        gl.RGBA, // Format\n        gl.RGBA,\n        gl.UNSIGNED_BYTE, // Size of each channel\n        this.source\n    );\n    gl.generateMipmap(gl.TEXTURE_2D);\n    gl.bindTexture(gl.TEXTURE_2D, null);\n};\n\nvar Sampler = MinimalGLTFLoader.Sampler = function (s) {\n    this.name = s.name !== undefined ? s.name : null;\n    this.magFilter = s.magFilter !== undefined ? s.magFilter : null;\n    this.minFilter = s.minFilter !== undefined ? s.minFilter : null;\n    this.wrapS = s.wrapS !== undefined ? s.wrapS : 10497;\n    this.wrapT = s.wrapT !== undefined ? s.wrapT : 10497;\n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n    this.sampler = null;\n};\n\nSampler.prototype.createSampler = function(gl) {\n    this.sampler = gl.createSampler();\n    if (this.minFilter) {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MIN_FILTER, this.minFilter);\n    } else {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);\n    }\n    if (this.magFilter) {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MAG_FILTER, this.magFilter);\n    } else {\n        gl.samplerParameteri(this.sampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n    }\n    gl.samplerParameteri(this.sampler, gl.TEXTURE_WRAP_S, this.wrapS);\n    gl.samplerParameteri(this.sampler, gl.TEXTURE_WRAP_T, this.wrapT);\n};\n\n// Sampler.prototype.bindSampler = function(i, gl) {\n//     gl.bindSampler(i, this.sampler);\n// }\n\nvar TextureInfo = MinimalGLTFLoader.TextureInfo = function (json) {\n    this.index = json.index;\n    this.texCoord = json.texCoord !== undefined ? json.texCoord : 0 ;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar PbrMetallicRoughness = MinimalGLTFLoader.PbrMetallicRoughness = function (json) {\n    this.baseColorFactor = json.baseColorFactor !== undefined ? json.baseColorFactor : [1, 1, 1, 1];\n    this.baseColorTexture = json.baseColorTexture !== undefined ? new TextureInfo(json.baseColorTexture): null;\n    this.metallicFactor = json.metallicFactor !== undefined ? json.metallicFactor : 1 ;\n    this.roughnessFactor = json.roughnessFactor !== undefined ? json.roughnessFactor : 1 ;\n    this.metallicRoughnessTexture = json.metallicRoughnessTexture !== undefined ? new TextureInfo(json.metallicRoughnessTexture): null;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar NormalTextureInfo = MinimalGLTFLoader.NormalTextureInfo = function (json) {\n    this.index = json.index;\n    this.texCoord = json.texCoord !== undefined ? json.texCoord : 0 ;\n    this.scale = json.scale !== undefined ? json.scale : 1 ;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar OcclusionTextureInfo = MinimalGLTFLoader.OcclusionTextureInfo = function (json) {\n    this.index = json.index;\n    this.texCoord = json.texCoord !== undefined ? json.texCoord : 0 ;\n    this.strength = json.strength !== undefined ? json.strength : 1 ;\n\n    this.extensions = json.extensions !== undefined ? json.extensions : null;\n    this.extras = json.extras !== undefined ? json.extras : null;\n};\n\nvar Material = MinimalGLTFLoader.Material = function (m) {\n    this.name = m.name !== undefined ? m.name : null;\n    \n    this.pbrMetallicRoughness = m.pbrMetallicRoughness !== undefined ? new PbrMetallicRoughness( m.pbrMetallicRoughness ) : new PbrMetallicRoughness({\n        baseColorFactor: [1, 1, 1, 1],\n        metallicFactor: 1,\n        metallicRoughnessTexture: 1\n    });\n    // this.normalTexture = m.normalTexture !== undefined ? m.normalTexture : null;\n    this.normalTexture = m.normalTexture !== undefined ? new NormalTextureInfo(m.normalTexture) : null;\n    this.occlusionTexture = m.occlusionTexture !== undefined ? new OcclusionTextureInfo(m.occlusionTexture) : null;\n    this.emissiveTexture = m.emissiveTexture !== undefined ? new TextureInfo(m.emissiveTexture) : null;\n\n    this.emissiveFactor = m.emissiveFactor !== undefined ? m.emissiveFactor : [0, 0, 0];\n    this.alphaMode = m.alphaMode !== undefined ? m.alphaMode : \"OPAQUE\";\n    this.alphaCutoff = m.alphaCutoff !== undefined ? m.alphaCutoff : 0.5;\n    this.doubleSided = m.doubleSided || false;\n\n    this.extensions = m.extensions !== undefined ? m.extensions : null;\n    this.extras = m.extras !== undefined ? m.extras : null;\n};\n\n\nvar Skin = MinimalGLTFLoader.Skin = function (gltf, s, skinID) {\n    this.name = s.name !== undefined ? s.name : null;\n    this.skinID = skinID;\n\n    this.joints = new Array(s.joints.length);   // required\n    var i, len;\n    for (i = 0, len = this.joints.length; i < len; i++) {\n        this.joints[i] = gltf.nodes[s.joints[i]];\n    }\n\n    this.skeleton = s.skeleton !== undefined ? gltf.nodes[s.skeleton] : null;\n    this.inverseBindMatrices = s.inverseBindMatrices !== undefined ? gltf.accessors[s.inverseBindMatrices] : null;\n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n\n    // @tmp: runtime stuff should be taken care of renderer\n    // since glTF model should only store info\n    // runtime can have multiple instances of this glTF models\n    this.uniformBlockID = globalUniformBlockID++;\n\n    if (this.inverseBindMatrices) {\n        // should be a mat4\n        this.inverseBindMatricesData = _getAccessorData(this.inverseBindMatrices);\n        // this.inverseBindMatricesMat4 = mat4.fromValues(this.inverseBindMatricesData);\n\n        this.inverseBindMatrix = [];  // for calculation\n        this.jointMatrixUniformBuffer = null;\n        // this.jointMatrixUnidormBufferData = _arrayBuffer2TypedArray(\n        //     this.inverseBindMatricesData, \n        //     0, \n        //     this.inverseBindMatricesData.length, \n        //     this.inverseBindMatrices.componentType\n        // );      // for copy to UBO\n\n        // @tmp: fixed length to coordinate with shader, for copy to UBO\n        this.jointMatrixUnidormBufferData = new Float32Array(NUM_MAX_JOINTS * 16);\n\n        for (i = 0, len = this.inverseBindMatricesData.length; i < len; i += 16) {\n            this.inverseBindMatrix.push(mat4.fromValues(\n                this.inverseBindMatricesData[i],\n                this.inverseBindMatricesData[i + 1],\n                this.inverseBindMatricesData[i + 2],\n                this.inverseBindMatricesData[i + 3],\n                this.inverseBindMatricesData[i + 4],\n                this.inverseBindMatricesData[i + 5],\n                this.inverseBindMatricesData[i + 6],\n                this.inverseBindMatricesData[i + 7],\n                this.inverseBindMatricesData[i + 8],\n                this.inverseBindMatricesData[i + 9],\n                this.inverseBindMatricesData[i + 10],\n                this.inverseBindMatricesData[i + 11],\n                this.inverseBindMatricesData[i + 12],\n                this.inverseBindMatricesData[i + 13],\n                this.inverseBindMatricesData[i + 14],\n                this.inverseBindMatricesData[i + 15]\n            ));\n        }\n    }\n\n};\n\nvar SkinLink = MinimalGLTFLoader.SkinLink = function (gltf, linkedSkin, inverseBindMatricesAccessorID) {\n    this.isLink = true;\n\n    if (!gltf.skins) {\n        gltf.skins = [];\n    }\n    gltf.skins.push(this);\n\n    this.name = linkedSkin.name;\n    // this.skinID = linkedSkin.skinID;   // use this for uniformblock id\n    // this.skinID = gltf.skins.length - 1;\n    // this.skinID = curLoader.skeletonGltf.skins.length + gltf.skins.length - 1;\n    this.skinID = gltf.skins.length - 1;\n\n    this.joints = linkedSkin.joints;\n\n    this.skeleton = linkedSkin.skeleton;\n    this.inverseBindMatrices = inverseBindMatricesAccessorID !== undefined ? gltf.accessors[inverseBindMatricesAccessorID] : null;\n\n    // @tmp: runtime stuff should be taken care of renderer\n    // since glTF model should only store info\n    // runtime can have multiple instances of this glTF models\n    this.uniformBlockID = globalUniformBlockID++;\n    if (this.inverseBindMatrices) {\n        // should be a mat4\n        this.inverseBindMatricesData = _getAccessorData(this.inverseBindMatrices);\n        // this.inverseBindMatricesMat4 = mat4.fromValues(this.inverseBindMatricesData);\n\n        this.inverseBindMatrix = [];  // for calculation\n        this.jointMatrixUniformBuffer = null;\n        // this.jointMatrixUnidormBufferData = _arrayBuffer2TypedArray(\n        //     this.inverseBindMatricesData, \n        //     0, \n        //     this.inverseBindMatricesData.length, \n        //     this.inverseBindMatrices.componentType\n        // );      // for copy to UBO\n\n        // @tmp: fixed length to coordinate with shader, for copy to UBO\n        this.jointMatrixUnidormBufferData = new Float32Array(NUM_MAX_JOINTS * 16);\n\n        for (var i = 0, len = this.inverseBindMatricesData.length; i < len; i += 16) {\n            this.inverseBindMatrix.push(mat4.fromValues(\n                this.inverseBindMatricesData[i],\n                this.inverseBindMatricesData[i + 1],\n                this.inverseBindMatricesData[i + 2],\n                this.inverseBindMatricesData[i + 3],\n                this.inverseBindMatricesData[i + 4],\n                this.inverseBindMatricesData[i + 5],\n                this.inverseBindMatricesData[i + 6],\n                this.inverseBindMatricesData[i + 7],\n                this.inverseBindMatricesData[i + 8],\n                this.inverseBindMatricesData[i + 9],\n                this.inverseBindMatricesData[i + 10],\n                this.inverseBindMatricesData[i + 11],\n                this.inverseBindMatricesData[i + 12],\n                this.inverseBindMatricesData[i + 13],\n                this.inverseBindMatricesData[i + 14],\n                this.inverseBindMatricesData[i + 15]\n            ));\n        }\n    }\n\n    \n\n};\n\n\n\n\n// animation has no potential plan for progressive rendering I guess\n// so everything happens after all buffers are loaded\n\nvar Target = MinimalGLTFLoader.Target = function (t) {\n    this.nodeID = t.node !== undefined ? t.node : null ;  //id, to be hooked up to object later\n    this.path = t.path;     //required, string\n\n    this.extensions = t.extensions !== undefined ? t.extensions : null;\n    this.extras = t.extras !== undefined ? t.extras : null;\n};\n\nvar Channel = MinimalGLTFLoader.Channel = function (c, animation) {\n    this.sampler = animation.samplers[c.sampler];   //required\n    this.target = new Target(c.target);     //required\n\n    this.extensions = c.extensions !== undefined ? c.extensions : null;\n    this.extras = c.extras !== undefined ? c.extras : null;\n};\n\nvar AnimationSampler = MinimalGLTFLoader.AnimationSampler = function (gltf, s) {\n    this.input = gltf.accessors[s.input];   //required, accessor object\n    this.output = gltf.accessors[s.output]; //required, accessor object\n\n    this.inputTypedArray = _getAccessorData(this.input);\n    this.outputTypedArray = _getAccessorData(this.output);\n\n\n    // \"LINEAR\"\n    // \"STEP\"\n    // \"CATMULLROMSPLINE\"\n    // \"CUBICSPLINE\"\n    this.interpolation = s.interpolation !== undefined ? s.interpolation : 'LINEAR' ;\n    \n\n    this.extensions = s.extensions !== undefined ? s.extensions : null;\n    this.extras = s.extras !== undefined ? s.extras : null;\n\n    // ------- extra runtime info -----------\n    // runtime status thing\n    this.curIdx = 0;\n    // this.curValue = 0;\n    this.curValue = vec4.create();\n    this.endT = this.inputTypedArray[this.inputTypedArray.length - 1];\n    this.inputMax = this.endT - this.inputTypedArray[0];\n};\n\nvar animationOutputValueVec4a = vec4.create();\nvar animationOutputValueVec4b = vec4.create();\n\nAnimationSampler.prototype.getValue = function (t) {\n    if (t > this.endT) {\n        t -= this.inputMax * Math.ceil((t - this.endT) / this.inputMax);\n        this.curIdx = 0;\n    }\n\n    var len = this.inputTypedArray.length;\n    while (this.curIdx <= len - 2 && t >= this.inputTypedArray[this.curIdx + 1]) {\n        this.curIdx++;\n    }\n\n\n    if (this.curIdx >= len - 1) {\n        // loop\n        t -= this.inputMax;\n        this.curIdx = 0;\n    }\n\n    // @tmp: assume no stride\n    var count = Type2NumOfComponent[this.output.type];\n    \n    var v4lerp = count === 4 ? quat.slerp: vec4.lerp;\n\n    var i = this.curIdx;\n    var o = i * count;\n    var on = o + count;\n\n    var u = Math.max( 0, t - this.inputTypedArray[i] ) / (this.inputTypedArray[i+1] - this.inputTypedArray[i]);\n\n    for (var j = 0; j < count; j++ ) {\n        animationOutputValueVec4a[j] = this.outputTypedArray[o + j];\n        animationOutputValueVec4b[j] = this.outputTypedArray[on + j];\n    }\n\n    switch(this.interpolation) {\n        case 'LINEAR': \n        v4lerp(this.curValue, animationOutputValueVec4a, animationOutputValueVec4b, u);\n        break;\n\n        default:\n        break;\n    }\n};\n\n\n\nvar Animation = MinimalGLTFLoader.Animation = function (gltf, a) {\n    this.name = a.name !== undefined ? a.name : null;\n\n    var i, len;\n\n    \n\n    this.samplers = []; // required, array of animation sampler\n    \n    for (i = 0, len = a.samplers.length; i < len; i++) {\n        this.samplers[i] = new AnimationSampler(gltf, a.samplers[i]);\n    }\n\n    this.channels = [];     //required, array of channel\n    \n    for (i = 0, len = a.channels.length; i < len; i++) {\n        this.channels[i] = new Channel(a.channels[i], this);\n    }\n\n    this.extensions = a.extensions !== undefined ? a.extensions : null;\n    this.extras = a.extras !== undefined ? a.extras : null;\n};\n\n\n/**\n * \n */\nvar glTFModel = MinimalGLTFLoader.glTFModel = function (gltf) {\n    this.json = gltf;\n    this.defaultScene = gltf.scene !== undefined ? gltf.scene : 0;\n\n    this.version = Number(gltf.asset.version);\n\n    if (gltf.accessors) {\n        this.accessors = new Array(gltf.accessors.length);\n    }\n\n    if (gltf.bufferViews) {\n        this.bufferViews = new Array(gltf.bufferViews.length);\n    }\n\n    if (gltf.scenes) {\n        this.scenes = new Array(gltf.scenes.length);   // store Scene object\n    }\n\n    if (gltf.nodes) {\n        this.nodes = new Array(gltf.nodes.length);    // store Node object\n    }\n\n    if (gltf.meshes) {\n        this.meshes = new Array(gltf.meshes.length);    // store mesh object\n    }\n\n    if (gltf.materials) {\n        this.materials = new Array(gltf.materials.length);  // store material object\n    }\n\n    if (gltf.textures) {\n        this.textures = new Array(gltf.textures.length);\n    }\n\n    if (gltf.samplers) {\n        this.samplers = new Array(gltf.samplers.length);\n    }\n\n    if (gltf.images) {\n        this.images = new Array(gltf.images.length);\n    }\n\n\n    if (gltf.skins) {\n        this.skins = new Array(gltf.skins.length);\n    }\n\n    if (gltf.animations) {\n        this.animations = new Array(gltf.animations.length);\n    }\n\n    if (gltf.cameras) {\n        this.cameras = new Array(gltf.cameras.length);\n    }\n\n    this.extensions = gltf.extensions !== undefined ? gltf.extensions : null;\n    this.extras = gltf.extras !== undefined ? gltf.extras : null;\n\n};\n\n\n\nvar gl;\n\nvar glTFLoader = MinimalGLTFLoader.glTFLoader = function (glContext) {\n    gl = glContext !== undefined ? glContext : null;\n    this._init();\n    this.glTF = null;\n\n    this.enableGLAvatar = false;\n    this.linkSkeletonGltf = null;\n};\n\nglTFLoader.prototype._init = function() {\n    this._loadDone = false;\n\n    this._bufferRequested = 0;\n    this._bufferLoaded = 0;\n    this._buffers = [];\n    this._bufferTasks = {};\n\n    this._shaderRequested = 0;\n    this._shaderLoaded = 0;\n\n    this._imageRequested = 0;\n    this._imageLoaded = 0;\n\n    this._pendingTasks = 0;\n    this._finishedPendingTasks = 0;\n\n    this.onload = null;\n\n    curLoader = this;\n};\n\n\nglTFLoader.prototype._checkComplete = function () {\n    if (this._bufferRequested == this._bufferLoaded && \n        // this._shaderRequested == this._shaderLoaded && \n        this._imageRequested == this._imageLoaded \n        // && other resources finish loading\n        ) {\n        this._loadDone = true;\n    }\n\n    if (this._loadDone && this._pendingTasks == this._finishedPendingTasks) {\n\n        this._postprocess();\n\n        this.onload(this.glTF);\n    }\n};\n\nglTFLoader.prototype.loadGLTF_GL_Avatar_Skin = function (uri, skeletonGltf, callback) {\n    this.enableGLAvatar = true;\n    this.skeletonGltf = skeletonGltf;\n\n    this.loadGLTF(uri, callback);\n};\n\n/**\n * load a glTF model\n * \n * @param {String} uri uri of the .glTF file. Other resources (bins, images) are assumed to be in the same base path\n * @param {Function} callback the onload callback function\n */\nglTFLoader.prototype.loadGLTF = function (uri, callback) {\n\n    this._init();\n\n    this.onload = callback || function(glTF) {\n        console.log('glTF model loaded.');\n        console.log(glTF);\n    };\n    \n\n    this.baseUri = _getBaseUri(uri);\n\n    var loader = this;\n\n    _loadJSON(uri, function (response) {\n        // Parse JSON string into object\n        var json = JSON.parse(response);\n\n        loader.glTF = new glTFModel(json);\n\n        var bid;\n\n        var loadArrayBufferCallback = function (resource) {\n            \n            loader._buffers[bid] = resource;\n            loader._bufferLoaded++;\n            if (loader._bufferTasks[bid]) {\n                var i,len;\n                for (i = 0, len = loader._bufferTasks[bid].length; i < len; ++i) {\n                    (loader._bufferTasks[bid][i])(resource);\n                }\n            }\n            loader._checkComplete();\n\n        };\n\n        // Launch loading resources task: buffers, etc.\n        if (json.buffers) {\n            for (bid in json.buffers) {\n\n                loader._bufferRequested++;\n\n                _loadArrayBuffer(loader.baseUri + json.buffers[bid].uri, loadArrayBufferCallback);\n\n            }\n        }\n\n        // load images\n        var loadImageCallback = function (img, iid) {\n            loader._imageLoaded++;\n            loader.glTF.images[iid] = img;\n            loader._checkComplete();\n        };\n\n        var iid;\n\n        if (json.images) {\n            for (iid in json.images) {\n                loader._imageRequested++;\n                _loadImage(loader.baseUri + json.images[iid].uri, iid, loadImageCallback);\n            }\n        }\n\n        loader._checkComplete();\n    });\n};\n\n\nglTFLoader.prototype._postprocess = function () {\n    // if there's no plan for progressive loading (streaming)\n    // than simply everything should be placed here\n    \n    // console.log('finish loading all assets, do a second pass postprocess');\n    \n    curLoader = this;\n\n    var i, leni, j, lenj;\n\n    var scene, s;\n    var node;\n    var mesh, primitive, accessor;\n\n    // cameras\n    if (this.glTF.cameras) {\n        for (i = 0, leni = this.glTF.cameras.length; i < leni; i++) {\n            this.glTF.cameras[i] = new Camera(this.glTF.json.cameras[i]);\n        }\n    }\n\n    // bufferviews\n    if (this.glTF.bufferViews) {\n        for (i = 0, leni = this.glTF.bufferViews.length; i < leni; i++) {\n            this.glTF.bufferViews[i] = new BufferView(this.glTF.json.bufferViews[i], this._buffers[ this.glTF.json.bufferViews[i].buffer ]);\n        }\n    }\n\n    // accessors\n    if (this.glTF.accessors) {\n        for (i = 0, leni = this.glTF.accessors.length; i < leni; i++) {\n            this.glTF.accessors[i] = new Accessor(this.glTF.json.accessors[i], this.glTF.bufferViews[ this.glTF.json.accessors[i].bufferView ]);\n        }\n    }\n\n    // load all materials\n    if (this.glTF.materials) {\n        for (i = 0, leni = this.glTF.materials.length; i < leni; i++) {\n            this.glTF.materials[i] = new Material(this.glTF.json.materials[i]);\n        }\n    }\n\n    // load all samplers \n    if (this.glTF.samplers) {\n        for (i = 0, leni = this.glTF.samplers.length; i < leni; i++) {\n            this.glTF.samplers[i] = new Sampler(this.glTF.json.samplers[i]);\n        } \n    }\n\n    // load all textures\n    if (this.glTF.textures) {\n        for (i = 0, leni = this.glTF.textures.length; i < leni; i++) {\n            this.glTF.textures[i] = new Texture(this.glTF.json.textures[i]);\n        }\n    }\n\n    // mesh\n    for (i = 0, leni = this.glTF.meshes.length; i < leni; i++) {\n        this.glTF.meshes[i] = new Mesh(this.glTF.json.meshes[i], i);\n    }\n\n    // node\n    for (i = 0, leni = this.glTF.nodes.length; i < leni; i++) {\n        this.glTF.nodes[i] = new Node(this.glTF.json.nodes[i], i);\n    }\n\n    // node: hook up children\n    for (i = 0, leni = this.glTF.nodes.length; i < leni; i++) {\n        node = this.glTF.nodes[i];\n        for (j = 0, lenj = node.children.length; j < lenj; j++) {\n            node.children[j] = this.glTF.nodes[ node.children[j] ];\n        }\n    }\n\n    // scene Bounding box\n    var nodeMatrix = new Array(this.glTF.nodes.length);\n    for(i = 0, leni = nodeMatrix.length; i < leni; i++) {\n        nodeMatrix[i] = mat4.create();\n    }\n\n    function execUpdateTransform(n, parent) {\n        var tmpMat4 = nodeMatrix[n.nodeID];\n\n        if (parent !== null) {\n            mat4.mul(tmpMat4, nodeMatrix[parent.nodeID], n.matrix);\n        } else {\n            mat4.copy(tmpMat4, n.matrix);\n        }\n    }\n\n    function execUpdateBBox(n, parent){\n        var tmpMat4 = nodeMatrix[n.nodeID];\n        var parentBVH;\n\n        if (parent !== null) {\n            parentBVH = parent.bvh;\n        } else {\n            parentBVH = scene.boundingBox;\n        }\n\n        if (n.mesh) {\n            mesh = n.mesh;\n            if (mesh.boundingBox) {\n\n                n.aabb = BoundingBox.getAABBFromOBB(mesh.boundingBox, tmpMat4);\n\n                if (n.children.length === 0) {\n                    // n.bvh = n.aabb;\n                    vec3.copy(n.bvh.min, n.aabb.min);\n                    vec3.copy(n.bvh.max, n.aabb.max);\n                }\n            }\n        }\n\n        vec3.min(parentBVH.min, parentBVH.min, n.bvh.min);\n        vec3.max(parentBVH.max, parentBVH.max, n.bvh.max);\n    }\n\n\n    for (i = 0, leni = this.glTF.scenes.length; i < leni; i++) {\n        scene = this.glTF.scenes[i] = new Scene(this.glTF, this.glTF.json.scenes[i]);\n\n        scene.boundingBox = new BoundingBox();\n\n\n        for (j = 0, lenj = scene.nodes.length; j < lenj; j++) {\n            node = scene.nodes[j];\n            // node.traverse(null, execUpdateBBox);\n            node.traverseTwoExecFun(null, execUpdateTransform, execUpdateBBox);\n        }\n\n        scene.boundingBox.calculateTransform();\n    }\n\n\n    for (j = 0, lenj = this.glTF.nodes.length; j < lenj; j++) {\n        node = this.glTF.nodes[j];\n        if (node.bvh !== null) {\n            node.bvh.calculateTransform();\n        }\n    }\n\n\n\n    // load animations (when all accessors are loaded correctly)\n    if (this.glTF.animations) {\n        for (i = 0, leni = this.glTF.animations.length; i < leni; i++) {\n            this.glTF.animations[i] = new Animation(this.glTF, this.glTF.json.animations[i]);\n        }\n    }\n\n    var joints;\n    // if (this.glTF.skins) {\n    if (this.glTF.json.skins) {\n        for (i = 0, leni = this.glTF.skins.length; i < leni; i++) {\n            this.glTF.skins[i] = new Skin(this.glTF, this.glTF.json.skins[i], i);\n            \n\n            joints = this.glTF.skins[i].joints;\n            for (j = 0, lenj = joints.length; j < lenj; j++) {\n                // this.glTF.nodes[ joints[j] ].jointID = j;\n                joints[j].jointID = j;\n            }\n        } \n    }\n\n    for (i = 0, leni = this.glTF.nodes.length; i < leni; i++) {\n        node = this.glTF.nodes[i];\n        if (node.skin !== null) {\n            if (typeof node.skin == 'number') {\n                // usual skin, hook up\n                node.skin = this.glTF.skins[ node.skin ];\n            } else {\n                // assume gl_avatar is in use\n                // do nothing\n            }\n            \n        }\n    } \n    \n\n};\n\n\n// TODO: get from gl context\nvar ComponentType2ByteSize = {\n    5120: 1, // BYTE\n    5121: 1, // UNSIGNED_BYTE\n    5122: 2, // SHORT\n    5123: 2, // UNSIGNED_SHORT\n    5126: 4  // FLOAT\n};\n\nvar Type2NumOfComponent = {\n    'SCALAR': 1,\n    'VEC2': 2,\n    'VEC3': 3,\n    'VEC4': 4,\n    'MAT2': 4,\n    'MAT3': 9,\n    'MAT4': 16\n};\n\n\n// ------ Scope limited private util functions---------------\n\n\n// for animation use\nfunction _arrayBuffer2TypedArray(buffer, byteOffset, countOfComponentType, componentType) {\n    switch(componentType) {\n        // @todo: finish\n        case 5122: return new Int16Array(buffer, byteOffset, countOfComponentType);\n        case 5123: return new Uint16Array(buffer, byteOffset, countOfComponentType);\n        case 5124: return new Int32Array(buffer, byteOffset, countOfComponentType);\n        case 5125: return new Uint32Array(buffer, byteOffset, countOfComponentType);\n        case 5126: return new Float32Array(buffer, byteOffset, countOfComponentType);\n        default: return null; \n    }\n}\n\nfunction _getAccessorData(accessor) {\n    return _arrayBuffer2TypedArray(\n        accessor.bufferView.data, \n        accessor.byteOffset, \n        accessor.count * Type2NumOfComponent[accessor.type],\n        accessor.componentType\n        );\n}\n\nfunction _getBaseUri(uri) {\n    \n    // https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Core/getBaseUri.js\n    \n    var basePath = '';\n    var i = uri.lastIndexOf('/');\n    if(i !== -1) {\n        basePath = uri.substring(0, i + 1);\n    }\n    \n    return basePath;\n}\n\nfunction _loadJSON(src, callback) {\n\n    // native json loading technique from @KryptoniteDove:\n    // http://codepen.io/KryptoniteDove/post/load-json-file-locally-using-pure-javascript\n\n    var xobj = new XMLHttpRequest();\n    xobj.overrideMimeType(\"application/json\");\n    xobj.open('GET', src, true);\n    xobj.onreadystatechange = function () {\n        if (xobj.readyState == 4 && // Request finished, response ready\n            xobj.status == \"200\") { // Status OK\n            callback(xobj.responseText, this);\n        }\n    };\n    xobj.send(null);\n}\n\nfunction _loadArrayBuffer(url, callback) {\n    var xobj = new XMLHttpRequest();\n    xobj.responseType = 'arraybuffer';\n    xobj.open('GET', url, true);\n    xobj.onreadystatechange = function () {\n        if (xobj.readyState == 4 && // Request finished, response ready\n            xobj.status == \"200\") { // Status OK\n            var arrayBuffer = xobj.response;\n            if (arrayBuffer && callback) {\n                callback(arrayBuffer);\n            }\n        }\n    };\n    xobj.send(null);\n}\n\nfunction _loadImage(url, iid, onload) {\n    var img = new Image();\n    img.crossOrigin = \"Anonymous\";\n    img.src = url;\n    img.onload = function() {\n        onload(img, iid);\n    };\n}\n\n// export { MinimalGLTFLoader };\nexport { glTFLoader };"
  },
  {
    "path": "src/shaders/fs-bbox.glsl",
    "content": "#version 300 es\n#define FRAG_COLOR_LOCATION 0\n\nprecision highp float;\nprecision highp int;\n\nlayout(location = FRAG_COLOR_LOCATION) out vec4 color;\n\nvoid main()\n{\n    color = vec4(1.0, 0.0, 0.0, 1.0);\n}"
  },
  {
    "path": "src/shaders/fs-cube-map.glsl",
    "content": "#version 300 es\nprecision highp float;\nprecision highp int;\n\nuniform samplerCube u_environment;\n\nin vec3 texcoord;\n\nout vec4 color;\n\nvoid main()\n{\n    color = texture(u_environment, texcoord);\n}"
  },
  {
    "path": "src/shaders/fs-pbr-master.glsl",
    "content": "#define FRAG_COLOR_LOCATION 0\r\n\r\n// reference: https://github.com/KhronosGroup/glTF-WebGL-PBR/blob/master/shaders/pbr-frag.glsl\r\n\r\nprecision highp float;\r\nprecision highp int;\r\n\r\n// IBL\r\nuniform samplerCube u_DiffuseEnvSampler;\r\nuniform samplerCube u_SpecularEnvSampler;\r\nuniform sampler2D u_brdfLUT;\r\n\r\n// Metallic-roughness material\r\n\r\n// base color\r\nuniform vec4 u_baseColorFactor;\r\n#ifdef HAS_BASECOLORMAP\r\nuniform sampler2D u_baseColorTexture;\r\n#endif\r\n\r\n// normal map\r\n#ifdef HAS_NORMALMAP\r\nuniform sampler2D u_normalTexture;\r\nuniform float u_normalTextureScale;\r\n#endif\r\n\r\n// emmisve map\r\n#ifdef HAS_EMISSIVEMAP\r\nuniform sampler2D u_emissiveTexture;\r\nuniform vec3 u_emissiveFactor;\r\n#endif\r\n\r\n// metal roughness\r\n#ifdef HAS_METALROUGHNESSMAP\r\nuniform sampler2D u_metallicRoughnessTexture;\r\n#endif\r\nuniform float u_metallicFactor;\r\nuniform float u_roughnessFactor;\r\n\r\n// occlusion texture\r\n#ifdef HAS_OCCLUSIONMAP\r\nuniform sampler2D u_occlusionTexture;\r\nuniform float u_occlusionStrength;\r\n#endif\r\n\r\nin vec3 v_position;\r\nin vec3 v_normal;\r\nin vec2 v_uv;\r\n\r\nlayout(location = FRAG_COLOR_LOCATION) out vec4 frag_color;\r\n\r\nstruct PBRInfo\r\n{\r\n    float NdotL;                  // cos angle between normal and light direction\r\n    float NdotV;                  // cos angle between normal and view direction\r\n    float NdotH;                  // cos angle between normal and half vector\r\n    float LdotH;                  // cos angle between light direction and half vector\r\n    float VdotH;                  // cos angle between view direction and half vector\r\n    float perceptualRoughness;    // roughness value, as authored by the model creator (input to shader)\r\n    float metalness;              // metallic value at the surface\r\n    vec3 reflectance0;            // full reflectance color (normal incidence angle)\r\n    vec3 reflectance90;           // reflectance color at grazing angle\r\n    float alphaRoughness;         // roughness mapped to a more linear change in the roughness (proposed by [2])\r\n    vec3 diffuseColor;            // color contribution from diffuse lighting\r\n    vec3 specularColor;           // color contribution from specular lighting\r\n};\r\n\r\n\r\n// vec3 applyNormalMap(vec3 geomnor, vec3 normap) {\r\n//     normap = normap * 2.0 - 1.0;\r\n//     vec3 up = normalize(vec3(0.01, 1, 0.01));\r\n//     vec3 surftan = normalize(cross(geomnor, up));\r\n//     vec3 surfbinor = cross(geomnor, surftan);\r\n//     return normap.y * surftan * u_normalTextureScale + normap.x * surfbinor * u_normalTextureScale + normap.z * geomnor;\r\n// }\r\n\r\nconst float M_PI = 3.141592653589793;\r\nconst float c_MinRoughness = 0.04;\r\n\r\n\r\n// vec3 getNormal()\r\n// {\r\n\r\n// #ifdef HAS_NORMALMAP\r\n// #ifdef HAS_TANGENTS\r\n//     vec3 n = texture(u_normalTexture, v_uv).rgb;\r\n//     n = normalize(v_TBN * (2.0 * n - 1.0) - vec3(u_normalTextureScale, u_normalTextureScale, 1.0));\r\n// #else\r\n//     vec3 n = applyNormalMap( v_normal, texture(u_normalTexture, v_uv).rgb );\r\n// #endif\r\n// #else\r\n//     vec3 n = v_normal;\r\n// #endif\r\n//     return n;\r\n\r\n// #endif\r\n// }\r\n\r\n// Find the normal for this fragment, pulling either from a predefined normal map\r\n// or from the interpolated mesh normal and tangent attributes.\r\nvec3 getNormal()\r\n{\r\n\r\n// #ifdef HAS_NORMALMAP\r\n//     vec3 n = applyNormalMap( v_normal, texture(u_normalTexture, v_uv).rgb );\r\n// #else\r\n//     vec3 n = v_normal;\r\n// #endif\r\n//     return n;\r\n\r\n\r\n    // Retrieve the tangent space matrix\r\n// #ifndef HAS_TANGENTS\r\n    vec3 pos_dx = dFdx(v_position);\r\n    vec3 pos_dy = dFdy(v_position);\r\n    vec3 tex_dx = dFdx(vec3(v_uv, 0.0));\r\n    vec3 tex_dy = dFdy(vec3(v_uv, 0.0));\r\n    vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);\r\n\r\n    vec3 ng = v_normal;\r\n// #ifdef HAS_NORMALS\r\n//     vec3 ng = normalize(v_normal);\r\n// #else\r\n//     vec3 ng = cross(pos_dx, pos_dy);\r\n// #endif\r\n\r\n    t = normalize(t - ng * dot(ng, t));\r\n    vec3 b = normalize(cross(ng, t));\r\n    mat3 tbn = mat3(t, b, ng);\r\n// #else // HAS_TANGENTS\r\n    // mat3 tbn = v_TBN;\r\n// #endif\r\n\r\n// TODO: TANGENTS\r\n\r\n#ifdef HAS_NORMALMAP\r\n    vec3 n = texture(u_normalTexture, v_uv).rgb;\r\n    n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_normalTextureScale, u_normalTextureScale, 1.0)));\r\n#else\r\n    vec3 n = tbn[2].xyz;\r\n#endif\r\n\r\n    return n;\r\n}\r\n\r\nvec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection)\r\n{\r\n    // float mipCount = 9.0; // resolution of 512x512\r\n    // float mipCount = 10.0; // resolution of 1024x1024\r\n    float mipCount = 10.0; // resolution of 256x256\r\n    float lod = (pbrInputs.perceptualRoughness * mipCount);\r\n    // retrieve a scale and bias to F0. See [1], Figure 3\r\n    vec3 brdf = texture(u_brdfLUT, vec2(pbrInputs.NdotV, 1.0 - pbrInputs.perceptualRoughness)).rgb;\r\n    vec3 diffuseLight = texture(u_DiffuseEnvSampler, n).rgb;\r\n\r\n// #ifdef USE_TEX_LOD\r\n    vec3 specularLight = texture(u_SpecularEnvSampler, reflection, lod).rgb;\r\n// #else\r\n    // vec3 specularLight = texture(u_SpecularEnvSampler, reflection).rgb;\r\n// #endif\r\n\r\n    vec3 diffuse = diffuseLight * pbrInputs.diffuseColor;\r\n    vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y);\r\n\r\n    // // For presentation, this allows us to disable IBL terms\r\n    // diffuse *= u_ScaleIBLAmbient.x;\r\n    // specular *= u_ScaleIBLAmbient.y;\r\n\r\n    return diffuse + specular;\r\n}\r\n\r\n// Basic Lambertian diffuse\r\n// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog\r\n// See also [1], Equation 1\r\nvec3 diffuse(PBRInfo pbrInputs)\r\n{\r\n    return pbrInputs.diffuseColor / M_PI;\r\n}\r\n\r\n\r\n// The following equation models the Fresnel reflectance term of the spec equation (aka F())\r\n// Implementation of fresnel from [4], Equation 15\r\nvec3 specularReflection(PBRInfo pbrInputs)\r\n{\r\n    return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);\r\n}\r\n\r\n\r\n// This calculates the specular geometric attenuation (aka G()),\r\n// where rougher material will reflect less light back to the viewer.\r\n// This implementation is based on [1] Equation 4, and we adopt their modifications to\r\n// alphaRoughness as input as originally proposed in [2].\r\nfloat geometricOcclusion(PBRInfo pbrInputs)\r\n{\r\n    float NdotL = pbrInputs.NdotL;\r\n    float NdotV = pbrInputs.NdotV;\r\n    float r = pbrInputs.alphaRoughness;\r\n\r\n    float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));\r\n    float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));\r\n    return attenuationL * attenuationV;\r\n}\r\n\r\n\r\n// The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D())\r\n// Implementation from \"Average Irregularity Representation of a Roughened Surface for Ray Reflection\" by T. S. Trowbridge, and K. P. Reitz\r\n// Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3.\r\nfloat microfacetDistribution(PBRInfo pbrInputs)\r\n{\r\n    float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;\r\n    float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;\r\n    return roughnessSq / (M_PI * f * f);\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\nvoid main()\r\n{\r\n    float perceptualRoughness = u_roughnessFactor;\r\n    float metallic = u_metallicFactor;\r\n\r\n#ifdef HAS_METALROUGHNESSMAP\r\n    // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.\r\n    // This layout intentionally reserves the 'r' channel for (optional) occlusion map data\r\n    vec4 mrSample = texture(u_metallicRoughnessTexture, v_uv);\r\n    perceptualRoughness = mrSample.g * perceptualRoughness;\r\n    metallic = mrSample.b * metallic;\r\n#endif\r\n    perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);\r\n    metallic = clamp(metallic, 0.0, 1.0);\r\n    // Roughness is authored as perceptual roughness; as is convention,\r\n    // convert to material roughness by squaring the perceptual roughness [2].\r\n    float alphaRoughness = perceptualRoughness * perceptualRoughness;\r\n\r\n\r\n    // The albedo may be defined from a base texture or a flat color\r\n#ifdef HAS_BASECOLORMAP\r\n    vec4 baseColor = texture(u_baseColorTexture, v_uv) * u_baseColorFactor;\r\n#else\r\n    vec4 baseColor = u_baseColorFactor;\r\n#endif\r\n\r\n\r\n\r\n    vec3 f0 = vec3(0.04);\r\n    vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);\r\n    diffuseColor *= 1.0 - metallic;\r\n    vec3 specularColor = mix(f0, baseColor.rgb, metallic);\r\n\r\n    // Compute reflectance.\r\n    float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\r\n\r\n\r\n    // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.\r\n    // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.\r\n    float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\r\n    vec3 specularEnvironmentR0 = specularColor.rgb;\r\n    vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;\r\n\r\n\r\n    vec3 n = getNormal();                             // normal at surface point\r\n    // vec3 v = vec3( 0.0, 0.0, 1.0 );        // Vector from surface point to camera\r\n    vec3 v = normalize(-v_position);                       // Vector from surface point to camera\r\n    // vec3 l = normalize(u_LightDirection);             // Vector from surface point to light\r\n    vec3 l = normalize(vec3( 1.0, 1.0, 1.0 ));             // Vector from surface point to light\r\n    // vec3 l = vec3( 0.0, 0.0, 1.0 );             // Vector from surface point to light\r\n    vec3 h = normalize(l+v);                          // Half vector between both l and v\r\n    vec3 reflection = -normalize(reflect(v, n));\r\n\r\n    float NdotL = clamp(dot(n, l), 0.001, 1.0);\r\n    float NdotV = abs(dot(n, v)) + 0.001;\r\n    float NdotH = clamp(dot(n, h), 0.0, 1.0);\r\n    float LdotH = clamp(dot(l, h), 0.0, 1.0);\r\n    float VdotH = clamp(dot(v, h), 0.0, 1.0);\r\n\r\n    PBRInfo pbrInputs = PBRInfo(\r\n        NdotL,\r\n        NdotV,\r\n        NdotH,\r\n        LdotH,\r\n        VdotH,\r\n        perceptualRoughness,\r\n        metallic,\r\n        specularEnvironmentR0,\r\n        specularEnvironmentR90,\r\n        alphaRoughness,\r\n        diffuseColor,\r\n        specularColor\r\n    );\r\n\r\n    // Calculate the shading terms for the microfacet specular shading model\r\n    vec3 F = specularReflection(pbrInputs);\r\n    float G = geometricOcclusion(pbrInputs);\r\n    float D = microfacetDistribution(pbrInputs);\r\n\r\n    // Calculation of analytical lighting contribution\r\n    vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs);\r\n    vec3 specContrib = max(vec3(0.0), F * G * D / (4.0 * NdotL * NdotV));\r\n    // vec3 color = NdotL * u_LightColor * (diffuseContrib + specContrib);\r\n    vec3 color = NdotL * (diffuseContrib + specContrib);    // assume light color vec3(1, 1, 1)\r\n\r\n    // Calculate lighting contribution from image based lighting source (IBL)\r\n// #ifdef USE_IBL\r\n    color += getIBLContribution(pbrInputs, n, reflection);\r\n// #endif\r\n\r\n\r\n    // Apply optional PBR terms for additional (optional) shading\r\n#ifdef HAS_OCCLUSIONMAP\r\n    float ao = texture(u_occlusionTexture, v_uv).r;\r\n    color = mix(color, color * ao, u_occlusionStrength);\r\n#endif\r\n\r\n#ifdef HAS_EMISSIVEMAP\r\n    vec3 emissive = texture(u_emissiveTexture, v_uv).rgb * u_emissiveFactor;\r\n    color += emissive;\r\n#endif\r\n\r\n    // // This section uses mix to override final color for reference app visualization\r\n    // // of various parameters in the lighting equation.\r\n    // color = mix(color, F, u_ScaleFGDSpec.x);\r\n    // color = mix(color, vec3(G), u_ScaleFGDSpec.y);\r\n    // color = mix(color, vec3(D), u_ScaleFGDSpec.z);\r\n    // color = mix(color, specContrib, u_ScaleFGDSpec.w);\r\n\r\n    // color = mix(color, diffuseContrib, u_ScaleDiffBaseMR.x);\r\n    // color = mix(color, baseColor.rgb, u_ScaleDiffBaseMR.y);\r\n    // color = mix(color, vec3(metallic), u_ScaleDiffBaseMR.z);\r\n    // color = mix(color, vec3(perceptualRoughness), u_ScaleDiffBaseMR.w);\r\n\r\n    frag_color = vec4(color, baseColor.a);\r\n}"
  },
  {
    "path": "src/shaders/vs-bbox.glsl",
    "content": "#version 300 es\n#define POSITION_LOCATION 0\n\nprecision highp float;\nprecision highp int;\n\nuniform mat4 u_MVP;\n\nlayout(location = POSITION_LOCATION) in vec3 position;\n\nvoid main()\n{\n    gl_Position = u_MVP * vec4(position, 1.0) ;\n}"
  },
  {
    "path": "src/shaders/vs-cube-map.glsl",
    "content": "#version 300 es\nprecision highp float;\nprecision highp int;\n\nuniform mat4 u_MVP;\n\nlayout(location = 0) in vec3 position;\n\nout vec3 texcoord;\n\nvoid main()\n{\n    vec4 pos = u_MVP * vec4(position, 1.0);\n    gl_Position = pos.xyww;\n    texcoord = position;\n}"
  },
  {
    "path": "src/shaders/vs-pbr-master.glsl",
    "content": "#define POSITION_LOCATION 0\r\n#define NORMAL_LOCATION 1\r\n#define TEXCOORD_0_LOCATION 2\r\n#define JOINTS_0_LOCATION 3\r\n#define JOINTS_1_LOCATION 5\r\n#define WEIGHTS_0_LOCATION 4\r\n#define WEIGHTS_1_LOCATION 6\r\n#define TANGENT_LOCATION 7\r\n\r\nprecision highp float;\r\nprecision highp int;\r\n\r\nuniform mat4 u_MVP;\r\nuniform mat4 u_MV;\r\nuniform mat4 u_MVNormal;\r\n\r\n#ifdef HAS_SKIN\r\nuniform JointMatrix\r\n{\r\n    mat4 matrix[65];\r\n} u_jointMatrix;\r\n#endif\r\n\r\nlayout(location = POSITION_LOCATION) in vec3 position;\r\nlayout(location = NORMAL_LOCATION) in vec3 normal;\r\nlayout(location = TEXCOORD_0_LOCATION) in vec2 uv;\r\n\r\n#ifdef HAS_SKIN\r\nlayout(location = JOINTS_0_LOCATION) in vec4 joint0;\r\nlayout(location = WEIGHTS_0_LOCATION) in vec4 weight0;\r\n#ifdef SKIN_VEC8\r\nlayout(location = JOINTS_1_LOCATION) in vec4 joint1;\r\nlayout(location = WEIGHTS_1_LOCATION) in vec4 weight1;\r\n#endif\r\n#endif\r\n\r\n\r\n// #ifdef HAS_TANGENTS\r\n// layout(location = TANGENT_LOCATION) in vec4 tangent;\r\n\r\n// out vec3 v_tangentW;\r\n// out vec3 v_bitangentW;\r\n// #endif\r\n\r\n\r\nout vec3 v_position;\r\nout vec3 v_normal;\r\nout vec2 v_uv;\r\n\r\nvoid main()\r\n{\r\n\r\n#ifdef HAS_SKIN\r\n    mat4 skinMatrix = \r\n        weight0.x * u_jointMatrix.matrix[int(joint0.x)] +\r\n        weight0.y * u_jointMatrix.matrix[int(joint0.y)] +\r\n        weight0.z * u_jointMatrix.matrix[int(joint0.z)] +\r\n        weight0.w * u_jointMatrix.matrix[int(joint0.w)];\r\n#ifdef SKIN_VEC8\r\n    skinMatrix +=\r\n        weight1.x * u_jointMatrix.matrix[int(joint1.x)] +\r\n        weight1.y * u_jointMatrix.matrix[int(joint1.y)] +\r\n        weight1.z * u_jointMatrix.matrix[int(joint1.z)] +\r\n        weight1.w * u_jointMatrix.matrix[int(joint1.w)];\r\n#endif\r\n#endif\r\n\r\n    v_uv = uv;\r\n\r\n#ifdef HAS_SKIN\r\n    v_normal = normalize(( u_MVNormal * transpose(inverse(skinMatrix)) * vec4(normal, 0)).xyz);\r\n    vec4 pos = u_MV * skinMatrix * vec4(position, 1.0);\r\n    gl_Position = u_MVP * skinMatrix * vec4(position, 1.0);\r\n#else\r\n    v_normal = normalize((u_MVNormal * vec4(normal, 0)).xyz);\r\n    vec4 pos = u_MV * vec4(position, 1.0);\r\n    gl_Position = u_MVP * vec4(position, 1.0);\r\n#endif\r\n\r\n    v_position = vec3(pos.xyz) / pos.w;\r\n    \r\n    \r\n}"
  },
  {
    "path": "third-party-license/glMatrix",
    "content": "Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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."
  },
  {
    "path": "webpack.config.js",
    "content": "var path = require('path');\r\nvar webpack = require('webpack');\r\n// var HtmlWebpackPlugin = require('html-webpack-plugin');\r\nconst UglifyJSPlugin = require('uglifyjs-webpack-plugin');\r\n\r\nmodule.exports = {\r\n  entry: {\r\n    lib: './src/minimal-gltf-loader.js'\r\n  },\r\n  resolve: {\r\n      alias: {\r\n        // Lib: path.resolve(__dirname, 'demo/lib/'),\r\n        // Shaders: path.resolve(__dirname, 'demo/lib/src/shaders')\r\n      }\r\n  },\r\n  output: {\r\n    filename: 'minimal-gltf-loader.js',\r\n    path: path.resolve(__dirname, 'build'),\r\n    library: 'MinimalGLTFLoader',\r\n    libraryTarget: 'umd'\r\n  },\r\n  externals: {\r\n    'gl-matrix': {\r\n      commonjs: 'gl-matrix',\r\n      commonjs2: 'gl-matrix',\r\n      amd: 'gl-matrix'\r\n    }\r\n  },\r\n  module: {\r\n    // rules: [\r\n\r\n    // ]\r\n    // loaders: [\r\n    //   {\r\n    //     test: /\\.glsl$/,\r\n    //     loader: \"webpack-glsl\"\r\n    //   },\r\n    // ]\r\n  },\r\n  plugins: [\r\n        // new webpack.optimize.UglifyJsPlugin({\r\n        //     compress: {\r\n        //     warnings: false,\r\n        //     drop_console: false,\r\n        //     }\r\n        // })\r\n        // new UglifyJSPlugin()\r\n\r\n        // new HtmlWebpackPlugin({\r\n        //   title: \"glAvatar demo\"\r\n        // })\r\n    ],\r\n  devServer: {\r\n    contentBase: path.join(__dirname, \"demo\"),\r\n    port: 7777\r\n  }\r\n};"
  }
]