diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..25d2636 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,28 @@ +name: Feder release action + +on: + release: + types: [released] + branches: + - main + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 14 + + - name: Install dependencies + run: npm install + + - name: Build app + run: | + npm run build + + - uses: JS-DevTools/npm-publish@v1 + with: + token: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index 02605f2..efab820 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,15 @@ .DS_Store .nyc_output +.vscode +.ipynb_checkpoints +*.egg-info coverage/ node_modules/ +# test/data/* +hnswlib_hnsw_random_1M.index +images/ +dist +*.csv +*.index +*.pyc +test/bundle.js diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b23d587 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "pwa-chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 273afe1..4895185 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,209 @@ -# feder +# Feder ## What is feder -Feder is built for visualize anns index files, so that we can have a better understanding of anns and high dimensional vectors. so far, we are focusing on Faiss index and HNSW index, we will cover more index types later. -## Quick start -### installation -``` shell -#install -npm install @zilliz/Feder +Feder is an javascript tool that built for understanding your embedding vectors, feder visualizes faiss, hnswlib and other anns index files, so that we can have a better understanding how anns work and what are high dimensional vector embeddings. + +So far, we are focusing on the Faiss (only ivf_flat) index file and HNSWlib (hnsw) index file, we will cover more index types later. + +Feder is written in **javascript**, and we also provide a python library **federpy**, which is based on federjs. + +> **_NOTE:_** + +- In IPython environment, it supports users to generate the corresponding visualization directly. +- In other environments, it supports outputting visualizations as html files, which can be opened by the user through the browser with web service enabled. + + +### Online demos +- [Understanding vector embeddings with Feder by a reverse image search example](https://observablehq.com/@min-tian/reverse-image-search-feder-faiss-ivf_flat-visualizations) +- [Javascript example (Observable)](https://observablehq.com/@min-tian/feder) +- [Jupternotebook example (Colab)](https://colab.research.google.com/drive/12L_oJPR-yFDlORpPondsqGNTPVsSsUwi#scrollTo=N3qqBAYxYcbt) + +### How feder works +- [Feder ivf layout](https://observablehq.com/@min-tian/feder-layout-ivf_flat/2) +- [Feder hnsw layout ](https://observablehq.com/@min-tian/feder-layout-hnsw/2) + +### Wiki + +- [Usage](https://github.com/zilliztech/feder/wiki) + +### HNSW visualization screenshots + +![image](./fig/hnsw_search.png) + +### IVF_Flat visualization screenshots + +![image](./fig/ivfflat_coarse.png) +![image](./fig/ivfflat_fine_polar.png) +![image](./fig/ivfflat_fine_project.png) + +## Quick Start + +### Installation + +Use npm or yarn. + +```shell +yarn install @zilliz/feder ``` -### basic usage +### Material Preparation + +Make sure that you have built an index and dumped the index file by Faiss or HNSWlib. + +### Init Feder + +Specifying the dom container that you want to show the visualizations. + ```js -import { Feder } from '@zilliz/Feder'; +import { Feder } from '@zilliz/feder'; const feder = new Feder({ - file: 'faiss_file', // file path - type: 'faiss', // faiss | hnsw - domContainer, // attach dom to render + filePath: 'faiss_file', // file path + source: 'faiss', // faiss | hnswlib + domSelector: '#container', // attach dom to render + viewParams: {}, // optional }); +``` + +### Visualize the index structure. -// you can call search to visualize the search process -feder.search(target, params); -// or reset to initialize state -feder.reset(); +- HNSW - Feder will show the top-3 levels of the hnsw-tree. +- IVF_Flat - Feder will show all the clusters. + +```js +feder.overview(); ``` -## API -TBD -## Examples -### Use feder with d3 -TBD +### Explore the search process. -### Use feder with react -TBD +Set search parameters (optional) and Specify the query vector. + +```js +feder + .setSearchParams({ + k: 8, // hnsw, ivf_flat + ef: 100, // hnsw (ef_search) + nprobe: 8, // ivf_flat + }) + .search(target_vector); +``` + +## Examples -## How feder works -TBD +We prepare a simple case, which is the visualizations of the `hnsw` and `ivf_flat` with 17,000+ vectors that embedded from [VOC 2012](http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar)). +Only need enable a web service. -## How to contribute ```shell -# install dependencies -npm install -# create build -npm run build -# test -npm run test +git clone git@github.com:zilliztech/feder.git +cd test +python -m http.server ``` + +Then open http://localhost:8000/ + +It will show 4 visualizations: +- `hnsw` overview +- `hnsw` search view +- `ivf_flat` overview +- `ivf_flat` search view + +## Pipeline - explore a new dataset with feder + +### Step 1. Dataset preparation + +Put all images to **test/data/images/**. (example dataset [VOC 2012](http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar)) + +You can also generate random vectors without embedding for index building and skip to **step 3**. + +### Step 2. Generate embedding vectors + +Recommend to use [towhee](https://github.com/towhee-io/towhee), one line of code to generating embedding vectors! + +We have the [encoded vectors](https://assets.zilliz.com/voc_vectors_e8ec5a5eae.csv) ready for you. + +### Step 3. Build an index and dump it. + +You can use [faiss](https://github.com/facebookresearch/faiss) or [hnswlib](https://github.com/nmslib/hnswlib) to build the index. + +(\*Detailed procedures please refer to their tutorials.) + +Referring to **test/data/gen_hnswlib_index_\*.py** or **test/data/gen_faiss_index_\*.py** + +Or we have the [index file](https://assets.zilliz.com/hnswlib_hnsw_voc_17k_1f1dfd63a9.index) ready for you. + +### Step 4. Init Feder. + +```js +import { Feder } from '@zilliz/feder'; +import * as d3 from 'd3'; + +const domSelector = '#container'; +const filePath = [index_file_path]; + +const mediaCallback = (rowId) => mediaUrl; + +const feder = new Feder({ + filePath, + source: 'hnswlib', + domSelector, + viewParams: { + mediaType: 'img', + mediaCallback, + }, +}); +``` + +If use the random_data, **no need** to specify the mediaType. + +```js +import { Feder } from '@zilliz/feder'; +import * as d3 from 'd3'; + +const domSelector = '#container'; +const filePath = [index_file_path]; + +const feder = new Feder({ + filePath, + source: 'hnswlib', + domSelector, +}); +``` + +### Step 5. Explore the index! + +Visualize the overview + +```js +feder.overview(); +``` + +or visualize the search process. + +```js +feder.search(target_vector[, targetMediaUrl]); +``` + +or randomly select an vector as the target to visualize the search process. + +```js +feder.searchRandTestVec(); +``` + +More cases refer to the **test/test.js** + +## Blogs + +- [Visualize Your Approximate Nearest Neighbor Search with Feder](https://zilliz.com/blog/Visualize-Your-Approximate-Nearest-Neighbor-Search-with-Feder) +- [Visualize Reverse Image Search with Feder](https://zilliz.com/blog/Visualize-Reverse-Image-Search-with-Feder) + +## Roadmap + +We're still in the early stages, we will support more types of anns index, and more unstructured data viewer, stay tuned. + +## Acknowledgments + +- [faiss](https://github.com/facebookresearch/faiss) +- [hnswlib](https://github.com/nmslib/hnswlib) +- [d3](https://github.com/d3/d3) diff --git a/cjs/Feder-core.js b/cjs/Feder-core.js deleted file mode 100644 index 41d7843..0000000 --- a/cjs/Feder-core.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; -/* Feder core class */ -module.exports = class Feder_core { - constructor({ file, type, project_params }) { - console.info('feder-core initialized') - } - - get meta() { - // define ivf-meta - // define hnsw-meta - } - get id2Vector() { - // id to vector map - } - search() { - // define ivf-vis_records - // define hnsw-vis_records - } - project() { - Utils.project(...arguments) - } - setProjectParams() {} - _parseFaissIVFFlat() { - this.index = index - } - _parseHNSWlibHNSW() { - this.index = index - } -} diff --git a/cjs/Feder.js b/cjs/Feder.js deleted file mode 100644 index e5f08b4..0000000 --- a/cjs/Feder.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; -/* Feder class */ -module.exports = class Feder { - constructor({ - core = {}, - file = '', - type = '', - vis = { render: function () {} }, - domContainer, - } = {}) { - console.info('feder initialized'); - this.core = core; - this.vis = vis; - this.domContainer = domContainer; - this.vis_records = null; - this.meta = core.meta; - this._render(); - } - update() { - // update core - - // render - this._render(); - } - search() { - this.vis_records = core.search(target, params); - this._render(); - } - reset() { - this.vis_records = null; - this._render(); - } - _render() { - this.vis.render(this.meta, this.vis_records, this.domContainer); - } -} diff --git a/cjs/Feder_core.js b/cjs/Feder_core.js deleted file mode 100644 index b08096d..0000000 --- a/cjs/Feder_core.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; -const Utils = require('./Utils.js'); - -/* Feder core class */ -module.exports = class Feder_core { - constructor({ file, type, project_params }) { - console.info('feder-core initialized'); - } - - get meta() { - // define ivf-meta - // define hnsw-meta - } - get id2Vector() { - // id to vector map - } - search() { - // define ivf-vis_records - // define hnsw-vis_records - } - project() { - Utils.project(...arguments); - } - setProjectParams() {} - _parseFaissIVFFlat() { - this.index = index; - } - _parseHNSWlibHNSW() { - this.index = index; - } -} diff --git a/cjs/Feder_view.js b/cjs/Feder_view.js deleted file mode 100644 index b93b5a2..0000000 --- a/cjs/Feder_view.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; -module.exports = class Feder_view { - project() {} - render(meta, vis_records, dom) {} -} diff --git a/cjs/Feder_view_HNSW.js b/cjs/Feder_view_HNSW.js deleted file mode 100644 index 5924662..0000000 --- a/cjs/Feder_view_HNSW.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict'; -const Feder_view = (m => /* c8 ignore start */ m.__esModule ? m.default : m /* c8 ignore stop */)(require('./Feder_view.js')); - -module.exports = class Feder_view_HNSW extends Feder_view {} \ No newline at end of file diff --git a/cjs/Feder_view_IVF.js b/cjs/Feder_view_IVF.js deleted file mode 100644 index fc0e93e..0000000 --- a/cjs/Feder_view_IVF.js +++ /dev/null @@ -1,4 +0,0 @@ -'use strict'; -const Feder_view = (m => /* c8 ignore start */ m.__esModule ? m.default : m /* c8 ignore stop */)(require('./Feder_view.js')); - -module.exports = class Feder_view_IVF extends Feder_view {} diff --git a/cjs/Utils.js b/cjs/Utils.js deleted file mode 100644 index a42d539..0000000 --- a/cjs/Utils.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; -function project() {} -exports.project = project diff --git a/cjs/index.js b/cjs/index.js deleted file mode 100644 index 125ab85..0000000 --- a/cjs/index.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -const Feder_core = (m => /* c8 ignore start */ m.__esModule ? m.default : m /* c8 ignore stop */)(require('./Feder_core.js')); -const Feder_view = (m => /* c8 ignore start */ m.__esModule ? m.default : m /* c8 ignore stop */)(require('./Feder_view.js')); -const Feder_view_IVF = (m => /* c8 ignore start */ m.__esModule ? m.default : m /* c8 ignore stop */)(require('./Feder_view_IVF.js')); -const Feder_view_HNSW = (m => /* c8 ignore start */ m.__esModule ? m.default : m /* c8 ignore stop */)(require('./Feder_view_HNSW.js')); -const Feder = (m => /* c8 ignore start */ m.__esModule ? m.default : m /* c8 ignore stop */)(require('./Feder.js')); -const utils = require('./Utils.js'); - -exports.Feder = Feder; -exports.Feder_core = Feder_core; -exports.Feder_view = Feder_view; -exports.Feder_view_IVF = Feder_view_IVF; -exports.Feder_view_HNSW = Feder_view_HNSW; -exports.utils = utils; diff --git a/cjs/package.json b/cjs/package.json deleted file mode 100644 index 0292b99..0000000 --- a/cjs/package.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"commonjs"} \ No newline at end of file diff --git a/docs/case_hnsw_overview_with_images.html b/docs/case_hnsw_overview_with_images.html new file mode 100644 index 0000000..422b1d9 --- /dev/null +++ b/docs/case_hnsw_overview_with_images.html @@ -0,0 +1,39 @@ + + + + + + + + Feder + + + + +
?????????
+ + + + + \ No newline at end of file diff --git a/docs/case_hnsw_search_with_images.html b/docs/case_hnsw_search_with_images.html new file mode 100644 index 0000000..b1c4cba --- /dev/null +++ b/docs/case_hnsw_search_with_images.html @@ -0,0 +1,39 @@ + + + + + + + + Feder + + + + +
?????????
+ + + + + \ No newline at end of file diff --git a/esm/Feder.js b/esm/Feder.js deleted file mode 100644 index 4daad10..0000000 --- a/esm/Feder.js +++ /dev/null @@ -1,35 +0,0 @@ -/* Feder class */ -export default class Feder { - constructor({ - core = {}, - file = '', - type = '', - vis = { render: function () {} }, - domContainer, - } = {}) { - console.info('feder initialized'); - this.core = core; - this.vis = vis; - this.domContainer = domContainer; - this.vis_records = null; - this.meta = core.meta; - this._render(); - } - update() { - // update core - - // render - this._render(); - } - search() { - this.vis_records = core.search(target, params); - this._render(); - } - reset() { - this.vis_records = null; - this._render(); - } - _render() { - this.vis.render(this.meta, this.vis_records, this.domContainer); - } -} diff --git a/esm/Feder_core.js b/esm/Feder_core.js deleted file mode 100644 index 978f9b7..0000000 --- a/esm/Feder_core.js +++ /dev/null @@ -1,30 +0,0 @@ -import * as Utils from './Utils.js'; - -/* Feder core class */ -export default class Feder_core { - constructor({ file, type, project_params }) { - console.info('feder-core initialized'); - } - - get meta() { - // define ivf-meta - // define hnsw-meta - } - get id2Vector() { - // id to vector map - } - search() { - // define ivf-vis_records - // define hnsw-vis_records - } - project() { - Utils.project(...arguments); - } - setProjectParams() {} - _parseFaissIVFFlat() { - this.index = index; - } - _parseHNSWlibHNSW() { - this.index = index; - } -} diff --git a/esm/Feder_view.js b/esm/Feder_view.js deleted file mode 100644 index 045e5af..0000000 --- a/esm/Feder_view.js +++ /dev/null @@ -1,4 +0,0 @@ -export default class Feder_view { - project() {} - render(meta, vis_records, dom) {} -} diff --git a/esm/Feder_view_HNSW.js b/esm/Feder_view_HNSW.js deleted file mode 100644 index 5257b72..0000000 --- a/esm/Feder_view_HNSW.js +++ /dev/null @@ -1,3 +0,0 @@ -import Feder_view from './Feder_view.js'; - -export default class Feder_view_HNSW extends Feder_view {} \ No newline at end of file diff --git a/esm/Feder_view_IVF.js b/esm/Feder_view_IVF.js deleted file mode 100644 index c9f583f..0000000 --- a/esm/Feder_view_IVF.js +++ /dev/null @@ -1,3 +0,0 @@ -import Feder_view from './Feder_view.js'; - -export default class Feder_view_IVF extends Feder_view {} diff --git a/esm/Utils.js b/esm/Utils.js deleted file mode 100644 index fbdfd83..0000000 --- a/esm/Utils.js +++ /dev/null @@ -1 +0,0 @@ -export function project() {} diff --git a/esm/index.js b/esm/index.js deleted file mode 100644 index b29645e..0000000 --- a/esm/index.js +++ /dev/null @@ -1,15 +0,0 @@ -import Feder_core from './Feder_core.js'; -import Feder_view from './Feder_view.js'; -import Feder_view_IVF from './Feder_view_IVF.js'; -import Feder_view_HNSW from './Feder_view_HNSW.js'; -import Feder from './Feder.js'; -import * as utils from './Utils.js'; - -export { - Feder, - Feder_core, - Feder_view, - Feder_view_IVF, - Feder_view_HNSW, - utils, -}; diff --git a/federjs/Feder.ts b/federjs/Feder.ts new file mode 100644 index 0000000..e69de29 diff --git a/federjs/FederIndex/Types.ts b/federjs/FederIndex/Types.ts new file mode 100644 index 0000000..843d314 --- /dev/null +++ b/federjs/FederIndex/Types.ts @@ -0,0 +1,24 @@ +export enum EDirectMapType { + NoMap = 0, // default + Array, // sequential ids (only for add, no add_with_ids) + Hashtable, // arbitrary ids +} + +export interface TDirectMap { + dmType: EDirectMapType; + size: number; +} + +export enum EMetricType { + METRIC_INNER_PRODUCT = 0, ///< maximum inner product search + METRIC_L2 = 1, ///< squared L2 search + METRIC_L1 = 2, ///< L1 (aka cityblock) + METRIC_Linf = 3, ///< infinity distance + METRIC_Lp = 4, ///< L_p distance, p is given by a faiss::Index + /// metric_arg + + /// some additional metrics defined in scipy.spatial.distance + METRIC_Canberra = 20, + METRIC_BrayCurtis = 21, + METRIC_JensenShannon = 22, +} diff --git a/federjs/FederIndex/Utils.ts b/federjs/FederIndex/Utils.ts new file mode 100644 index 0000000..d26f85d --- /dev/null +++ b/federjs/FederIndex/Utils.ts @@ -0,0 +1,3 @@ +export const uint8toChars = (data: number[]) => { + return String.fromCharCode(...data); +}; diff --git a/federjs/FederIndex/index.ts b/federjs/FederIndex/index.ts new file mode 100644 index 0000000..576c3f3 --- /dev/null +++ b/federjs/FederIndex/index.ts @@ -0,0 +1,32 @@ +import { ESourceType, EIndexType, TVec, TSearchParams } from 'Types'; + +import { Parser } from './parser'; +import { SearchHandler } from './searchHandler'; + +export class FederIndex { + private index: any; + indexType: EIndexType; + private parser: Parser; + private searchHandler: SearchHandler; + constructor(sourceType: ESourceType) { + this.parser = new Parser(sourceType); + } + initByArrayBuffer(arrayBuffer: ArrayBuffer) { + this.index = this.parser.parse(arrayBuffer); + this.indexType = this.index.indexType; + this.searchHandler = new SearchHandler(this.indexType); + } + async getIndexType() { + return this.indexType; + } + async getIndexMeta() { + return ''; + } + async getSearchRecords(target: TVec, searchParams: TSearchParams) { + return this.searchHandler.search({ + index: this.index, + target, + params: searchParams, + }); + } +} diff --git a/federjs/FederIndex/parser/FileReader.ts b/federjs/FederIndex/parser/FileReader.ts new file mode 100644 index 0000000..d25e570 --- /dev/null +++ b/federjs/FederIndex/parser/FileReader.ts @@ -0,0 +1,77 @@ +export default class FileReader { + data: ArrayBuffer; + dataview: DataView; + p: number; + constructor(arrayBuffer: ArrayBuffer) { + this.data = arrayBuffer; + this.dataview = new DataView(arrayBuffer); + + this.p = 0; + } + get isEmpty() { + return this.p >= this.data.byteLength; + } + readInt8() { + const int8 = this.dataview.getInt8(this.p); + this.p += 1; + return int8; + } + readUint8() { + const uint8 = this.dataview.getUint8(this.p); + this.p += 1; + return uint8; + } + readBool() { + const int8 = this.readInt8(); + return Boolean(int8); + } + readUint16() { + const uint16 = this.dataview.getUint16(this.p, true); + this.p += 2; + return uint16; + } + readInt32() { + const int32 = this.dataview.getInt32(this.p, true); + this.p += 4; + return int32; + } + readUint32() { + const uint32 = this.dataview.getUint32(this.p, true); + this.p += 4; + return uint32; + } + readUint64() { + const left = this.readUint32(); + const right = this.readUint32(); + const int64 = left + Math.pow(2, 32) * right; + if (!Number.isSafeInteger(int64)) + console.warn(int64, "Exceeds MAX_SAFE_INTEGER. Precision may be lost"); + return int64; + } + readFloat64() { + const float64 = this.dataview.getFloat64(this.p, true); + this.p += 8; + return float64; + } + readDouble() { + return this.readFloat64(); + } + + readUint32Array(n) { + const res = Array(n) + .fill(0) + .map((_) => this.readUint32()); + return res; + } + readFloat32Array(n) { + const res = new Float32Array(this.data.slice(this.p, this.p + n * 4)); + this.p += n * 4; + return res; + } + readUint64Array(n) { + const res = Array(n) + .fill(0) + .map((_) => this.readUint64()); + return res; + } +} diff --git a/federjs/FederIndex/parser/faissParser/FaissFileReader.ts b/federjs/FederIndex/parser/faissParser/FaissFileReader.ts new file mode 100644 index 0000000..b7123fc --- /dev/null +++ b/federjs/FederIndex/parser/faissParser/FaissFileReader.ts @@ -0,0 +1,19 @@ +import FileReader from "../FileReader"; +import { uint8toChars } from "FederIndex/Utils"; + +export default class FaissFileReader extends FileReader { + constructor(arrayBuffer) { + super(arrayBuffer); + } + readH() { + const uint8Array = Array(4) + .fill(0) + .map((_) => this.readUint8()); + const h = uint8toChars(uint8Array); + return h; + } + readDummy() { + const dummy = this.readUint64(); + return dummy; + } +} diff --git a/federjs/FederIndex/parser/faissParser/index.js b/federjs/FederIndex/parser/faissParser/index.js new file mode 100644 index 0000000..3b810d2 --- /dev/null +++ b/federjs/FederIndex/parser/faissParser/index.js @@ -0,0 +1,51 @@ +import FaissFileReader from './FaissFileReader.js'; +import readInvertedLists from './readInvertedLists.js'; +import readDirectMap from './readDirectMap.js'; +import readIndexHeader from './readIndexHeader.js'; + +import { generateArray } from 'Utils'; +import { INDEX_TYPE, IndexHeader } from 'Types'; + +const readIvfHeader = (reader, index) => { + readIndexHeader(reader, index); + + index.nlist = reader.readUint64(); + index.nprobe = reader.readUint64(); + + index.childIndex = readIndex(reader); + + readDirectMap(reader, index); +}; + +const readXbVectors = (reader, index) => { + index.codeSize = reader.readUint64(); + + index.vectors = generateArray(index.ntotal).map((_) => + reader.readFloat32Array(index.d) + ); +}; + +const readIndex = (reader) => { + const index = {}; + index.h = reader.readH(); + if (index.h === IndexHeader.IVFFlat) { + index.indexType = INDEX_TYPE.ivf_flat; + readIvfHeader(reader, index); + readInvertedLists(reader, index); + } else if (index.h === IndexHeader.FlatIR || index.h === IndexHeader.FlatL2) { + index.indexType = INDEX_TYPE.flat; + readIndexHeader(reader, index); + readXbVectors(reader, index); + } else { + console.warn('[index type] not supported -', index.h); + } + return index; +}; + +const faissIndexParser = (arraybuffer) => { + const faissFileReader = new FaissFileReader(arraybuffer); + const index = readIndex(faissFileReader); + return index; +}; + +export default faissIndexParser; diff --git a/federjs/FederIndex/parser/faissParser/readDirectMap.ts b/federjs/FederIndex/parser/faissParser/readDirectMap.ts new file mode 100644 index 0000000..34598d9 --- /dev/null +++ b/federjs/FederIndex/parser/faissParser/readDirectMap.ts @@ -0,0 +1,24 @@ +import { EDirectMapType, TDirectMap } from "FederIndex/Types"; + +const checkDmType = (dmType: EDirectMapType | number) => { + if (dmType !== EDirectMapType.NoMap) { + console.warn("[directmap_type] only support NoMap."); + } +}; + +const checkDmSize = (dmSize: number) => { + if (dmSize !== 0) { + console.warn("[directmap_size] should be 0."); + } +}; + +const readDirectMap = (reader, index) => { + const directMap = {} as TDirectMap; + directMap.dmType = reader.readUint8(); + checkDmType(directMap.dmType); + directMap.size = reader.readUint64(); + checkDmSize(directMap.size); + index.directMap = directMap; +}; + +export default readDirectMap; diff --git a/federjs/FederIndex/parser/faissParser/readIndexHeader.ts b/federjs/FederIndex/parser/faissParser/readIndexHeader.ts new file mode 100644 index 0000000..3ad36ef --- /dev/null +++ b/federjs/FederIndex/parser/faissParser/readIndexHeader.ts @@ -0,0 +1,39 @@ +import { EMetricType } from 'FederIndex/Types'; + +const checkMetricType = (metricType: EMetricType | number) => { + if ( + metricType !== EMetricType.METRIC_L2 && + metricType !== EMetricType.METRIC_INNER_PRODUCT + ) { + console.warn('[metric_type] only support l2 and inner_product.'); + } +}; + +const checkDummy = (dummy_1, dummy_2) => { + if (dummy_1 !== dummy_2) { + console.warn('[dummy] not equal.', dummy_1, dummy_2); + } +}; + +const checkIsTrained = (isTrained) => { + if (!isTrained) { + console.warn('[is_trained] should be trained.', isTrained); + } +}; + +const readIndexHeader = (reader, index) => { + index.d = reader.readUint32(); + index.ntotal = reader.readUint64(); + + const dummy_1 = reader.readDummy(); + const dummy_2 = reader.readDummy(); + checkDummy(dummy_1, dummy_2); + + index.isTrained = reader.readBool(); + checkIsTrained(index.isTrained); + + index.metricType = reader.readUint32(); + checkMetricType(index.metricType); +}; + +export default readIndexHeader; diff --git a/federjs/FederIndex/parser/faissParser/readInvertedLists.js b/federjs/FederIndex/parser/faissParser/readInvertedLists.js new file mode 100644 index 0000000..d2b0ec1 --- /dev/null +++ b/federjs/FederIndex/parser/faissParser/readInvertedLists.js @@ -0,0 +1,47 @@ +import { generateArray } from 'Utils'; + +const checkInvH = (h) => { + if (h !== 'ilar') { + console.warn('[invlists h] not ilar.', h); + } +}; + +const checkInvListType = (listType) => { + if (listType !== 'full') { + console.warn('[inverted_lists list_type] only support full.', listType); + } +}; + +const readArrayInvLists = (reader, invlists) => { + invlists.listType = reader.readH(); + checkInvListType(invlists.listType); + + invlists.listSizesSize = reader.readUint64(); + invlists.listSizes = generateArray(invlists.listSizesSize).map((_) => + reader.readUint64() + ); + + const data = []; + generateArray(invlists.listSizesSize).forEach((_, i) => { + const vectors = generateArray(invlists.listSizes[i]).map((_) => + reader.readFloat32Array(invlists.codeSize / 4) + ); + const ids = reader.readUint64Array(invlists.listSizes[i]); + data.push({ ids, vectors }); + }); + invlists.data = data; +}; + +export const readInvertedLists = (reader, index) => { + const invlists = {}; + invlists.h = reader.readH(); + checkInvH(invlists.h); + invlists.nlist = reader.readUint64(); + invlists.codeSize = reader.readUint64(); + + readArrayInvLists(reader, invlists); + + index.invlists = invlists; +}; + +export default readInvertedLists; diff --git a/federjs/FederIndex/parser/faissParser/types.ts b/federjs/FederIndex/parser/faissParser/types.ts new file mode 100644 index 0000000..42b7774 --- /dev/null +++ b/federjs/FederIndex/parser/faissParser/types.ts @@ -0,0 +1,10 @@ +export enum EDirectMapType { + NoMap = 0, // default + Array, // sequential ids (only for add, no add_with_ids) + Hashtable, // arbitrary ids +} + +export interface TDirectMap { + dmType: EDirectMapType; + size: number; +} diff --git a/federjs/FederIndex/parser/hnswlibParser/HNSWlibFileReader.ts b/federjs/FederIndex/parser/hnswlibParser/HNSWlibFileReader.ts new file mode 100644 index 0000000..eb9b41e --- /dev/null +++ b/federjs/FederIndex/parser/hnswlibParser/HNSWlibFileReader.ts @@ -0,0 +1,16 @@ +import FileReader from "../FileReader"; + +export default class HNSWlibFileReader extends FileReader { + constructor(arrayBuffer: ArrayBuffer) { + super(arrayBuffer); + } + readIsDeleted() { + return this.readUint8(); + } + readIsReused() { + return this.readUint8(); + } + readLevelOCount() { + return this.readUint16(); + } +} diff --git a/federjs/FederIndex/parser/hnswlibParser/index.ts b/federjs/FederIndex/parser/hnswlibParser/index.ts new file mode 100644 index 0000000..6cd1985 --- /dev/null +++ b/federjs/FederIndex/parser/hnswlibParser/index.ts @@ -0,0 +1,102 @@ +import HNSWlibFileReader from "./HNSWlibFileReader.js"; +import { EIndexType } from "Types"; +import { TIndexStructureHnswDetail, TIndexStructureHnsw } from "./types"; +export { TIndexStructureHnsw } from "./types"; + +export const hnswlibIndexParser = (arrayBuffer: ArrayBuffer) => { + const reader = new HNSWlibFileReader(arrayBuffer); + const index = {} as TIndexStructureHnswDetail; + index.offsetLevel0_ = reader.readUint64(); + index.max_elements_ = reader.readUint64(); + index.cur_element_count = reader.readUint64(); + // index.ntotal = index.cur_element_count; // consistent with Faiss + index.size_data_per_element_ = reader.readUint64(); + index.label_offset_ = reader.readUint64(); + index.offsetData_ = reader.readUint64(); + index.dim = (index.size_data_per_element_ - index.offsetData_ - 8) / 4; + + index.maxlevel_ = reader.readUint32(); + index.enterpoint_node_ = reader.readUint32(); + index.maxM_ = reader.readUint64(); + index.maxM0_ = reader.readUint64(); + index.M = reader.readUint64(); + + index.mult_ = reader.readFloat64(); + index.ef_construction_ = reader.readUint64(); + + index.size_links_per_element_ = index.maxM_ * 4 + 4; + index.size_links_level0_ = index.maxM0_ * 4 + 4; + index.revSize_ = 1.0 / index.mult_; + index.ef_ = 10; + + read_data_level0_memory_(reader, index); + + const linkListSizes = []; + const linkLists_ = []; + for (let i = 0; i < index.cur_element_count; i++) { + const linkListSize = reader.readUint32(); + linkListSizes.push(linkListSize); + if (linkListSize === 0) { + linkLists_[i] = []; + } else { + const levelCount = linkListSize / 4 / (index.maxM_ + 1); + linkLists_[i] = Array(levelCount) + .fill(0) + .map((_) => reader.readUint32Array(index.maxM_ + 1)) + .map((linkLists) => linkLists.slice(1, linkLists[0] + 1)); + // .filter((a) => a.length > 0); + } + } + index.linkListSizes = linkListSizes; + index.linkLists_ = linkLists_; + + console.assert( + reader.isEmpty, + "HNSWlib Parser Failed. Not empty when the parser completes." + ); + + return { + indexType: EIndexType.hnsw, + ntotal: index.cur_element_count, + vectors: index.vectors, + maxLevel: index.maxlevel_, + linkLists_level0_count: index.linkLists_level0_count, + linkLists_level_0: index.linkLists_level0, + linkLists_levels: index.linkLists_, + enterPoint: index.enterpoint_node_, + labels: index.externalLabel, + isDeleted: index.isDeleted, + numDeleted: index.num_deleted_, + M: index.M, + ef_construction: index.ef_construction_, + } as TIndexStructureHnsw; +}; + +const read_data_level0_memory_ = ( + reader: HNSWlibFileReader, + index: TIndexStructureHnswDetail +) => { + // size_data = links_level0[M0 + 1] * 4 + vector[dim * 4] * 4 + label[1] * 8; + const isDeleted = []; + const linkLists_level0_count = []; + const linkLists_level0 = []; + const vectors = []; + const externalLabel = []; + for (let i = 0; i < index.cur_element_count; i++) { + linkLists_level0_count.push(reader.readLevelOCount()); + isDeleted.push(reader.readIsDeleted()); + reader.readIsReused(); // Unknown use. + linkLists_level0.push(reader.readUint32Array(index.maxM0_)); + vectors.push(reader.readFloat32Array(index.dim)); + externalLabel.push(reader.readUint64()); + // console.log(isDeleted, linkLists_level0_count); + } + index.isDeleted = isDeleted; + index.num_deleted_ = isDeleted.reduce((acc, cur) => acc + cur, 0); + index.linkLists_level0_count = linkLists_level0_count; + index.linkLists_level0 = linkLists_level0; + index.vectors = vectors; + index.externalLabel = externalLabel; +}; + +export default hnswlibIndexParser; diff --git a/federjs/FederIndex/parser/hnswlibParser/types.ts b/federjs/FederIndex/parser/hnswlibParser/types.ts new file mode 100644 index 0000000..567c21f --- /dev/null +++ b/federjs/FederIndex/parser/hnswlibParser/types.ts @@ -0,0 +1,48 @@ +import { TVec, TId, EIndexType } from "Types"; +export type THnswlibLinkList = TId[]; +export type THnswlibLinkLists = THnswlibLinkList[]; + +export interface TIndexStructureHnswDetail { + offsetLevel0_: number; + max_elements_: number; + cur_element_count: number; + size_data_per_element_: number; + label_offset_: number; + offsetData_: number; + dim: number; + maxlevel_: number; + enterpoint_node_: TId; + maxM_: number; + maxM0_: number; + M: number; + mult_: number; + ef_construction_: number; + size_links_per_element_: number; + size_links_level0_: number; + revSize_: number; + ef_: number; + linkListSizes: number[]; + linkLists_: THnswlibLinkLists[]; + vectors: TVec[]; + linkLists_level0_count: number[]; + linkLists_level0: THnswlibLinkLists; + externalLabel: TId[]; + isDeleted: number[]; + num_deleted_: number; +} + +export interface TIndexStructureHnsw { + indexType: EIndexType; + ntotal: number; + vectors: TVec[]; + maxLevel: number; + linkLists_level0_count: number[]; + linkLists_level_0: THnswlibLinkLists; + linkLists_levels: THnswlibLinkLists[]; + enterPoint: TId; + labels: TId[]; + isDeleted: number[]; + numDeleted: number; + M: number; + ef_construction: number; +} diff --git a/federjs/FederIndex/parser/index.ts b/federjs/FederIndex/parser/index.ts new file mode 100644 index 0000000..695093c --- /dev/null +++ b/federjs/FederIndex/parser/index.ts @@ -0,0 +1,17 @@ +import { TIndexStructureHnsw, hnswlibIndexParser } from './hnswlibParser'; +import { ESourceType } from 'Types'; + +const parserMap = { + [ESourceType.hnswlib]: hnswlibIndexParser, + // [ESourceType.faiss]: , + // [ESourceType.milvus]: , +}; + +export type TIndexParseFunc = (arrayBuffer: ArrayBuffer) => TIndexStructureHnsw; + +export class Parser { + parse: TIndexParseFunc; + constructor(indexType: ESourceType) { + this.parse = parserMap[indexType]; + } +} diff --git a/federjs/FederIndex/searchHandler/hnswSearch/index.ts b/federjs/FederIndex/searchHandler/hnswSearch/index.ts new file mode 100644 index 0000000..f4285da --- /dev/null +++ b/federjs/FederIndex/searchHandler/hnswSearch/index.ts @@ -0,0 +1,87 @@ +import { getDisFunc } from "Utils/distFunc"; +import { EMetricType, TSearchParams } from "Types"; +import { TSearchRecordsHnsw } from "Types/searchRecords"; +import searchLevelO from "./searchLevel0"; + +export const hnswlibHNSWSearch = ({ + index, + target, + params = {} as TSearchParams, +}) => { + const { ef = 10, k = 8, metricType = EMetricType.METRIC_L2 } = params; + const disfunc = getDisFunc(metricType); + + let topkResults = []; + const vis_records_all = []; + + const { + enterPoint, + vectors, + maxLevel, + linkLists_levels, + linkLists_level_0, + numDeleted, + labels, + isDeleted, + } = index; + + let curNodeId = enterPoint; + let curDist = disfunc(vectors[curNodeId], target); + + for (let level = maxLevel; level > 0; level--) { + const vis_records = []; + vis_records.push([labels[curNodeId], labels[curNodeId], curDist]); + let changed = true; + while (changed) { + changed = false; + + const curlinks = linkLists_levels[curNodeId][level - 1]; + + curlinks.forEach((candidateId) => { + const dist = disfunc(vectors[candidateId], target); + vis_records.push([labels[curNodeId], labels[candidateId], dist]); + if (dist < curDist) { + curDist = dist; + curNodeId = candidateId; + changed = true; + } + }); + } + vis_records_all.push(vis_records); + } + + const hasDeleted = numDeleted > 0; + const { top_candidates, vis_records_level_0 } = searchLevelO({ + ep_id: curNodeId, + target, + vectors, + ef: Math.max(ef, k), + hasDeleted, + isDeleted, + linkLists_level_0, + disfunc, + labels, + }); + vis_records_all.push(vis_records_level_0); + + while (top_candidates.size > k) { + top_candidates.pop(); + } + + while (top_candidates.size > 0) { + const res = top_candidates.pop(); + topkResults.push({ + id: labels[res[1]], + internalId: res[1], + dis: -res[0], + }); + } + + topkResults = topkResults.reverse(); + + return { + searchRecords: vis_records_all, + topkResults, + searchParams: { k, ef }, + } as TSearchRecordsHnsw; +}; diff --git a/federjs/FederIndex/searchHandler/hnswSearch/searchLevel0.ts b/federjs/FederIndex/searchHandler/hnswSearch/searchLevel0.ts new file mode 100644 index 0000000..a835758 --- /dev/null +++ b/federjs/FederIndex/searchHandler/hnswSearch/searchLevel0.ts @@ -0,0 +1,82 @@ + +import PriorityQueue from 'Utils/PriorityQueue'; + +export const searchLevelO = ({ + ep_id, + target, + vectors, + ef, + isDeleted, + hasDeleted, + linkLists_level_0, + disfunc, + labels, +}) => { + const top_candidates = new PriorityQueue([], (d) => d[0]); + const candidates = new PriorityQueue([], (d) => d[0]); + const vis_records_level_0 = []; + + const visited = new Set(); + + let lowerBound; + if (!hasDeleted || !isDeleted[ep_id]) { + const dist = disfunc(vectors[ep_id], target); + lowerBound = dist; + top_candidates.add([-dist, ep_id]); + candidates.add([dist, ep_id]); + } else { + lowerBound = 9999999; + candidates.add([lowerBound, ep_id]); + } + + visited.add(ep_id); + vis_records_level_0.push([labels[ep_id], labels[ep_id], lowerBound]); + + while (!candidates.isEmpty) { + const curNodePair = candidates.top; + if ( + curNodePair[0] > lowerBound && + (top_candidates.size === ef || !hasDeleted) + ) { + break; + } + candidates.pop(); + + const curNodeId = curNodePair[1]; + const curLinks = linkLists_level_0[curNodeId]; + + curLinks.forEach((candidateId) => { + if (!visited.has(candidateId)) { + visited.add(candidateId); + + const dist = disfunc(vectors[candidateId], target); + vis_records_level_0.push([ + labels[curNodeId], + labels[candidateId], + dist, + ]); + + if (top_candidates.size < ef || lowerBound > dist) { + candidates.add([dist, candidateId]); + + if (!hasDeleted || !isDeleted(candidateId)) { + top_candidates.add([-dist, candidateId]); + } + + if (top_candidates.size > ef) { + top_candidates.pop(); + } + + if (!top_candidates.isEmpty) { + lowerBound = -top_candidates.top[0]; + } + } + } else { + vis_records_level_0.push([labels[curNodeId], labels[candidateId], -1]); + } + }); + } + return { top_candidates, vis_records_level_0 }; +}; + +export default searchLevelO; \ No newline at end of file diff --git a/federjs/FederIndex/searchHandler/index.ts b/federjs/FederIndex/searchHandler/index.ts new file mode 100644 index 0000000..3a61960 --- /dev/null +++ b/federjs/FederIndex/searchHandler/index.ts @@ -0,0 +1,24 @@ +import { hnswlibHNSWSearch } from "./hnswSearch"; +import { EIndexType, TVec, TSearchParams } from "Types"; +import { TSearchRecords } from "Types/searchRecords"; + +const searchFuncMap = { + [EIndexType.hnsw]: hnswlibHNSWSearch, +}; + +export interface TSearchVectorAndParams { + index: any; + target: TVec; + params: TSearchParams; +} + +export type TSearchFunc = ( + searchParams: TSearchVectorAndParams +) => TSearchRecords; + +export class SearchHandler { + search: TSearchFunc; + constructor(indexType: EIndexType) { + this.search = searchFuncMap[indexType]; + } +} diff --git a/federjs/FederLayout/FederLayoutHandler.ts b/federjs/FederLayout/FederLayoutHandler.ts new file mode 100644 index 0000000..a83d69b --- /dev/null +++ b/federjs/FederLayout/FederLayoutHandler.ts @@ -0,0 +1,12 @@ +import { EViewType, TLayoutParams } from 'Types'; +import { TSearchRecords } from 'Types/searchRecords'; +import { TAcitonData, TVisDataAll } from 'Types/visData'; + +export interface TFederLayoutHandler { + computeOverviewVisData(): TVisDataAll; + computeSearchViewVisData( + viewType: EViewType, + searchRecords: TSearchRecords, + layoutParams: TLayoutParams + ): TVisDataAll; +} diff --git a/federjs/FederLayout/codeStructure.ts b/federjs/FederLayout/codeStructure.ts new file mode 100644 index 0000000..22d82ac --- /dev/null +++ b/federjs/FederLayout/codeStructure.ts @@ -0,0 +1,65 @@ +// service + +import { EActionType, EViewType, EIndexType, TLayoutParams } from 'Types'; +import { TVisDataAll, TAcitonData } from 'Types/visData'; +import { FederIndex } from 'FederIndex'; + +export class FederLayout { + indexType: EIndexType; + federIndex: FederIndex; + constructor(federIndex: FederIndex) { + this.federIndex = federIndex; + this.indexType = this.federIndex.indexType; + } + + async getVisData({ + actionType, + actionData, + viewType, + layoutParams, + }: { + actionType: EActionType; + actionData: TAcitonData; + viewType: EViewType; + layoutParams: TLayoutParams; + }): Promise { + const visData = + actionType === EActionType.search + ? await this.getSearchViewVisData({ + actionData, + viewType, + layoutParams, + }) + : await this.getOverviewVisData({ viewType, layoutParams }); + + return { + indexType: this.indexType, + actionType, + actionData, + viewType, + visData, + }; + } + + async getSearchViewVisData({ + actionData, + viewType, + layoutParams, + }: { + actionData: TAcitonData; + viewType: EViewType; + layoutParams: TLayoutParams; + }) {} + + async getOverviewVisData({ + viewType, + layoutParams, + }: { + viewType: EViewType; + layoutParams: TLayoutParams; + }) {} +} + +export class FederLayoutHnsw extends FederLayout { + getSearchViewVisData; +} diff --git a/federjs/FederLayout/index.ts b/federjs/FederLayout/index.ts new file mode 100644 index 0000000..bd5b3a3 --- /dev/null +++ b/federjs/FederLayout/index.ts @@ -0,0 +1,73 @@ +import { FederIndex } from 'FederIndex'; +import { + EViewType, + EActionType, + EIndexType, + TVec, + TSearchParams, + TLayoutParams, +} from 'Types'; +import { TVisDataAll, TAcitonData } from 'Types/visData'; +import { TFederLayoutHandler } from './FederLayoutHandler'; +import FederLayoutHnsw from './visDataHandler/hnsw'; + +const federLayoutHandlerMap = { + [EIndexType.hnsw]: FederLayoutHnsw, + // [EIndexType.ivfflat]: FederLayoutIVFFlat; +}; + +export class FederLayout { + private federIndex: FederIndex; + indexType: EIndexType; + private federLayoutHandler: TFederLayoutHandler; + constructor(federIndex: FederIndex) { + this.federIndex = federIndex; + this.indexType = federIndex.indexType; + this.federLayoutHandler = new federLayoutHandlerMap[federIndex.indexType](); + } + + async getOverviewVisData(viewType: EViewType, layoutParams: TLayoutParams) { + return {}; + } + + async getSearchViewVisData( + actionData: TAcitonData, + viewType: EViewType, + layoutParams: TLayoutParams + ) { + const searchRecords = await this.federIndex.getSearchRecords( + actionData.target, + actionData.searchParams + ); + console.log('searchRecords', searchRecords); + return this.federLayoutHandler.computeSearchViewVisData( + viewType, + searchRecords, + layoutParams + ); + } + + async getVisData({ + actionType, + actionData, + viewType = EViewType.default, + layoutParams = {}, + }: { + actionType: EActionType; + actionData?: TAcitonData; + viewType?: EViewType; + layoutParams?: TLayoutParams; + }) { + const visData = + actionType === EActionType.search + ? await this.getSearchViewVisData(actionData, viewType, layoutParams) + : await this.getOverviewVisData(viewType, layoutParams); + return { + indexType: this.indexType, + actionType, + actionData, + viewType, + visData, + } as TVisDataAll; + } +} diff --git a/federjs/FederLayout/projector/index.ts b/federjs/FederLayout/projector/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/federjs/FederLayout/visDataHandler/hnsw/index.ts b/federjs/FederLayout/visDataHandler/hnsw/index.ts new file mode 100644 index 0000000..2f7b0a4 --- /dev/null +++ b/federjs/FederLayout/visDataHandler/hnsw/index.ts @@ -0,0 +1,57 @@ +import { TFederLayoutHandler } from 'FederLayout/FederLayoutHandler'; +import { TVec, TSearchParams, EViewType, TLayoutParams } from 'Types'; +import { TSearchRecords, TSearchRecordsHnsw } from 'Types/searchRecords'; +import { TVisData } from 'Types/visData'; + +import { searchViewLayoutHandler } from './search'; +import { searchViewLayoutHandler3d } from './search/hnsw3d'; + +const searchViewLayoutHandlerMap = { + [EViewType.default]: searchViewLayoutHandler, + [EViewType.hnsw3d]: searchViewLayoutHandler3d, +}; + +const defaultHnswLayoutParams = { + padding: [80, 200, 60, 220], + forceTime: 3000, + layerDotNum: 20, + shortenLineD: 8, + overviewLinkLineWidth: 2, + reachableLineWidth: 3, + shortestPathLineWidth: 4, + ellipseRation: 1.4, + shadowBlur: 4, + mouse2nodeBias: 3, + highlightRadiusExt: 0.5, + targetR: 3, + searchViewNodeBasicR: 1.5, + searchInterLevelTime: 300, + searchIntraLevelTime: 100, + HoveredPanelLine_1_x: 15, + HoveredPanelLine_1_y: -25, + HoveredPanelLine_2_x: 30, + hoveredPanelLineWidth: 2, + forceIterations: 100, + targetOrigin: [0, 0], +}; + +export default class FederLayoutHnsw implements TFederLayoutHandler { + constructor() {} + + computeOverviewVisData() { + return {} as TVisData; + } + + computeSearchViewVisData( + viewType: EViewType, + searchRecords: TSearchRecordsHnsw, + layoutParams: TLayoutParams + ) { + const searchViewLayoutHandler = searchViewLayoutHandlerMap[viewType]; + + return searchViewLayoutHandler( + searchRecords, + Object.assign({}, defaultHnswLayoutParams, layoutParams) + ) as TVisData; + } +} diff --git a/federjs/FederLayout/visDataHandler/hnsw/search/computeSearchViewTransition.ts b/federjs/FederLayout/visDataHandler/hnsw/search/computeSearchViewTransition.ts new file mode 100644 index 0000000..949edb3 --- /dev/null +++ b/federjs/FederLayout/visDataHandler/hnsw/search/computeSearchViewTransition.ts @@ -0,0 +1,86 @@ +import { + getNodeIdWithLevel, + getLinkIdWithLevel, + getEntryLinkIdWithLevel, +} from './utils'; + +import { EHnswLinkType } from 'Types'; + +export const computeSearchViewTransition = ({ + linksLevels, + entryNodesLevels, + interLevelGap = 1000, + intraLevelGap = 300, +}) => { + let currentTime = 0; + const targetShowTime = []; + const nodeShowTime = {}; + const linkShowTime = {}; + + let isPreLinkImportant = true; + let isSourceChanged = true; + let preSourceIdWithLevel = ''; + for (let level = linksLevels.length - 1; level >= 0; level--) { + const links = linksLevels[level]; + if (links.length === 0) { + const sourceId = entryNodesLevels[level].id; + const sourceIdWithLevel = getNodeIdWithLevel(sourceId, level); + nodeShowTime[sourceIdWithLevel] = currentTime; + } else { + links.forEach((link) => { + const sourceId = link.source.id; + const targetId = link.target.id; + const sourceIdWithLevel = getNodeIdWithLevel(sourceId, level); + const targetIdWithLevel = getNodeIdWithLevel(targetId, level); + const linkIdWithLevel = getLinkIdWithLevel(sourceId, targetId, level); + const isCurrentLinkImportant = + link.type === EHnswLinkType.Searched || + link.type === EHnswLinkType.Fine; + isSourceChanged = preSourceIdWithLevel !== sourceIdWithLevel; + + const isSourceEntry = !(sourceIdWithLevel in nodeShowTime); + if (isSourceEntry) { + if (level < linksLevels.length - 1) { + const entryLinkIdWithLevel = getEntryLinkIdWithLevel( + sourceId, + level + ); + linkShowTime[entryLinkIdWithLevel] = currentTime; + const targetLinkIdWithLevel = getEntryLinkIdWithLevel( + 'target', + level + ); + linkShowTime[targetLinkIdWithLevel] = currentTime; + currentTime += interLevelGap; + isPreLinkImportant = true; + } + targetShowTime[level] = currentTime; + nodeShowTime[sourceIdWithLevel] = currentTime; + } + + // something wrong + if (isPreLinkImportant || isCurrentLinkImportant || isSourceChanged) { + currentTime += intraLevelGap; + } else { + currentTime += intraLevelGap * 0.5; + } + + linkShowTime[linkIdWithLevel] = currentTime; + + if (!(targetIdWithLevel in nodeShowTime)) { + nodeShowTime[targetIdWithLevel] = currentTime += intraLevelGap; + } + + isPreLinkImportant = isCurrentLinkImportant; + preSourceIdWithLevel = sourceIdWithLevel; + }); + } + + currentTime += intraLevelGap; + isPreLinkImportant = true; + isSourceChanged = true; + } + return { targetShowTime, nodeShowTime, linkShowTime, duration: currentTime }; +}; + +export default computeSearchViewTransition; diff --git a/federjs/FederLayout/visDataHandler/hnsw/search/forceSearchView.ts b/federjs/FederLayout/visDataHandler/hnsw/search/forceSearchView.ts new file mode 100644 index 0000000..5fe3197 --- /dev/null +++ b/federjs/FederLayout/visDataHandler/hnsw/search/forceSearchView.ts @@ -0,0 +1,83 @@ +import * as d3 from "d3"; +import { EHnswLinkType } from "Types"; +import { deDupLink } from "./utils"; + +const forceSearchView = ( + visData, + targetOrigin = [0, 0], + forceIterations = 100 +) => { + return new Promise((resolve) => { + const nodeId2dist = {}; + visData.forEach((levelData) => + levelData.nodes.forEach((node) => (nodeId2dist[node.id] = node.dist || 0)) + ); + const nodeIds = Object.keys(nodeId2dist); + const nodes = nodeIds.map((nodeId) => ({ + nodeId: nodeId, + dist: nodeId2dist[nodeId], + })); + + const linksAll = visData.reduce((acc, cur) => acc.concat(cur.links), []); + const links = deDupLink(linksAll); + // console.log(nodes, links); + // console.log(links.length, linksAll.length); + + const targetNode = { + nodeId: "target", + dist: 0, + fx: targetOrigin[0], + fy: targetOrigin[1], + }; + nodes.push(targetNode); + + const targetLinks = visData[0].fineIds.map((fineId) => ({ + source: `${fineId}`, + target: "target", + type: EHnswLinkType.None, + })); + links.push(...targetLinks); + // console.log(nodes, links); + + const rScale = d3 + .scaleLinear() + .domain( + d3.extent( + nodes.filter((node) => node.dist > 0), + (node) => node.dist + ) + ) + .range([10, 1000]) + .clamp(true); + const simulation = d3 + .forceSimulation(nodes as any[]) + .alphaDecay(1 - Math.pow(0.001, 1 / forceIterations)) + .force( + "link", + d3 + .forceLink(links) + .id((d: any) => `${d.nodeId}`) + .strength((d) => (d.type === EHnswLinkType.None ? 2 : 0.4)) + ) + .force( + "r", + d3 + .forceRadial( + (node: any) => rScale(node.dist), + targetOrigin[0], + targetOrigin[1] + ) + .strength(1) + ) + .force("charge", d3.forceManyBody().strength(-10000)) + .on("end", () => { + const id2forcePos = {}; + nodes.forEach( + (node: any) => (id2forcePos[node.nodeId] = [node.x, node.y]) + ); + resolve(id2forcePos); + }); + }); +}; + +export default forceSearchView; diff --git a/federjs/FederLayout/visDataHandler/hnsw/search/hnsw3d.ts b/federjs/FederLayout/visDataHandler/hnsw/search/hnsw3d.ts new file mode 100644 index 0000000..0ed6869 --- /dev/null +++ b/federjs/FederLayout/visDataHandler/hnsw/search/hnsw3d.ts @@ -0,0 +1,89 @@ +import { TSearchRecordsHnsw } from 'Types/searchRecords'; +import { EHnswLinkType, TCoord } from 'Types'; +import parseVisRecords from './parseVisRecords'; +import forceSearchView from './forceSearchView'; +import transformHandler from './transformHandler'; +import * as d3 from 'd3'; + +export const searchViewLayoutHandler3d = async ( + searchRecords: TSearchRecordsHnsw, + layoutParams: any +) => { + const visData = parseVisRecords(searchRecords); + const { + targetR, + canvasScale = 1, + targetOrigin, + searchViewNodeBasicR, + forceIterations, + } = layoutParams; + + const id2forcePos = await forceSearchView( + visData, + targetOrigin, + forceIterations + ); + + const searchNodesLevels = visData.map((levelData) => levelData.nodes); + searchNodesLevels.forEach((levelData) => + levelData.forEach((node) => { + node.forcePos = id2forcePos[node.id]; + node.x = node.forcePos[0]; + node.y = node.forcePos[1]; + }) + ); + const { layerPosLevels, transformFunc } = transformHandler( + searchNodesLevels.reduce((acc, node) => acc.concat(node), []), + layoutParams + ); + + const searchTarget = { + id: 'target', + r: targetR * canvasScale, + searchViewPosLevels: d3 + .range(visData.length) + .map((i) => transformFunc(...(targetOrigin as TCoord), i)), + }; + + searchNodesLevels.forEach((nodes, level) => { + nodes.forEach((node) => { + node.searchViewPosLevels = d3 + .range(level + 1) + .map((i) => transformFunc(...(node.forcePos as TCoord), i)); + node.r = (searchViewNodeBasicR + node.type * 0.5) * canvasScale; + }); + }); + + const id2searchNode = {}; + searchNodesLevels.forEach((levelData) => + levelData.forEach((node) => (id2searchNode[node.id] = node)) + ); + + const searchLinksLevels = parseVisRecords(searchRecords).map((levelData) => + levelData.links.filter((link) => link.type !== EHnswLinkType.None) + ); + searchLinksLevels.forEach((levelData) => + levelData.forEach((link) => { + const sourceId = link.source; + const targetId = link.target; + const sourceNode = id2searchNode[sourceId]; + const targetNode = id2searchNode[targetId]; + link.source = sourceNode; + link.target = targetNode; + }) + ); + + const entryNodesLevels = visData.map((levelData) => + levelData.entryIds.map((id) => id2searchNode[id]) + ); + + return { + visData, + id2forcePos, + searchTarget, + entryNodesLevels, + searchNodesLevels, + searchLinksLevels, + searchRecords + }; +}; diff --git a/federjs/FederLayout/visDataHandler/hnsw/search/index.ts b/federjs/FederLayout/visDataHandler/hnsw/search/index.ts new file mode 100644 index 0000000..a8cf724 --- /dev/null +++ b/federjs/FederLayout/visDataHandler/hnsw/search/index.ts @@ -0,0 +1,106 @@ +import { TSearchRecordsHnsw } from "Types/searchRecords"; +import { EHnswLinkType, TCoord } from "Types"; +import parseVisRecords from "./parseVisRecords"; +import forceSearchView from "./forceSearchView"; +import transformHandler from "./transformHandler"; +import computeSearchViewTransition from "./computeSearchViewTransition"; +import * as d3 from "d3"; + +export const searchViewLayoutHandler = async ( + searchRecords: TSearchRecordsHnsw, + layoutParams: any +) => { + const visData = parseVisRecords(searchRecords); + + const { + targetR, + canvasScale = 1, + targetOrigin, + searchViewNodeBasicR, + searchInterLevelTime, + searchIntraLevelTime, + forceIterations, + } = layoutParams; + + const id2forcePos = await forceSearchView( + visData, + targetOrigin, + forceIterations + ); + + const searchNodesLevels = visData.map((levelData) => levelData.nodes); + searchNodesLevels.forEach((levelData) => + levelData.forEach((node) => { + node.forcePos = id2forcePos[node.id]; + node.x = node.forcePos[0]; + node.y = node.forcePos[1]; + }) + ); + const { layerPosLevels, transformFunc } = transformHandler( + searchNodesLevels.reduce((acc, node) => acc.concat(node), []), + layoutParams + ); + + const searchTarget = { + id: "target", + r: targetR * canvasScale, + searchViewPosLevels: d3 + .range(visData.length) + .map((i) => transformFunc(...(targetOrigin as TCoord), i)), + }; + + searchNodesLevels.forEach((nodes, level) => { + nodes.forEach((node) => { + node.searchViewPosLevels = d3 + .range(level + 1) + .map((i) => transformFunc(...(node.forcePos as TCoord), i)); + node.r = (searchViewNodeBasicR + node.type * 0.5) * canvasScale; + }); + }); + + const id2searchNode = {}; + searchNodesLevels.forEach((levelData) => + levelData.forEach((node) => (id2searchNode[node.id] = node)) + ); + + const searchLinksLevels = parseVisRecords(searchRecords).map((levelData) => + levelData.links.filter((link) => link.type !== EHnswLinkType.None) + ); + searchLinksLevels.forEach((levelData) => + levelData.forEach((link) => { + const sourceId = link.source; + const targetId = link.target; + const sourceNode = id2searchNode[sourceId]; + const targetNode = id2searchNode[targetId]; + link.source = sourceNode; + link.target = targetNode; + }) + ); + + const entryNodesLevels = visData.map((levelData) => + levelData.entryIds.map((id) => id2searchNode[id]) + ); + + const { targetShowTime, nodeShowTime, linkShowTime, duration } = + computeSearchViewTransition({ + linksLevels: searchLinksLevels, + entryNodesLevels, + interLevelGap: searchInterLevelTime, + intraLevelGap: searchIntraLevelTime, + }); + + return { + visData, + id2forcePos, + searchTarget, + entryNodesLevels, + searchNodesLevels, + searchLinksLevels, + searchLayerPosLevels: layerPosLevels, + searchTargetShowTime: targetShowTime, + searchNodeShowTime: nodeShowTime, + searchLinkShowTime: linkShowTime, + searchTransitionDuration: duration, + searchParams: searchRecords.searchParams, + }; +}; diff --git a/federjs/FederLayout/visDataHandler/hnsw/search/parseVisRecords.ts b/federjs/FederLayout/visDataHandler/hnsw/search/parseVisRecords.ts new file mode 100644 index 0000000..8873cb8 --- /dev/null +++ b/federjs/FederLayout/visDataHandler/hnsw/search/parseVisRecords.ts @@ -0,0 +1,113 @@ +import { EHnswNodeType, EHnswLinkType, TId } from "Types"; +import { TSearchRecordsHnsw } from "Types/searchRecords"; +import { getLinkId, parseLinkId } from "./utils"; + +export const parseVisRecords = ({ + topkResults, + searchRecords, +}: TSearchRecordsHnsw) => { + const visData = []; + const numLevels = searchRecords.length; + let fineIds = topkResults.map((d) => d.id); + let entryId = -1; + for (let i = numLevels - 1; i >= 0; i--) { + const level = numLevels - 1 - i; + if (level > 0) { + fineIds = [entryId]; + } + + const visRecordsLevel = searchRecords[i]; + + const id2nodeType = {}; + const linkId2linkType = {}; + const updateNodeType = (nodeId: TId, type: EHnswNodeType) => { + if (id2nodeType[nodeId]) { + id2nodeType[nodeId] = Math.max(id2nodeType[nodeId], type); + } else { + id2nodeType[nodeId] = type; + } + }; + const updateLinkType = ( + sourceId: TId, + targetId: TId, + type: EHnswLinkType + ) => { + const linkId = getLinkId(sourceId, targetId); + if (linkId2linkType[linkId]) { + linkId2linkType[linkId] = Math.max(linkId2linkType[linkId], type); + } else { + linkId2linkType[linkId] = type; + } + }; + const id2dist = {}; + const sourceMap = {}; + + visRecordsLevel.forEach((record) => { + const [sourceId, targetId, dist] = record; + + if (sourceId === targetId) { + // entry + entryId = targetId; + id2dist[targetId] = dist; + } else { + updateNodeType(sourceId, EHnswNodeType.Candidate); + updateNodeType(targetId, EHnswNodeType.Coarse); + + if (id2dist[targetId] >= 0) { + // visited + updateLinkType(sourceId, targetId, EHnswLinkType.Visited); + } else { + // not visited + id2dist[targetId] = dist; + updateLinkType(sourceId, targetId, EHnswLinkType.Extended); + + sourceMap[targetId] = sourceId; + + // only level-0 have "link_type - search" + if (level === 0) { + const preSourceId = sourceMap[sourceId]; + if (preSourceId >= 0) { + updateLinkType(preSourceId, sourceId, EHnswLinkType.Searched); + } + } + } + } + }); + + fineIds.forEach((fineId) => { + updateNodeType(fineId, EHnswNodeType.Fine); + + let t = fineId; + while (t in sourceMap) { + let s = sourceMap[t]; + updateLinkType(s, t, EHnswLinkType.Fine); + t = s; + } + }); + + const nodes = Object.keys(id2nodeType).map((id) => ({ + id: `${id}`, + type: id2nodeType[id], + dist: id2dist[id], + })); + const links = Object.keys(linkId2linkType).map((linkId) => { + const [source, target] = parseLinkId(linkId); + return { + source: `${source}`, + target: `${target}`, + type: linkId2linkType[linkId], + }; + }); + const visDataLevel = { + entryIds: [`${entryId}`], + fineIds: fineIds.map((id) => `${id}`), + links, + nodes, + }; + visData.push(visDataLevel); + } + + return visData; +}; + +export default parseVisRecords; diff --git a/federjs/FederLayout/visDataHandler/hnsw/search/transformHandler.ts b/federjs/FederLayout/visDataHandler/hnsw/search/transformHandler.ts new file mode 100644 index 0000000..5415f49 --- /dev/null +++ b/federjs/FederLayout/visDataHandler/hnsw/search/transformHandler.ts @@ -0,0 +1,47 @@ +import * as d3 from 'd3'; + +export const transformHandler = ( + nodes, + { levelCount, width, height, padding, xBias = 0.65, yBias = 0.4, yOver = 0.1 } +) => { + const layerWidth = width - padding[1] - padding[3]; + const layerHeight = + (height - padding[0] - padding[2]) / + (levelCount - (levelCount - 1) * yOver); + const xRange = d3.extent(nodes, (node: any) => node.x) as [number, number]; + const yRange = d3.extent(nodes, (node: any) => node.y) as [number, number]; + + const xOffset = padding[3] + layerWidth * xBias; + const transformFunc = (x, y, level) => { + const _x = (x - xRange[0]) / (xRange[1] - xRange[0]); + const _y = (y - yRange[0]) / (yRange[1] - yRange[0]); + + const newX = + xOffset + _x * layerWidth * (1 - xBias) - _y * layerWidth * xBias; + + const newY = + padding[0] + + layerHeight * (1 - yOver) * (levelCount - 1 - level) + + _x * layerHeight * (1 - yBias) + + _y * layerHeight * yBias; + + return [newX, newY]; + }; + const layerPos = [ + [layerWidth * xBias, 0], + [layerWidth, layerHeight * (1 - yBias)], + [layerWidth * (1 - xBias), layerHeight], + [0, layerHeight * yBias], + ]; + const layerPosLevels = Array(levelCount).fill(0).map((_, level) => + layerPos.map((coord) => [ + coord[0] + padding[3], + coord[1] + + padding[0] + + layerHeight * (1 - yOver) * (levelCount - 1 - level), + ]) + ); + return { layerPosLevels, transformFunc }; +}; + +export default transformHandler; diff --git a/federjs/FederLayout/visDataHandler/hnsw/search/utils.ts b/federjs/FederLayout/visDataHandler/hnsw/search/utils.ts new file mode 100644 index 0000000..7ff6d4b --- /dev/null +++ b/federjs/FederLayout/visDataHandler/hnsw/search/utils.ts @@ -0,0 +1,39 @@ +import { TId } from "Types"; + +const connection = "---"; + +export const getLinkId = (sourceId: TId, targetId: TId) => + `${sourceId}${connection}${targetId}`; + +export const parseLinkId = (linkId: string) => + linkId.split(connection).map((d) => +d); + +export const getLinkIdWithLevel = ( + sourceId: TId, + targetId: TId, + level: number +) => `link-${level}-${sourceId}-${targetId}`; + +export const getNodeIdWithLevel = (nodeId: TId, level: number) => + `node-${level}-${nodeId}`; + +export const getEntryLinkIdWithLevel = (nodeId: TId | string, level: number) => + `inter-level-${level}-${nodeId}`; + +export const deDupLink = ( + links: any[], + source = "source", + target = "target" +) => { + const linkStringSet = new Set(); + return links.filter((link) => { + const linkString = `${link[source]}---${link[target]}`; + const linkStringReverse = `${link[target]}---${link[source]}`; + if (linkStringSet.has(linkString) || linkStringSet.has(linkStringReverse)) { + return false; + } else { + linkStringSet.add(linkString); + return true; + } + }); +}; diff --git a/federjs/FederView/ViewHandler.ts b/federjs/FederView/ViewHandler.ts new file mode 100644 index 0000000..83f5a00 --- /dev/null +++ b/federjs/FederView/ViewHandler.ts @@ -0,0 +1,8 @@ +import { TViewParams } from 'Types'; +import { TVisData } from 'Types/visData'; + +export default interface TViewHandler { + node: HTMLElement; + init(visData: TVisData, viewParams: TViewParams): void; + render(): void; +} diff --git a/federjs/FederView/hnswView/HnswSearchHnsw3dView.ts b/federjs/FederView/hnswView/HnswSearchHnsw3dView.ts new file mode 100644 index 0000000..89cd85a --- /dev/null +++ b/federjs/FederView/hnswView/HnswSearchHnsw3dView.ts @@ -0,0 +1,1331 @@ +import { TViewParams } from 'Types'; +import { TVisData, TVisDataHnsw3d } from 'Types/visData'; +import TViewHandler from '../ViewHandler'; +import InfoPanel from 'FederView/InfoPanel'; +import * as THREE from 'three'; +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; +import { MeshLine, MeshLineMaterial, MeshLineRaycast } from 'three.meshline'; +import { MeshBasicMaterial } from 'three'; +import { hnswlibHNSWSearch } from 'FederIndex/searchHandler/hnswSearch'; +import anime from 'animejs/lib/anime.es.js'; + +const defaultViewParams = { + width: 800, + height: 600, +}; + +export const HNSW_NODE_TYPE = { + Coarse: 1, + Candidate: 2, + Fine: 3, + Target: 4, +}; + +export default class HnswSearchHnsw3dView implements TViewHandler { + node: HTMLElement; + staticPanel: InfoPanel; + clickedPanel: InfoPanel; + hoveredPanel: InfoPanel; + canvas: HTMLCanvasElement; + visData: TVisDataHnsw3d; + static colors = { + candidateBlue: 0x175fff, + searchedYellow: 0xfffc85, + fineOrange: 0xf36e4b, + targetWhite: 0xffffff, + labelGreen: 0x7fff7c, + }; + selectedLayer = -1; + lastSelectedLayer = -1; + intervalId: number; + + //threejs stuff + longerLineMap = new Map(); + longerDashedLineMap = new Map(); + layerUi: HTMLDivElement; + scene: THREE.Scene; + camera: THREE.OrthographicCamera; + renderer: THREE.WebGLRenderer; + spheres: THREE.Mesh[] = []; + targetSpheres: THREE.Mesh[] = []; + planes: THREE.Mesh[] = []; + lines: THREE.Mesh[] = []; + controller: OrbitControls; + canvasWidth: number; + canvasHeight: number; + minX = Infinity; + minY = Infinity; + maxX = -Infinity; + maxY = -Infinity; + scenes: THREE.Scene[] = []; + pickingScene: THREE.Scene; + sphere2id = new Map(); + static defaultCamera = { + position: { + isVector3: true, + x: 85.73523132349014, + y: 21.163507502655282, + z: 46.92095544735611, + }, + rotation: { + isEuler: true, + x: -0.42372340871438785, + y: 1.0301035872063589, + z: 0.36899315353677475, + order: 'XYZ', + }, + zoom: 0.14239574134637464, + }; + dashedLines: THREE.Mesh[] = []; + orangeLines: THREE.Mesh[] = []; + pickingTarget: THREE.WebGLRenderTarget; + pickingMap: Map< + number, + THREE.Mesh + >; + objectsPerLayer: Map = new Map(); //存储每一层的mesh,包括节点、连接线、plane + moveObjects: THREE.Mesh[] = []; + playerUi: HTMLDivElement; + playBtn: HTMLDivElement; + resetBtn: HTMLDivElement; + prevBtn: HTMLDivElement; + nextBtn: HTMLDivElement; + originCamBtn: HTMLDivElement; + static stopHtml = ` + + + + + + `; + static playHtml = ` + + + + + `; + played: boolean; + currentSceneIndex: number; + slider: HTMLInputElement; + + get k() { + return this.visData.searchRecords.searchParams.k; + } + + constructor(visData: TVisData, viewParams: TViewParams) { + this.staticPanel = new InfoPanel(); + this.clickedPanel = new InfoPanel(); + this.hoveredPanel = new InfoPanel(); + this.init(visData, viewParams); + } + + addCss() { + //create a div element + this.layerUi = document.createElement('div'); + //flex column display + this.layerUi.style.display = 'flex'; + this.layerUi.style.flexDirection = 'column'; + this.layerUi.style.position = 'absolute'; + this.layerUi.style.top = '0'; + this.layerUi.style.right = '0'; + + this.layerUi.style.height = '100%'; + //center justify + this.layerUi.style.justifyContent = 'center'; + this.node.style.position = 'relative'; + const style = document.createElement('style'); + style.innerHTML = ` + .layer-ui{ + position: absolute; + top: 0; + right: 0; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: center; + pointer-events: none; + } + .layer-ui-item{ + justify-content: center; + align-items: center; + display: flex; + transition: transform 0.3s; + } + + .layer-ui-item-inner-circle{ + width:12px; + height:12px; + border-radius: 50%; + background-color: #fff; + position: relative; + + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + .layer-ui-item-outer-circle{ + width:32px; + height:32px; + border-radius: 50%; + border: 1px dashed #fff; + opacity: 0.3; + } + .layer-ui-item-outer-circle:hover{ + boxShadow: 0 0 10px white; + opacity: 1; + border: 1px solid #fff; + } + .hnsw-search-hnsw3d-view-player-ui{ + position: absolute; + bottom: -128; + flex-direction: column; + display: flex; + height:128px; + } + .hnsw-search-hnsw3d-view-player-ui-row{ + display: flex; + flex-direction: row; + justify-content: space-between; + flex: 1; + } + .hnsw-search-hnsw3d-view-player-ui-row-item{ + display: flex; + flex-direction: row; + justify-content:left; + align-items: center; + flex: 1; + } + .hnsw-search-hnsw3d-view-player-ui-row-item > .icon{ + margin-right: 15px; + } + .hnsw-search-hnsw3d-view-player-ui-row-item > .icon:hover{ + cursor: pointer; + } + .hnsw-search-hnsw3d-view-player-ui-row > input{ + width: 100%; + background: rgba(255,255,255,0.3); + } + .hnsw-search-hnsw3d-view-player-ui-row > input::-webkit-slider-thumb{ + -webkit-appearance: none; + appearance: none; + visibility: hidden; + } + .hnsw-search-hnsw3d-view-player-ui-row > input::-moz-range-thumb{ + visibility: hidden; + } + //focus style + .hnsw-search-hnsw3d-view-player-ui-row > input:focus{ + outline: none; + } + //track style + .hnsw-search-hnsw3d-view-player-ui-row > input::-webkit-slider-runnable-track{ + width: 100%; + background: rgba(255,255,255); + } + .hnsw-search-hnsw3d-view-player-ui-row > input::-moz-range-track{ + width: 100%; + background: rgba(255,255,255,0.3); + } + .hnsw-search-hnsw3d-view-player-ui-row > input::-ms-track{ + width: 100%; + background: rgba(255,255,255,0.3); + } + `; + + //hover glow bloom + document.head.appendChild(style); + } + + createCircleDom() { + const circleDom = document.createElement('div'); + circleDom.classList.add('layer-ui-item'); + const parentDiv = document.createElement('div'); + parentDiv.classList.add('layer-ui-item-outer-circle'); + //hover cursor pointer + parentDiv.style.cursor = 'pointer'; + parentDiv.style.marginBottom = '16px'; + parentDiv.style.transition = 'box-shadow 0.3s'; + parentDiv.style.transition = 'opacity 0.3s'; + + const childDiv = document.createElement('div'); + // + childDiv.classList.add('layer-ui-item-inner-circle'); + + parentDiv.appendChild(childDiv); + + circleDom.appendChild(parentDiv); + return circleDom; + } + + setUpLayerUi() { + this.addCss(); + //create a div element + this.layerUi = document.createElement('div'); + //flex column display + this.layerUi.style.display = 'flex'; + this.layerUi.style.flexDirection = 'column'; + this.layerUi.style.position = 'absolute'; + this.layerUi.style.top = '0'; + this.layerUi.style.right = '0'; + this.node.style.width = '1200px'; + this.layerUi.style.height = '100%'; + //center justify + this.layerUi.style.justifyContent = 'center'; + this.node.style.position = 'relative'; + + const adjustLayout = () => { + //make all div above ith layer translateY(100%) + const children = this.layerUi.children; + for (let i = 0; i < children.length; i++) { + const child = children[i]; + if (this.selectedLayer <= i) { + (child as HTMLDivElement).style.transform = 'translateY(0)'; + } else { + (child as HTMLDivElement).style.transform = 'translateY(-100%)'; + } + } + }; + + const highlightLayer = () => { + const children = this.layerUi.children; + for (let i = 0; i < children.length; i++) { + const child = children[i]; + if (this.selectedLayer === i) { + (child.children[0] as HTMLDivElement).style.boxShadow = + '0 0 10px white'; + (child.children[0] as HTMLDivElement).style.opacity = '1'; + (child.children[0] as HTMLDivElement).style.border = '1px solid #fff'; + } else { + (child.children[0] as HTMLDivElement).style.boxShadow = 'none'; + (child.children[0] as HTMLDivElement).style.opacity = '0.3'; + (child.children[0] as HTMLDivElement).style.border = + '1px dashed #fff'; + } + } + }; + + //create circleDoms represent layers + for (let i = 0; i < this.visData.searchRecords.searchRecords.length; i++) { + const circleDom = this.createCircleDom(); + let toggled = false; + circleDom.children[0].addEventListener('click', () => { + if(this.played){ + return; + } + if (this.selectedLayer !== i) { + this.selectedLayer = i; + } else { + this.selectedLayer = -1; + } + adjustLayout(); + this.startTransition(); + highlightLayer(); + this.lastSelectedLayer = this.selectedLayer; + }); + //add circleDom to layerUi + this.layerUi.appendChild(circleDom); + } + this.node.appendChild(this.layerUi); + } + + startTransition() { + debugger; + if (this.lastSelectedLayer !== this.selectedLayer) { + //iterate all the scene objects + for (let i = 0; i < this.scene.children.length; i++) { + const child = this.scene.children[i]; + //if the object userdata.longer is true + if (child.userData.longer) { + debugger; + const layer = parseInt(child.userData.layer.split('-')[1]); + if (this.selectedLayer === layer) { + child.visible = true; + } else { + child.visible = false; + } + } else if (typeof child.userData.layer === 'string') { + const layer = parseInt(child.userData.layer.split('-')[1]); + if (this.selectedLayer === layer) { + child.visible = false; + } else { + child.visible = true; + } + } + } + + //计算diff + const lastOffsets = new Array( + this.visData.searchRecords.searchRecords.length + ) + .fill(undefined) + .map((v, idx) => { + return idx < this.lastSelectedLayer ? 1200 : 0; + }); + const offsets = new Array(this.visData.searchRecords.searchRecords.length) + .fill(undefined) + .map((v, idx) => { + return idx < this.selectedLayer ? 1200 : 0; + }); + const diff = offsets.map((v, idx) => v - lastOffsets[idx]); + this.scene.children.forEach((obj, idx) => { + if ( + obj instanceof THREE.Mesh && + obj.userData.layer !== undefined && + !obj.userData.longer + ) { + let layer = obj.userData.layer; + //layer type is string + if (typeof layer === 'string') { + layer = parseInt(layer.split('-')[0]); + } + const offset = diff[layer]; + + //animejs animation + anime({ + targets: obj.position, + y: obj.position.y + offset, + duration: 200, + easing: 'easeInOutQuad', + }); + } + }); + this.pickingScene.children.forEach((pickingObj) => { + if ( + pickingObj instanceof THREE.Mesh && + pickingObj.userData.layer !== undefined + ) { + let layer = pickingObj.userData.layer; + if (typeof layer === 'string') { + layer = parseInt(layer.split('-')[0]); + } + const offset = diff[layer]; + pickingObj.position.y += offset; + } + }); + } + } + + init(visData: TVisData, viewParams: TViewParams) { + this.visData = visData as TVisDataHnsw3d; + console.log(visData); + const searchRecords = this.visData.searchRecords; + console.log(searchRecords); + this.node = document.createElement('div'); + this.setUpLayerUi(); + this.node.className = 'hnsw-search-hnsw3d-view'; + viewParams = Object.assign({}, defaultViewParams, viewParams); + this.canvasWidth = viewParams.width; + this.canvasHeight = viewParams.height; + this.node.style.width = `${this.canvasWidth}px`; + this.node.style.height = `${this.canvasHeight}px`; + this.setupCanvas(); + this.setupRenderer(); + this.setupScene(); + this.parseSearchRecords(); + this.setupPickingScene(); + this.setupEventListeners(); + this.setupCamera(); + this.setupController(); + this.setupPlayerUi(); + } + + setupPlayerUi() { + this.playerUi = document.createElement('div'); + this.playerUi.className = 'hnsw-search-hnsw3d-view-player-ui'; + this.node.appendChild(this.playerUi); + this.playerUi.style.width = `${this.canvasWidth}px`; + //white border + this.playerUi.style.border = '1px solid white'; + + //1st row + const row1 = document.createElement('div'); + row1.className = 'hnsw-search-hnsw3d-view-player-ui-row'; + this.playerUi.appendChild(row1); + //set row1 innnerHTML + row1.innerHTML = ` +
+
+ + + + +
+
+ + + + + + + + + + + +
+
+
+ + +
+
+
+ + + + + + + + + + +
+
+ `; + + this.playBtn = this.playerUi.querySelector('.play') as HTMLDivElement; + this.resetBtn = this.playerUi.querySelector('.replay') as HTMLDivElement; + this.prevBtn = this.playerUi.querySelector('.prev') as HTMLDivElement; + this.nextBtn = this.playerUi.querySelector('.next') as HTMLDivElement; + this.originCamBtn = this.playerUi.querySelector( + '.origin-cam' + ) as HTMLDivElement; + this.playBtn.addEventListener('click', () => { + console.log('play'); + + this.play(); + }); + this.resetBtn.addEventListener('click', () => { + this.currentSceneIndex = 0; + this.slider.value = '0'; + }); + this.prevBtn.addEventListener('click', () => { + console.log('prev'); + this.currentSceneIndex = Math.max(0, this.currentSceneIndex - 1); + this.slider.value = this.currentSceneIndex.toString(); + }); + this.nextBtn.addEventListener('click', () => { + console.log('next'); + this.currentSceneIndex = Math.min( + this.currentSceneIndex + 1, + this.scenes.length - 1 + ); + this.slider.value = `${this.currentSceneIndex}`; + }); + this.originCamBtn.addEventListener('click', () => { + console.log('origin cam'); + this.resetCamera(); + }); + + //2nd row + const row2 = document.createElement('div'); + row2.className = 'hnsw-search-hnsw3d-view-player-ui-row'; + this.playerUi.appendChild(row2); + //create a slider + const slider = document.createElement('input'); + slider.type = 'range'; + slider.min = '0'; + slider.max = (this.scenes.length - 1).toString(); + slider.value = slider.max; + this.currentSceneIndex = this.scenes.length - 1; + slider.className = 'hnsw-search-hnsw3d-view-player-ui-slider'; + slider.addEventListener('input', () => { + this.currentSceneIndex = parseInt(slider.value); + this.played = false; + this.playBtn.innerHTML = HnswSearchHnsw3dView.playHtml; + }); + row2.appendChild(slider); + this.slider = slider; + } + play() { + this.played = !this.played; + if (this.played) { + this.playBtn.innerHTML = HnswSearchHnsw3dView.stopHtml; + this.intervalId = window.setInterval(() => { + if (this.played) { + this.currentSceneIndex++; + if (this.currentSceneIndex >= this.scenes.length) { + this.currentSceneIndex = 0; + } + //update slider + this.slider.value = this.currentSceneIndex.toString(); + } + }, 300); + } else { + this.playBtn.innerHTML = HnswSearchHnsw3dView.playHtml; + window.clearInterval(this.intervalId); + } + } + + createLine( + from: THREE.Vector3, + to: THREE.Vector3, + color: number | THREE.Texture, + width = 10 + ) { + const line = new MeshLine(); + line.setPoints([from.x, from.y, from.z, to.x, to.y, to.z]); + let material: MeshLineMaterial; + if (color instanceof THREE.Texture) { + material = new MeshLineMaterial({ + useMap: true, + transparent: true, + map: color, + opacity: 1, + lineWidth: width, + }); + } else { + material = new MeshLineMaterial({ + color: new THREE.Color(color), + lineWidth: width, + }); + } + + const mesh = new THREE.Mesh(line, material); + return mesh; + } + + createSphere(x: number, y: number, z: number, color: number) { + const geometry = new THREE.SphereGeometry(20); + const material = new THREE.MeshBasicMaterial({ + color: new THREE.Color(color), + }); + const sphere = new THREE.Mesh(geometry, material); + sphere.position.set(x, y, z); + return sphere; + } + + stepTo(steps: number) {} + + getPositionXZ(id: number) { + const { id2forcePos } = this.visData; + const pos = id2forcePos[id]; + return { x: pos[0], z: pos[1] }; + } + + //change sphere color + changeSphereColor(sphere: THREE.Mesh, color: number) { + //clone sphere + const material = new THREE.MeshBasicMaterial({ + color: new THREE.Color(color), + }); + const geometry = sphere.geometry.clone(); + const newSphere = new THREE.Mesh(geometry, material); + newSphere.name = sphere.name; + newSphere.position.copy(sphere.position); + // copy userData + newSphere.userData = sphere.userData; + this.scene.remove(sphere); + this.scene.add(newSphere); + // (newSphere.material as MeshBasicMaterial).color = new THREE.Color(color); + } + + async wait(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + + createGradientTexture(color1: number, color2: number) { + const canvas = document.createElement('canvas'); + canvas.width = 256; + canvas.height = 256; + const ctx = canvas.getContext('2d'); + const gradient = ctx.createLinearGradient(0, 0, 256, 0); + gradient.addColorStop(0, '#' + color1.toString(16)); + gradient.addColorStop(1, '#' + color2.toString(16)); + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, 256, 256); + const texture = new THREE.CanvasTexture(canvas); + return texture; + } + + parseSearchRecords() { + let y0 = 0; + const { searchRecords } = this.visData.searchRecords; + + //建立id与sphere的映射 + let sphere2idArray: Map< + THREE.Mesh, + number + >[] = []; + let id2sphereArray: Map< + number, + THREE.Mesh + >[] = []; + let id2lineArray: Map>[] = []; + + for (let i = 0; i < searchRecords.length; i++) { + let records = searchRecords[i]; + const sphere2id = new Map< + THREE.Mesh, + number + >(); + const id2sphere = new Map< + number, + THREE.Mesh + >(); + const id2line = new Map>(); + + for (let j = 0; j < records.length; j++) { + const record = records[j]; + const startNode = record[0]; + const endNode = record[1]; + const { x: x0, z: z0 } = this.getPositionXZ(startNode); + const { x: x1, z: z1 } = this.getPositionXZ(endNode); + if (!id2line.has(`${startNode}-${endNode}`)) { + const line = this.createLine( + new THREE.Vector3(x0, y0, z0), + new THREE.Vector3(x1, y0, z1), + 0x000000 + ); + line.userData = { + layer: i, + }; + this.scene.add(line); + line.visible = false; + line.name = `${startNode}-${endNode}`; + id2line.set(`${startNode}-${endNode}`, line); + } + if (!id2sphere.has(startNode)) { + const startNodeSphere = this.createSphere( + x0, + y0, + z0, + HnswSearchHnsw3dView.colors.searchedYellow + ); + startNodeSphere.visible = false; + startNodeSphere.name = `${startNode}`; + startNodeSphere.userData = { + layer: i, + }; + this.scene.add(startNodeSphere); + id2sphere.set(startNode, startNodeSphere); + sphere2id.set(startNodeSphere, startNode); + } + if (!id2sphere.has(endNode)) { + const endNodeSphere = this.createSphere( + x1, + y0, + z1, + HnswSearchHnsw3dView.colors.searchedYellow + ); + endNodeSphere.visible = false; + endNodeSphere.name = `${endNode}`; + endNodeSphere.userData = { + layer: i, + }; + this.scene.add(endNodeSphere); + id2sphere.set(endNode, endNodeSphere); + sphere2id.set(endNodeSphere, endNode); + } + } + y0 += -400; + sphere2idArray.push(sphere2id); + id2sphereArray.push(id2sphere); + id2lineArray.push(id2line); + } + + y0 = 0; + const topVisitedNodes: { id: number; distance: number }[] = []; + for (let i = 0; i < searchRecords.length; i++) { + const records = searchRecords[i]; + const visited = new Set(); + + const firstRecord = records[0]; + let lastVisited = firstRecord[0]; + if (i === 0) { + const targetSphere = this.createSphere( + 0, + 0, + 0, + HnswSearchHnsw3dView.colors.targetWhite + ); + targetSphere.userData = { + layer: i, + }; + this.scene.add(targetSphere); + this.targetSpheres.push(targetSphere); + } + for (let j = 0; j < records.length; j++) { + const record = records[j]; + const startNode = record[0]; + const endNode = record[1]; + const distance = record[2]; + const { x: x0, z: z0 } = this.getPositionXZ(startNode); + const { x: x1, z: z1 } = this.getPositionXZ(endNode); + const startNodeSphere = id2sphereArray[i].get(startNode); + const endNodeSphere = id2sphereArray[i].get(endNode); + const line = id2lineArray[i].get(`${startNode}-${endNode}`); + + if (startNodeSphere) { + if ( + i === searchRecords.length - 1 && + !topVisitedNodes.find((v) => v.id === endNode) + ) { + topVisitedNodes.push({ id: endNode, distance }); + } + startNodeSphere.visible = true; + this.changeSphereColor( + startNodeSphere, + HnswSearchHnsw3dView.colors.searchedYellow + ); + visited.add(startNode); + if (lastVisited !== startNode) { + const line = id2lineArray[i].get(`${lastVisited}-${startNode}`); + if (line) { + //create yellow texture + const texture = this.createGradientTexture( + 0xffffff00, + HnswSearchHnsw3dView.colors.searchedYellow + ); + //delete line + this.scene.remove(line); + //create line connect to startNodeSphere from lastVisitedSphere + const { x: x2, z: z2 } = this.getPositionXZ(lastVisited); + const line2 = this.createLine( + new THREE.Vector3(x2, y0, z2), + new THREE.Vector3(x0, y0, z0), + texture + ); + line2.userData = { + layer: i, + }; + this.scene.add(line2); + id2lineArray[i].set(`${lastVisited}-${startNode}`, line2); + } else if (i === searchRecords.length - 1) { + //当发现需要回溯访问过的节点时 + //find line whose name has startNode + const id2line = id2lineArray[i]; + const key = Array.from(id2line.keys()).find((key) => + key.includes(`-${startNode}`) + ); + const line = id2line.get(key); + if (line) { + //create yellow texture + const texture = this.createGradientTexture( + 0xffffff00, + HnswSearchHnsw3dView.colors.searchedYellow + ); + //delete line + this.scene.remove(line); + //parse line name + const [start, end] = key.split('-').map((v) => parseInt(v)); + //create line connect start and end + const { x: x0, z: z0 } = this.getPositionXZ(start); + const { x: x1, z: z1 } = this.getPositionXZ(end); + const line2 = this.createLine( + new THREE.Vector3(x0, y0, z0), + new THREE.Vector3(x1, y0, z1), + texture + ); + line2.userData = { + layer: i, + }; + this.scene.add(line2); + line2.name = `${start}-${end}`; + id2lineArray[i].set(`${start}-${end}`, line2); + } + } + } + } + if (endNodeSphere && !visited.has(endNode)) { + endNodeSphere.visible = true; + this.changeSphereColor( + endNodeSphere, + HnswSearchHnsw3dView.colors.candidateBlue + ); + } + if (line && !visited.has(endNode)) { + let texture = null; + texture = this.createGradientTexture( + 0xffffff00, + HnswSearchHnsw3dView.colors.candidateBlue + ); + const newLine = this.createLine( + new THREE.Vector3(x0, y0, z0), + new THREE.Vector3(x1, y0, z1), + texture + ); + newLine.userData = { + layer: i, + }; + + this.scene.remove(line); + this.scene.add(newLine); + id2lineArray[i].set(`${startNode}-${endNode}`, newLine); + } + + lastVisited = startNode; + + this.scenes.push(this.scene.clone()); + } + let nextLevelMap = id2sphereArray[i + 1]; + if (nextLevelMap) { + const nextLevelSphere = nextLevelMap.get(lastVisited); + if (nextLevelSphere) { + this.changeSphereColor( + nextLevelSphere, + HnswSearchHnsw3dView.colors.searchedYellow + ); + nextLevelSphere.visible = true; + const currentLevelSphere = id2sphereArray[i].get(lastVisited); + if (currentLevelSphere) { + this.changeSphereColor( + currentLevelSphere, + HnswSearchHnsw3dView.colors.fineOrange + ); + } + //create line connecting current level and next level + const orangeYellowTexture = this.createGradientTexture( + HnswSearchHnsw3dView.colors.fineOrange, + HnswSearchHnsw3dView.colors.searchedYellow + ); + const { x: x0, z: z0 } = this.getPositionXZ(lastVisited); + const { x: x1, z: z1 } = this.getPositionXZ(lastVisited); + const line = this.createLine( + new THREE.Vector3(x0, y0, z0), + new THREE.Vector3(x1, y0 - 400, z1), + orangeYellowTexture + ); + line.userData = { + layer: `${i}-${i + 1}`, + }; + this.orangeLines.push(line); + const longerLine = this.createLine( + new THREE.Vector3(x0, y0 + 1200, z0), + new THREE.Vector3(x1, y0 - 400, z1), + orangeYellowTexture + ); + longerLine.userData = { + layer: `${i}-${i + 1}`, + longer: true, + }; + longerLine.visible = false; + this.longerLineMap.set(`${i}-${i + 1}`, longerLine); + this.scene.add(longerLine); + this.scene.add(line); + } + } + //处理最终的橙色情况 + if (i === searchRecords.length - 1) { + //sort topVisitedNodes in ascending order + topVisitedNodes.sort((a, b) => a.distance - b.distance); + //get ef search parameter + const k = this.k; + //get top ef nodes + const topEfNodes = topVisitedNodes.slice(0, k); + //change color of top ef nodes to orange + for (let j = 0; j < topEfNodes.length; j++) { + const { id } = topEfNodes[j]; + const sphere = id2sphereArray[i].get(id); + if (sphere) { + this.changeSphereColor( + sphere, + HnswSearchHnsw3dView.colors.fineOrange + ); + } + } + this.scenes.push(this.scene.clone()); + } + + //layer切换创建新的target连接线 + if (i < searchRecords.length - 1) { + //create a white sphere + const targetSphere = this.createSphere( + 0, + y0 - 400, + 0, + HnswSearchHnsw3dView.colors.targetWhite + ); + targetSphere.userData = { + layer: i + 1, + }; + this.targetSpheres.push(targetSphere); + this.scene.add(targetSphere); + const dashedMaterial = new MeshLineMaterial({ + color: new THREE.Color(HnswSearchHnsw3dView.colors.targetWhite), + lineWidth: 10, + dashed: true, + dashArray: 0.1, + dashRatio: 0.5, + transparent: true, + }); + + const line = new MeshLine(); + line.setPoints([0, y0, 0, 0, y0 - 400, 0]); + const mesh = new THREE.Mesh(line.geometry, dashedMaterial); + mesh.userData = { + layer: `${i}-${i + 1}`, + }; + this.dashedLines.push(mesh); + + const dashedMaterial2= new MeshLineMaterial({ + color: new THREE.Color(HnswSearchHnsw3dView.colors.targetWhite), + lineWidth: 10, + dashed: true, + dashArray: 0.025, + dashRatio: 0.5, + transparent: true, + }); + const longerDashedLineGeometry = new MeshLine(); + longerDashedLineGeometry.setPoints([0, y0 + 1200, 0, 0, y0 - 400, 0]); + const longerDashedLine = new THREE.Mesh( + longerDashedLineGeometry, + dashedMaterial2 + ); + longerDashedLine.userData = { + layer: `${i}-${i + 1}`, + longer: true, + }; + longerDashedLine.visible = false; + this.scene.add(longerDashedLine); + this.longerDashedLineMap.set(`${i}-${i + 1}`, longerDashedLine); + + this.scene.add(mesh); + if (i === searchRecords.length - 2) { + const targetSphere = this.createSphere( + 0, + y0 - 400, + 0, + HnswSearchHnsw3dView.colors.targetWhite + ); + targetSphere.userData = { + layer: i + 1, + }; + this.targetSpheres.push(targetSphere); + this.scene.add(targetSphere); + } + } + y0 += -400; + } + } + + createDashedLineTexture( + backgroundColor = 0x00000000, + color = 0xffffff00, + dashSize = 20, + gapSize = 10 + ) { + const canvas = document.createElement('canvas'); + canvas.width = 128; + canvas.height = 1; + const context = canvas.getContext('2d'); + context.fillStyle = `#${backgroundColor.toString(16)}`; + context.fillRect(0, 0, canvas.width, canvas.height); + context.strokeStyle = `#${color.toString(16)}`; + context.lineWidth = 10; + context.beginPath(); + context.setLineDash([dashSize, gapSize]); + context.moveTo(0, 0); + context.lineTo(canvas.width, canvas.height); + context.stroke(); + const texture = new THREE.Texture(canvas); + texture.needsUpdate = true; + return texture; + } + + setupPickingScene() { + // create picking scene + this.pickingScene = new THREE.Scene(); + this.pickingTarget = new THREE.WebGLRenderTarget( + this.renderer.domElement.width, + this.renderer.domElement.height + ); + this.pickingScene.background = new THREE.Color(0x000000); + let count = 1; + this.pickingMap = new Map(); + const pickingMaterial = new THREE.MeshBasicMaterial({ + vertexColors: true, + }); + this.scene.traverse((obj) => { + if (obj instanceof THREE.Mesh) { + //check if the object is a sphere + if (obj.geometry.type === 'SphereGeometry') { + const geometry = obj.geometry.clone(); + //apply vertex color to picking mesh + let color = new THREE.Color(); + applyVertexColors(geometry, color.setHex(count)); + const pickingMesh = new THREE.Mesh(geometry, pickingMaterial); + pickingMesh.position.copy(obj.position); + pickingMesh.rotation.copy(obj.rotation); + pickingMesh.scale.copy(obj.scale); + pickingMesh.userData = obj.userData; + pickingMesh.name = obj.name; + this.pickingScene.add(pickingMesh); + this.pickingMap.set(count, pickingMesh); + count++; + } + } + }); + const pickingPlaneMaterial = new THREE.MeshBasicMaterial({ + vertexColors: true, + }); + + //create a plane for each layer + for (let i = 0; i < this.visData.searchRecords.searchRecords.length; i++) { + let geometry = this.planes[i].clone().geometry.clone(); + //set vertex color for plane + let color = new THREE.Color(); + applyVertexColors(geometry, color.setHex(count)); + const plane = new THREE.Mesh(geometry, pickingPlaneMaterial); + const { x, y, z } = this.planes[i].position; + const scale = this.planes[i].scale; + plane.scale.set(scale.x, scale.y, scale.z); + plane.position.set(x, y, z); + plane.rotation.x = -Math.PI / 2; + plane.scale.set(1.2, 1.2, 1.2); + plane.name = `plane${i}`; + plane.userData = { layer: i }; + this.pickingScene.add(plane); + this.pickingMap.set(count, plane); + count += 0x000042; + } + } + + //add event listener to the canvas + setupEventListeners() { + this.renderer.domElement.addEventListener('click', (event) => { + //pointer = { x: e.offsetX, y: e.offsetY }; + + let id = this.pick(event.offsetX, event.offsetY); + //console.log(id); + const obj = this.pickingMap.get(id); + console.log('picked', obj.userData, obj.name); + //if picking a plane + if (obj?.name?.startsWith('plane')) { + const layer = obj.userData.layer; + console.log(layer); + } + }); + } + + pick(x: number, y: number) { + if (x < 0 || y < 0) return -1; + const pixelRatio = this.renderer.getPixelRatio(); + // console.log(pixelRatio, x, y); + // set the view offset to represent just a single pixel under the mouse + this.camera.setViewOffset( + this.canvas.clientWidth, + this.canvas.clientHeight, + x * pixelRatio, + y * pixelRatio, + 1, + 1 + ); + // render the scene + this.renderer.setRenderTarget(this.pickingTarget); + this.renderer.render(this.pickingScene, this.camera); + this.renderer.setRenderTarget(null); + //clear the view offset so the camera returns to normal + this.camera.clearViewOffset(); + // get the pixel color under the mouse + const pixelBuffer = new Uint8Array(4); + this.renderer.readRenderTargetPixels( + this.pickingTarget, + 0, + 0, + 1, + 1, + pixelBuffer + ); + const id = (pixelBuffer[0] << 16) | (pixelBuffer[1] << 8) | pixelBuffer[2]; + return id; + } + + createPlaneGradientTexture() { + const canvas = document.createElement('canvas'); + canvas.width = 256; + canvas.height = 256; + const ctx = canvas.getContext('2d'); + const gradient = ctx.createLinearGradient(0, 0, 0, 256); + gradient.addColorStop(0, 'rgba(30, 100, 255, 1)'); + gradient.addColorStop(1, 'rgba(0, 35, 77, 0)'); + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, 256, 256); + //draw white borders 1px + ctx.fillStyle = '#D9EAFF'; + ctx.fillRect(0, 0, 1, 256); + ctx.fillRect(0, 0, 256, 1); + ctx.fillRect(0, 255, 256, 1); + ctx.fillRect(255, 0, 1, 256); + const texture = new THREE.Texture(canvas); + texture.needsUpdate = true; + return texture; + } + + drawBorderLine(from: THREE.Vector3, to: THREE.Vector3, color: string) { + const line = new MeshLine(); + line.setPoints([from.x, from.y, from.z, to.x, to.y, to.z]); + const material = new MeshLineMaterial({ + color: new THREE.Color(color), + lineWidth: 0.01, + sizeAttenuation: false, + }); + const mesh = new THREE.Mesh(line, material); + this.scene.add(mesh); + } + + setupPlanes() { + let z0 = -30; + const { visData } = this.visData; + for (let i = visData.length - 1; i >= 0; i--) { + //add planes + const width = this.maxX - this.minX; + const height = this.maxY - this.minY; + const planeGeometry = new THREE.PlaneGeometry(width, height); + const texture = this.createPlaneGradientTexture(); + const planeMaterial = new THREE.MeshBasicMaterial({ + map: texture, + side: THREE.DoubleSide, + transparent: true, + opacity: 0.5, + depthWrite: false, + }); + const plane = new THREE.Mesh(planeGeometry, planeMaterial); + plane.rotation.x = Math.PI / 2; + plane.position.z = (this.maxY + this.minY) / 2; + plane.position.x = (this.maxX + this.minX) / 2; + plane.scale.set(1.2, 1.2, 1.2); + plane.position.y = z0; + plane.name = `plane${i}`; + plane.userData = { layer: visData.length - 1 - i }; + z0 += -400; + this.planes.push(plane); + } + console.log(this.planes); + } + + computeBoundries() { + const { visData } = this.visData; + console.log(visData); + for (let i = visData.length - 1; i >= 0; i--) { + const { nodes } = visData[i]; + for (let j = 0; j < nodes.length; j++) { + const node = nodes[j]; + const { id, x, y, type } = node; + this.maxX = Math.max(this.maxX, x); + this.maxY = Math.max(this.maxY, y); + this.minX = Math.min(this.minX, x); + this.minY = Math.min(this.minY, y); + } + } + } + + render() { + //render + const render = (t) => { + //update camera zoom + //change dashed line offset + if (this.dashedLines.length > 0) { + this.dashedLines.forEach((line) => { + line.material.uniforms.dashOffset.value -= 0.01; + }); + this.longerDashedLineMap.forEach((line) => { + (line.material as any).uniforms.dashOffset.value -= 0.0025; + }); + } + this.controller.update(); + if (this.currentSceneIndex !== undefined) { + this.scene = this.scenes[this.currentSceneIndex]; + } + this.renderer.render(this.scene, this.camera); + + requestAnimationFrame(render); + }; + requestAnimationFrame(render); + } + + private setupController() { + this.controller = new OrbitControls(this.camera, this.canvas); + this.controller.enableZoom = true; + this.controller.enablePan = true; + this.controller.enableDamping = true; + this.controller.enableRotate = true; + } + + private setupCamera() { + this.camera = new THREE.OrthographicCamera( + -this.canvas.width / 2, + this.canvas.width / 2, + this.canvas.height / 2, + -this.canvas.height / 2, + -4000, + 4000 + ); + //default camera position + this.camera.position.set( + HnswSearchHnsw3dView.defaultCamera.position.x, + HnswSearchHnsw3dView.defaultCamera.position.y, + HnswSearchHnsw3dView.defaultCamera.position.z + ); + this.camera.rotation.set( + HnswSearchHnsw3dView.defaultCamera.rotation.x, + HnswSearchHnsw3dView.defaultCamera.rotation.y, + HnswSearchHnsw3dView.defaultCamera.rotation.z + ); + this.camera.zoom = HnswSearchHnsw3dView.defaultCamera.zoom; + this.camera.updateProjectionMatrix(); + } + + private resetCamera() { + this.camera.position.set( + HnswSearchHnsw3dView.defaultCamera.position.x, + HnswSearchHnsw3dView.defaultCamera.position.y, + HnswSearchHnsw3dView.defaultCamera.position.z + ); + this.camera.rotation.set( + HnswSearchHnsw3dView.defaultCamera.rotation.x, + HnswSearchHnsw3dView.defaultCamera.rotation.y, + HnswSearchHnsw3dView.defaultCamera.rotation.z + ); + this.camera.zoom = HnswSearchHnsw3dView.defaultCamera.zoom; + this.camera.updateProjectionMatrix(); + } + + private setupScene() { + this.scene = new THREE.Scene(); + this.computeBoundries(); + this.setupPlanes(); + this.scene.add(...this.planes); + } + + private setupRenderer() { + this.renderer = new THREE.WebGLRenderer({ + canvas: this.canvas, + antialias: true, + }); + this.renderer.setSize(this.canvas.width, this.canvas.height); + } + + setupCanvas() { + this.canvas = document.createElement('canvas'); + this.node.appendChild(this.canvas); + this.canvas.width = this.canvasWidth; + this.canvas.height = this.canvasHeight; + } +} +/** + * + * @param {THREE.Geometry} geometry + * @param {THREE.Color } color + */ +function applyVertexColors(geometry: THREE.BufferGeometry, color: THREE.Color) { + const positions = geometry.getAttribute('position'); + const colors = []; + for (let i = 0; i < positions.count; i++) { + colors.push(color.r, color.g, color.b); + } + geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3)); +} diff --git a/federjs/FederView/hnswView/HnswSearchView.ts b/federjs/FederView/hnswView/HnswSearchView.ts new file mode 100644 index 0000000..723fed7 --- /dev/null +++ b/federjs/FederView/hnswView/HnswSearchView.ts @@ -0,0 +1,21 @@ +import { TViewParams } from 'Types'; +import { TVisData } from 'Types/visData'; +import TViewHandler from '../ViewHandler'; + +import InfoPanel from 'FederView/InfoPanel'; + +export default class HnswSearchView implements TViewHandler { + node: HTMLElement; + staticPanel: InfoPanel; + clickedPanel: InfoPanel; + hoveredPanel: InfoPanel; + constructor(visData: TVisData, viewParams: TViewParams) { + this.staticPanel = new InfoPanel(); + this.clickedPanel = new InfoPanel(); + this.hoveredPanel = new InfoPanel(); + + this.init(visData, viewParams); + } + init(visData: TVisData, viewParams: TViewParams) {} + render() {} +} \ No newline at end of file diff --git a/federjs/FederView/index.ts b/federjs/FederView/index.ts new file mode 100644 index 0000000..6315762 --- /dev/null +++ b/federjs/FederView/index.ts @@ -0,0 +1,30 @@ +import { TVisDataAll } from 'Types/visData'; +import { TViewParams, EIndexType, EActionType, EViewType } from 'Types'; + +import HnswSearchHnsw3dView from './hnswView/HnswSearchHnsw3dView'; +import HnswSearchView from './hnswView/HnswSearchView'; +import ViewHandler from './ViewHandler'; + +const viewMap = { + [EIndexType.hnsw + EActionType.search + EViewType.hnsw3d]: + HnswSearchHnsw3dView, + [EIndexType.hnsw + EActionType.search + EViewType.default]: + HnswSearchView, +}; +export class FederView { + node: HTMLElement; + view: ViewHandler; + constructor( + { indexType, actionType, viewType, visData }: TVisDataAll, + viewParams: TViewParams + ) { + this.view = new viewMap[indexType + actionType + viewType]( + visData, + viewParams + ); + } + + render() { + this.view.render(); + } +} diff --git a/federjs/FederView/infoPanel/index.ts b/federjs/FederView/infoPanel/index.ts new file mode 100644 index 0000000..723689b --- /dev/null +++ b/federjs/FederView/infoPanel/index.ts @@ -0,0 +1,12 @@ +import { TCoord, TViewParams } from 'Types'; + +export interface TInfoPanelStyles {} + +export interface TInfoPanelContext {} + +export default class infoPanel { + constructor(styles: TInfoPanelStyles = {}, viewParams: TViewParams = {}) {} + init() {} + setContext(context: TInfoPanelContext = null) {} + setPosition(pos: TCoord = null) {} +} diff --git a/federjs/Types/index.ts b/federjs/Types/index.ts new file mode 100644 index 0000000..3b2c953 --- /dev/null +++ b/federjs/Types/index.ts @@ -0,0 +1,64 @@ +export type TVec = number[]; +export type TId = number; +export type TCoord = [number, number]; + +export enum ESourceType { + faiss = 'faiss', + hnswlib = 'hnswlib', + milvus = 'milvus', +} + +export enum EIndexType { + hnsw = 'hnsw', + ivfflat = 'ivfflat', +} + +export enum EMetricType { + METRIC_INNER_PRODUCT = 0, ///< maximum inner product search + METRIC_L2 = 1, ///< squared L2 search + METRIC_L1 = 2, ///< L1 (aka cityblock) + METRIC_Linf = 3, ///< infinity distance + METRIC_Lp = 4, ///< L_p distance, p is given by a faiss::Index + /// metric_arg + + /// some additional metrics defined in scipy.spatial.distance + METRIC_Canberra = 20, + METRIC_BrayCurtis = 21, + METRIC_JensenShannon = 22, +} + +export enum EActionType { + overview = 'overview', + search = 'search', +} + +export enum EViewType { + default = 'default', + hnsw3d = 'hnsw3d', +} + +export interface TSearchParams { + k: number; + ef?: number; + nprobe?: number; + metricType?: EMetricType; +} + +export enum EHnswNodeType { + Coarse = 1, + Candidate = 2, + Fine = 3, + Target = 4, +} + +export enum EHnswLinkType { + None = 0, + Visited = 1, + Extended = 2, + Searched = 3, + Fine = 4, +} + +export type TViewParams = any; + +export type TLayoutParams = any; diff --git a/federjs/Types/indexMeta/index.ts b/federjs/Types/indexMeta/index.ts new file mode 100644 index 0000000..f2cbf78 --- /dev/null +++ b/federjs/Types/indexMeta/index.ts @@ -0,0 +1,21 @@ +import { + IIndexMetaHnsw, + TIndexMetaHnswGraphNode, + TIndexMetaHnswGraph, +} from "./indexMetaHnsw"; + +import { + TIndexMetaIvfflat, + TIndexMetaIvfflatCluster, +} from "./indexMetaIvfflat"; + +type TIndexMeta = TIndexMetaIvfflat | IIndexMetaHnsw; + +export { + TIndexMeta, + IIndexMetaHnsw, + TIndexMetaHnswGraphNode, + TIndexMetaHnswGraph, + TIndexMetaIvfflat, + TIndexMetaIvfflatCluster, +}; diff --git a/federjs/Types/indexMeta/indexMetaHnsw.ts b/federjs/Types/indexMeta/indexMetaHnsw.ts new file mode 100644 index 0000000..6f233e0 --- /dev/null +++ b/federjs/Types/indexMeta/indexMetaHnsw.ts @@ -0,0 +1,22 @@ +import { TId } from "Types"; + +export interface TIndexMetaHnswGraphNode { + id: TId; + links: TId[]; +} + +export interface TIndexMetaHnswGraph { + level: number; + nodes: TIndexMetaHnswGraphNode[]; +} + +export interface IIndexMetaHnsw { + efConstruction: number; + M: number; + ntotal: number; + ndeleted: number; + nLevels: number; + entryPointId: TId; + nOverviewLevels: number; + overviewGraphLayers: TIndexMetaHnswGraph[]; +} \ No newline at end of file diff --git a/federjs/Types/indexMeta/indexMetaIvfflat.ts b/federjs/Types/indexMeta/indexMetaIvfflat.ts new file mode 100644 index 0000000..da1c1b1 --- /dev/null +++ b/federjs/Types/indexMeta/indexMetaIvfflat.ts @@ -0,0 +1,14 @@ +import { TVec, TId } from "Types"; + +export interface TIndexMetaIvfflatCluster { + clusterId: TId; + ids: TId[]; + centroidVectors: TVec[]; +} + +export interface TIndexMetaIvfflat { + nlist: number; + ntotal: number; + ndeleted: number; + clusters: TIndexMetaIvfflatCluster[]; +} diff --git a/federjs/Types/searchRecords/index.ts b/federjs/Types/searchRecords/index.ts new file mode 100644 index 0000000..0fe6926 --- /dev/null +++ b/federjs/Types/searchRecords/index.ts @@ -0,0 +1,23 @@ +import { + TSearchRecordsHnswLayerItem, + TSearchRecordsHnswLayer, + TSearchRecordsHnsw, +} from "./searchRecordsHnsw"; + +import { + TSearchRecordsIvfflatCoarseCluster, + TSearchRecordsIvfflatFineNode, + TSearchRecordsIvfflat, +} from "./searchRecordsIvfflat"; + +type TSearchRecords = TSearchRecordsIvfflat | TSearchRecordsHnsw; + +export { + TSearchRecords, + TSearchRecordsHnswLayerItem, + TSearchRecordsHnswLayer, + TSearchRecordsHnsw, + TSearchRecordsIvfflatCoarseCluster, + TSearchRecordsIvfflatFineNode, + TSearchRecordsIvfflat, +}; diff --git a/federjs/Types/searchRecords/searchRecordsHnsw.ts b/federjs/Types/searchRecords/searchRecordsHnsw.ts new file mode 100644 index 0000000..1b5aa5c --- /dev/null +++ b/federjs/Types/searchRecords/searchRecordsHnsw.ts @@ -0,0 +1,16 @@ +import { TId } from "Types"; + +export type TSearchRecordsHnswLayerItem = [TId, TId, number]; + +export type TSearchRecordsHnswLayer = TSearchRecordsHnswLayerItem[]; + +export interface TSearchRecordsHnswTopkResultItem { + id: TId; + distance: number; +} + +export interface TSearchRecordsHnsw { + searchRecords: TSearchRecordsHnswLayer[]; + topkResults: TSearchRecordsHnswTopkResultItem[]; + searchParams: any; +} diff --git a/federjs/Types/searchRecords/searchRecordsIvfflat.ts b/federjs/Types/searchRecords/searchRecordsIvfflat.ts new file mode 100644 index 0000000..ee98736 --- /dev/null +++ b/federjs/Types/searchRecords/searchRecordsIvfflat.ts @@ -0,0 +1,21 @@ +import { TVec, TId } from "Types"; + +export interface TSearchRecordsIvfflatCoarseCluster { + clusterId: TId; + distance: number; + vector: TVec; +} + +export interface TSearchRecordsIvfflatFineNode { + id: TId; + clusterId: TId; + distance: number; + vector: TVec; +} + +export interface TSearchRecordsIvfflat { + coarseSearchRecords: TSearchRecordsIvfflatCoarseCluster[]; + nprobeClusterIds: TId[]; + fineSearchRecords: TSearchRecordsIvfflatFineNode[]; + topKVectorIds: TId[]; +} diff --git a/federjs/Types/visData/index.ts b/federjs/Types/visData/index.ts new file mode 100644 index 0000000..8d8d858 --- /dev/null +++ b/federjs/Types/visData/index.ts @@ -0,0 +1,128 @@ +import { EActionType, EIndexType, EViewType, TSearchParams, TVec } from 'Types'; + +export type TVisData = any; +export interface TVisDataAll { + indexType: EIndexType; + actionType: EActionType; + actionData?: TAcitonData; + viewType: EViewType; + visData: TVisData; +} + +export interface TAcitonData { + target: TVec; + targetUrl?: string; + searchParams: TSearchParams; +} + +export interface TopkResult { + id: number; + internalId: number; + dis: number; +} + +export interface SearchParams { + k: number; + ef: number; +} + +export interface SearchRecords { + searchRecords: number[][][]; + topkResults: TopkResult[]; + searchParams: SearchParams; +} + +export interface TVisDataHnsw3d { + visData: VisDaum[]; + id2forcePos: Id2forcePos; + searchTarget: SearchTarget; + entryNodesLevels: EntryNodesLevel[][]; + searchNodesLevels: SearchNodesLevel[][]; + searchLinksLevels: SearchLinksLevel[][]; + searchRecords: SearchRecords; +} + +export interface VisDaum { + entryIds: string[]; + fineIds: string[]; + links: Link[]; + nodes: Node[]; +} + +export interface Link { + source: any; + target: any; + type: number; + index?: number; +} + +export interface Node { + id: string; + type: number; + dist: number; + forcePos: number[]; + x: number; + y: number; + searchViewPosLevels: any[][]; + r: number; +} + +export interface Id2forcePos { + [key: string]: number[]; +} + +export interface SearchTarget { + id: string; + r: number; + searchViewPosLevels: any[][]; +} + +export interface EntryNodesLevel { + id: string; + type: number; + dist: number; + forcePos: number[]; + x: number; + y: number; + searchViewPosLevels: any[][]; + r: number; +} + +export interface SearchNodesLevel { + id: string; + type: number; + dist: number; + forcePos: number[]; + x: number; + y: number; + searchViewPosLevels: any[][]; + r: number; +} + +export interface SearchLinksLevel { + source: Source; + target: Target; + type: number; +} + +export interface Source { + id: string; + type: number; + dist: number; + forcePos: number[]; + x: number; + y: number; + searchViewPosLevels: any[][]; + r: number; +} + +export interface Target { + id: string; + type: number; + dist: number; + forcePos: number[]; + x: number; + y: number; + searchViewPosLevels: any[][]; + r: number; +} diff --git a/federjs/Utils/PriorityQueue.js b/federjs/Utils/PriorityQueue.js new file mode 100644 index 0000000..b95c76a --- /dev/null +++ b/federjs/Utils/PriorityQueue.js @@ -0,0 +1,78 @@ +//Minimum Heap +class PriorityQueue { + constructor(arr = [], key = null) { + if (typeof key == 'string') { + this._key = (item) => item[key]; + } else this._key = key; + this._tree = []; + arr.forEach((d) => this.add(d)); + } + add(item) { + this._tree.push(item); + let id = this._tree.length - 1; + while (id) { + const fatherId = Math.floor((id - 1) / 2); + if (this._getValue(id) >= this._getValue(fatherId)) break; + else { + this._swap(fatherId, id); + id = fatherId; + } + } + } + get top() { + return this._tree[0]; + } + pop() { + if (this.isEmpty) { + return 'empty'; + } + const item = this.top; + if (this._tree.length > 1) { + const lastItem = this._tree.pop(); + let id = 0; + this._tree[id] = lastItem; + while (!this._isLeaf(id)) { + const curValue = this._getValue(id); + const leftId = id * 2 + 1; + const leftValue = this._getValue(leftId); + const rightId = leftId >= this._tree.length - 1 ? leftId : id * 2 + 2; + const rightValue = this._getValue(rightId); + const minValue = Math.min(leftValue, rightValue); + if (curValue <= minValue) break; + else { + const minId = leftValue < rightValue ? leftId : rightId; + this._swap(minId, id); + id = minId; + } + } + } else { + this._tree = []; + } + return item; + } + get isEmpty() { + return this._tree.length === 0; + } + get size() { + return this._tree.length; + } + get _firstLeaf() { + return Math.floor(this._tree.length / 2); + } + _isLeaf(id) { + return id >= this._firstLeaf; + } + _getValue(id) { + if (this._key) { + return this._key(this._tree[id]); + } else { + return this._tree[id]; + } + } + _swap(id0, id1) { + const tree = this._tree; + [tree[id0], tree[id1]] = [tree[id1], tree[id0]]; + } +} + +export default PriorityQueue; diff --git a/federjs/Utils/distFunc.ts b/federjs/Utils/distFunc.ts new file mode 100644 index 0000000..b2317f9 --- /dev/null +++ b/federjs/Utils/distFunc.ts @@ -0,0 +1,24 @@ +import { EMetricType, TVec } from "Types"; + +export const getDisL2 = (vec1: TVec, vec2: TVec) => { + return Math.sqrt( + vec1 + .map((num, i) => num - vec2[i]) + .map((num) => num * num) + .reduce((a, c) => a + c, 0) + ); +}; + +export const getDisIR = (vec1: TVec, vec2: TVec) => { + return vec1.map((num, i) => num * vec2[i]).reduce((acc, cur) => acc + cur, 0); +}; + +export const getDisFunc = (metricType: EMetricType) => { + if (metricType === EMetricType.METRIC_L2) { + return getDisL2; + } else if (metricType === EMetricType.METRIC_INNER_PRODUCT) { + return getDisIR; + } + console.warn("[getDisFunc] wrong metric_type, use L2 (default).", metricType); + return getDisL2; +}; diff --git a/federjs/index.ts b/federjs/index.ts new file mode 100644 index 0000000..454668d --- /dev/null +++ b/federjs/index.ts @@ -0,0 +1,5 @@ +import { FederIndex } from "FederIndex"; +import { FederLayout } from "FederLayout"; +import { FederView } from "FederView"; + +export { FederIndex, FederLayout, FederView }; diff --git a/federjs_old/Feder.js b/federjs_old/Feder.js new file mode 100644 index 0000000..36fb76a --- /dev/null +++ b/federjs_old/Feder.js @@ -0,0 +1,142 @@ +import FederCore from './FederCore'; +import FederView from './FederView'; +import { FEDER_CORE_REQUEST } from 'Types'; + +export default class Feder { + constructor({ + coreUrl = null, + filePath = '', + source = '', + domSelector = null, + viewParams = {}, + }) { + this.federView = new FederView({ domSelector, viewParams }); + this.viewParams = viewParams; + if (!coreUrl) { + this.initCoreAndViewPromise = fetch(filePath, { mode: 'cors' }) + .then((res) => res.arrayBuffer()) + .then((data) => { + const core = new FederCore({ data, source, viewParams }); + this.core = core; + const indexType = core.indexType; + const indexMeta = core.indexMeta; + const getVectorById = (id) => + id in core.id2vector ? core.id2vector[id] : null; + this.core.getVectorById = getVectorById; + this.federView.initView({ + indexType, + indexMeta, + getVectorById, + }); + }); + } else { + const getUrl = (path) => `${coreUrl}/${path}?`; + + const requestData = (path, params = {}) => + fetch(getUrl(path) + new URLSearchParams(params), { + mode: 'cors', + }) + .then((res) => res.json()) + .then((res) => { + if (res.message === 'succeed') return res.data; + else throw new Error(res); + }); + + this.initCoreAndViewPromise = new Promise(async (resolve) => { + const indexType = await requestData(FEDER_CORE_REQUEST.get_index_type); + const indexMeta = await requestData(FEDER_CORE_REQUEST.get_index_meta); + const getVectorById = (id) => + requestData(FEDER_CORE_REQUEST.get_vector_by_id, { id }); + this.core = { + indexType, + indexMeta, + getVectorById, + getTestIdAndVec: () => + requestData(FEDER_CORE_REQUEST.get_test_id_and_vector), + search: (target) => + requestData(FEDER_CORE_REQUEST.search, { target }), + setSearchParams: (params) => + requestData(FEDER_CORE_REQUEST.set_search_params, params), + }; + this.federView.initView({ indexType, indexMeta, getVectorById }); + resolve(); + }); + } + + this.setSearchParamsPromise = null; + } + + overview() { + return this.federView.overview(this.initCoreAndViewPromise); + } + search(target = null, targetMediaUrl = null) { + if (target) { + const searchResPromise = Promise.all([ + this.initCoreAndViewPromise, + this.setSearchParamsPromise, + ]).then(async () => { + const searchRes = await this.core.search(target); + console.log(searchRes); + this.searchRes = searchRes; + this.targetMediaUrl = targetMediaUrl; + return { searchRes, targetMediaUrl }; + }); + return this.federView.search({ searchResPromise }); + } else { + if (!this.searchRes) { + console.error('No target'); + return; + } + const searchRes = this.searchRes; + const targetMediaUrl = this.targetMediaUrl; + return this.federView.search({ searchRes, targetMediaUrl }); + } + } + searchById(testId) { + const searchResPromise = this.initCoreAndViewPromise.then(async () => { + const testVec = await this.core.getVectorById(testId); + const targetMediaUrl = + this.viewParams && this.viewParams.mediaCallback + ? this.viewParams.mediaCallback(testId) + : null; + const searchRes = await this.core.search(testVec); + console.log(searchRes); + this.searchRes = searchRes; + return { searchRes, targetMediaUrl }; + }); + return this.federView.search({ searchResPromise }); + } + searchRandTestVec() { + const searchResPromise = new Promise(async (resolve) => { + this.initCoreAndViewPromise && (await this.initCoreAndViewPromise); + let { testId, testVec } = await this.core.getTestIdAndVec(); + while (isNaN(testId)) { + [testId, testVec] = await this.core.getTestIdAndVec(); + } + console.log('random test vector:', testId, testVec); + const targetMediaUrl = + this.viewParams && this.viewParams.mediaCallback + ? this.viewParams.mediaCallback(testId) + : null; + const searchRes = await this.core.search(testVec); + console.log(searchRes); + this.searchRes = searchRes; + resolve({ searchRes, targetMediaUrl }); + }); + + return this.federView.search({ searchResPromise }); + } + + setSearchParams(params) { + this.setSearchParamsPromise = new Promise(async (resolve) => { + this.initCoreAndViewPromise && (await this.initCoreAndViewPromise); + if (!this.core) { + console.error('No feder-core'); + } else { + await this.core.setSearchParams(params); + } + resolve(); + }); + return this; + } +} diff --git a/federjs_old/FederCore/index.js b/federjs_old/FederCore/index.js new file mode 100644 index 0000000..0fcd8ca --- /dev/null +++ b/federjs_old/FederCore/index.js @@ -0,0 +1,89 @@ +import getIndexParser from './parser'; +import getMetaHandler from './metaHandler'; +import getIndexSearchHandler from './searchHandler'; +import getProjectorHandler from './projector'; +import seedrandom from 'seedrandom'; +import { INDEX_TYPE } from 'Types'; +export default class FederCore { + constructor({ + data, // arraybuffer + source, + viewParams, + }) { + try { + this.viewParams = viewParams; + const index = this.parserIndex(data, source); + this.index = index; + this.indexType = index.indexType; + + const { indexMeta, id2vector } = this.extractMeta(index, viewParams); + this.indexMeta = indexMeta; + this.id2vector = id2vector; + + this.indexSearchHandler = getIndexSearchHandler(index.indexType); + } catch (e) { + console.log(e); + } + } + parserIndex(data, source) { + const indexParser = getIndexParser(source); + const index = indexParser(data); + return index; + } + extractMeta(index, viewParams = {}) { + const metaHandler = getMetaHandler(index.indexType); + const meta = metaHandler(index, viewParams); + return meta; + } + getTestIdAndVec() { + const ids = Object.keys(this.id2vector); + const r = Math.floor(Math.random() * ids.length); + const testId = ids[r]; + const testVec = this.id2vector[testId]; + return [testId, testVec]; + } + + setSearchParams(params) { + const newSearchParams = Object.assign({}, this.searchParams, params); + this.searchParams = newSearchParams; + } + search(target) { + const searchRes = this.indexSearchHandler({ + index: this.index, + params: this.searchParams, + target, + }); + + if (this.index.indexType === INDEX_TYPE.ivf_flat) { + const { + fineSearchWithProjection = true, + projectMethod = 'umap', + projectSeed = null, + projectParams = {}, + } = this.viewParams; + if (fineSearchWithProjection) { + const ids = searchRes.fine.map((item) => item.id); + const params = projectParams; + if (!!projectSeed) { + params.random = seedrandom(projectSeed); + } + this.initProjector({ + method: projectMethod, + params, + }); + const projections = this.projectByIds(ids); + searchRes.fine.map((item, i) => (item.projection = projections[i])); + } + } + + return searchRes; + } + + initProjector({ method, params = {} }) { + this.project = getProjectorHandler({ method, params }); + } + projectByIds(ids) { + const vectors = ids.map((id) => this.id2vector[id]); + return this.project(vectors); + } +} diff --git a/federjs_old/FederCore/metaHandler/hnswMeta/hnswOverviewData.js b/federjs_old/FederCore/metaHandler/hnswMeta/hnswOverviewData.js new file mode 100644 index 0000000..4cbb0c5 --- /dev/null +++ b/federjs_old/FederCore/metaHandler/hnswMeta/hnswOverviewData.js @@ -0,0 +1,54 @@ +const getHnswlibHNSWOverviewData = ({ index, overviewLevelCount = 3 }) => { + const { maxLevel, linkLists_levels, labels, enterPoint } = index; + const highlevel = Math.min(maxLevel, overviewLevelCount); + const lowlevel = maxLevel - highlevel; + + const highLevelNodes = linkLists_levels + .map((linkLists_levels_item, internalId) => + linkLists_levels_item.length > lowlevel + ? { + internalId, + id: labels[internalId], + linksLevels: linkLists_levels_item.slice( + lowlevel, + linkLists_levels_item.length + ), + path: [], + } + : null + ) + .filter((d) => d); + // console.log('highLevelNodes', highLevelNodes) + + const internalId2node = {}; + highLevelNodes.forEach((node) => { + internalId2node[node.internalId] = node; + }); + + let queue = [enterPoint]; + let start = 0; + internalId2node[enterPoint].path = []; + for (let level = highlevel - 1; level >= 0; level--) { + while (start < queue.length) { + const curNodeId = queue[start]; + const curNode = internalId2node[curNodeId]; + const candidateNodes = curNode.linksLevels[level]; + candidateNodes.forEach((candidateNodeId) => { + const candidateNode = internalId2node[candidateNodeId]; + if (candidateNode.path.length === 0 && candidateNodeId !== enterPoint) { + candidateNode.path = [...curNode.path, curNodeId]; + queue.push(candidateNodeId); + } + }); + start += 1; + } + queue = highLevelNodes + .filter((node) => node.linksLevels.length > level) + .map((node) => node.internalId); + start = 0; + } + + return highLevelNodes; +}; + +export default getHnswlibHNSWOverviewData; diff --git a/federjs_old/FederCore/metaHandler/hnswMeta/index.js b/federjs_old/FederCore/metaHandler/hnswMeta/index.js new file mode 100644 index 0000000..2b40d7b --- /dev/null +++ b/federjs_old/FederCore/metaHandler/hnswMeta/index.js @@ -0,0 +1,26 @@ +import getHnswlibHNSWOverviewData from './hnswOverviewData'; +export const getHnswMeta = (index, { overviewLevelCount = 3 }) => { + const { labels, vectors } = index; + + const id2vector = {}; + labels.forEach((id, i) => { + id2vector[id] = vectors[i]; + }); + + const overviewNodes = getHnswlibHNSWOverviewData({ + index, + overviewLevelCount, + }); + const indexMeta = { + ntotal: index.ntotal, + M: index.M, + ef_construction: index.ef_construction, + overviewLevelCount, + levelCount: index.maxLevel + 1, + overviewNodes, + }; + + return { id2vector, indexMeta }; +}; + +export default getHnswMeta; diff --git a/federjs_old/FederCore/metaHandler/index.js b/federjs_old/FederCore/metaHandler/index.js new file mode 100644 index 0000000..f7b6bfc --- /dev/null +++ b/federjs_old/FederCore/metaHandler/index.js @@ -0,0 +1,17 @@ +import { INDEX_TYPE } from 'Types'; +import getHnswMeta from './hnswMeta'; +import getIvfflatMeta from './ivfflatMeta'; + + +const metaHandlerMap = { + [INDEX_TYPE.hnsw]: getHnswMeta, + [INDEX_TYPE.ivf_flat]: getIvfflatMeta, +}; + +export const getMetaHandler = (indexType) => { + if (indexType in metaHandlerMap) { + return metaHandlerMap[indexType]; + } else throw `No meta handler for [${indexType}]`; +}; + +export default getMetaHandler; diff --git a/federjs_old/FederCore/metaHandler/ivfflatMeta/index.js b/federjs_old/FederCore/metaHandler/ivfflatMeta/index.js new file mode 100644 index 0000000..0957e2c --- /dev/null +++ b/federjs_old/FederCore/metaHandler/ivfflatMeta/index.js @@ -0,0 +1,42 @@ +import { getIvfListId } from 'Utils'; +import getProjectorHandler from 'FederCore/projector'; +import seedrandom from 'seedrandom'; + +export const getIvfflatMeta = (index, params) => { + const id2vector = {}; + const inv = index.invlists; + for (let list_no = 0; list_no < inv.nlist; list_no++) { + inv.data[list_no].ids.forEach((id, ofs) => { + id2vector[id] = inv.data[list_no].vectors[ofs]; + }); + } + index.childIndex.vectors.forEach( + (vector, i) => (id2vector[getIvfListId(i)] = vector) + ); + + const indexMeta = {}; + indexMeta.ntotal = index.ntotal; + indexMeta.nlist = index.nlist; + indexMeta.listIds = index.invlists.data.map((d) => d.ids); + indexMeta.listSizes = index.invlists.data.map((d) => d.ids.length); + + const { + coarseSearchWithProjection = true, + projectMethod = 'umap', + projectSeed = null, + projectParams = {}, + } = params; + if (coarseSearchWithProjection) { + const params = Object.assign({}, projectParams); + if (!!projectSeed) { + params.random = seedrandom(projectSeed); + } + const project = getProjectorHandler({ method: projectMethod, params }); + const vectors = index.childIndex.vectors; + indexMeta.listCentroidProjections = project(vectors); + } + + return { id2vector, indexMeta }; +}; + +export default getIvfflatMeta; diff --git a/federjs_old/FederCore/parser/FileReader.js b/federjs_old/FederCore/parser/FileReader.js new file mode 100644 index 0000000..90f900f --- /dev/null +++ b/federjs_old/FederCore/parser/FileReader.js @@ -0,0 +1,72 @@ +import { generateArray } from 'Utils'; + +export default class FileReader { + constructor(arrayBuffer) { + this.data = arrayBuffer; + this.dataview = new DataView(arrayBuffer); + + this.p = 0; + } + get isEmpty() { + return this.p >= this.data.byteLength; + } + readInt8() { + const int8 = this.dataview.getInt8(this.p, true); + this.p += 1; + return int8; + } + readUint8() { + const uint8 = this.dataview.getUint8(this.p, true); + this.p += 1; + return uint8; + } + readBool() { + const int8 = this.readInt8(); + return Boolean(int8); + } + readUint16() { + const uint16 = this.dataview.getUint16(this.p, true); + this.p += 2; + return uint16; + } + readInt32() { + const int32 = this.dataview.getInt32(this.p, true); + this.p += 4; + return int32; + } + readUint32() { + const uint32 = this.dataview.getUint32(this.p, true); + this.p += 4; + return uint32; + } + readUint64() { + const left = this.readUint32(); + const right = this.readUint32(); + const int64 = left + Math.pow(2, 32) * right; + if (!Number.isSafeInteger(int64)) + console.warn(int64, 'Exceeds MAX_SAFE_INTEGER. Precision may be lost'); + return int64; + } + readFloat64() { + const float64 = this.dataview.getFloat64(this.p, true); + this.p += 8; + return float64; + } + readDouble() { + return this.readFloat64(); + } + + readUint32Array(n) { + const res = generateArray(n).map((_) => this.readUint32()); + return res; + } + readFloat32Array(n) { + const res = new Float32Array(this.data.slice(this.p, this.p + n * 4)); + this.p += n * 4; + return res; + } + readUint64Array(n) { + const res = generateArray(n).map((_) => this.readUint64()); + return res; + } +} diff --git a/federjs_old/FederCore/parser/faissIndexParser/FaissFileReader.js b/federjs_old/FederCore/parser/faissIndexParser/FaissFileReader.js new file mode 100644 index 0000000..5c3a73b --- /dev/null +++ b/federjs_old/FederCore/parser/faissIndexParser/FaissFileReader.js @@ -0,0 +1,17 @@ +import FileReader from '../FileReader.js'; +import { uint8toChars, generateArray } from 'Utils'; + +export default class FaissFileReader extends FileReader { + constructor(arrayBuffer) { + super(arrayBuffer); + } + readH() { + const uint8Array = generateArray(4).map((_) => this.readUint8()); + const h = uint8toChars(uint8Array); + return h; + } + readDummy() { + const dummy = this.readUint64(); + return dummy; + } +} diff --git a/federjs_old/FederCore/parser/faissIndexParser/index.js b/federjs_old/FederCore/parser/faissIndexParser/index.js new file mode 100644 index 0000000..3b810d2 --- /dev/null +++ b/federjs_old/FederCore/parser/faissIndexParser/index.js @@ -0,0 +1,51 @@ +import FaissFileReader from './FaissFileReader.js'; +import readInvertedLists from './readInvertedLists.js'; +import readDirectMap from './readDirectMap.js'; +import readIndexHeader from './readIndexHeader.js'; + +import { generateArray } from 'Utils'; +import { INDEX_TYPE, IndexHeader } from 'Types'; + +const readIvfHeader = (reader, index) => { + readIndexHeader(reader, index); + + index.nlist = reader.readUint64(); + index.nprobe = reader.readUint64(); + + index.childIndex = readIndex(reader); + + readDirectMap(reader, index); +}; + +const readXbVectors = (reader, index) => { + index.codeSize = reader.readUint64(); + + index.vectors = generateArray(index.ntotal).map((_) => + reader.readFloat32Array(index.d) + ); +}; + +const readIndex = (reader) => { + const index = {}; + index.h = reader.readH(); + if (index.h === IndexHeader.IVFFlat) { + index.indexType = INDEX_TYPE.ivf_flat; + readIvfHeader(reader, index); + readInvertedLists(reader, index); + } else if (index.h === IndexHeader.FlatIR || index.h === IndexHeader.FlatL2) { + index.indexType = INDEX_TYPE.flat; + readIndexHeader(reader, index); + readXbVectors(reader, index); + } else { + console.warn('[index type] not supported -', index.h); + } + return index; +}; + +const faissIndexParser = (arraybuffer) => { + const faissFileReader = new FaissFileReader(arraybuffer); + const index = readIndex(faissFileReader); + return index; +}; + +export default faissIndexParser; diff --git a/federjs_old/FederCore/parser/faissIndexParser/readDirectMap.js b/federjs_old/FederCore/parser/faissIndexParser/readDirectMap.js new file mode 100644 index 0000000..2927181 --- /dev/null +++ b/federjs_old/FederCore/parser/faissIndexParser/readDirectMap.js @@ -0,0 +1,24 @@ +import { DirectMapType } from 'Types'; + +const checkDmType = (dmType) => { + if (dmType !== DirectMapType.NoMap) { + console.warn('[directmap_type] only support NoMap.'); + } +}; + +const checkDmSize = (dmSize) => { + if (dmSize !== 0) { + console.warn('[directmap_size] should be 0.'); + } +}; + +const readDirectMap = (reader, index) => { + const directMap = {}; + directMap.dmType = reader.readUint8(); + checkDmType(directMap.dmType); + directMap.size = reader.readUint64(); + checkDmSize(directMap.size); + index.directMap = directMap; +}; + +export default readDirectMap; diff --git a/federjs_old/FederCore/parser/faissIndexParser/readIndexHeader.js b/federjs_old/FederCore/parser/faissIndexParser/readIndexHeader.js new file mode 100644 index 0000000..8c5102e --- /dev/null +++ b/federjs_old/FederCore/parser/faissIndexParser/readIndexHeader.js @@ -0,0 +1,39 @@ +import { MetricType } from 'Types'; + +const checkMetricType = (metricType) => { + if ( + metricType !== MetricType.METRIC_L2 && + metricType !== MetricType.METRIC_INNER_PRODUCT + ) { + console.warn('[metric_type] only support l2 and inner_product.'); + } +}; + +const checkDummy = (dummy_1, dummy_2) => { + if (dummy_1 !== dummy_2) { + console.warn('[dummy] not equal.', dummy_1, dummy_2); + } +}; + +const checkIsTrained = (isTrained) => { + if (!isTrained) { + console.warn('[is_trained] should be trained.', isTrained); + } +}; + +const readIndexHeader = (reader, index) => { + index.d = reader.readUint32(); + index.ntotal = reader.readUint64(); + + const dummy_1 = reader.readDummy(); + const dummy_2 = reader.readDummy(); + checkDummy(dummy_1, dummy_2); + + index.isTrained = reader.readBool(); + checkIsTrained(index.isTrained); + + index.metricType = reader.readUint32(); + checkMetricType(index.metricType); +}; + +export default readIndexHeader; diff --git a/federjs_old/FederCore/parser/faissIndexParser/readInvertedLists.js b/federjs_old/FederCore/parser/faissIndexParser/readInvertedLists.js new file mode 100644 index 0000000..d2b0ec1 --- /dev/null +++ b/federjs_old/FederCore/parser/faissIndexParser/readInvertedLists.js @@ -0,0 +1,47 @@ +import { generateArray } from 'Utils'; + +const checkInvH = (h) => { + if (h !== 'ilar') { + console.warn('[invlists h] not ilar.', h); + } +}; + +const checkInvListType = (listType) => { + if (listType !== 'full') { + console.warn('[inverted_lists list_type] only support full.', listType); + } +}; + +const readArrayInvLists = (reader, invlists) => { + invlists.listType = reader.readH(); + checkInvListType(invlists.listType); + + invlists.listSizesSize = reader.readUint64(); + invlists.listSizes = generateArray(invlists.listSizesSize).map((_) => + reader.readUint64() + ); + + const data = []; + generateArray(invlists.listSizesSize).forEach((_, i) => { + const vectors = generateArray(invlists.listSizes[i]).map((_) => + reader.readFloat32Array(invlists.codeSize / 4) + ); + const ids = reader.readUint64Array(invlists.listSizes[i]); + data.push({ ids, vectors }); + }); + invlists.data = data; +}; + +export const readInvertedLists = (reader, index) => { + const invlists = {}; + invlists.h = reader.readH(); + checkInvH(invlists.h); + invlists.nlist = reader.readUint64(); + invlists.codeSize = reader.readUint64(); + + readArrayInvLists(reader, invlists); + + index.invlists = invlists; +}; + +export default readInvertedLists; diff --git a/federjs_old/FederCore/parser/hnswlibIndexParser/HNSWlibFileReader.js b/federjs_old/FederCore/parser/hnswlibIndexParser/HNSWlibFileReader.js new file mode 100644 index 0000000..358a45c --- /dev/null +++ b/federjs_old/FederCore/parser/hnswlibIndexParser/HNSWlibFileReader.js @@ -0,0 +1,16 @@ +import FileReader from '../FileReader.js'; + +export default class HNSWlibFileReader extends FileReader { + constructor(arrayBuffer) { + super(arrayBuffer); + } + readIsDeleted() { + return this.readUint8() + } + readIsReused() { + return this.readUint8() + } + readLevelOCount() { + return this.readUint16(); + } +} diff --git a/federjs_old/FederCore/parser/hnswlibIndexParser/index.js b/federjs_old/FederCore/parser/hnswlibIndexParser/index.js new file mode 100644 index 0000000..53be995 --- /dev/null +++ b/federjs_old/FederCore/parser/hnswlibIndexParser/index.js @@ -0,0 +1,97 @@ +import HNSWlibFileReader from './HNSWlibFileReader.js'; +import { INDEX_TYPE } from 'Types'; +import { generateArray } from 'Utils'; + +export const hnswlibIndexParser = (arrayBuffer) => { + const reader = new HNSWlibFileReader(arrayBuffer); + const index = {}; + index.offsetLevel0_ = reader.readUint64(); + index.max_elements_ = reader.readUint64(); + index.cur_element_count = reader.readUint64(); + // index.ntotal = index.cur_element_count; // consistent with Faiss + index.size_data_per_element_ = reader.readUint64(); + index.label_offset_ = reader.readUint64(); + index.offsetData_ = reader.readUint64(); + index.dim = (index.size_data_per_element_ - index.offsetData_ - 8) / 4; + + index.maxlevel_ = reader.readUint32(); + index.enterpoint_node_ = reader.readUint32(); + index.maxM_ = reader.readUint64(); + index.maxM0_ = reader.readUint64(); + index.M = reader.readUint64(); + + index.mult_ = reader.readFloat64(); + index.ef_construction_ = reader.readUint64(); + + index.size_links_per_element_ = index.maxM_ * 4 + 4; + index.size_links_level0_ = index.maxM0_ * 4 + 4; + index.revSize_ = 1.0 / index.mult_; + index.ef_ = 10; + + read_data_level0_memory_(reader, index); + + const linkListSizes = []; + const linkLists_ = []; + for (let i = 0; i < index.cur_element_count; i++) { + const linkListSize = reader.readUint32(); + linkListSizes.push(linkListSize); + if (linkListSize === 0) { + linkLists_[i] = []; + } else { + const levelCount = linkListSize / 4 / (index.maxM_ + 1); + linkLists_[i] = generateArray(levelCount) + .map((_) => reader.readUint32Array(index.maxM_ + 1)) + .map((linkLists) => linkLists.slice(1, linkLists[0] + 1)) + // .filter((a) => a.length > 0); + } + } + index.linkListSizes = linkListSizes; + index.linkLists_ = linkLists_; + + console.assert( + reader.isEmpty, + 'HNSWlib Parser Failed. Not empty when the parser completes.' + ); + + return { + indexType: INDEX_TYPE.hnsw, + ntotal: index.cur_element_count, + vectors: index.vectors, + maxLevel: index.maxlevel_, + linkLists_level0_count: index.linkLists_level0_count, + linkLists_level_0: index.linkLists_level0, + linkLists_levels: index.linkLists_, + enterPoint: index.enterpoint_node_, + labels: index.externalLabel, + isDeleted: index.isDeleted, + numDeleted: index.num_deleted_, + M: index.M, + ef_construction: index.ef_construction_, + }; +}; + +const read_data_level0_memory_ = (reader, index) => { + // size_data = links_level0[M0 + 1] * 4 + vector[dim * 4] * 4 + label[1] * 8; + const isDeleted = []; + const linkLists_level0_count = []; + const linkLists_level0 = []; + const vectors = []; + const externalLabel = []; + for (let i = 0; i < index.cur_element_count; i++) { + linkLists_level0_count.push(reader.readLevelOCount()); + isDeleted.push(reader.readIsDeleted()); + reader.readIsReused(); // Unknown use. + linkLists_level0.push(reader.readUint32Array(index.maxM0_)); + vectors.push(reader.readFloat32Array(index.dim)); + externalLabel.push(reader.readUint64()); + // console.log(isDeleted, linkLists_level0_count); + } + index.isDeleted = isDeleted; + index.num_deleted_ = isDeleted.reduce((acc, cur) => acc + cur, 0); + index.linkLists_level0_count = linkLists_level0_count; + index.linkLists_level0 = linkLists_level0; + index.vectors = vectors; + index.externalLabel = externalLabel; +}; + +export default hnswlibIndexParser; diff --git a/federjs_old/FederCore/parser/index.js b/federjs_old/FederCore/parser/index.js new file mode 100644 index 0000000..728d9b8 --- /dev/null +++ b/federjs_old/FederCore/parser/index.js @@ -0,0 +1,16 @@ +import { SOURCE_TYPE } from 'Types'; +import hnswlibIndexParser from './hnswlibIndexParser'; +import faissIndexParser from "./faissIndexParser"; + +const indexParserMap = { + [SOURCE_TYPE.hnswlib]: hnswlibIndexParser, + [SOURCE_TYPE.faiss]: faissIndexParser, +}; + +export const getIndexParser = (sourceType) => { + if (sourceType in indexParserMap) { + return indexParserMap[sourceType]; + } else throw `No index parser for [${sourceType}]`; +}; + +export default getIndexParser; diff --git a/federjs_old/FederCore/projector/index.js b/federjs_old/FederCore/projector/index.js new file mode 100644 index 0000000..e22a2b6 --- /dev/null +++ b/federjs_old/FederCore/projector/index.js @@ -0,0 +1,17 @@ +import umapProject from './umap'; + +import { PROJECT_METHOD } from 'Types'; + +const projectorMap = { + [PROJECT_METHOD.umap]: umapProject, +}; + +export const getProjector = ({ method, params = {} }) => { + if (method in projectorMap) { + return projectorMap[method](params); + } else { + console.error(`No projector for [${method}]`) + } +}; + +export default getProjector; diff --git a/federjs_old/FederCore/projector/umap.js b/federjs_old/FederCore/projector/umap.js new file mode 100644 index 0000000..73da5a0 --- /dev/null +++ b/federjs_old/FederCore/projector/umap.js @@ -0,0 +1,32 @@ +import { UMAP } from 'umap-js'; + +const fixedParams = { + nComponents: 2, +}; + +export const UMAP_PROJECT_PARAMETERS = { + nComponents: + 'The number of components (dimensions) to project the data to. (default 2)', + nEpochs: + 'The number of epochs to optimize embeddings via SGD. (computed automatically)', + nNeighbors: + 'The number of nearest neighbors to construct the fuzzy manifold. (default 15)', + minDist: + 'The effective minimum distance between embedded points, used with spread to control the clumped/dispersed nature of the embedding. (default 0.1)', + spread: + 'The effective scale of embedded points, used with minDist to control the clumped/dispersed nature of the embedding. (default 1.0)', + random: + 'A pseudo-random-number generator for controlling stochastic processes. (default Math.random())', + distanceFn: 'A custom distance function to use. (default L2)', + url: 'https://github.com/PAIR-code/umap-js', +}; + +export const umapProject = (projectParams = {}) => { + const params = Object.assign({}, projectParams, fixedParams); + return (vectors) => { + const umap = new UMAP(params); + return umap.fit(vectors); + }; +}; + +export default umapProject; diff --git a/federjs_old/FederCore/searchHandler/hnswSearch/index.js b/federjs_old/FederCore/searchHandler/hnswSearch/index.js new file mode 100644 index 0000000..e1b0a91 --- /dev/null +++ b/federjs_old/FederCore/searchHandler/hnswSearch/index.js @@ -0,0 +1,78 @@ +import { getDisFunc } from 'Utils'; +import { MetricType } from 'Types'; +import searchLevelO from './searchLevel0'; + +const hnswlibHNSWSearch = ({ index, target, params = {} }) => { + const { ef = 10, k = 8, metricType = MetricType.METRIC_L2 } = params; + const disfunc = getDisFunc(metricType); + + let topkResults = []; + const vis_records_all = []; + + const { + enterPoint, + vectors, + maxLevel, + linkLists_levels, + linkLists_level_0, + numDeleted, + labels, + } = index; + + let curNodeId = enterPoint; + let curDist = disfunc(vectors[curNodeId], target); + + for (let level = maxLevel; level > 0; level--) { + const vis_records = []; + vis_records.push([labels[curNodeId], labels[curNodeId], curDist]); + let changed = true; + while (changed) { + changed = false; + + const curlinks = linkLists_levels[curNodeId][level - 1]; + + curlinks.forEach((candidateId) => { + const dist = disfunc(vectors[candidateId], target); + vis_records.push([labels[curNodeId], labels[candidateId], dist]); + if (dist < curDist) { + curDist = dist; + curNodeId = candidateId; + changed = true; + } + }); + } + vis_records_all.push(vis_records); + } + + const hasDeleted = numDeleted > 0; + const { top_candidates, vis_records_level_0 } = searchLevelO({ + ep_id: curNodeId, + target, + vectors, + ef: Math.max(ef, k), + hasDeleted, + linkLists_level_0, + disfunc, + labels, + }); + vis_records_all.push(vis_records_level_0); + + while (top_candidates.size > k) { + top_candidates.pop(); + } + + while (top_candidates.size > 0) { + const res = top_candidates.pop(); + topkResults.push({ + id: labels[res[1]], + internalId: res[1], + dis: -res[0], + }); + } + + topkResults = topkResults.reverse(); + + return { vis_records: vis_records_all, topkResults, searchParams: { k, ef } }; +}; + +export default hnswlibHNSWSearch; diff --git a/federjs_old/FederCore/searchHandler/hnswSearch/searchLevel0.js b/federjs_old/FederCore/searchHandler/hnswSearch/searchLevel0.js new file mode 100644 index 0000000..a835758 --- /dev/null +++ b/federjs_old/FederCore/searchHandler/hnswSearch/searchLevel0.js @@ -0,0 +1,82 @@ + +import PriorityQueue from 'Utils/PriorityQueue'; + +export const searchLevelO = ({ + ep_id, + target, + vectors, + ef, + isDeleted, + hasDeleted, + linkLists_level_0, + disfunc, + labels, +}) => { + const top_candidates = new PriorityQueue([], (d) => d[0]); + const candidates = new PriorityQueue([], (d) => d[0]); + const vis_records_level_0 = []; + + const visited = new Set(); + + let lowerBound; + if (!hasDeleted || !isDeleted[ep_id]) { + const dist = disfunc(vectors[ep_id], target); + lowerBound = dist; + top_candidates.add([-dist, ep_id]); + candidates.add([dist, ep_id]); + } else { + lowerBound = 9999999; + candidates.add([lowerBound, ep_id]); + } + + visited.add(ep_id); + vis_records_level_0.push([labels[ep_id], labels[ep_id], lowerBound]); + + while (!candidates.isEmpty) { + const curNodePair = candidates.top; + if ( + curNodePair[0] > lowerBound && + (top_candidates.size === ef || !hasDeleted) + ) { + break; + } + candidates.pop(); + + const curNodeId = curNodePair[1]; + const curLinks = linkLists_level_0[curNodeId]; + + curLinks.forEach((candidateId) => { + if (!visited.has(candidateId)) { + visited.add(candidateId); + + const dist = disfunc(vectors[candidateId], target); + vis_records_level_0.push([ + labels[curNodeId], + labels[candidateId], + dist, + ]); + + if (top_candidates.size < ef || lowerBound > dist) { + candidates.add([dist, candidateId]); + + if (!hasDeleted || !isDeleted(candidateId)) { + top_candidates.add([-dist, candidateId]); + } + + if (top_candidates.size > ef) { + top_candidates.pop(); + } + + if (!top_candidates.isEmpty) { + lowerBound = -top_candidates.top[0]; + } + } + } else { + vis_records_level_0.push([labels[curNodeId], labels[candidateId], -1]); + } + }); + } + return { top_candidates, vis_records_level_0 }; +}; + +export default searchLevelO; \ No newline at end of file diff --git a/federjs_old/FederCore/searchHandler/index.js b/federjs_old/FederCore/searchHandler/index.js new file mode 100644 index 0000000..58cde6c --- /dev/null +++ b/federjs_old/FederCore/searchHandler/index.js @@ -0,0 +1,17 @@ +import hnswSearchHandler from './hnswSearch'; +import ivfflatSearchHandler from './ivfflatSearch'; +import { INDEX_TYPE } from 'Types'; + +const indexSearchHandlerMap = { + [INDEX_TYPE.hnsw]: hnswSearchHandler, + [INDEX_TYPE.ivf_flat]: ivfflatSearchHandler, +}; + +export const getIndexSearchHandler = (indexType) => { + if (indexType in indexSearchHandlerMap) { + return indexSearchHandlerMap[indexType]; + } else throw `No search handler for [${indexType}]`; +}; + +export default getIndexSearchHandler; + diff --git a/federjs_old/FederCore/searchHandler/ivfflatSearch/faissFlatSearch.js b/federjs_old/FederCore/searchHandler/ivfflatSearch/faissFlatSearch.js new file mode 100644 index 0000000..d480f77 --- /dev/null +++ b/federjs_old/FederCore/searchHandler/ivfflatSearch/faissFlatSearch.js @@ -0,0 +1,13 @@ +import { getDisFunc } from 'Utils'; + +export const faissFlatSearch = ({ index, target}) => { + const disFunc = getDisFunc(index.metricType); + const distances = index.vectors.map((vec, id) => ({ + id, + dis: disFunc(vec, target), + })); + distances.sort((a, b) => a.dis - b.dis); + return distances; +}; + +export default faissFlatSearch; diff --git a/federjs_old/FederCore/searchHandler/ivfflatSearch/faissIVFSearch.js b/federjs_old/FederCore/searchHandler/ivfflatSearch/faissIVFSearch.js new file mode 100644 index 0000000..1904b2c --- /dev/null +++ b/federjs_old/FederCore/searchHandler/ivfflatSearch/faissIVFSearch.js @@ -0,0 +1,23 @@ +import { getDisFunc } from 'Utils'; + +export const faissIVFSearch = ({ index, csListIds, target }) => { + const disFunc = getDisFunc(index.metricType); + const distances = index.invlists.data.reduce( + (acc, cur, listId) => + acc.concat( + csListIds.includes(listId) + ? cur.ids.map((id, ofs) => ({ + id, + listId, + dis: disFunc(cur.vectors[ofs], target), + // vec: cur.vectors[ofs] + })) + : [] + ), + [] + ); + distances.sort((a, b) => a.dis - b.dis); + return distances; +}; + +export default faissIVFSearch; diff --git a/federjs_old/FederCore/searchHandler/ivfflatSearch/index.js b/federjs_old/FederCore/searchHandler/ivfflatSearch/index.js new file mode 100644 index 0000000..48c0b1f --- /dev/null +++ b/federjs_old/FederCore/searchHandler/ivfflatSearch/index.js @@ -0,0 +1,39 @@ +import faissFlatSearch from './faissFlatSearch.js'; +import faissIVFSearch from './faissIVFSearch.js'; + +export const faissIVFFlatSearch = ({ index, target, params = {} }) => { + const { nprobe = 8, k = 10 } = params; + + // cs: coarse-search + // fs: fine-search + const csAllListIdsAndDistances = faissFlatSearch({ + index: index.childIndex, + target, + }); + const csRes = csAllListIdsAndDistances.slice( + 0, + Math.min(index.nlist, nprobe) + ); + const csListIds = csRes.map((res) => res.id); + + const fsAllIdsAndDistances = faissIVFSearch({ + index, + csListIds, + target, + }); + // console.log('fsResProjections', fsResProjections); + const fsRes = fsAllIdsAndDistances.slice(0, Math.min(index.ntotal, k)); + + const coarse = csAllListIdsAndDistances; + const fine = fsAllIdsAndDistances; + const res = { + coarse, + fine, + csResIds: csListIds, + fsResIds: fsRes.map((d) => d.id), + }; + + return res; +}; + +export default faissIVFFlatSearch; diff --git a/federjs_old/FederView/BaseView.js b/federjs_old/FederView/BaseView.js new file mode 100644 index 0000000..abfa801 --- /dev/null +++ b/federjs_old/FederView/BaseView.js @@ -0,0 +1,109 @@ +import * as d3 from 'd3'; +import { renderLoading, finishLoading } from './loading'; +// import { VIEW_TYPE } from 'Types'; + +export default class BaseView { + constructor({ viewParams, getVectorById }) { + this.viewParams = viewParams; + + const { width, height, canvasScale, mediaType, mediaCallback } = viewParams; + this.clientWidth = width; + this.width = width * canvasScale; + this.clientHeight = height; + this.height = height * canvasScale; + this.getVectorById = getVectorById; + this.canvasScale = canvasScale; + this.mediaType = mediaType; + this.mediaCallback = mediaCallback; + } + + // override + initInfoPanel() {} + renderOverview() {} + renderSearchView() {} + searchViewHandler() {} + getOverviewEventHandler() {} + getSearchViewEventHandler() {} + + async overview(dom) { + const canvas = initCanvas( + dom, + this.clientWidth, + this.clientHeight, + this.canvasScale + ); + const ctx = canvas.getContext('2d'); + const infoPanel = this.initInfoPanel(dom); + + this.overviewLayoutPromise && (await this.overviewLayoutPromise); + finishLoading(dom); + this.renderOverview(ctx, infoPanel); + const eventHandlers = this.getOverviewEventHandler(ctx, infoPanel); + addMouseListener(canvas, this.canvasScale, eventHandlers); + } + + async search(dom, { searchRes, targetMediaUrl }) { + const canvas = initCanvas( + dom, + this.clientWidth, + this.clientHeight, + this.canvasScale + ); + const ctx = canvas.getContext('2d'); + const infoPanel = this.initInfoPanel(dom); + + const searchViewLayoutData = await this.searchViewHandler(searchRes); + finishLoading(dom); + this.renderSearchView( + ctx, + infoPanel, + searchViewLayoutData, + targetMediaUrl, + dom + ); + const eventHandlers = this.getSearchViewEventHandler( + ctx, + searchViewLayoutData, + infoPanel + ); + addMouseListener(canvas, this.canvasScale, eventHandlers); + } +} + +const addMouseListener = ( + element, + canvasScale, + { mouseMoveHandler, mouseClickHandler, mouseLeaveHandler } = {} +) => { + element.addEventListener('mousemove', (e) => { + const { offsetX, offsetY } = e; + const x = offsetX * canvasScale; + const y = offsetY * canvasScale; + mouseMoveHandler && mouseMoveHandler({ x, y }); + }); + element.addEventListener('click', (e) => { + const { offsetX, offsetY } = e; + const x = offsetX * canvasScale; + const y = offsetY * canvasScale; + mouseClickHandler && mouseClickHandler({ x, y }); + }); + element.addEventListener('mouseleave', () => { + mouseLeaveHandler && mouseLeaveHandler(); + }); +}; + +const initCanvas = (dom, clientWidth, clientHeight, canvasScale) => { + renderLoading(dom, clientWidth, clientHeight); + + const domD3 = d3.select(dom); + domD3.selectAll('canvas').remove(); + + const canvas = domD3 + .append('canvas') + .attr('width', clientWidth) + .attr('height', clientHeight); + const ctx = canvas.node().getContext('2d'); + ctx.scale(1 / canvasScale, 1 / canvasScale); + + return canvas.node(); +}; diff --git a/federjs_old/FederView/HnswView/InfoPanel/index.js b/federjs_old/FederView/HnswView/InfoPanel/index.js new file mode 100644 index 0000000..683f55e --- /dev/null +++ b/federjs_old/FederView/HnswView/InfoPanel/index.js @@ -0,0 +1,425 @@ +import * as d3 from 'd3'; + +import { + ZYellow, + ZBlue, + whiteColor, + blackColor, + drawPath, + hexWithOpacity, +} from 'Utils/renderUtils'; + +import { showVectors } from 'Utils'; +import { HNSW_NODE_TYPE } from 'Types'; + +export const overviewPanelId = 'feder-info-overview-panel'; +export const selectedPanelId = 'feder-info-selected-panel'; +export const hoveredPanelId = 'feder-info-hovered-panel'; + +const panelBackgroundColor = hexWithOpacity(blackColor, 0.6); + +export default class InfoPanel { + constructor({ dom, width, height }) { + this.dom = dom; + this.width = width; + this.height = height; + + const overviewPanel = document.createElement('div'); + overviewPanel.setAttribute('id', overviewPanelId); + overviewPanel.className = + overviewPanel.className + ' panel-border panel hide'; + const overviewPanelStyle = { + position: 'absolute', + // left: `${canvas.width - 10}px`, + left: '16px', + top: '10px', + width: '280px', + 'max-height': `${height - 20}px`, + overflow: 'auto', + borderColor: whiteColor, + backgroundColor: panelBackgroundColor, + }; + Object.assign(overviewPanel.style, overviewPanelStyle); + dom.appendChild(overviewPanel); + + const selectedPanel = document.createElement('div'); + selectedPanel.setAttribute('id', selectedPanelId); + selectedPanel.className = + selectedPanel.className + ' panel-border panel hide'; + const selectedPanelStyle = { + position: 'absolute', + // left: `${canvas.width - 10}px`, + right: '16px', + top: '10px', + 'max-width': '180px', + 'max-height': `${height - 20}px`, + overflow: 'auto', + borderColor: ZYellow, + backgroundColor: panelBackgroundColor, + }; + Object.assign(selectedPanel.style, selectedPanelStyle); + dom.appendChild(selectedPanel); + + const hoveredPanel = document.createElement('div'); + hoveredPanel.setAttribute('id', hoveredPanelId); + hoveredPanel.className = hoveredPanel.className + ' hide'; + const hoveredPanelStyle = { + position: 'absolute', + left: 0, + // right: '30px', + top: 0, + width: '240px', + display: 'flex', + pointerEvents: 'none', + }; + Object.assign(hoveredPanel.style, hoveredPanelStyle); + dom.appendChild(hoveredPanel); + + this.initStyle(); + } + + initStyle() { + const style = document.createElement('style'); + style.type = 'text/css'; + style.innerHTML = ` + .panel-border { + border-style: dashed; + border-width: 1px; + } + .panel { + padding: 6px 8px; + font-size: 12px; + } + .hide { + opacity: 0; + } + .panel-item { + margin-bottom: 6px; + } + .panel-img { + width: 150px; + height: 100px; + background-size: cover; + margin-bottom: 12px; + border-radius: 4px; + border: 1px solid ${ZYellow}; + } + .panel-item-display-flex { + display: flex; + } + .panel-item-title { + font-weight: 600; + margin-bottom: 3px; + } + .panel-item-text { + font-weight: 400; + font-size: 10px; + word-break: break-all; + } + .panel-item-text-flex { + margin-left: 8px; + } + .panel-item-text-margin { + margin: 0 6px; + } + .text-no-wrap { + white-space: nowrap; + } + `; + document.getElementsByTagName('head').item(0).appendChild(style); + } + + renderSelectedPanel(itemList = [], color = '#000') { + const panel = d3.select(this.dom).select(`#${selectedPanelId}`); + panel.style('color', color); + if (itemList.length === 0) panel.classed('hide', true); + else { + this.renderPanel(panel, itemList); + } + } + renderHoveredPanel({ + itemList = [], + canvasScale = 1, + color = '#000', + x = 0, + y = 0, + isLeft = false, + } = {}) { + const panel = d3.select(this.dom).select(`#${hoveredPanelId}`); + if (itemList.length === 0) panel.classed('hide', true); + else { + panel.style('color', color); + // panel.style.left = x + 'px'; + // panel.style.top = y + 'px'; + if (isLeft) { + panel.style('left', null); + panel.style('right', this.width - x / canvasScale + 'px'); + panel.style('flex-direction', 'row-reverse'); + } else { + panel.style('left', x / canvasScale + 'px'); + panel.style('flex-direction', 'row'); + } + + panel.style('transform', `translateY(-6px)`); + + panel.style('top', y / canvasScale + 'px'); + this.renderPanel(panel, itemList); + } + } + renderOverviewPanel(itemList = [], color) { + const panel = d3.select(this.dom).select(`#${overviewPanelId}`); + panel.style('color', color); + if (itemList.length === 0) panel.classed('hide', true); + else { + this.renderPanel(panel, itemList); + } + } + renderPanel(panel, itemList) { + panel.classed('hide', false); + panel.selectAll('*').remove(); + + itemList.forEach((item) => { + const div = panel.append('div'); + div.classed('panel-item', true); + item.isFlex && div.classed('panel-item-display-flex', true); + if (item.isImg && item.imgUrl) { + div.classed('panel-img', true); + div.style('background-image', `url(${item.imgUrl})`); + } + if (item.title) { + const title = div.append('div'); + title.classed('panel-item-title', true); + title.text(item.title); + } + if (item.text) { + const title = div.append('div'); + title.classed('panel-item-text', true); + item.isFlex && title.classed('panel-item-text-flex', true); + item.textWithMargin && title.classed('panel-item-text-margin', true); + item.noWrap && title.classed('text-no-wrap', true); + title.text(item.text); + } + }); + } + + updateOverviewOverviewInfo({ indexMeta, nodesCount, linksCount }) { + const overviewInfo = [ + { + title: 'HNSW', + }, + { + title: `M = ${indexMeta.M}, ef_construction = ${indexMeta.ef_construction}`, + }, + { + title: `${indexMeta.ntotal} vectors, including ${indexMeta.levelCount} levels (only show the top 3 levels).`, + }, + ]; + for (let level = indexMeta.overviewLevelCount - 1; level >= 0; level--) { + overviewInfo.push({ + isFlex: true, + title: `Level ${ + level + indexMeta.levelCount - indexMeta.overviewLevelCount + }`, + text: `${nodesCount[level]} vectors, ${linksCount[level]} links`, + }); + } + this.renderOverviewPanel(overviewInfo, whiteColor); + } + async updateOverviewClickedInfo( + node, + level, + { indexMeta, mediaType, mediaCallback, getVectorById } + ) { + const itemList = []; + if (node) { + itemList.push({ + title: `Level ${ + level + indexMeta.levelCount - indexMeta.overviewLevelCount + }`, + }); + itemList.push({ + title: `Row No. ${node.id}`, + }); + mediaType === 'img' && + itemList.push({ + isImg: true, + imgUrl: mediaCallback(node.id), + }); + itemList.push({ + title: `Shortest path from the entry:`, + text: `${[...node.path, node.id].join(' => ')}`, + }); + itemList.push({ + title: `Linked vectors:`, + text: `${node.linksLevels[level].join(', ')}`, + }); + itemList.push({ + title: `Vectors:`, + text: `${showVectors(await getVectorById(node.id))}`, + }); + } + this.renderSelectedPanel(itemList, ZYellow); + } + updateOverviewHoveredInfo( + hoveredNode, + { isLeft, endX, endY }, + { mediaType, mediaCallback, canvasScale } + ) { + if (!!hoveredNode) { + const itemList = []; + itemList.push({ + text: `No. ${hoveredNode.id}`, + textWithMargin: true, + noWrap: true, + }); + mediaType === 'img' && + itemList.push({ + isImg: true, + imgUrl: mediaCallback(hoveredNode.id), + }); + + this.renderHoveredPanel({ + itemList, + color: ZYellow, + x: endX, + y: endY, + isLeft, + canvasScale, + }); + } else { + this.renderHoveredPanel(); + } + } + + updateSearchViewOverviewInfo( + { + targetMediaUrl, + id2forcePos, + searchNodesLevels, + searchLinksLevels, + searchParams, + }, + { indexMeta } + ) { + const overviewInfo = [ + { + title: 'HNSW - Search', + }, + { + isImg: true, + imgUrl: targetMediaUrl, + }, + { + title: `M = ${indexMeta.M}, ef_construction = ${indexMeta.ef_construction}.`, + }, + { + title: `k = ${searchParams.k}, ef_search = ${searchParams.ef}.`, + }, + { + title: `${indexMeta.ntotal} vectors, including ${indexMeta.levelCount} levels.`, + }, + { + title: `During the search, a total of ${ + Object.keys(id2forcePos).length - 1 + } of these vectors were visited.`, + }, + ]; + for (let level = indexMeta.levelCount - 1; level >= 0; level--) { + const nodes = searchNodesLevels[level]; + const links = searchLinksLevels[level]; + const minDist = + level > 0 + ? nodes + .find((node) => node.type === HNSW_NODE_TYPE.Fine) + .dist.toFixed(3) + : d3.min( + nodes.filter((node) => node.type === HNSW_NODE_TYPE.Fine), + (node) => node.dist.toFixed(3) + ); + overviewInfo.push({ + isFlex: true, + title: `Level ${level}`, + text: `${nodes.length} vectors, ${links.length} links, min-dist: ${minDist}`, + }); + } + this.renderOverviewPanel(overviewInfo, whiteColor); + } + updateSearchViewHoveredInfo( + { hoveredNode, hoveredLevel }, + { + mediaType, + mediaCallback, + width, + padding, + + HoveredPanelLine_1_x, + HoveredPanelLine_1_y, + HoveredPanelLine_2_x, + canvasScale, + } + ) { + if (!hoveredNode) { + this.renderHoveredPanel(); + } else { + const [x, y] = hoveredNode.searchViewPosLevels[hoveredLevel]; + const originX = (width - padding[1] - padding[3]) / 2 + padding[3]; + const isLeft = originX > x; + const k = isLeft ? -1 : 1; + const endX = + x + + HoveredPanelLine_1_x * canvasScale * k + + HoveredPanelLine_2_x * canvasScale * k; + const endY = y + HoveredPanelLine_1_y * canvasScale * k; + + const itemList = []; + itemList.push({ + text: `No. ${hoveredNode.id}`, + textWithMargin: true, + noWrap: true, + }); + mediaType === 'img' && + itemList.push({ + isImg: true, + imgUrl: mediaCallback(hoveredNode.id), + }); + + this.renderHoveredPanel({ + itemList, + color: ZYellow, + x: endX, + y: endY, + isLeft, + canvasScale, + }); + } + } + async updateSearchViewClickedInfo( + { clickedNode, clickedLevel }, + { mediaType, mediaCallback, getVectorById } + ) { + const itemList = []; + if (!clickedNode) { + this.renderSelectedPanel([], ZYellow); + } else { + itemList.push({ + title: `Level ${clickedLevel}`, + }); + itemList.push({ + title: `Row No. ${clickedNode.id}`, + }); + itemList.push({ + title: `Distance to the target: ${clickedNode.dist.toFixed(3)}`, + }); + mediaType === 'img' && + itemList.push({ + isImg: true, + imgUrl: mediaCallback(clickedNode.id), + }); + itemList.push({ + title: `Vector:`, + text: `${showVectors(await getVectorById(clickedNode.id))}`, + }); + } + this.renderSelectedPanel(itemList, ZYellow); + } +} diff --git a/federjs_old/FederView/HnswView/index.js b/federjs_old/FederView/HnswView/index.js new file mode 100644 index 0000000..5d6e740 --- /dev/null +++ b/federjs_old/FederView/HnswView/index.js @@ -0,0 +1,257 @@ +import * as d3 from 'd3'; +import BaseView from '../BaseView.js'; +import overviewLayoutHandler from './layout/overviewLayout'; +import mouse2node from './layout/mouse2node'; +import renderOverview from './render/renderOverview'; +import getOverviewShortestPathData from './layout/overviewShortestPath'; +import searchViewLayoutHandler from './layout/searchViewLayout'; +import TimeControllerView from './render/TimeControllerView'; +import TimerController from './render/TimerController'; +import renderHoverLine from './render/renderHoverLine'; +import renderSearchViewTransition from './render/renderSearchViewTransition'; +import InfoPanel from './InfoPanel'; + +const defaultHnswViewParams = { + padding: [80, 200, 60, 220], + forceTime: 3000, + layerDotNum: 20, + shortenLineD: 8, + overviewLinkLineWidth: 2, + reachableLineWidth: 3, + shortestPathLineWidth: 4, + ellipseRation: 1.4, + shadowBlur: 4, + mouse2nodeBias: 3, + highlightRadiusExt: 0.5, + targetR: 3, + searchViewNodeBasicR: 1.5, + searchInterLevelTime: 300, + searchIntraLevelTime: 100, + HoveredPanelLine_1_x: 15, + HoveredPanelLine_1_y: -25, + HoveredPanelLine_2_x: 30, + hoveredPanelLineWidth: 2, + forceIterations: 100, + targetOrigin: [0, 0], +}; +export default class HnswView extends BaseView { + constructor({ indexMeta, viewParams, getVectorById }) { + super({ + indexMeta, + viewParams, + getVectorById, + }); + for (let key in defaultHnswViewParams) { + this[key] = + key in viewParams ? viewParams[key] : defaultHnswViewParams[key]; + } + this.padding = this.padding.map((num) => num * this.canvasScale); + + this.overviewHandler(indexMeta); + } + initInfoPanel(dom) { + const infoPanel = new InfoPanel({ + dom, + width: this.viewParams.width, + height: this.viewParams.height, + }); + return infoPanel; + } + overviewHandler(indexMeta) { + console.log(indexMeta); + this.indexMeta = indexMeta; + Object.assign(this, indexMeta); + + const internalId2overviewNode = {}; + this.overviewNodes.forEach( + (node) => (internalId2overviewNode[node.internalId] = node) + ); + this.internalId2overviewNode = internalId2overviewNode; + + this.overviewLayoutPromise = overviewLayoutHandler(this).then( + ({ + overviewLayerPosLevels, + overviewNodesLevels, + overviewLinksLevels, + }) => { + this.overviewLayerPosLevels = overviewLayerPosLevels; + this.overviewNodesLevels = overviewNodesLevels; + this.overviewLinksLevels = overviewLinksLevels; + } + ); + } + renderOverview(ctx, infoPanel) { + const indexMeta = this.indexMeta; + const nodesCount = this.overviewNodesLevels.map( + (nodesLevel) => nodesLevel.length + ); + const linksCount = this.overviewLinksLevels.map( + (linksLevel) => linksLevel.length + ); + const overviewInfo = { indexMeta, nodesCount, linksCount }; + infoPanel.updateOverviewOverviewInfo(overviewInfo); + + // this.searchTransitionTimer && this.searchTransitionTimer.stop(); + renderOverview(ctx, this); + } + getOverviewEventHandler(ctx, infoPanel) { + let clickedNode = null; + let clickedLevel = null; + let hoveredNode = null; + let hoveredLevel = null; + let overviewHighlightData = null; + const mouseMoveHandler = ({ x, y }) => { + const mouse = [x, y]; + const { mouseLevel, mouseNode } = mouse2node( + { + mouse, + layerPosLevels: this.overviewLayerPosLevels, + nodesLevels: this.overviewNodesLevels, + posAttr: 'overviewPosLevels', + }, + this + ); + const hoveredNodeChanged = + hoveredLevel !== mouseLevel || hoveredNode !== mouseNode; + hoveredNode = mouseNode; + hoveredLevel = mouseLevel; + + if (hoveredNodeChanged) { + if (!clickedNode) { + overviewHighlightData = getOverviewShortestPathData( + mouseNode, + mouseLevel, + this + ); + } + renderOverview(ctx, this, overviewHighlightData); + const hoveredPanelPos = renderHoverLine( + ctx, + { + hoveredNode, + hoveredLevel, + clickedNode, + clickedLevel, + }, + this + ); + infoPanel.updateOverviewHoveredInfo(mouseNode, hoveredPanelPos, this); + } + }; + const mouseClickHandler = ({ x, y }) => { + const mouse = [x, y]; + const { mouseLevel, mouseNode } = mouse2node( + { + mouse, + layerPosLevels: this.overviewLayerPosLevels, + nodesLevels: this.overviewNodesLevels, + posAttr: 'overviewPosLevels', + }, + this + ); + const clickedNodeChanged = + clickedLevel !== mouseLevel || clickedNode !== mouseNode; + clickedNode = mouseNode; + clickedLevel = mouseLevel; + + if (clickedNodeChanged) { + overviewHighlightData = getOverviewShortestPathData( + mouseNode, + mouseLevel, + this + ); + renderOverview(ctx, this, overviewHighlightData); + infoPanel.updateOverviewClickedInfo(mouseNode, mouseLevel, this); + } + }; + return { mouseMoveHandler, mouseClickHandler }; + } + + searchViewHandler(searchRes) { + return searchViewLayoutHandler(searchRes, this); + } + renderSearchView(ctx, infoPanel, searchViewLayoutData, targetMediaUrl, dom) { + searchViewLayoutData.targetMediaUrl = targetMediaUrl; + infoPanel.updateSearchViewOverviewInfo(searchViewLayoutData, this); + const timeControllerView = new TimeControllerView(dom); + + const callback = ({ t, p }) => { + renderSearchViewTransition(ctx, searchViewLayoutData, this, { + t, + p, + }); + timeControllerView.moveSilderBar(p); + }; + const timer = new TimerController({ + duration: searchViewLayoutData.searchTransitionDuration, + callback, + playCallback: () => timeControllerView.play(), + pauseCallback: () => timeControllerView.pause(), + }); + timeControllerView.setTimer(timer); + timer.start(); + searchViewLayoutData.searchTransitionTimer = timer; + } + getSearchViewEventHandler(ctx, searchViewLayoutData, infoPanel) { + searchViewLayoutData.clickedLevel = null; + searchViewLayoutData.clickedNode = null; + searchViewLayoutData.hoveredLevel = null; + searchViewLayoutData.hoveredNode = null; + + const mouseMoveHandler = ({ x, y }) => { + const mouse = [x, y]; + const { mouseLevel, mouseNode } = mouse2node( + { + mouse, + layerPosLevels: searchViewLayoutData.searchLayerPosLevels, + nodesLevels: searchViewLayoutData.searchNodesLevels, + posAttr: 'searchViewPosLevels', + }, + this + ); + const hoveredNodeChanged = + searchViewLayoutData.hoveredLevel !== mouseLevel || + searchViewLayoutData.hoveredNode !== mouseNode; + searchViewLayoutData.hoveredNode = mouseNode; + searchViewLayoutData.hoveredLevel = mouseLevel; + + if (hoveredNodeChanged) { + infoPanel.updateSearchViewHoveredInfo(searchViewLayoutData, this); + if (!searchViewLayoutData.searchTransitionTimer.isPlaying) { + renderSearchViewTransition(ctx, searchViewLayoutData, this, { + t: searchViewLayoutData.searchTransitionTimer.tAlready, + }); + } + } + }; + + const mouseClickHandler = ({ x, y }) => { + const mouse = [x, y]; + const { mouseLevel, mouseNode } = mouse2node( + { + mouse, + layerPosLevels: searchViewLayoutData.searchLayerPosLevels, + nodesLevels: searchViewLayoutData.searchNodesLevels, + posAttr: 'searchViewPosLevels', + }, + this + ); + const clickedNodeChanged = + searchViewLayoutData.clickedLevel !== mouseLevel || + searchViewLayoutData.clickedNode !== mouseNode; + searchViewLayoutData.clickedNode = mouseNode; + searchViewLayoutData.clickedLevel = mouseLevel; + + if (clickedNodeChanged) { + infoPanel.updateSearchViewClickedInfo(searchViewLayoutData, this); + if (!searchViewLayoutData.searchTransitionTimer.isPlaying) { + renderSearchViewTransition(ctx, searchViewLayoutData, this, { + t: searchViewLayoutData.searchTransitionTimer.tAlready, + }); + } + } + }; + + return { mouseMoveHandler, mouseClickHandler }; + } +} diff --git a/federjs_old/FederView/HnswView/layout/computeSearchViewTransition.js b/federjs_old/FederView/HnswView/layout/computeSearchViewTransition.js new file mode 100644 index 0000000..9d914c9 --- /dev/null +++ b/federjs_old/FederView/HnswView/layout/computeSearchViewTransition.js @@ -0,0 +1,86 @@ +import { + getNodeIdWithLevel, + getLinkIdWithLevel, + getEntryLinkIdWithLevel, +} from 'Utils'; + +import { HNSW_LINK_TYPE } from 'Types'; + +export const computeSearchViewTransition = ({ + linksLevels, + entryNodesLevels, + interLevelGap = 1000, + intraLevelGap = 300, +}) => { + let currentTime = 0; + const targetShowTime = []; + const nodeShowTime = {}; + const linkShowTime = {}; + + let isPreLinkImportant = true; + let isSourceChanged = true; + let preSourceIdWithLevel = ''; + for (let level = linksLevels.length - 1; level >= 0; level--) { + const links = linksLevels[level]; + if (links.length === 0) { + const sourceId = entryNodesLevels[level].id; + const sourceIdWithLevel = getNodeIdWithLevel(sourceId, level); + nodeShowTime[sourceIdWithLevel] = currentTime; + } else { + links.forEach((link) => { + const sourceId = link.source.id; + const targetId = link.target.id; + const sourceIdWithLevel = getNodeIdWithLevel(sourceId, level); + const targetIdWithLevel = getNodeIdWithLevel(targetId, level); + const linkIdWithLevel = getLinkIdWithLevel(sourceId, targetId, level); + const isCurrentLinkImportant = + link.type === HNSW_LINK_TYPE.Searched || + link.type === HNSW_LINK_TYPE.Fine; + isSourceChanged = preSourceIdWithLevel !== sourceIdWithLevel; + + const isSourceEntry = !(sourceIdWithLevel in nodeShowTime); + if (isSourceEntry) { + if (level < linksLevels.length - 1) { + const entryLinkIdWithLevel = getEntryLinkIdWithLevel( + sourceId, + level + ); + linkShowTime[entryLinkIdWithLevel] = currentTime; + const targetLinkIdWithLevel = getEntryLinkIdWithLevel( + 'target', + level + ); + linkShowTime[targetLinkIdWithLevel] = currentTime; + currentTime += interLevelGap; + isPreLinkImportant = true; + } + targetShowTime[level] = currentTime; + nodeShowTime[sourceIdWithLevel] = currentTime; + } + + // something wrong + if (isPreLinkImportant || isCurrentLinkImportant || isSourceChanged) { + currentTime += intraLevelGap; + } else { + currentTime += intraLevelGap * 0.5; + } + + linkShowTime[linkIdWithLevel] = currentTime; + + if (!(targetIdWithLevel in nodeShowTime)) { + nodeShowTime[targetIdWithLevel] = currentTime += intraLevelGap; + } + + isPreLinkImportant = isCurrentLinkImportant; + preSourceIdWithLevel = sourceIdWithLevel; + }); + } + + currentTime += intraLevelGap; + isPreLinkImportant = true; + isSourceChanged = true; + } + return { targetShowTime, nodeShowTime, linkShowTime, duration: currentTime }; +}; + +export default computeSearchViewTransition; diff --git a/federjs_old/FederView/HnswView/layout/forceSearchView.js b/federjs_old/FederView/HnswView/layout/forceSearchView.js new file mode 100644 index 0000000..6863b79 --- /dev/null +++ b/federjs_old/FederView/HnswView/layout/forceSearchView.js @@ -0,0 +1,81 @@ +import * as d3 from 'd3'; +import { HNSW_LINK_TYPE } from 'Types'; +import { deDupLink } from 'Utils'; + +const forceSearchView = ( + visData, + targetOrigin = [0, 0], + forceIterations = 100 +) => { + return new Promise((resolve) => { + const nodeId2dist = {}; + visData.forEach((levelData) => + levelData.nodes.forEach((node) => (nodeId2dist[node.id] = node.dist || 0)) + ); + const nodeIds = Object.keys(nodeId2dist); + const nodes = nodeIds.map((nodeId) => ({ + nodeId: nodeId, + dist: nodeId2dist[nodeId], + })); + + const linksAll = visData.reduce((acc, cur) => acc.concat(cur.links), []); + const links = deDupLink(linksAll); + // console.log(nodes, links); + // console.log(links.length, linksAll.length); + + const targetNode = { + nodeId: 'target', + dist: 0, + fx: targetOrigin[0], + fy: targetOrigin[1], + }; + nodes.push(targetNode); + + const targetLinks = visData[0].fineIds.map((fineId) => ({ + source: `${fineId}`, + target: 'target', + type: HNSW_LINK_TYPE.None, + })); + links.push(...targetLinks); + // console.log(nodes, links); + + const rScale = d3 + .scaleLinear() + .domain( + d3.extent( + nodes.filter((node) => node.dist > 0), + (node) => node.dist + ) + ) + .range([10, 1000]) + .clamp(true); + const simulation = d3 + .forceSimulation(nodes) + .alphaDecay(1 - Math.pow(0.001, 1 / forceIterations)) + .force( + 'link', + d3 + .forceLink(links) + .id((d) => `${d.nodeId}`) + .strength((d) => (d.type === HNSW_LINK_TYPE.None ? 2 : 0.4)) + ) + .force( + 'r', + d3 + .forceRadial( + (node) => rScale(node.dist), + targetOrigin[0], + targetOrigin[1] + ) + .strength(1) + ) + .force('charge', d3.forceManyBody().strength(-10000)) + .on('end', () => { + const id2forcePos = {}; + nodes.forEach((node) => (id2forcePos[node.nodeId] = [node.x, node.y])); + resolve(id2forcePos); + }); + }); +}; + +export default forceSearchView; diff --git a/federjs_old/FederView/HnswView/layout/mouse2node.js b/federjs_old/FederView/HnswView/layout/mouse2node.js new file mode 100644 index 0000000..e340615 --- /dev/null +++ b/federjs_old/FederView/HnswView/layout/mouse2node.js @@ -0,0 +1,27 @@ +import * as d3 from 'd3'; +import { dist2 } from 'Utils'; + +export default function mouse2node( + { mouse, layerPosLevels, nodesLevels, posAttr }, + { mouse2nodeBias, canvasScale } +) { + const mouseLevel = layerPosLevels.findIndex((points) => + d3.polygonContains(points, mouse) + ); + let mouseNode; + if (mouseLevel >= 0) { + const allDis = nodesLevels[mouseLevel].map((node) => + dist2(node[posAttr][mouseLevel], mouse) + ); + const minDistIndex = d3.minIndex(allDis); + const minDist = allDis[minDistIndex]; + const clearestNode = nodesLevels[mouseLevel][minDistIndex]; + mouseNode = + minDist < Math.pow((clearestNode.r + mouse2nodeBias) * canvasScale, 2) + ? clearestNode + : null; + } else { + mouseNode = null; + } + return { mouseLevel, mouseNode }; +} diff --git a/federjs_old/FederView/HnswView/layout/overviewLayout.js b/federjs_old/FederView/HnswView/layout/overviewLayout.js new file mode 100644 index 0000000..d08620c --- /dev/null +++ b/federjs_old/FederView/HnswView/layout/overviewLayout.js @@ -0,0 +1,103 @@ +import * as d3 from 'd3'; +import transformHandler from './transformHandler'; + +export const overviewLayoutHandler = ({ + overviewNodes, + overviewLevelCount, + width, + height, + padding, + forceIterations, + M, +}) => { + return new Promise(async (resolve) => { + const overviewNodesLevels = []; + const overviewLinksLevels = []; + for (let level = overviewLevelCount - 1; level >= 0; level--) { + const nodes = overviewNodes.filter( + (node) => node.linksLevels.length > level + ); + const links = nodes.reduce( + (acc, curNode) => + acc.concat( + curNode.linksLevels[level].map((targetNodeInternalId) => ({ + source: curNode.internalId, + target: targetNodeInternalId, + })) + ), + [] + ); + await forceLevel({ nodes, links, forceIterations }); + level > 0 && scaleNodes({ nodes, M }); + level > 0 && fixedCurLevel({ nodes }); + overviewNodesLevels[level] = nodes; + overviewLinksLevels[level] = links; + } + + const { layerPosLevels: overviewLayerPosLevels, transformFunc } = + transformHandler(overviewNodes, { + levelCount: overviewLevelCount, + width, + height, + padding, + }); + + overviewNodes.forEach((node) => { + node.overviewPosLevels = node.linksLevels.map((_, level) => + transformFunc(node.x, node.y, level) + ); + node.r = node.linksLevels.length * 0.8 + 1; + }); + + resolve({ + overviewLayerPosLevels, + overviewNodesLevels, + overviewLinksLevels, + }); + }); +}; + +export default overviewLayoutHandler; + +export const forceLevel = ({ nodes, links, forceIterations }) => { + return new Promise((resolve) => { + const simulation = d3 + .forceSimulation(nodes) + .alphaDecay(1 - Math.pow(0.001, (1 / forceIterations) * 2)) + .force( + 'link', + d3 + .forceLink(links) + .id((d) => d.internalId) + .strength(1) + ) + .force('center', d3.forceCenter(0, 0)) + .force('charge', d3.forceManyBody().strength(-500)) + .on('end', () => { + resolve(); + }); + }); +}; + +export const scaleNodes = ({ nodes, M }) => { + const xRange = d3.extent(nodes, (node) => node.x); + const yRange = d3.extent(nodes, (node) => node.y); + + const isXLonger = xRange[1] - xRange[0] > yRange[1] - yRange[0]; + if (!isXLonger) { + nodes.forEach((node) => ([node.x, node.y] = [node.y, node.x])); + } + + const t = Math.sqrt(M) * 0.85; + nodes.forEach((node) => { + node.x = node.x * t; + node.y = node.y * t; + }); +}; + +export const fixedCurLevel = ({ nodes }) => { + nodes.forEach((node) => { + node.fx = node.x; + node.fy = node.y; + }); +}; diff --git a/federjs_old/FederView/HnswView/layout/overviewShortestPath.js b/federjs_old/FederView/HnswView/layout/overviewShortestPath.js new file mode 100644 index 0000000..3ab2f53 --- /dev/null +++ b/federjs_old/FederView/HnswView/layout/overviewShortestPath.js @@ -0,0 +1,65 @@ +export default function getOverviewShortestPathData( + keyNode, + keyLevel, + { overviewNodesLevels, internalId2overviewNode, overviewLevelCount } +) { + let SPLinksLevels = overviewNodesLevels.map((_) => []); + let SPNodesLevels = overviewNodesLevels.map((_) => []); + let reachableNodes = []; + let reachableLinks = []; + let reachableLevel = null; + if (keyNode) { + const path = [...keyNode.path, keyNode.internalId]; + if (path.length === 0) { + SPNodesLevels = [keyNode.overviewPosLevels[keyLevel]]; + } else { + let preNodeId = path[0]; + let preNode = internalId2overviewNode[preNodeId]; + let preLevel = overviewLevelCount - 1; + SPNodesLevels[preLevel].push(preNode); + for (let i = 1; i < path.length; i++) { + let curNodeId = path[i]; + let curNode = internalId2overviewNode[curNodeId]; + while (curNode.overviewPosLevels.length <= preLevel) { + preLevel -= 1; + SPLinksLevels[preLevel].push({ + source: preNode, + target: preNode, + }); + SPNodesLevels[preLevel].push(preNode); + } + SPNodesLevels[preLevel].push(curNode); + SPLinksLevels[preLevel].push({ + source: preNode, + target: curNode, + }); + preNode = curNode; + } + while (preLevel > keyLevel) { + preLevel -= 1; + SPLinksLevels[preLevel].push({ + source: preNode, + target: preNode, + }); + SPNodesLevels[preLevel].push(preNode); + } + } + const preNodeInternalId = + keyNode.path.length > 0 ? keyNode.path[keyNode.path.length - 1] : null; + reachableLevel = keyLevel; + reachableNodes = keyNode.linksLevels[keyLevel] + .filter((internalId) => internalId != preNodeInternalId) + .map((internalId) => internalId2overviewNode[internalId]); + reachableLinks = reachableNodes.map((target) => ({ + source: keyNode, + target, + })); + } + return { + SPLinksLevels, + SPNodesLevels, + reachableLevel, + reachableNodes, + reachableLinks, + }; +} diff --git a/federjs_old/FederView/HnswView/layout/parseVisRecords.js b/federjs_old/FederView/HnswView/layout/parseVisRecords.js new file mode 100644 index 0000000..1630d21 --- /dev/null +++ b/federjs_old/FederView/HnswView/layout/parseVisRecords.js @@ -0,0 +1,105 @@ +import { HNSW_NODE_TYPE, HNSW_LINK_TYPE } from 'Types'; +import { getLinkId, parseLinkId } from 'Utils'; + +export const parseVisRecords = ({ topkResults, vis_records }) => { + const visData = []; + const numLevels = vis_records.length; + let fineIds = topkResults.map((d) => d.id); + let entryId = -1; + for (let i = numLevels - 1; i >= 0; i--) { + const level = numLevels - 1 - i; + if (level > 0) { + fineIds = [entryId]; + } + + const visRecordsLevel = vis_records[i]; + + const id2nodeType = {}; + const linkId2linkType = {}; + const updateNodeType = (nodeId, type) => { + if (id2nodeType[nodeId]) { + id2nodeType[nodeId] = Math.max(id2nodeType[nodeId], type); + } else { + id2nodeType[nodeId] = type; + } + }; + const updateLinkType = (sourceId, targetId, type) => { + const linkId = getLinkId(sourceId, targetId, type); + if (linkId2linkType[linkId]) { + linkId2linkType[linkId] = Math.max(linkId2linkType[linkId], type); + } else { + linkId2linkType[linkId] = type; + } + }; + const id2dist = {}; + const sourceMap = {}; + + visRecordsLevel.forEach((record) => { + const [sourceId, targetId, dist] = record; + + if (sourceId === targetId) { + // entry + entryId = targetId; + id2dist[targetId] = dist; + } else { + updateNodeType(sourceId, HNSW_NODE_TYPE.Candidate); + updateNodeType(targetId, HNSW_NODE_TYPE.Coarse); + + if (id2dist[targetId] >= 0) { + // visited + updateLinkType(sourceId, targetId, HNSW_LINK_TYPE.Visited); + } else { + // not visited + id2dist[targetId] = dist; + updateLinkType(sourceId, targetId, HNSW_LINK_TYPE.Extended); + + sourceMap[targetId] = sourceId; + + // only level-0 have "link_type - search" + if (level === 0) { + const preSourceId = sourceMap[sourceId]; + if (preSourceId >= 0) { + updateLinkType(preSourceId, sourceId, HNSW_LINK_TYPE.Searched); + } + } + } + } + }); + + fineIds.forEach((fineId) => { + updateNodeType(fineId, HNSW_NODE_TYPE.Fine); + + let t = fineId; + while (t in sourceMap) { + let s = sourceMap[t]; + updateLinkType(s, t, HNSW_LINK_TYPE.Fine); + t = s; + } + }); + + const nodes = Object.keys(id2nodeType).map((id) => ({ + id: `${id}`, + type: id2nodeType[id], + dist: id2dist[id], + })); + const links = Object.keys(linkId2linkType).map((linkId) => { + const [source, target] = parseLinkId(linkId); + return { + source: `${source}`, + target: `${target}`, + type: linkId2linkType[linkId], + }; + }); + const visDataLevel = { + entryIds: [`${entryId}`], + fineIds: fineIds.map((id) => `${id}`), + links, + nodes, + }; + visData.push(visDataLevel); + } + + return visData; +}; + +export default parseVisRecords; diff --git a/federjs_old/FederView/HnswView/layout/searchViewLayout.js b/federjs_old/FederView/HnswView/layout/searchViewLayout.js new file mode 100644 index 0000000..f00ca6b --- /dev/null +++ b/federjs_old/FederView/HnswView/layout/searchViewLayout.js @@ -0,0 +1,102 @@ +import * as d3 from 'd3'; +import parseVisRecords from './parseVisRecords'; +import forceSearchView from './forceSearchView'; +import transformHandler from './transformHandler'; +import computeSearchViewTransition from './computeSearchViewTransition'; +import { HNSW_LINK_TYPE, HNSW_NODE_TYPE } from 'Types'; + +export default async function searchViewLayoutHandler(searchRes, federView) { + const { + targetR, + canvasScale, + targetOrigin, + searchViewNodeBasicR, + searchInterLevelTime, + searchIntraLevelTime, + forceIterations, + } = federView; + + const visData = parseVisRecords(searchRes); + + const id2forcePos = await forceSearchView( + visData, + targetOrigin, + forceIterations + ); + + const searchNodesLevels = visData.map((levelData) => levelData.nodes); + searchNodesLevels.forEach((levelData) => + levelData.forEach((node) => { + node.forcePos = id2forcePos[node.id]; + node.x = node.forcePos[0]; + node.y = node.forcePos[1]; + }) + ); + const { layerPosLevels, transformFunc } = transformHandler( + searchNodesLevels.reduce((acc, node) => acc.concat(node), []), + federView + ); + + const searchTarget = { + id: 'target', + r: targetR * canvasScale, + searchViewPosLevels: d3 + .range(visData.length) + .map((i) => transformFunc(...targetOrigin, i)), + }; + + searchNodesLevels.forEach((nodes, level) => { + nodes.forEach((node) => { + node.searchViewPosLevels = d3 + .range(level + 1) + .map((i) => transformFunc(...node.forcePos, i)); + node.r = (searchViewNodeBasicR + node.type * 0.5) * canvasScale; + }); + }); + + const id2searchNode = {}; + searchNodesLevels.forEach((levelData) => + levelData.forEach((node) => (id2searchNode[node.id] = node)) + ); + + const searchLinksLevels = parseVisRecords(searchRes).map((levelData) => + levelData.links.filter((link) => link.type !== HNSW_LINK_TYPE.None) + ); + searchLinksLevels.forEach((levelData) => + levelData.forEach((link) => { + const sourceId = link.source; + const targetId = link.target; + const sourceNode = id2searchNode[sourceId]; + const targetNode = id2searchNode[targetId]; + link.source = sourceNode; + link.target = targetNode; + }) + ); + + const entryNodesLevels = visData.map((levelData) => + levelData.entryIds.map((id) => id2searchNode[id]) + ); + + const { targetShowTime, nodeShowTime, linkShowTime, duration } = + computeSearchViewTransition({ + linksLevels: searchLinksLevels, + entryNodesLevels, + interLevelGap: searchInterLevelTime, + intraLevelGap: searchIntraLevelTime, + }); + + return { + visData, + id2forcePos, + searchTarget, + entryNodesLevels, + searchNodesLevels, + searchLinksLevels, + searchLayerPosLevels: layerPosLevels, + searchTargetShowTime: targetShowTime, + searchNodeShowTime: nodeShowTime, + searchLinkShowTime: linkShowTime, + searchTransitionDuration: duration, + searchParams: searchRes.searchParams, + }; +} diff --git a/federjs_old/FederView/HnswView/layout/transformHandler.js b/federjs_old/FederView/HnswView/layout/transformHandler.js new file mode 100644 index 0000000..dd10153 --- /dev/null +++ b/federjs_old/FederView/HnswView/layout/transformHandler.js @@ -0,0 +1,48 @@ +import * as d3 from 'd3'; +import { generateArray } from 'Utils'; + +export const transformHandler = ( + nodes, + { levelCount, width, height, padding, xBias = 0.65, yBias = 0.4, yOver = 0.1 } +) => { + const layerWidth = width - padding[1] - padding[3]; + const layerHeight = + (height - padding[0] - padding[2]) / + (levelCount - (levelCount - 1) * yOver); + const xRange = d3.extent(nodes, (node) => node.x); + const yRange = d3.extent(nodes, (node) => node.y); + + const xOffset = padding[3] + layerWidth * xBias; + const transformFunc = (x, y, level) => { + const _x = (x - xRange[0]) / (xRange[1] - xRange[0]); + const _y = (y - yRange[0]) / (yRange[1] - yRange[0]); + + const newX = + xOffset + _x * layerWidth * (1 - xBias) - _y * layerWidth * xBias; + + const newY = + padding[0] + + layerHeight * (1 - yOver) * (levelCount - 1 - level) + + _x * layerHeight * (1 - yBias) + + _y * layerHeight * yBias; + + return [newX, newY]; + }; + const layerPos = [ + [layerWidth * xBias, 0], + [layerWidth, layerHeight * (1 - yBias)], + [layerWidth * (1 - xBias), layerHeight], + [0, layerHeight * yBias], + ]; + const layerPosLevels = generateArray(levelCount).map((_, level) => + layerPos.map((coord) => [ + coord[0] + padding[3], + coord[1] + + padding[0] + + layerHeight * (1 - yOver) * (levelCount - 1 - level), + ]) + ); + return { layerPosLevels, transformFunc }; +}; + +export default transformHandler; diff --git a/federjs_old/FederView/HnswView/render/TimeControllerView.js b/federjs_old/FederView/HnswView/render/TimeControllerView.js new file mode 100644 index 0000000..ececbfb --- /dev/null +++ b/federjs_old/FederView/HnswView/render/TimeControllerView.js @@ -0,0 +1,166 @@ +import * as d3 from 'd3'; + +const iconGap = 10; +const rectW = 36; +const sliderBackGroundWidth = 200; +const sliderWidth = sliderBackGroundWidth * 0.8; +const sliderHeight = rectW * 0.15; +const sliderBarWidth = 10; +const sliderBarHeight = rectW * 0.6; +const resetW = 16; +const resetIconD = `M12.3579 13.0447C11.1482 14.0929 9.60059 14.6689 7.99992 14.6667C4.31792 14.6667 1.33325 11.682 1.33325 8.00004C1.33325 4.31804 4.31792 1.33337 7.99992 1.33337C11.6819 1.33337 14.6666 4.31804 14.6666 8.00004C14.6666 9.42404 14.2199 10.744 13.4599 11.8267L11.3333 8.00004H13.3333C13.3332 6.77085 12.9085 5.57942 12.131 4.6273C11.3536 3.67519 10.2712 3.02084 9.06681 2.77495C7.86246 2.52906 6.61014 2.70672 5.5217 3.27788C4.43327 3.84905 3.57553 4.77865 3.0936 5.90943C2.61167 7.04021 2.53512 8.30275 2.87691 9.48347C3.2187 10.6642 3.95785 11.6906 4.96931 12.3891C5.98077 13.0876 7.20245 13.4152 8.42768 13.3166C9.65292 13.218 10.8065 12.6993 11.6933 11.848L12.3579 13.0447Z`; +const pauseIconHeight = rectW * 0.4; +const pauseIconWidth = rectW * 0.08; +const pauseIconGap = rectW * 0.15; +const pauseIconX = (rectW - pauseIconWidth * 2 - pauseIconGap) / 2; +export class TimeControllerView { + constructor(domSelector) { + this.render(domSelector); + this.moveSilderBar = () => {}; + } + play() { + this.renderPauseIcon(); + } + pause() { + this.renderPlayIcon(); + } + renderPlayIcon() { + const playPauseIconG = this.playPauseIconG; + playPauseIconG.selectAll('*').remove(); + playPauseIconG + .append('path') + .attr( + 'd', + `M${rectW * 0.36},${rectW * 0.3}L${rectW * 0.64},${rectW * 0.5}L${ + rectW * 0.36 + },${rectW * 0.7}Z` + ) + .attr('fill', '#000'); + } + renderPauseIcon() { + const playPauseIconG = this.playPauseIconG; + playPauseIconG.selectAll('*').remove(); + playPauseIconG + .selectAll('rect') + .data([, ,]) + .join('rect') + .attr('x', (_, i) => pauseIconX + i * (pauseIconGap + pauseIconWidth)) + .attr('y', (rectW - pauseIconHeight) / 2) + .attr('rx', pauseIconWidth / 2) + .attr('ry', pauseIconWidth / 2) + .attr('width', pauseIconWidth) + .attr('height', pauseIconHeight) + .attr('fill', '#000'); + } + render(domSelector) { + const _dom = d3.select(domSelector); + _dom.selectAll('svg#feder-timer').remove(); + const svg = _dom + .append('svg') + .attr('id', 'feder-timer') + .attr('width', 300) + .attr('height', rectW) + .style('position', 'absolute') + .style('left', '20px') + .style('bottom', '32px'); + // .style('border', '1px solid red'); + + const playPauseG = svg.append('g'); + playPauseG + .append('rect') + .attr('x', 0) + .attr('y', 0) + .attr('width', rectW) + .attr('height', rectW) + .attr('fill', '#fff'); + const playPauseIconG = playPauseG.append('g'); + this.playPauseIconG = playPauseIconG; + this.renderPlayIcon(); + + const sliderG = svg + .append('g') + .attr('transform', `translate(${rectW + iconGap}, 0)`); + sliderG + .append('rect') + .attr('x', 0) + .attr('y', 0) + .attr('width', sliderBackGroundWidth) + .attr('height', rectW) + .attr('fill', '#1D2939'); + sliderG + .append('rect') + .attr('x', sliderBackGroundWidth / 2 - sliderWidth / 2) + .attr('y', rectW / 2 - sliderHeight / 2) + .attr('width', sliderWidth) + .attr('height', sliderHeight) + .attr('fill', '#fff'); + const sliderBar = sliderG + .append('g') + .append('rect') + .datum({ x: 0, y: 0 }) + .attr( + 'transform', + `translate(${ + sliderBackGroundWidth / 2 - sliderWidth / 2 - sliderBarWidth / 2 + },0)` + ) + .attr('x', 0) + .attr('y', rectW / 2 - sliderBarHeight / 2) + .attr('width', sliderBarWidth) + .attr('height', sliderBarHeight) + .attr('fill', '#fff'); + + const resetG = svg + .append('g') + .attr( + 'transform', + `translate(${rectW + iconGap + sliderBackGroundWidth + iconGap}, 0)` + ); + resetG + .append('rect') + .attr('x', 0) + .attr('y', 0) + .attr('width', rectW) + .attr('height', rectW) + .attr('fill', '#fff'); + + resetG + .append('path') + .attr('d', resetIconD) + .attr('fill', '#000') + .attr( + 'transform', + `translate(${rectW / 2 - resetW / 2},${rectW / 2 - resetW / 2})` + ); + + this.playPauseG = playPauseG; + this.sliderBar = sliderBar; + this.resetG = resetG; + } + + setTimer(timer) { + this.playPauseG.on('click', () => timer.playPause()); + this.resetG.on('click', () => timer.restart()); + + const drag = d3 + .drag() + .on('start', () => timer.stop()) + .on('drag', (e, d) => { + const x = Math.max(0, Math.min(e.x, sliderWidth)); + sliderBar.attr('x', (d.x = x)); + timer.setTimeP(x / sliderWidth); + }); + // .on('end', continue); + + const sliderBar = this.sliderBar; + sliderBar.call(drag); + + this.moveSilderBar = (p) => { + const x = p * sliderWidth; + sliderBar.datum().x = x; + sliderBar.attr('x', x); + }; + } +} + +export default TimeControllerView; diff --git a/federjs_old/FederView/HnswView/render/TimerController.js b/federjs_old/FederView/HnswView/render/TimerController.js new file mode 100644 index 0000000..f77c246 --- /dev/null +++ b/federjs_old/FederView/HnswView/render/TimerController.js @@ -0,0 +1,82 @@ +import * as d3 from 'd3'; + +export default class TimerController { + constructor({ duration, speed = 1, callback, playCallback, pauseCallback }) { + this.callback = callback; + this.speed = speed; + this.duration = duration; + this.playCallback = playCallback; + this.pauseCallback = pauseCallback; + + this.tAlready = 0; + this.t = 0; + this.timer = null; + this.isPlaying = false; + } + get currentT() { + return this.t; + } + start() { + const speed = this.speed; + this.isPlaying || this.playCallback(); + this.isPlaying = true; + this.timer = d3.timer((elapsed) => { + const t = elapsed * speed + this.tAlready; + const p = t / this.duration; + this.t = t; + this.callback({ + t, + p, + }); + if (p >= 1) { + this.stop(); + } + }); + } + restart() { + this.timer.stop(); + this.tAlready = 0; + this.start(); + } + stop() { + this.timer.stop(); + this.tAlready = this.t; + + this.isPlaying && this.pauseCallback(); + this.isPlaying = false; + } + playPause() { + if (this.isPlaying) this.stop(); + else this.start(); + } + continue() { + this.start(); + } + setSpeed(speed) { + this.stop(); + this.speed = speed; + this.continue(); + } + setTimeT(t) { + this.stop(); + const p = t / this.duration; + this.tAlready = t; + this.t = t; + this.callback({ + t, + p, + }); + // this.continue(); + } + setTimeP(p) { + this.stop(); + const t = this.duration * p; + this.tAlready = t; + this.t = t; + this.callback({ + t, + p, + }); + // this.continue(); + } +} diff --git a/federjs_old/FederView/HnswView/render/renderBackground.js b/federjs_old/FederView/HnswView/render/renderBackground.js new file mode 100644 index 0000000..efbb6d3 --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderBackground.js @@ -0,0 +1,11 @@ +import { drawRect, blackColor } from 'Utils/renderUtils'; + +export default function renderBackground(ctx, { width, height }) { + drawRect({ + ctx, + width, + height, + hasFill: true, + fillStyle: blackColor, + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderHoverLine.js b/federjs_old/FederView/HnswView/render/renderHoverLine.js new file mode 100644 index 0000000..ab6c100 --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderHoverLine.js @@ -0,0 +1,56 @@ +import { drawPath, hexWithOpacity, ZYellow } from 'Utils/renderUtils'; + +const renderHoverLine = ( + ctx, + { hoveredNode, hoveredLevel, clickedNode, clickedLevel }, + { + width, + padding, + hoveredPanelLineWidth, + HoveredPanelLine_1_x, + HoveredPanelLine_1_y, + HoveredPanelLine_2_x, + canvasScale, + } +) => { + let isLeft = true; + let endX = 0; + let endY = 0; + if (!!hoveredNode) { + const [x, y] = hoveredNode.overviewPosLevels[hoveredLevel]; + const originX = (width - padding[1] - padding[3]) / 2 + padding[3]; + isLeft = !clickedNode + ? originX > x + : clickedNode.overviewPosLevels[clickedLevel][0] > x; + const k = isLeft ? -1 : 1; + endX = + x + + HoveredPanelLine_1_x * canvasScale * k + + HoveredPanelLine_2_x * canvasScale * k; + endY = y + HoveredPanelLine_1_y * canvasScale * k; + const points = [ + [x, y], + [ + x + HoveredPanelLine_1_x * canvasScale * k, + y + HoveredPanelLine_1_y * canvasScale * k, + ], + [ + x + + HoveredPanelLine_1_x * canvasScale * k + + HoveredPanelLine_2_x * canvasScale * k, + y + HoveredPanelLine_1_y * canvasScale * k, + ], + ]; + drawPath({ + ctx, + points, + withZ: false, + hasStroke: true, + strokeStyle: hexWithOpacity(ZYellow, 1), + lineWidth: hoveredPanelLineWidth * canvasScale, + }); + } + return { isLeft, endX, endY }; +}; + +export default renderHoverLine; diff --git a/federjs_old/FederView/HnswView/render/renderHoveredPanelLine.js b/federjs_old/FederView/HnswView/render/renderHoveredPanelLine.js new file mode 100644 index 0000000..3d3abca --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderHoveredPanelLine.js @@ -0,0 +1,36 @@ +import { drawPath, hexWithOpacity, ZYellow } from 'Utils/renderUtils'; + +export default function renderHoveredPanelLine( + ctx, + { x, y, isLeft }, + { + hoveredPanelLineWidth, + HoveredPanelLine_1_x, + HoveredPanelLine_1_y, + HoveredPanelLine_2_x, + canvasScale, + } +) { + const k = isLeft ? -1 : 1; + const points = [ + [x, y], + [ + x + HoveredPanelLine_1_x * canvasScale * k, + y + HoveredPanelLine_1_y * canvasScale * k, + ], + [ + x + + HoveredPanelLine_1_x * canvasScale * k + + HoveredPanelLine_2_x * canvasScale * k, + y + HoveredPanelLine_1_y * canvasScale * k, + ], + ]; + drawPath({ + ctx, + points, + withZ: false, + hasStroke: true, + strokeStyle: hexWithOpacity(ZYellow, 1), + lineWidth: hoveredPanelLineWidth * canvasScale, + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderLinks.js b/federjs_old/FederView/HnswView/render/renderLinks.js new file mode 100644 index 0000000..024972f --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderLinks.js @@ -0,0 +1,29 @@ +import { + drawLinesWithLinearGradient, + normalGradientStopColors, +} from 'Utils/renderUtils'; +import { shortenLine } from 'Utils'; + +export default function renderLinks( + ctx, + links, + level, + { shortenLineD, overviewLinkLineWidth, canvasScale } +) { + const pointsList = links.map((link) => + shortenLine( + link.source.overviewPosLevels[level], + link.target.overviewPosLevels[level], + shortenLineD * canvasScale + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: normalGradientStopColors, + lineWidth: overviewLinkLineWidth * canvasScale, + lineCap: 'round', + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderNodes.js b/federjs_old/FederView/HnswView/render/renderNodes.js new file mode 100644 index 0000000..fa2c3f7 --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderNodes.js @@ -0,0 +1,21 @@ +import { drawEllipse, ZBlue, hexWithOpacity } from 'Utils/renderUtils'; + +export default function renderNodes( + ctx, + nodes, + level, + { canvasScale, ellipseRation, shadowBlur } +) { + drawEllipse({ + ctx, + circles: nodes.map((node) => [ + ...node.overviewPosLevels[level], + node.r * ellipseRation * canvasScale, + node.r * canvasScale, + ]), + hasFill: true, + fillStyle: hexWithOpacity(ZBlue, 0.75), + shadowColor: ZBlue, + shadowBlur: shadowBlur * canvasScale, + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderOverview.js b/federjs_old/FederView/HnswView/render/renderOverview.js new file mode 100644 index 0000000..cbf2a13 --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderOverview.js @@ -0,0 +1,28 @@ +import renderBackground from './renderBackground'; +import renderlevelLayer from './renderlevelLayer'; +import renderLinks from './renderLinks'; +import renderNodes from './renderNodes'; +import renderReachable from './renderReachable'; +import renderShortestPath from './renderShortestPath'; + +export default function renderOverview(ctx, federView, overviewHighlightData) { + const { + overviewLevelCount, + overviewNodesLevels, + overviewLinksLevels, + overviewLayerPosLevels, + } = federView; + renderBackground(ctx, federView); + for (let level = 0; level < overviewLevelCount; level++) { + renderlevelLayer(ctx, overviewLayerPosLevels[level], federView); + const nodes = overviewNodesLevels[level]; + const links = overviewLinksLevels[level]; + level > 0 && renderLinks(ctx, links, level, federView); + renderNodes(ctx, nodes, level, federView); + + if (overviewHighlightData) { + renderReachable(ctx, level, overviewHighlightData, federView); + renderShortestPath(ctx, level, overviewHighlightData, federView); + } + } +} diff --git a/federjs_old/FederView/HnswView/render/renderReachable.js b/federjs_old/FederView/HnswView/render/renderReachable.js new file mode 100644 index 0000000..13c718a --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderReachable.js @@ -0,0 +1,51 @@ +import { + hexWithOpacity, + whiteColor, + drawLinesWithLinearGradient, + neighbourGradientStopColors, + drawEllipse, +} from 'Utils/renderUtils'; + +import { shortenLine } from 'Utils'; + +export default function renderReachableData( + ctx, + level, + { reachableLevel, reachableNodes, reachableLinks }, + { + shortenLineD, + canvasScale, + reachableLineWidth, + ellipseRation, + shadowBlur, + highlightRadiusExt, + posAttr = 'overviewPosLevels', + } +) { + if (level != reachableLevel) return; + const pointsList = reachableLinks + .map((link) => [link.source[posAttr][level], link.target[posAttr][level]]) + .map((points) => shortenLine(...points, shortenLineD * canvasScale)); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: neighbourGradientStopColors, + lineWidth: reachableLineWidth * canvasScale, + lineCap: 'round', + }); + + drawEllipse({ + ctx, + circles: reachableNodes.map((node) => [ + ...node[posAttr][level], + (node.r + highlightRadiusExt) * ellipseRation * canvasScale, + (node.r + highlightRadiusExt) * canvasScale, + ]), + hasFill: true, + fillStyle: hexWithOpacity(whiteColor, 1), + shadowColor: whiteColor, + shadowBlur: shadowBlur * canvasScale, + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderSearchViewInterLevelLinks.js b/federjs_old/FederView/HnswView/render/renderSearchViewInterLevelLinks.js new file mode 100644 index 0000000..7181e44 --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderSearchViewInterLevelLinks.js @@ -0,0 +1,92 @@ +import { + drawLinesWithLinearGradient, + highLightGradientStopColors, + targetLevelGradientStopColors, +} from 'Utils/renderUtils'; +import { shortenLine, getInprocessPos } from 'Utils'; + +export default function renderSearchViewInterLevelLinks( + ctx, + { entryNodes, inprocessEntryNodes, searchTarget, level }, + { shortenLineD, canvasScale } +) { + const pointsList = entryNodes.map((node) => + shortenLine( + node.searchViewPosLevels[level + 1], + node.searchViewPosLevels[level], + shortenLineD * canvasScale + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: 'round', + }); + const targetPointsList = + pointsList.length === 0 + ? [] + : [ + shortenLine( + searchTarget.searchViewPosLevels[level + 1], + searchTarget.searchViewPosLevels[level], + shortenLineD + ), + ]; + drawLinesWithLinearGradient({ + ctx, + pointsList: targetPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: targetLevelGradientStopColors, + lineWidth: 6, + lineCap: 'round', + }); + + const inprocessPointsList = inprocessEntryNodes.map(({ node, t }) => + shortenLine( + node.searchViewPosLevels[level + 1], + getInprocessPos( + node.searchViewPosLevels[level + 1], + node.searchViewPosLevels[level], + t + ), + shortenLineD + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: 'round', + }); + const inprocessTargetPointsList = + inprocessPointsList.length === 0 + ? [] + : [ + shortenLine( + searchTarget.searchViewPosLevels[level + 1], + getInprocessPos( + searchTarget.searchViewPosLevels[level + 1], + searchTarget.searchViewPosLevels[level], + inprocessEntryNodes[0].t + ), + shortenLineD + ), + ]; + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessTargetPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: targetLevelGradientStopColors, + lineWidth: 6, + lineCap: 'round', + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderSearchViewLinks.js b/federjs_old/FederView/HnswView/render/renderSearchViewLinks.js new file mode 100644 index 0000000..fc439ad --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderSearchViewLinks.js @@ -0,0 +1,184 @@ +import { + drawLinesWithLinearGradient, + highLightGradientStopColors, + normalGradientStopColors, +} from 'Utils/renderUtils'; +import { shortenLine, getInprocessPos } from 'Utils'; +import { HNSW_LINK_TYPE } from 'Types'; + +export default function renderSearchViewLinks( + ctx, + { links, inProcessLinks, level }, + { shortenLineD, canvasScale } +) { + let pointsList = []; + let inprocessPointsList = []; + + // Visited + pointsList = links + .filter((link) => link.type === HNSW_LINK_TYPE.Visited) + .map((link) => + shortenLine( + link.source.searchViewPosLevels[level], + link.target.searchViewPosLevels[level], + shortenLineD * canvasScale + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: normalGradientStopColors, + lineWidth: 4, + lineCap: 'round', + }); + inprocessPointsList = inProcessLinks + .filter(({ link }) => link.type === HNSW_LINK_TYPE.Visited) + .map(({ t, link }) => + shortenLine( + link.source.searchViewPosLevels[level], + getInprocessPos( + link.source.searchViewPosLevels[level], + link.target.searchViewPosLevels[level], + t + ), + shortenLineD + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: normalGradientStopColors, + lineWidth: 4, + lineCap: 'round', + }); + + // Extended + pointsList = links + .filter((link) => link.type === HNSW_LINK_TYPE.Extended) + .map((link) => + shortenLine( + link.source.searchViewPosLevels[level], + link.target.searchViewPosLevels[level], + shortenLineD + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: normalGradientStopColors, + lineWidth: 4, + lineCap: 'round', + }); + inprocessPointsList = inProcessLinks + .filter(({ link }) => link.type === HNSW_LINK_TYPE.Extended) + .map(({ t, link }) => + shortenLine( + link.source.searchViewPosLevels[level], + getInprocessPos( + link.source.searchViewPosLevels[level], + link.target.searchViewPosLevels[level], + t + ), + shortenLineD + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: normalGradientStopColors, + lineWidth: 4, + lineCap: 'round', + }); + + // Searched + pointsList = links + .filter((link) => link.type === HNSW_LINK_TYPE.Searched) + .map((link) => + shortenLine( + link.source.searchViewPosLevels[level], + link.target.searchViewPosLevels[level], + shortenLineD + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: 'round', + }); + inprocessPointsList = inProcessLinks + .filter(({ link }) => link.type === HNSW_LINK_TYPE.Searched) + .map(({ t, link }) => + shortenLine( + link.source.searchViewPosLevels[level], + getInprocessPos( + link.source.searchViewPosLevels[level], + link.target.searchViewPosLevels[level], + t + ), + shortenLineD + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: 'round', + }); + + // Fine + pointsList = links + .filter((link) => link.type === HNSW_LINK_TYPE.Fine) + .map((link) => + shortenLine( + link.source.searchViewPosLevels[level], + link.target.searchViewPosLevels[level], + shortenLineD + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: 'round', + }); + inprocessPointsList = inProcessLinks + .filter(({ link }) => link.type === HNSW_LINK_TYPE.Fine) + .map(({ t, link }) => + shortenLine( + link.source.searchViewPosLevels[level], + getInprocessPos( + link.source.searchViewPosLevels[level], + link.target.searchViewPosLevels[level], + t + ), + shortenLineD + ) + ); + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: 'round', + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderSearchViewNodes.js b/federjs_old/FederView/HnswView/render/renderSearchViewNodes.js new file mode 100644 index 0000000..3123e6e --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderSearchViewNodes.js @@ -0,0 +1,66 @@ +import { + drawEllipse, + hexWithOpacity, + ZBlue, + ZYellow, + ZOrange, + colorScheme, +} from 'Utils/renderUtils'; + +import { HNSW_NODE_TYPE } from 'Types'; + +export default function renderSearchViewNodes( + ctx, + { nodes, level }, + { ellipseRation, shadowBlur } +) { + let _nodes = []; + + // coarse + _nodes = nodes.filter((node) => node.type === HNSW_NODE_TYPE.Coarse); + drawEllipse({ + ctx, + circles: _nodes.map((node) => [ + ...node.searchViewPosLevels[level], + node.r * ellipseRation, + node.r, + ]), + hasFill: true, + fillStyle: hexWithOpacity(ZBlue, 0.7), + shadowColor: ZBlue, + shadowBlur, + }); + + // candidate + _nodes = nodes.filter((node) => node.type === HNSW_NODE_TYPE.Candidate); + drawEllipse({ + ctx, + circles: _nodes.map((node) => [ + ...node.searchViewPosLevels[level], + node.r * ellipseRation, + node.r, + ]), + hasFill: true, + fillStyle: hexWithOpacity(ZYellow, 0.8), + shadowColor: ZYellow, + shadowBlur, + }); + + // fine + _nodes = nodes.filter((node) => node.type === HNSW_NODE_TYPE.Fine); + drawEllipse({ + ctx, + circles: _nodes.map((node) => [ + ...node.searchViewPosLevels[level], + node.r * ellipseRation, + node.r, + ]), + hasFill: true, + fillStyle: hexWithOpacity(colorScheme[2], 1), + hasStroke: true, + lineWidth: 1, + strokeStyle: hexWithOpacity(ZOrange, 0.8), + shadowColor: ZOrange, + shadowBlur, + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderSearchViewTarget.js b/federjs_old/FederView/HnswView/render/renderSearchViewTarget.js new file mode 100644 index 0000000..ccb9c60 --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderSearchViewTarget.js @@ -0,0 +1,18 @@ +import { drawEllipse, hexWithOpacity, whiteColor } from 'Utils/renderUtils'; + +export default function renderSearchViewTarget( + ctx, + { node, level }, + { ellipseRation } +) { + drawEllipse({ + ctx, + circles: [ + [...node.searchViewPosLevels[level], node.r * ellipseRation, node.r], + ], + hasFill: true, + fillStyle: hexWithOpacity(whiteColor, 1), + shadowColor: whiteColor, + shadowBlur: 6, + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderSearchViewTransition.js b/federjs_old/FederView/HnswView/render/renderSearchViewTransition.js new file mode 100644 index 0000000..8a116eb --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderSearchViewTransition.js @@ -0,0 +1,146 @@ +import * as d3 from 'd3'; +import renderBackground from './renderBackground'; +import renderlevelLayer from './renderlevelLayer'; +import renderSearchViewLinks from './renderSearchViewLinks'; +import renderSearchViewInterLevelLinks from './renderSearchViewInterLevelLinks'; +import renderSearchViewNodes from './renderSearchViewNodes'; +import renderSearchViewTarget from './renderSearchViewTarget'; +import renderSelectedNode from './renderSelectedNode'; +import renderHoveredPanelLine from './renderHoveredPanelLine'; +import { + getNodeIdWithLevel, + getLinkIdWithLevel, + getEntryLinkIdWithLevel, +} from 'Utils'; + +export default function renderSearchViewTransition( + ctx, + { + searchNodesLevels, + searchLinksLevels, + searchLayerPosLevels, + searchNodeShowTime, + searchLinkShowTime, + searchTarget, + searchTargetShowTime, + entryNodesLevels, + + clickedLevel, + clickedNode, + hoveredLevel, + hoveredNode, + }, + federView, + { t, p } +) { + const { + searchIntraLevelTime, + searchInterLevelTime, + width, + padding, + canvasScale, + } = federView; + renderBackground(ctx, federView); + + for (let level = 0; level < searchNodesLevels.length; level++) { + renderlevelLayer(ctx, searchLayerPosLevels[level], federView); + const nodes = searchNodesLevels[level].filter( + (node) => searchNodeShowTime[getNodeIdWithLevel(node.id, level)] < t + ); + const links = searchLinksLevels[level].filter( + (link) => + searchLinkShowTime[ + getLinkIdWithLevel(link.source.id, link.target.id, level) + ] + + searchIntraLevelTime < + t + ); + const inProcessLinks = searchLinksLevels[level] + .filter( + (link) => + searchLinkShowTime[ + getLinkIdWithLevel(link.source.id, link.target.id, level) + ] < t && + searchLinkShowTime[ + getLinkIdWithLevel(link.source.id, link.target.id, level) + ] + + searchIntraLevelTime >= + t + ) + .map((link) => ({ + t: + (t - + searchLinkShowTime[ + getLinkIdWithLevel(link.source.id, link.target.id, level) + ]) / + searchIntraLevelTime, + link, + })); + const entryNodes = + level === entryNodesLevels.length - 1 + ? [] + : entryNodesLevels[level].filter( + (entryNode) => + searchLinkShowTime[getEntryLinkIdWithLevel(entryNode.id, level)] + + searchInterLevelTime < + t + ); + const inprocessEntryNodes = + level === entryNodesLevels.length - 1 + ? [] + : entryNodesLevels[level] + .filter( + (entryNode) => + searchLinkShowTime[ + getEntryLinkIdWithLevel(entryNode.id, level) + ] < t && + searchLinkShowTime[ + getEntryLinkIdWithLevel(entryNode.id, level) + ] + + searchInterLevelTime >= + t + ) + .map((node) => ({ + node, + t: + (t - + searchLinkShowTime[getEntryLinkIdWithLevel(node.id, level)]) / + searchInterLevelTime, + })); + renderSearchViewLinks(ctx, { links, inProcessLinks, level }, federView); + // console.log(level, entryNodes); + renderSearchViewInterLevelLinks( + ctx, + { + entryNodes, + inprocessEntryNodes, + searchTarget, + level, + }, + federView + ); + renderSearchViewNodes(ctx, { nodes, level }, federView); + + searchTargetShowTime[level] < t && + renderSearchViewTarget(ctx, { node: searchTarget, level }, federView); + + if (!!hoveredNode) { + const [x, y] = hoveredNode.searchViewPosLevels[hoveredLevel]; + const originX = (width - padding[1] - padding[3]) / 2 + padding[3]; + const isLeft = originX > x; + + renderHoveredPanelLine(ctx, { x, y, isLeft }, federView); + } + + if (!!clickedNode) { + renderSelectedNode( + ctx, + { + pos: clickedNode.searchViewPosLevels[clickedLevel], + r: clickedNode.r + 2 * canvasScale, + }, + federView + ); + } + } +} diff --git a/federjs_old/FederView/HnswView/render/renderSelectedNode.js b/federjs_old/FederView/HnswView/render/renderSelectedNode.js new file mode 100644 index 0000000..9afcfde --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderSelectedNode.js @@ -0,0 +1,11 @@ +import { drawEllipse, hexWithOpacity, ZYellow } from 'Utils/renderUtils'; + +export default function renderSelectedNode(ctx, { pos, r }, { ellipseRation }) { + drawEllipse({ + ctx, + circles: [[...pos, r * ellipseRation, r]], + hasStroke: true, + strokeStyle: hexWithOpacity(ZYellow, 0.8), + lineWidth: 4, + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderShortestPath.js b/federjs_old/FederView/HnswView/render/renderShortestPath.js new file mode 100644 index 0000000..cd4c292 --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderShortestPath.js @@ -0,0 +1,58 @@ +import { shortenLine } from 'Utils'; +import { + drawEllipse, + drawLinesWithLinearGradient, + highLightGradientStopColors, + highLightColor, + hexWithOpacity, +} from 'Utils/renderUtils'; + +export default function renderShortestPath( + ctx, + level, + { SPLinksLevels, SPNodesLevels }, + { + shortenLineD, + canvasScale, + shortestPathLineWidth, + highlightRadiusExt, + shadowBlur, + ellipseRation, + posAttr = 'overviewPosLevels', + } +) { + const pointsList = (SPLinksLevels ? SPLinksLevels[level] : []) + .map((link) => + link.source === link.target + ? !!link.source[posAttr][level + 1] + ? [link.source[posAttr][level + 1], link.target[posAttr][level]] + : null + : [link.source[posAttr][level], link.target[posAttr][level]] + ) + .filter((a) => a) + .map((points) => shortenLine(...points, shortenLineD * canvasScale)); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: shortestPathLineWidth * canvasScale, + lineCap: 'round', + }); + + drawEllipse({ + ctx, + circles: (SPNodesLevels ? SPNodesLevels[level] : []) + .filter((node) => !!node[posAttr][level]) + .map((node) => [ + ...node[posAttr][level], + (node.r + highlightRadiusExt) * ellipseRation * canvasScale, + (node.r + highlightRadiusExt) * canvasScale, + ]), + hasFill: true, + fillStyle: hexWithOpacity(highLightColor, 1), + shadowColor: highLightColor, + shadowBlur: shadowBlur * canvasScale, + }); +} diff --git a/federjs_old/FederView/HnswView/render/renderlevelLayer.js b/federjs_old/FederView/HnswView/render/renderlevelLayer.js new file mode 100644 index 0000000..34e7f49 --- /dev/null +++ b/federjs_old/FederView/HnswView/render/renderlevelLayer.js @@ -0,0 +1,63 @@ +import * as d3 from 'd3'; +import { + drawCircle, + drawPath, + hexWithOpacity, + ZLayerBorder, + whiteColor, + layerGradientStopColors, +} from 'Utils/renderUtils'; +import { dist } from 'Utils'; + +export default function renderlevelLayer( + ctx, + points, + { canvasScale, layerDotNum } +) { + drawPath({ + ctx, + points, + hasStroke: true, + isStrokeLinearGradient: false, + strokeStyle: hexWithOpacity(ZLayerBorder, 0.6), + lineWidth: 0.5 * canvasScale, + hasFill: true, + isFillLinearGradient: true, + gradientStopColors: layerGradientStopColors, + gradientPos: [points[1][0], points[0][1], points[3][0], points[2][1]], + }); + + const rightTopLength = dist(points[0], points[1]); + const leftTopLength = dist(points[0], points[3]); + const rightTopDotNum = layerDotNum; + // const leftTopDotNum = (layerDotNum / rightTopLength) * leftTopLength; + const leftTopDotNum = layerDotNum; + const rightTopVec = [ + points[1][0] - points[0][0], + points[1][1] - points[0][1], + ]; + const leftTopVec = [points[3][0] - points[0][0], points[3][1] - points[0][1]]; + const dots = []; + for (let i = 0; i < layerDotNum; i++) { + const rightTopT = i / layerDotNum + 1 / (2 * layerDotNum); + for (let j = 0; j < layerDotNum; j++) { + const leftTopT = j / layerDotNum + 1 / (2 * layerDotNum); + dots.push([ + points[0][0] + rightTopVec[0] * rightTopT + leftTopVec[0] * leftTopT, + points[0][1] + rightTopVec[1] * rightTopT + leftTopVec[1] * leftTopT, + 0.8 * canvasScale, + ]); + } + } + // d3.range(0.02, 0.98, 1 / rightTopDotNum).forEach((rightTopT) => + // d3.range(0.02, 0.98, 1 / leftTopDotNum).forEach((leftTopT) => { + + // }) + // ); + drawCircle({ + ctx, + circles: dots, + hasFill: true, + fillStyle: hexWithOpacity(whiteColor, 0.4), + }); +} diff --git a/federjs_old/FederView/IvfflatView/InfoPanel/index.js b/federjs_old/FederView/IvfflatView/InfoPanel/index.js new file mode 100644 index 0000000..a795e39 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/InfoPanel/index.js @@ -0,0 +1,528 @@ +import * as d3 from 'd3'; + +import { + ZYellow, + ZBlue, + whiteColor, + blackColor, + drawPath, + hexWithOpacity, +} from 'Utils/renderUtils'; + +import { showVectors, randomSelect } from 'Utils'; + +export const overviewPanelId = 'feder-info-overview-panel'; +export const hoveredPanelId = 'feder-info-hovered-panel'; + +const panelBackgroundColor = hexWithOpacity(blackColor, 0.6); + +export default class InfoPanel { + constructor({ dom, width, height }) { + this.dom = dom; + this.width = width; + this.height = height; + + this.initOverviewPanel(); + this.initHoveredPanel(); + this.initStyle(); + } + initOverviewPanel() { + const dom = this.dom; + const overviewPanel = document.createElement('div'); + overviewPanel.setAttribute('id', overviewPanelId); + overviewPanel.className = + overviewPanel.className + ' panel-border panel hide'; + const overviewPanelStyle = { + position: 'absolute', + // left: `${canvas.width - 10}px`, + left: '16px', + top: '10px', + width: '240px', + 'max-height': `${this.height - 40}px`, + overflow: 'auto', + borderColor: whiteColor, + backgroundColor: panelBackgroundColor, + // pointerEvents: 'none', + }; + Object.assign(overviewPanel.style, overviewPanelStyle); + dom.appendChild(overviewPanel); + this.overviewPanel = overviewPanel; + } + setOverviewPanelPos(isPanelLeft) { + const overviewPanel = this.overviewPanel; + const overviewPanelStyle = isPanelLeft + ? { + left: '16px', + } + : { + left: null, + right: '16px', + }; + Object.assign(overviewPanel.style, overviewPanelStyle); + } + + updateOverviewOverviewInfo({ indexMeta }) { + const { ntotal, nlist, listSizes } = indexMeta; + const items = [ + { + title: 'IVF_Flat', + }, + { + text: `${ntotal} vectors, divided into ${nlist} clusters.`, + }, + { + text: `The largest cluster has ${d3.max( + listSizes + )} vectors and the smallest cluster has only ${d3.min( + listSizes + )} vectors.`, + }, + ]; + + this.renderOverviewPanel(items, whiteColor); + } + + updateSearchViewCoarseOverviewInfo(searchViewLayoutData, federView) { + const { + nprobe, + clusters, + targetMediaUrl, + nprobeClusters, + switchSearchViewHandlers, + } = searchViewLayoutData; + const { indexMeta } = federView; + const { ntotal, nlist, listSizes } = indexMeta; + const { switchVoronoi, switchPolar, switchProject } = + switchSearchViewHandlers; + const items = [ + { + title: 'IVF_Flat - Search', + }, + { + isImg: true, + imgUrl: targetMediaUrl, + }, + { + isOption: true, + isActive: true, + label: 'Coarse Search', + callback: switchVoronoi, + }, + { + isOption: true, + isActive: false, + label: 'Fine Search (Distance)', + callback: switchPolar, + }, + { + isOption: true, + isActive: false, + label: 'Fine Search (Project)', + callback: switchProject, + }, + { + text: `${ntotal} vectors, divided into ${nlist} clusters.`, + }, + { + title: `Find the ${nprobe} (nprobe=${nprobe}) closest clusters.`, + }, + ...nprobeClusters.map(({ clusterId }) => ({ + text: `cluster-${clusterId} (${ + listSizes[clusterId] + } vectors) dist: ${clusters[clusterId].dis.toFixed(3)}.`, + })), + ]; + + this.renderOverviewPanel(items, whiteColor); + } + + updateSearchViewFinePolarOverviewInfo(searchViewLayoutData, federView) { + const { + k, + nprobe, + nodes, + topKNodes, + switchSearchViewHandlers, + targetMediaUrl, + } = searchViewLayoutData; + const { switchVoronoi, switchPolar, switchProject } = + switchSearchViewHandlers; + const { mediaCallback } = federView; + const fineAllVectorsCount = nodes.length; + const showImages = topKNodes + .map(({ id }) => mediaCallback(id)) + .filter((a) => a); + const items = [ + { + title: 'IVF_Flat - Search', + }, + { + isImg: true, + imgUrl: targetMediaUrl, + }, + { + isOption: true, + isActive: false, + label: 'Coarse Search', + callback: switchVoronoi, + }, + { + isOption: true, + isActive: true, + label: 'Fine Search (Distance)', + callback: switchPolar, + }, + { + isOption: true, + isActive: false, + label: 'Fine Search (Project)', + callback: switchProject, + }, + { + text: `Find the ${k} (k=${k}) vectors closest to the target from these ${nprobe} (nprobe=${nprobe}) clusters, ${fineAllVectorsCount} vectors in total.`, + }, + { + images: showImages, + }, + ]; + + this.renderOverviewPanel(items, whiteColor); + } + + updateSearchViewFineProjectOverviewInfo(searchViewLayoutData, federView) { + const { + nprobe, + nodes, + topKNodes, + targetMediaUrl, + switchSearchViewHandlers, + } = searchViewLayoutData; + const { switchVoronoi, switchPolar, switchProject } = + switchSearchViewHandlers; + const { mediaCallback, viewParams } = federView; + const fineAllVectorsCount = nodes.length; + const showImages = topKNodes + .map(({ id }) => mediaCallback(id)) + .filter((a) => a); + const items = [ + { + title: 'IVF_Flat - Search', + }, + { + isImg: true, + imgUrl: targetMediaUrl, + }, + { + isOption: true, + isActive: false, + label: 'Coarse Search', + callback: switchVoronoi, + }, + { + isOption: true, + isActive: false, + label: 'Fine Search (Distance)', + callback: switchPolar, + }, + { + isOption: true, + isActive: true, + label: 'Fine Search (Project)', + callback: switchProject, + }, + { + text: `Projection of all ${fineAllVectorsCount} vectors in the ${nprobe} (nprobe=${nprobe}) clusters using ${ + viewParams.projectMethod || 'random' + }.`, + }, + { + images: showImages, + }, + ]; + + this.renderOverviewPanel(items, whiteColor); + } + + initHoveredPanel() { + const dom = this.dom; + const hoveredPanel = document.createElement('div'); + hoveredPanel.setAttribute('id', hoveredPanelId); + hoveredPanel.className = hoveredPanel.className + 'panel-border panel hide'; + const hoveredPanelStyle = { + position: 'absolute', + left: 0, + // right: '30px', + top: 0, + width: '200px', + // display: 'flex', + pointerEvents: 'none', + backgroundColor: panelBackgroundColor, + }; + Object.assign(hoveredPanel.style, hoveredPanelStyle); + dom.appendChild(hoveredPanel); + } + + updateOverviewHoveredInfo({ + hoveredCluster = null, + listIds = [], + images = [], + x = 0, + y = 0, + } = {}) { + const showImages = randomSelect(images, 9).filter((a) => a); + // console.log('showImages', showImages); + const items = hoveredCluster + ? [ + { + title: `cluster-${hoveredCluster.clusterId}`, + }, + { + text: `including ${listIds.length} vectors`, + }, + { + images: showImages, + }, + ] + : []; + + this.renderHoveredPanel(items, ZYellow, x, y); + } + + updateSearchViewHoveredInfo({ + hoveredCluster = null, + listIds = [], + images = [], + x = 0, + y = 0, + } = {}) { + if (!hoveredCluster) { + this.renderHoveredPanel(); + } else { + const showImages = randomSelect( + images.filter((a) => a), + 9 + ); + // console.log('showImages', showImages, images); + const items = hoveredCluster + ? [ + { + title: `cluster-${hoveredCluster.clusterId}`, + }, + { + text: `including ${listIds.length} vectors`, + }, + { + text: `distance from center: ${hoveredCluster.dis.toFixed(3)}`, + }, + { + images: showImages, + }, + ] + : []; + + this.renderHoveredPanel(items, ZYellow, x, y); + } + } + + updateSearchViewHoveredNodeInfo({ + hoveredNode = null, + img = '', + x = 0, + y = 0, + } = {}) { + if (!hoveredNode) { + this.renderHoveredPanel(); + } else { + const items = hoveredNode + ? [ + { + title: `Row No. ${hoveredNode.id}`, + }, + { + text: `belong to cluster-${hoveredNode.listId}`, + }, + { + text: `distance the target: ${hoveredNode.dis.toFixed(3)}`, + }, + { + isImg: true, + imgUrl: img, + }, + ] + : []; + + this.renderHoveredPanel(items, ZYellow, x, y); + } + } + + initStyle() { + const style = document.createElement('style'); + style.type = 'text/css'; + style.innerHTML = ` + .panel-border { + border-style: dashed; + border-width: 1px; + } + .panel { + padding: 6px 8px; + font-size: 12px; + } + .hide { + opacity: 0; + } + .panel-item { + margin-bottom: 6px; + } + .panel-img { + width: 150px; + height: 100px; + background-size: cover; + margin-bottom: 12px; + border-radius: 4px; + border: 1px solid ${ZYellow}; + } + .panel-item-display-flex { + display: flex; + } + .panel-item-title { + font-weight: 600; + margin-bottom: 3px; + } + .panel-item-text { + font-weight: 400; + font-size: 10px; + word-break: break-all; + } + .panel-item-text-flex { + margin-left: 8px; + } + .panel-item-text-margin { + margin: 0 6px; + } + .text-no-wrap { + white-space: nowrap; + } + .panel-img-gallery { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-row-gap: 8px; + grid-column-gap: 8px; + // flex-wrap: wrap; + } + .panel-img-gallery-item { + width: 100%; + height: 44px; + background-size: cover; + border-radius: 2px; + // border: 1px solid ${ZYellow}; + } + .panel-item-option { + display: flex; + align-items: center; + cursor: pointer; + // pointer-events: auto; + } + .panel-item-option-icon { + width: 6px; + height: 6px; + border-radius: 7px; + border: 2px solid ${ZYellow}; + margin-left: 2px; + } + .panel-item-option-icon-active { + background-color: ${ZYellow}; + } + .panel-item-option-label { + margin-left: 6px; + } + `; + document.getElementsByTagName('head').item(0).appendChild(style); + } + renderHoveredPanel(itemList = [], color = '#000', x = 0, y = 0) { + const panel = d3.select(this.dom).select(`#${hoveredPanelId}`); + if (itemList.length === 0) panel.classed('hide', true); + else { + panel.style('color', color); + // panel.style.left = x + 'px'; + // panel.style.top = y + 'px'; + const isLeft = x > this.width * 0.7; + if (isLeft) { + panel.style('left', null); + panel.style('right', this.width - x - 10 + 'px'); + } else { + panel.style('left', x + 10 + 'px'); + panel.style('right', null); + } + + const isTop = y > this.height * 0.7; + if (isTop) { + panel.style('top', null); + panel.style('bottom', this.height - y - 6 + 'px'); + } else { + panel.style('top', y + 6 + 'px'); + panel.style('bottom', null); + } + + this.renderPanel(panel, itemList); + } + } + renderOverviewPanel(itemList = [], color) { + const panel = d3.select(this.dom).select(`#${overviewPanelId}`); + panel.style('color', color); + if (itemList.length === 0) panel.classed('hide', true); + else { + this.renderPanel(panel, itemList); + } + } + renderPanel(panel, itemList) { + panel.classed('hide', false); + panel.selectAll('*').remove(); + + itemList.forEach((item) => { + const div = panel.append('div'); + div.classed('panel-item', true); + item.isFlex && div.classed('panel-item-display-flex', true); + if (item.isImg && item.imgUrl) { + div.classed('panel-img', true); + div.style('background-image', `url(${item.imgUrl})`); + } + if (item.title) { + const title = div.append('div'); + title.classed('panel-item-title', true); + title.text(item.title); + } + if (item.text) { + const title = div.append('div'); + title.classed('panel-item-text', true); + item.isFlex && title.classed('panel-item-text-flex', true); + item.textWithMargin && title.classed('panel-item-text-margin', true); + item.noWrap && title.classed('text-no-wrap', true); + title.text(item.text); + } + if (item.images) { + const imagesDiv = div.append('div'); + imagesDiv.classed('panel-img-gallery', true); + item.images.forEach((url) => { + const imgItem = imagesDiv.append('div'); + imgItem.classed('panel-img-gallery-item', true); + imgItem.style('background-image', `url(${url})`); + }); + } + if (item.isOption) { + const optionDiv = div.append('div'); + optionDiv.classed('panel-item-option', true); + const optionIcon = optionDiv.append('div'); + optionIcon.classed('panel-item-option-icon', true); + if (item.isActive) + optionIcon.classed('panel-item-option-icon-active', true); + else optionIcon.classed('panel-item-option-icon-active', false); + + const optionLabel = optionDiv.append('div'); + optionLabel.classed('panel-item-option-label', true); + optionLabel.text(item.label); + + item.callback && optionDiv.on('click', item.callback); + } + }); + } +} diff --git a/federjs_old/FederView/IvfflatView/index.js b/federjs_old/FederView/IvfflatView/index.js new file mode 100644 index 0000000..09cd9a8 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/index.js @@ -0,0 +1,378 @@ +import * as d3 from 'd3'; +import BaseView from '../BaseView.js'; +import overviewLayoutHandler from './layout/overviewLayout'; +import renderVoronoiView from './render/renderVoronoiView'; +import renderNodeView from './render/renderNodeView'; +import mouse2voronoi from './layout/mouse2voronoi'; +import mouse2node from './layout/mouse2node'; +import searchViewLayoutHandler from './layout/searchViewLayout'; +import { SEARCH_VIEW_TYPE, VIEW_TYPE } from 'Types.js'; +import animateCoarse2Fine from './render/animateCoarse2Fine'; +import animateFine2Coarse from './render/animateFine2Coarse'; +import animateFine2Fine from './render/animateFine2Fine'; +import InfoPanel from './InfoPanel'; + +const defaultIvfflatViewParams = { + minVoronoiRadius: 4, + // voronoiForceTime: 3000, + // nodeCollisionForceTime: 1000, + backgroundColor: 'red', + voronoiStrokeWidth: 2, + targetNodeStrokeWidth: 5, + targetNodeR: 7, + topKNodeR: 5, + hoveredNodeR: 6, + hoveredNodeStrokeWidth: 1, + hoveredNodeOpacity: 1, + topKNodeOpacity: 0.7, + topKNodeStrokeWidth: 1, + nonTopKNodeR: 3, + nonTopKNodeOpacity: 0.4, + projectPadding: [20, 20, 20, 260], + axisTickCount: 5, + polarAxisStrokeWidth: 1, + polarAxisOpacity: 0.4, + polarOriginBias: 0.15, + ease: d3.easeCubic, + animateExitTime: 1500, + animateEnterTime: 1000, + fineSearchNodeTransTime: 1200, + forceIterations: 100, +}; + +export default class IvfflatView extends BaseView { + constructor({ indexMeta, viewParams, getVectorById }) { + super({ + viewParams, + getVectorById, + }); + for (let key in defaultIvfflatViewParams) { + this[key] = + key in viewParams ? viewParams[key] : defaultIvfflatViewParams[key]; + } + + this.projectPadding = this.projectPadding.map( + (num) => num * this.canvasScale + ); + this.indexMeta = indexMeta; + this.overviewLayoutHandler(); + } + initInfoPanel(dom) { + const infoPanel = new InfoPanel({ + dom, + width: this.clientWidth, + height: this.clientHeight, + }); + return infoPanel; + } + overviewLayoutHandler() { + this.overviewLayoutPromise = overviewLayoutHandler(this).then( + ({ clusters, voronoi }) => { + // this.clusters = clusters; + // this.OVVoronoi = voronoi; + this.overviewLayoutData = { clusters, OVVoronoi: voronoi }; + } + ); + } + renderOverview(ctx, infoPanel) { + infoPanel.updateOverviewOverviewInfo(this); + renderVoronoiView(ctx, VIEW_TYPE.overview, this.overviewLayoutData, this); + } + getOverviewEventHandler(ctx, infoPanel) { + let hoveredClusterId = null; + + const mouseLeaveHandler = () => { + hoveredClusterId = null; + renderVoronoiView(ctx, VIEW_TYPE.overview, this.overviewLayoutData, this); + infoPanel.updateOverviewHoveredInfo(); + }; + + const mouseMoveHandler = ({ x, y }) => { + const currentHoveredClusterId = mouse2voronoi({ + voronoi: this.overviewLayoutData.OVVoronoi, + x, + y, + }); + + if (hoveredClusterId !== currentHoveredClusterId) { + hoveredClusterId = currentHoveredClusterId; + const hoveredCluster = this.overviewLayoutData.clusters.find( + (cluster) => cluster.clusterId == hoveredClusterId + ); + if (!!hoveredCluster) { + renderVoronoiView( + ctx, + VIEW_TYPE.overview, + this.overviewLayoutData, + this, + hoveredCluster + ); + infoPanel.updateOverviewHoveredInfo({ + hoveredCluster, + listIds: this.indexMeta.listIds[hoveredClusterId], + images: this.mediaCallback + ? this.indexMeta.listIds[hoveredClusterId].map((listId) => + this.mediaCallback(listId) + ) + : [], + x: hoveredCluster.OVPolyCentroid[0] / this.canvasScale, + y: hoveredCluster.OVPolyCentroid[1] / this.canvasScale, + }); + } + } + }; + + return { mouseLeaveHandler, mouseMoveHandler }; + } + + async searchViewHandler(searchRes) { + this.overviewLayoutPromise && (await this.overviewLayoutPromise); + + const searchViewLayoutData = { + nprobe: searchRes.csResIds.length, + k: searchRes.fsResIds.length, + clusters: JSON.parse(JSON.stringify(this.overviewLayoutData.clusters)), + }; + searchViewLayoutData.nprobeClusters = searchViewLayoutData.clusters.filter( + (cluster) => searchRes.csResIds.indexOf(cluster.clusterId) >= 0 + ); + searchViewLayoutData.nonNprobeClusters = + searchViewLayoutData.clusters.filter( + (cluster) => searchRes.csResIds.indexOf(cluster.clusterId) < 0 + ); + searchViewLayoutData.colorScheme = d3 + .range(searchViewLayoutData.nprobe) + .map((i) => + d3.hsl((360 * i) / searchViewLayoutData.nprobe, 1, 0.5).formatHex() + ); + await searchViewLayoutHandler(searchRes, searchViewLayoutData, this); + return searchViewLayoutData; + } + renderSearchView(ctx, infoPanel, searchViewLayoutData, targetMediaUrl) { + searchViewLayoutData.targetMediaUrl = targetMediaUrl; + searchViewLayoutData.switchSearchViewHandlers = { + switchVoronoi: () => + this.switchSearchView( + SEARCH_VIEW_TYPE.voronoi, + ctx, + infoPanel, + searchViewLayoutData + ), + switchPolar: () => + this.switchSearchView( + SEARCH_VIEW_TYPE.polar, + ctx, + infoPanel, + searchViewLayoutData + ), + switchProject: () => + this.switchSearchView( + SEARCH_VIEW_TYPE.project, + ctx, + infoPanel, + searchViewLayoutData + ), + }; + searchViewLayoutData.searchViewType = SEARCH_VIEW_TYPE.voronoi; + this.updateCoarseSearchInfoPanel(infoPanel, searchViewLayoutData); + this.renderCoarseSearch(ctx, searchViewLayoutData); + } + renderCoarseSearch(ctx, searchViewLayoutData) { + renderVoronoiView(ctx, VIEW_TYPE.search, searchViewLayoutData, this); + } + updateCoarseSearchInfoPanel(infoPanel, searchViewLayoutData) { + infoPanel.setOverviewPanelPos( + !searchViewLayoutData.targetNode.isLeft_coarseLevel + ); + infoPanel.updateSearchViewCoarseOverviewInfo(searchViewLayoutData, this); + } + renderFineSearch( + ctx, + searchViewLayoutData, + searchViewType = SEARCH_VIEW_TYPE.polar, + hoveredNode + ) { + renderNodeView( + ctx, + searchViewLayoutData, + this, + searchViewType, + hoveredNode + ); + } + updateFineSearchInfoPanel( + infoPanel, + searchViewLayoutData, + searchViewType = SEARCH_VIEW_TYPE.polar + ) { + searchViewType === SEARCH_VIEW_TYPE.polar && + infoPanel.updateSearchViewFinePolarOverviewInfo( + searchViewLayoutData, + this + ); + searchViewType === SEARCH_VIEW_TYPE.project && + infoPanel.updateSearchViewFineProjectOverviewInfo( + searchViewLayoutData, + this + ); + } + switchSearchView(searchViewType, ctx, infoPanel, searchViewLayoutData) { + if (searchViewType == searchViewLayoutData.searchViewType) return; + + const oldSearchViewType = searchViewLayoutData.searchViewType; + const newSearchViewType = searchViewType; + + // coarse => fine + + if (oldSearchViewType === SEARCH_VIEW_TYPE.voronoi) { + // console.log('coarse => fine [start]'); + this.updateFineSearchInfoPanel( + infoPanel, + searchViewLayoutData, + newSearchViewType + ); + const endCallback = () => { + searchViewLayoutData.searchViewType = newSearchViewType; + this.renderFineSearch(ctx, searchViewLayoutData, newSearchViewType); + }; + animateCoarse2Fine( + oldSearchViewType, + newSearchViewType, + ctx, + searchViewLayoutData, + this, + endCallback + ); + } + + // fine => coarse + if (newSearchViewType === SEARCH_VIEW_TYPE.voronoi) { + // console.log('fine => coarse [start]'); + this.updateCoarseSearchInfoPanel(infoPanel, searchViewLayoutData); + const endCallback = () => { + searchViewLayoutData.searchViewType = newSearchViewType; + this.renderCoarseSearch(ctx, searchViewLayoutData); + }; + animateFine2Coarse( + oldSearchViewType, + newSearchViewType, + ctx, + searchViewLayoutData, + this, + endCallback + ); + } + + // fine - intra + if ( + newSearchViewType !== SEARCH_VIEW_TYPE.voronoi && + oldSearchViewType !== SEARCH_VIEW_TYPE.voronoi + ) { + this.updateFineSearchInfoPanel( + infoPanel, + searchViewLayoutData, + newSearchViewType + ); + // console.log('fine - intra [start]'); + const endCallback = () => { + searchViewLayoutData.searchViewType = newSearchViewType; + this.renderFineSearch(ctx, searchViewLayoutData, newSearchViewType); + }; + animateFine2Fine( + oldSearchViewType, + newSearchViewType, + ctx, + searchViewLayoutData, + this, + endCallback + ); + } + } + getSearchViewEventHandler(ctx, searchViewLayoutData, infoPanel) { + let hoveredClusterId = null; + let hoveredNode = null; + const mouseLeaveHandler = () => { + hoveredClusterId = null; + hoveredNode = null; + const { searchViewType } = searchViewLayoutData; + if (searchViewType === SEARCH_VIEW_TYPE.voronoi) { + renderVoronoiView(ctx, VIEW_TYPE.search, searchViewLayoutData, this); + infoPanel.updateSearchViewHoveredInfo(); + } else { + infoPanel.updateSearchViewHoveredNodeInfo(); + } + }; + const mouseMoveHandler = ({ x, y }) => { + const { searchViewType, clusters, nodes } = searchViewLayoutData; + if (searchViewType === SEARCH_VIEW_TYPE.voronoi) { + const currentHoveredClusterId = mouse2voronoi({ + voronoi: searchViewLayoutData.SVVoronoi, + x, + y, + }); + if (hoveredClusterId !== currentHoveredClusterId) { + hoveredClusterId = currentHoveredClusterId; + const hoveredCluster = clusters.find( + (cluster) => cluster.clusterId == hoveredClusterId + ); + renderVoronoiView( + ctx, + VIEW_TYPE.search, + searchViewLayoutData, + this, + hoveredCluster + ); + + if (!!hoveredCluster) { + infoPanel.updateSearchViewHoveredInfo({ + hoveredCluster, + listIds: this.indexMeta.listIds[hoveredClusterId], + images: this.mediaCallback + ? this.indexMeta.listIds[hoveredClusterId].map((listId) => + this.mediaCallback(listId) + ) + : [], + x: hoveredCluster.SVPolyCentroid[0] / this.canvasScale, + y: hoveredCluster.SVPolyCentroid[1] / this.canvasScale, + }); + } + } + } else { + if (!nodes) return; + const nodesPos = + searchViewType === SEARCH_VIEW_TYPE.polar + ? nodes.map((node) => node.polarPos) + : nodes.map((node) => node.projectPos); + const hoveredNodeIndex = mouse2node({ + nodesPos, + x, + y, + bias: (this.hoveredNodeR + 2) * this.canvasScale, + }); + const currentHoveredNode = + hoveredNodeIndex >= 0 ? nodes[hoveredNodeIndex] : null; + if (hoveredNode !== currentHoveredNode) { + hoveredNode = currentHoveredNode; + this.renderFineSearch( + ctx, + searchViewLayoutData, + searchViewType, + hoveredNode + ); + } + + const img = + hoveredNode && this.mediaCallback + ? this.mediaCallback(hoveredNode.id) + : ''; + infoPanel.updateSearchViewHoveredNodeInfo({ + hoveredNode, + img, + x: x / this.canvasScale, + y: y / this.canvasScale, + }); + } + }; + return { mouseLeaveHandler, mouseMoveHandler }; + } +} diff --git a/federjs_old/FederView/IvfflatView/layout/SVCoarseVoronoiHandler.js b/federjs_old/FederView/IvfflatView/layout/SVCoarseVoronoiHandler.js new file mode 100644 index 0000000..931673e --- /dev/null +++ b/federjs_old/FederView/IvfflatView/layout/SVCoarseVoronoiHandler.js @@ -0,0 +1,153 @@ +import * as d3 from 'd3'; +import getVoronoi from './getVoronoi'; +import { vecSort } from 'Utils'; + +export default function SVCoarseVoronoiHandler( + searchRes, + searchViewLayoutData, + federView +) { + return new Promise((resolve) => { + const { clusters, nprobeClusters, nprobe } = searchViewLayoutData; + const { width, height, forceIterations, polarOriginBias } = federView; + const fineClusterOrder = vecSort( + nprobeClusters, + 'OVPolyCentroid', + 'clusterId' + ); + // console.log('fineClusterOrder', fineClusterOrder); + + const targetClusterId = searchRes.coarse[0].id; + const targetCluster = clusters.find( + (cluster) => cluster.clusterId === targetClusterId + ); + const otherFineClustersId = fineClusterOrder.filter( + (clusterId) => clusterId !== targetClusterId + ); + const links = otherFineClustersId.map((clusterId) => ({ + source: clusterId, + target: targetClusterId, + })); + clusters.forEach((cluster) => { + cluster.x = cluster.forceProjection[0]; + cluster.y = cluster.forceProjection[1]; + }); + const targetClusterX = + nprobeClusters.reduce((acc, cluster) => acc + cluster.x, 0) / nprobe; + const targetClusterY = + nprobeClusters.reduce((acc, cluster) => acc + cluster.y, 0) / nprobe; + targetCluster.x = targetClusterX; + targetCluster.y = targetClusterY; + + const otherFineCluster = otherFineClustersId.map((clusterId) => + nprobeClusters.find((cluster) => cluster.clusterId === clusterId) + ); + const angleStep = (2 * Math.PI) / (nprobe - 1); + const biasR = targetCluster.r * 0.5; + otherFineCluster.forEach((cluster, i) => { + cluster.x = targetClusterX + biasR * Math.sin(angleStep * i); + cluster.y = targetClusterY + biasR * Math.cos(angleStep * i); + }); + + const simulation = d3 + .forceSimulation(clusters) + .alphaDecay(1 - Math.pow(0.001, 1 / forceIterations)) + .force( + 'links', + d3 + .forceLink(links) + .id((cluster) => cluster.clusterId) + .strength((_) => 0.25) + ) + .force( + 'collision', + d3 + .forceCollide() + .radius((cluster) => cluster.r) + .strength(0.1) + ) + .force('center', d3.forceCenter(width / 2, height / 2)) + .on('tick', () => { + // border + clusters.forEach((cluster) => { + cluster.x = Math.max( + cluster.r, + Math.min(width - cluster.r, cluster.x) + ); + cluster.y = Math.max( + cluster.r, + Math.min(height - cluster.r, cluster.y) + ); + }); + }) + .on('end', () => { + clusters.forEach((cluster) => { + cluster.SVPos = [cluster.x, cluster.y]; + }); + const voronoi = getVoronoi(clusters, width, height); + clusters.forEach((cluster, i) => { + const points = voronoi.cellPolygon(i); + points.pop(); + cluster.SVPolyPoints = points; + cluster.SVPolyCentroid = d3.polygonCentroid(points); + }); + searchViewLayoutData.SVVoronoi = voronoi; + + const targetCluster = clusters.find( + (cluster) => cluster.clusterId === targetClusterId + ); + const centoid_fineClusters_x = + nprobeClusters.reduce( + (acc, cluster) => acc + cluster.SVPolyCentroid[0], + 0 + ) / nprobe; + const centroid_fineClusters_y = + nprobeClusters.reduce( + (acc, cluster) => acc + cluster.SVPolyCentroid[1], + 0 + ) / nprobe; + const _x = centoid_fineClusters_x - targetCluster.SVPos[0]; + const _y = centroid_fineClusters_y - targetCluster.SVPos[1]; + const biasR = Math.sqrt(_x * _x + _y * _y); + const targetNode = { + SVPos: [ + targetCluster.SVPos[0] + targetCluster.r * 0.4 * (_x / biasR), + targetCluster.SVPos[1] + targetCluster.r * 0.4 * (_y / biasR), + ], + }; + targetNode.isLeft_coarseLevel = targetNode.SVPos[0] < width / 2; + searchViewLayoutData.targetNode = targetNode; + + const polarOrigin = [ + width / 2 + + (targetNode.isLeft_coarseLevel ? -1 : 1) * polarOriginBias * width, + height / 2, + ]; + // const polarOrigin = [width / 2, height / 2]; + searchViewLayoutData.polarOrigin = polarOrigin; + targetNode.polarPos = polarOrigin; + const polarMaxR = Math.min(width, height) * 0.5 - 5; + searchViewLayoutData.polarMaxR = polarMaxR; + const angleStep = (Math.PI * 2) / fineClusterOrder.length; + nprobeClusters.forEach((cluster) => { + const order = fineClusterOrder.indexOf(cluster.clusterId); + cluster.polarOrder = order; + cluster.SVNextLevelPos = [ + polarOrigin[0] + (polarMaxR / 2) * Math.sin(angleStep * order), + polarOrigin[1] + (polarMaxR / 2) * Math.cos(angleStep * order), + ]; + cluster.SVNextLevelTran = [ + cluster.SVNextLevelPos[0] - cluster.SVPolyCentroid[0], + cluster.SVNextLevelPos[1] - cluster.SVPolyCentroid[1], + ]; + }); + const clusterId2cluster = {}; + nprobeClusters.forEach((cluster) => { + clusterId2cluster[cluster.clusterId] = cluster; + }); + searchViewLayoutData.clusterId2cluster = clusterId2cluster; + + resolve(); + }); + }); +} diff --git a/federjs_old/FederView/IvfflatView/layout/SVFinePolarHandler.js b/federjs_old/FederView/IvfflatView/layout/SVFinePolarHandler.js new file mode 100644 index 0000000..154f9cd --- /dev/null +++ b/federjs_old/FederView/IvfflatView/layout/SVFinePolarHandler.js @@ -0,0 +1,67 @@ +import * as d3 from 'd3'; + +export default function SVFinePolarHandler( + searchRes, + searchViewLayoutData, + federView +) { + return new Promise((resolve) => { + const { polarMaxR, polarOrigin, clusterId2cluster } = searchViewLayoutData; + const { forceIterations, nonTopKNodeR, canvasScale } = federView; + const nodes = searchRes.fine; + + const distances = nodes + .map((node) => node.dis) + .filter((a) => a > 0) + .sort(); + const minDis = distances.length > 0 ? distances[0] : 0; + const maxDis = + distances.length > 0 + ? distances[Math.round((distances.length - 1) * 0.98)] + : 0; + const r = d3 + .scaleLinear() + .domain([minDis, maxDis]) + .range([polarMaxR * 0.2, polarMaxR]) + .clamp(true); + + nodes.forEach((node) => { + const cluster = clusterId2cluster[node.listId]; + const { polarOrder, SVNextLevelPos } = cluster; + node.polarOrder = polarOrder; + const randAngle = Math.random() * Math.PI * 2; + const randBias = [Math.sin, Math.cos].map( + (f) => cluster.r * Math.random() * 0.7 * f(randAngle) + ); + node.voronoiPos = SVNextLevelPos.map((d, i) => d + randBias[i]); + node.x = node.voronoiPos[0]; + node.y = node.voronoiPos[1]; + node.r = r(node.dis); + }); + + const simulation = d3 + .forceSimulation(nodes) + .alphaDecay(1 - Math.pow(0.001, (1 / forceIterations) * 2)) + .force( + 'collide', + d3 + .forceCollide() + .radius((_) => nonTopKNodeR * canvasScale) + .strength(0.4) + ) + .force('r', d3.forceRadial((node) => node.r, ...polarOrigin).strength(1)) + .on('end', () => { + nodes.forEach((node) => { + node.polarPos = [node.x, node.y]; + }); + searchViewLayoutData.nodes = nodes; + searchViewLayoutData.topKNodes = nodes.filter((node) => + searchRes.fsResIds.find((id) => id == node.id) + ); + searchViewLayoutData.nonTopKNodes = nodes.filter( + (node) => !searchRes.fsResIds.find((id) => id == node.id) + ); + resolve(); + }); + }); +} diff --git a/federjs_old/FederView/IvfflatView/layout/SVFineProjectHandler.js b/federjs_old/FederView/IvfflatView/layout/SVFineProjectHandler.js new file mode 100644 index 0000000..fc1b200 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/layout/SVFineProjectHandler.js @@ -0,0 +1,30 @@ +import * as d3 from 'd3'; + +export default function SVFineProjectHandler( + searchRes, + searchViewLayoutData, + federView +) { + const { nodes, targetNode } = searchViewLayoutData; + const { projectPadding, width, height } = federView; + if (!nodes[0].projection) { + console.log('No Projection Data. Should use "fineWithProjection".'); + nodes.forEach((node) => { + node.projection = [Math.random(), Math.random()]; + }); + } + const xRange = targetNode.isLeft_coarseLevel + ? [projectPadding[1], width - projectPadding[3]] + : [projectPadding[3], width - projectPadding[1]]; + const x = d3 + .scaleLinear() + .domain(d3.extent(nodes, (node) => node.projection[0])) + .range(xRange); + const y = d3 + .scaleLinear() + .domain(d3.extent(nodes, (node) => node.projection[1])) + .range([projectPadding[0], height - projectPadding[2]]); + nodes.forEach((node) => { + node.projectPos = [x(node.projection[0]), y(node.projection[1])]; + }); +} diff --git a/federjs_old/FederView/IvfflatView/layout/getVoronoi.js b/federjs_old/FederView/IvfflatView/layout/getVoronoi.js new file mode 100644 index 0000000..c9e0ba4 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/layout/getVoronoi.js @@ -0,0 +1,9 @@ +import * as d3 from 'd3'; + +export default function getVoronoi(clusters, width, height) { + const delaunay = d3.Delaunay.from( + clusters.map((cluster) => [cluster.x, cluster.y]) + ); + const voronoi = delaunay.voronoi([0, 0, width, height]); + return voronoi; +} diff --git a/federjs_old/FederView/IvfflatView/layout/mouse2node.js b/federjs_old/FederView/IvfflatView/layout/mouse2node.js new file mode 100644 index 0000000..19ce021 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/layout/mouse2node.js @@ -0,0 +1,8 @@ +import { dist2 } from 'Utils'; +import * as d3 from 'd3'; + +export default function mouse2node({ nodesPos, x, y, bias }) { + const minIndex = d3.minIndex(nodesPos, (nodePos) => dist2(nodePos, [x, y])); + + return dist2(nodesPos[minIndex], [x, y]) > Math.pow(bias, 2) ? -1 : minIndex; +} diff --git a/federjs_old/FederView/IvfflatView/layout/mouse2voronoi.js b/federjs_old/FederView/IvfflatView/layout/mouse2voronoi.js new file mode 100644 index 0000000..ba6636b --- /dev/null +++ b/federjs_old/FederView/IvfflatView/layout/mouse2voronoi.js @@ -0,0 +1,3 @@ +export default function mouse2node({ voronoi, x, y }) { + return voronoi.delaunay.find(x, y); +} \ No newline at end of file diff --git a/federjs_old/FederView/IvfflatView/layout/overviewLayout.js b/federjs_old/FederView/IvfflatView/layout/overviewLayout.js new file mode 100644 index 0000000..6862e16 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/layout/overviewLayout.js @@ -0,0 +1,78 @@ +import * as d3 from 'd3'; +import getVoronoi from './getVoronoi'; + +export default function overviewLayoutHandler({ + indexMeta, + width, + height, + canvasScale, + minVoronoiRadius, + forceIterations, +}) { + return new Promise((resolve) => { + const allArea = width * height; + const { ntotal, listCentroidProjections = null, listSizes } = indexMeta; + const clusters = listSizes.map((listSize, i) => ({ + clusterId: i, + oriProjection: listCentroidProjections + ? listCentroidProjections[i] + : [Math.random(), Math.random()], + count: listSize, + countP: listSize / ntotal, + countArea: allArea * (listSize / ntotal), + })); + + const x = d3 + .scaleLinear() + .domain(d3.extent(clusters, (cluster) => cluster.oriProjection[0])) + .range([0, width]); + const y = d3 + .scaleLinear() + .domain(d3.extent(clusters, (cluster) => cluster.oriProjection[1])) + .range([0, height]); + + clusters.forEach((cluster) => { + cluster.x = x(cluster.oriProjection[0]); + cluster.y = y(cluster.oriProjection[1]); + cluster.r = Math.max( + minVoronoiRadius * canvasScale, + Math.sqrt(cluster.countArea / Math.PI) + ); + }); + + const simulation = d3 + .forceSimulation(clusters) + .alphaDecay(1 - Math.pow(0.001, 1 / forceIterations)) + .force( + 'collision', + d3.forceCollide().radius((cluster) => cluster.r) + ) + .force('center', d3.forceCenter(width / 2, height / 2)) + .on('tick', () => { + // border + clusters.forEach((cluster) => { + cluster.x = Math.max( + cluster.r, + Math.min(width - cluster.r, cluster.x) + ); + cluster.y = Math.max( + cluster.r, + Math.min(height - cluster.r, cluster.y) + ); + }); + }) + .on('end', () => { + clusters.forEach((cluster) => { + cluster.forceProjection = [cluster.x, cluster.y]; + }); + const voronoi = getVoronoi(clusters, width, height); + clusters.forEach((cluster, i) => { + const points = voronoi.cellPolygon(i); + points.pop(); + cluster.OVPolyPoints = points; + cluster.OVPolyCentroid = d3.polygonCentroid(points); + }); + resolve({ clusters, voronoi }); + }); + }); +} diff --git a/federjs_old/FederView/IvfflatView/layout/searchViewLayout.js b/federjs_old/FederView/IvfflatView/layout/searchViewLayout.js new file mode 100644 index 0000000..e0e072d --- /dev/null +++ b/federjs_old/FederView/IvfflatView/layout/searchViewLayout.js @@ -0,0 +1,20 @@ +import SVCoarseVoronoiHandler from './SVCoarseVoronoiHandler'; +import SVFinePolarHandler from './SVFinePolarHandler'; +import SVFineProjectHandler from './SVFineProjectHandler'; + +export default function searchViewLayoutHandler( + searchRes, + searchViewLayoutData, + federView +) { + return new Promise(async (resolve) => { + searchRes.coarse.forEach( + ({ id, dis }) => (searchViewLayoutData.clusters[id].dis = dis) + ); + await SVCoarseVoronoiHandler(searchRes, searchViewLayoutData, federView); + await SVFinePolarHandler(searchRes, searchViewLayoutData, federView); + SVFineProjectHandler(searchRes, searchViewLayoutData, federView); + // console.log('searchViewLayoutData', searchViewLayoutData); + resolve(); + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/animateCoarse2Fine.js b/federjs_old/FederView/IvfflatView/render/animateCoarse2Fine.js new file mode 100644 index 0000000..1a540e5 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/animateCoarse2Fine.js @@ -0,0 +1,82 @@ +import * as d3 from 'd3'; +import renderBackground from './renderBackground'; +import animateNonNprobeClusters from './animateNonNprobeClusters'; +import animateNprobeClustersTrans from './animateNprobeClustersTrans'; +import animateTargetNode from './animateTargetNode'; +import animateNprobeClustersOpacity from './animateNprobeClustersOpacity'; +import animateNodesOpacityAndTrans from './animateNodesOpacityAndTrans'; +import { ANIMATION_TYPE } from 'Types'; + +export default function animateCoarse2Fine( + oldSearchViewType, + newSearchViewType, + ctx, + searchViewLayoutData, + federView, + endCallback = () => {} +) { + const { animateExitTime, animateEnterTime } = federView; + const stepAllTime = animateExitTime + animateEnterTime; + const timer = d3.timer((elapsed) => { + renderBackground(ctx, federView); + + animateNonNprobeClusters({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: 0, + duration: animateExitTime, + animationType: ANIMATION_TYPE.exit, + }); + + animateNprobeClustersTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: 0, + duration: animateExitTime, + animationType: ANIMATION_TYPE.exit, + }); + + animateTargetNode({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: 0, + duration: animateExitTime, + animationType: ANIMATION_TYPE.exit, + newSearchViewType, + }); + + animateNprobeClustersOpacity({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: animateExitTime, + duration: animateEnterTime, + animationType: ANIMATION_TYPE.exit, + }); + + animateNodesOpacityAndTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: animateExitTime, + duration: animateEnterTime, + animationType: ANIMATION_TYPE.enter, + oldSearchViewType, + newSearchViewType, + }); + + if (elapsed >= stepAllTime) { + console.log('Coarse => Fine [OK]'); + timer.stop(); + endCallback(); + } + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/animateFine2Coarse.js b/federjs_old/FederView/IvfflatView/render/animateFine2Coarse.js new file mode 100644 index 0000000..11fd978 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/animateFine2Coarse.js @@ -0,0 +1,83 @@ +import * as d3 from 'd3'; +import renderBackground from './renderBackground'; +import animateNonNprobeClusters from './animateNonNprobeClusters'; +import animateNprobeClustersTrans from './animateNprobeClustersTrans'; +import animateTargetNode from './animateTargetNode'; +import animateNprobeClustersOpacity from './animateNprobeClustersOpacity'; +import animateNodesOpacityAndTrans from './animateNodesOpacityAndTrans'; +import { ANIMATION_TYPE } from 'Types'; + +export default function animateFine2Coarse( + oldSearchViewType, + newSearchViewType, + ctx, + searchViewLayoutData, + federView, + endCallback = () => {} +) { + const { animateExitTime, animateEnterTime } = federView; + + const stepAllTime = animateExitTime + animateEnterTime; + const timer = d3.timer((elapsed) => { + renderBackground(ctx, federView); + + animateNodesOpacityAndTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: 0, + duration: animateExitTime, + animationType: ANIMATION_TYPE.exit, + oldSearchViewType, + newSearchViewType, + }); + + animateNprobeClustersOpacity({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: 0, + duration: animateExitTime, + animationType: ANIMATION_TYPE.enter, + }); + + animateNonNprobeClusters({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: animateExitTime, + duration: animateEnterTime, + animationType: ANIMATION_TYPE.enter, + }); + + animateNprobeClustersTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: animateExitTime, + duration: animateEnterTime, + animationType: ANIMATION_TYPE.enter, + }); + + animateTargetNode({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: animateExitTime, + duration: animateEnterTime, + animationType: ANIMATION_TYPE.enter, + newSearchViewType, + }); + + if (elapsed >= stepAllTime) { + console.log('Fine => Coarse [OK]'); + timer.stop(); + endCallback(); + } + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/animateFine2Fine.js b/federjs_old/FederView/IvfflatView/render/animateFine2Fine.js new file mode 100644 index 0000000..347d7a4 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/animateFine2Fine.js @@ -0,0 +1,32 @@ +import renderBackground from './renderBackground'; +import animateNodesTrans from './animateNodesTrans'; +import * as d3 from 'd3'; + +export default function animateFine2Fine( + oldSearchViewType, + newSearchViewType, + ctx, + searchViewLayoutData, + federView, + endCallback +) { + const { fineSearchNodeTransTime } = federView; + const timer = d3.timer((elapsed) => { + renderBackground(ctx, federView); + animateNodesTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration: fineSearchNodeTransTime, + delay: 0, + newSearchViewType, + }); + + if (elapsed >= fineSearchNodeTransTime) { + console.log(`${oldSearchViewType} To ${newSearchViewType} OK!`); + timer.stop(); + endCallback(); + } + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/animateNodesOpacityAndTrans.js b/federjs_old/FederView/IvfflatView/render/animateNodesOpacityAndTrans.js new file mode 100644 index 0000000..58461f2 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/animateNodesOpacityAndTrans.js @@ -0,0 +1,85 @@ +import { drawCircle, hexWithOpacity, whiteColor } from 'Utils/renderUtils'; +import { ANIMATION_TYPE, SEARCH_VIEW_TYPE } from 'Types'; + +export default function animateNodesOpacityAndTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration, + delay, + animationType, + newSearchViewType, + oldSearchViewType, +}) { + const { colorScheme, nprobe, topKNodes, nonTopKNodes } = searchViewLayoutData; + const { + ease, + topKNodeR, + topKNodeOpacity, + topKNodeStrokeWidth, + nonTopKNodeR, + nonTopKNodeOpacity, + canvasScale, + } = federView; + let t = ease((elapsed - delay) / duration); + if (t > 1 || t < 0) return; + t = animationType === ANIMATION_TYPE.enter ? 1 - t : t; + + const nonTopKCircles = + (newSearchViewType === SEARCH_VIEW_TYPE.polar && + animationType === ANIMATION_TYPE.enter) || + (oldSearchViewType === SEARCH_VIEW_TYPE.polar && + animationType === ANIMATION_TYPE.exit) + ? nonTopKNodes.map((node) => [ + t * node.voronoiPos[0] + (1 - t) * node.polarPos[0], + t * node.voronoiPos[1] + (1 - t) * node.polarPos[1], + nonTopKNodeR * canvasScale, + node.polarOrder, + ]) + : nonTopKNodes.map((node) => [ + t * node.voronoiPos[0] + (1 - t) * node.projectPos[0], + t * node.voronoiPos[1] + (1 - t) * node.projectPos[1], + nonTopKNodeR * canvasScale, + node.polarOrder, + ]); + const topKCircles = + (newSearchViewType === SEARCH_VIEW_TYPE.polar && + animationType === ANIMATION_TYPE.enter) || + (oldSearchViewType === SEARCH_VIEW_TYPE.polar && + animationType === ANIMATION_TYPE.exit) + ? topKNodes.map((node) => [ + t * node.voronoiPos[0] + (1 - t) * node.polarPos[0], + t * node.voronoiPos[1] + (1 - t) * node.polarPos[1], + topKNodeR * canvasScale, + node.polarOrder, + ]) + : topKNodes.map((node) => [ + t * node.voronoiPos[0] + (1 - t) * node.projectPos[0], + t * node.voronoiPos[1] + (1 - t) * node.projectPos[1], + topKNodeR * canvasScale, + node.polarOrder, + ]); + for (let i = 0; i < nprobe; i++) { + let circles = nonTopKCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme[i], nonTopKNodeOpacity), + }); + } + const opacity = t * 0.5 + (1 - t) * topKNodeOpacity; + for (let i = 0; i < nprobe; i++) { + let circles = topKCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme[i], opacity), + hasStroke: true, + strokeStyle: hexWithOpacity(whiteColor, opacity), + lineWidth: topKNodeStrokeWidth * canvasScale, + }); + } +} diff --git a/federjs_old/FederView/IvfflatView/render/animateNodesTrans.js b/federjs_old/FederView/IvfflatView/render/animateNodesTrans.js new file mode 100644 index 0000000..a5e98b0 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/animateNodesTrans.js @@ -0,0 +1,61 @@ +import { SEARCH_VIEW_TYPE } from 'Types'; +import { hexWithOpacity, drawCircle, whiteColor } from 'Utils/renderUtils'; + +export default function animateNodesTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration, + delay, + newSearchViewType, +}) { + const { colorScheme, nonTopKNodes, topKNodes, nprobe } = searchViewLayoutData; + const { + ease, + nonTopKNodeR, + canvasScale, + topKNodeR, + topKNodeStrokeWidth, + nonTopKNodeOpacity, + topKNodeOpacity, + } = federView; + let t = ease((elapsed - delay) / duration); + if (t > 1 || t < 0) return; + + t = newSearchViewType === SEARCH_VIEW_TYPE.polar ? 1 - t : t; + + const nonTopKCircles = nonTopKNodes.map((node) => [ + t * node.projectPos[0] + (1 - t) * node.polarPos[0], + t * node.projectPos[1] + (1 - t) * node.polarPos[1], + nonTopKNodeR * canvasScale, + node.polarOrder, + ]); + const topKCircles = topKNodes.map((node) => [ + t * node.projectPos[0] + (1 - t) * node.polarPos[0], + t * node.projectPos[1] + (1 - t) * node.polarPos[1], + topKNodeR * canvasScale, + node.polarOrder, + ]); + for (let i = 0; i < nprobe; i++) { + let circles = nonTopKCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme[i], nonTopKNodeOpacity), + }); + } + for (let i = 0; i < nprobe; i++) { + let circles = topKCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme[i], topKNodeOpacity), + hasStroke: true, + strokeStyle: hexWithOpacity(whiteColor, topKNodeOpacity), + lineWidth: topKNodeStrokeWidth * canvasScale, + }); + } +} diff --git a/federjs_old/FederView/IvfflatView/render/animateNonNprobeClusters.js b/federjs_old/FederView/IvfflatView/render/animateNonNprobeClusters.js new file mode 100644 index 0000000..7a56657 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/animateNonNprobeClusters.js @@ -0,0 +1,33 @@ +import { + drawVoronoi, + hexWithOpacity, + blackColor, + ZBlue, +} from 'Utils/renderUtils'; +import { ANIMATION_TYPE } from 'Types'; + +export default function animateNonNprobeClusters({ + ctx, + elapsed, + duration, + delay, + animationType, + searchViewLayoutData, + federView, +}) { + const { ease, voronoiStrokeWidth, canvasScale } = federView; + const { nonNprobeClusters } = searchViewLayoutData; + let t = ease((elapsed - delay) / duration); + if (t > 1 || t < 0) return; + const opacity = animationType === ANIMATION_TYPE.enter ? t : 1 - t; + const pointsList = nonNprobeClusters.map((cluster) => cluster.SVPolyPoints); + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZBlue, opacity), + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/animateNprobeClustersOpacity.js b/federjs_old/FederView/IvfflatView/render/animateNprobeClustersOpacity.js new file mode 100644 index 0000000..ab4ded6 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/animateNprobeClustersOpacity.js @@ -0,0 +1,39 @@ +import { + drawVoronoi, + hexWithOpacity, + blackColor, + ZLightBlue, +} from 'Utils/renderUtils'; +import { ANIMATION_TYPE } from 'Types'; + +export default function animateNonNprobeClusters({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration, + delay, + animationType, +}) { + const { nprobeClusters } = searchViewLayoutData; + const { ease, voronoiStrokeWidth, canvasScale } = federView; + let t = ease((elapsed - delay) / duration); + if (t > 1 || t < 0) return; + t = animationType === ANIMATION_TYPE.enter ? t : 1 - t; + const opacity = t; + const pointsList = nprobeClusters.map((cluster) => + cluster.SVPolyPoints.map((point) => [ + point[0] + cluster.SVNextLevelTran[0], + point[1] + cluster.SVNextLevelTran[1], + ]) + ); + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZLightBlue, opacity), + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/animateNprobeClustersTrans.js b/federjs_old/FederView/IvfflatView/render/animateNprobeClustersTrans.js new file mode 100644 index 0000000..c0adcb6 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/animateNprobeClustersTrans.js @@ -0,0 +1,40 @@ +import { + drawVoronoi, + hexWithOpacity, + whiteColor, + blackColor, + ZLightBlue, +} from 'Utils/renderUtils'; +import { ANIMATION_TYPE } from 'Types'; + +export default function animateNprobeClustersTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration, + delay, + animationType, +}) { + const { nprobeClusters } = searchViewLayoutData; + const { ease, voronoiStrokeWidth, canvasScale } = federView; + let t = ease((elapsed - delay) / duration); + if (t > 1 || t < 0) return; + t = animationType === ANIMATION_TYPE.enter ? 1 - t : t; + + const pointsList = nprobeClusters.map((cluster) => + cluster.SVPolyPoints.map((point) => [ + point[0] + t * cluster.SVNextLevelTran[0], + point[1] + t * cluster.SVNextLevelTran[1], + ]) + ); + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZLightBlue, 1), + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/animateTargetNode.js b/federjs_old/FederView/IvfflatView/render/animateTargetNode.js new file mode 100644 index 0000000..3ba0e20 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/animateTargetNode.js @@ -0,0 +1,33 @@ +import { whiteColor, drawCircle } from 'Utils/renderUtils'; +import { ANIMATION_TYPE, SEARCH_VIEW_TYPE } from 'Types'; + +export default function animateTargetNode({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration, + delay, + animationType, + newSearchViewType, +}) { + const { targetNode } = searchViewLayoutData; + const { ease, targetNodeR, canvasScale, targetNodeStrokeWidth } = federView; + let t = ease((elapsed - delay) / duration); + if (newSearchViewType === SEARCH_VIEW_TYPE.project) { + if (t < 0 || t > 1) return; + } + if (t > 1) t = 1; + if (t < 0) t = 0; + t = animationType === ANIMATION_TYPE.enter ? t : 1 - t; + const x = targetNode.SVPos[0] * t + targetNode.polarPos[0] * (1 - t); + const y = targetNode.SVPos[1] * t + targetNode.polarPos[1] * (1 - t); + + drawCircle({ + ctx, + circles: [[x, y, targetNodeR * canvasScale]], + hasStroke: true, + strokeStyle: whiteColor, + lineWidth: targetNodeStrokeWidth * canvasScale, + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/renderBackground.js b/federjs_old/FederView/IvfflatView/render/renderBackground.js new file mode 100644 index 0000000..e1cd225 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderBackground.js @@ -0,0 +1,14 @@ +import { drawRect, blackColor } from 'Utils/renderUtils'; + +export default function renderBackground(ctx, { + width, + height, +}) { + drawRect({ + ctx, + width, + height, + hasFill: true, + fillStyle: blackColor, + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/renderHighLightNodes.js b/federjs_old/FederView/IvfflatView/render/renderHighLightNodes.js new file mode 100644 index 0000000..216e270 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderHighLightNodes.js @@ -0,0 +1,34 @@ +import { SEARCH_VIEW_TYPE } from 'Types'; +import { hexWithOpacity, drawCircle, whiteColor } from 'Utils/renderUtils'; + +export default function renderHighLightNodes( + ctx, + { colorScheme, topKNodes, nprobe }, + { topKNodeR, canvasScale, topKNodeOpacity, topKNodeStrokeWidth }, + searchViewType +) { + const allCircles = + searchViewType === SEARCH_VIEW_TYPE.polar + ? topKNodes.map((node) => [ + ...node.polarPos, + topKNodeR * canvasScale, + node.polarOrder, + ]) + : topKNodes.map((node) => [ + ...node.projectPos, + topKNodeR * canvasScale, + node.polarOrder, + ]); + for (let i = 0; i < nprobe; i++) { + let circles = allCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme[i], topKNodeOpacity), + hasStroke: true, + strokeStyle: hexWithOpacity(whiteColor, topKNodeOpacity), + lineWidth: topKNodeStrokeWidth * canvasScale, + }); + } +} diff --git a/federjs_old/FederView/IvfflatView/render/renderHighlightVoronoi.js b/federjs_old/FederView/IvfflatView/render/renderHighlightVoronoi.js new file mode 100644 index 0000000..0d9330c --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderHighlightVoronoi.js @@ -0,0 +1,25 @@ +import { VIEW_TYPE } from 'Types'; +import { + drawVoronoi, + ZYellow, + ZLightBlue, + hexWithOpacity, + blackColor, +} from 'Utils/renderUtils'; + +export default function renderHighlightVoronoi( + ctx, + { nprobeClusters }, + { voronoiStrokeWidth, canvasScale } +) { + const pointsList = nprobeClusters.map((cluster) => cluster.SVPolyPoints); + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZLightBlue, 1), + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/renderNodeView.js b/federjs_old/FederView/IvfflatView/render/renderNodeView.js new file mode 100644 index 0000000..89123e9 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderNodeView.js @@ -0,0 +1,41 @@ +import renderBackground from './renderBackground'; +import renderPolarAxis from './renderPolarAxis'; +import renderNormalNodes from './renderNormalNodes'; +import renderHighLightNodes from './renderHighLightNodes'; +import renderSelectedNode from './renderSelectedNode'; +import renderTarget from './renderTarget'; +import { SEARCH_VIEW_TYPE } from 'Types'; + +export default function renderNodeView( + ctx, + searchViewLayoutData, + federView, + searchViewType = SEARCH_VIEW_TYPE.polar, + hoveredNode = null +) { + // background + renderBackground(ctx, federView); + + // axis polar + searchViewType === SEARCH_VIEW_TYPE.polar && + renderPolarAxis(ctx, searchViewLayoutData, federView); + + // normal-nodes + renderNormalNodes(ctx, searchViewLayoutData, federView, searchViewType); + + // topk-nodes + renderHighLightNodes(ctx, searchViewLayoutData, federView, searchViewType); + + // hovered node + !!hoveredNode && + renderSelectedNode( + ctx, + searchViewLayoutData, + federView, + searchViewType, + hoveredNode + ); + + // target + renderTarget(ctx, searchViewType, searchViewLayoutData, federView); +} diff --git a/federjs_old/FederView/IvfflatView/render/renderNormalNodes.js b/federjs_old/FederView/IvfflatView/render/renderNormalNodes.js new file mode 100644 index 0000000..d136c49 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderNormalNodes.js @@ -0,0 +1,31 @@ +import { SEARCH_VIEW_TYPE } from 'Types'; +import { hexWithOpacity, drawCircle } from 'Utils/renderUtils'; + +export default function renderNormalNodes( + ctx, + { colorScheme, nonTopKNodes, nprobe }, + { nonTopKNodeR, canvasScale, nonTopKNodeOpacity }, + searchViewType +) { + const allCircles = + searchViewType === SEARCH_VIEW_TYPE.polar + ? nonTopKNodes.map((node) => [ + ...node.polarPos, + nonTopKNodeR * canvasScale, + node.polarOrder, + ]) + : nonTopKNodes.map((node) => [ + ...node.projectPos, + nonTopKNodeR * canvasScale, + node.polarOrder, + ]); + for (let i = 0; i < nprobe; i++) { + let circles = allCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme[i], nonTopKNodeOpacity), + }); + } +} diff --git a/federjs_old/FederView/IvfflatView/render/renderNormalVoronoi.js b/federjs_old/FederView/IvfflatView/render/renderNormalVoronoi.js new file mode 100644 index 0000000..296d88c --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderNormalVoronoi.js @@ -0,0 +1,28 @@ +import { VIEW_TYPE } from 'Types'; +import { + drawVoronoi, + ZBlue, + hexWithOpacity, + blackColor, +} from 'Utils/renderUtils'; + +export default function renderNormalVoronoi( + ctx, + viewType, + { clusters, nonNprobeClusters }, + { voronoiStrokeWidth, canvasScale } +) { + const pointsList = + viewType === VIEW_TYPE.overview + ? clusters.map((cluster) => cluster.OVPolyPoints) + : nonNprobeClusters.map((cluster) => cluster.SVPolyPoints); + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZBlue, 1), + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/renderPolarAxis.js b/federjs_old/FederView/IvfflatView/render/renderPolarAxis.js new file mode 100644 index 0000000..bcc4135 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderPolarAxis.js @@ -0,0 +1,19 @@ +import { hexWithOpacity, drawCircle, ZBlue } from 'Utils/renderUtils'; +import * as d3 from 'd3'; + +export default function renderPolarAxis( + ctx, + { polarOrigin, polarMaxR }, + { axisTickCount, polarAxisStrokeWidth, canvasScale, polarAxisOpacity } +) { + const circles = d3 + .range(axisTickCount) + .map((i) => [...polarOrigin, ((i + 0.7) / axisTickCount) * polarMaxR]); + drawCircle({ + ctx, + circles, + hasStroke: true, + lineWidth: polarAxisStrokeWidth * canvasScale, + strokeStyle: hexWithOpacity(ZBlue, polarAxisOpacity), + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/renderSelectedNode.js b/federjs_old/FederView/IvfflatView/render/renderSelectedNode.js new file mode 100644 index 0000000..f774f0f --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderSelectedNode.js @@ -0,0 +1,32 @@ +import { SEARCH_VIEW_TYPE } from 'Types'; +import { hexWithOpacity, drawCircle, whiteColor } from 'Utils/renderUtils'; + +export default function renderSelectedNode( + ctx, + { colorScheme }, + { hoveredNodeR, canvasScale, hoveredNodeOpacity, hoveredNodeStrokeWidth }, + searchViewType, + hoveredNode +) { + const circle = + searchViewType === SEARCH_VIEW_TYPE.polar + ? [ + ...hoveredNode.polarPos, + hoveredNodeR * canvasScale, + hoveredNode.polarOrder, + ] + : [ + ...hoveredNode.projectPos, + hoveredNodeR * canvasScale, + hoveredNode.polarOrder, + ]; + drawCircle({ + ctx, + circles: [circle], + hasFill: true, + fillStyle: hexWithOpacity(colorScheme[circle[3]], hoveredNodeOpacity), + hasStroke: true, + lineWidth: hoveredNodeStrokeWidth * canvasScale, + strokeStyle: hexWithOpacity(whiteColor, 1), + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/renderSelectedVoronoi.js b/federjs_old/FederView/IvfflatView/render/renderSelectedVoronoi.js new file mode 100644 index 0000000..71165e6 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderSelectedVoronoi.js @@ -0,0 +1,27 @@ +import { VIEW_TYPE } from 'Types'; +import { + drawVoronoi, + ZLightBlue, + ZYellow, + hexWithOpacity, + blackColor, +} from 'Utils/renderUtils'; + +export default function renderNormalVoronoi(ctx, viewType, hoveredCluster, { + voronoiStrokeWidth, + canvasScale, +}) { + const pointsList = + viewType === VIEW_TYPE.overview + ? [hoveredCluster.OVPolyPoints] + : [hoveredCluster.SVPolyPoints]; + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZYellow, 0.8), + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/renderTarget.js b/federjs_old/FederView/IvfflatView/render/renderTarget.js new file mode 100644 index 0000000..6309889 --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderTarget.js @@ -0,0 +1,22 @@ +import { SEARCH_VIEW_TYPE } from 'Types'; +import { whiteColor, drawCircle } from 'Utils/renderUtils'; + +export default function renderTarget( + ctx, + searchViewType, + { targetNode }, + { targetNodeR, canvasScale, targetNodeStrokeWidth } +) { + if (searchViewType === SEARCH_VIEW_TYPE.project) return; + const circle = + searchViewType === SEARCH_VIEW_TYPE.voronoi + ? [...targetNode.SVPos, targetNodeR * canvasScale] + : [...targetNode.polarPos, targetNodeR * canvasScale]; + drawCircle({ + ctx, + circles: [circle], + hasStroke: true, + strokeStyle: whiteColor, + lineWidth: targetNodeStrokeWidth * canvasScale, + }); +} diff --git a/federjs_old/FederView/IvfflatView/render/renderVoronoiView.js b/federjs_old/FederView/IvfflatView/render/renderVoronoiView.js new file mode 100644 index 0000000..d62ee2f --- /dev/null +++ b/federjs_old/FederView/IvfflatView/render/renderVoronoiView.js @@ -0,0 +1,31 @@ +import renderBackground from './renderBackground'; +import renderNormalVoronoi from './renderNormalVoronoi'; +import renderHighlightVoronoi from './renderHighlightVoronoi'; +import renderSelectedVoronoi from './renderSelectedVoronoi'; +import renderTarget from './renderTarget'; +import { VIEW_TYPE, SEARCH_VIEW_TYPE } from 'Types'; + +export default function renderVoronoiView( + ctx, + viewType, + layoutData, + federView, + hoveredCluster = null, +) { + // background + renderBackground(ctx, federView); + + // normal-cluster + renderNormalVoronoi(ctx, viewType, layoutData, federView); + + // nprobe-cluster search + viewType === VIEW_TYPE.search && + renderHighlightVoronoi(ctx, layoutData, federView); + + // hoverCluster + !!hoveredCluster && + renderSelectedVoronoi(ctx, viewType, hoveredCluster, federView); + + // target search + viewType === VIEW_TYPE.search && renderTarget(ctx, SEARCH_VIEW_TYPE.voronoi, layoutData, federView); +} diff --git a/federjs_old/FederView/index.js b/federjs_old/FederView/index.js new file mode 100644 index 0000000..67941d7 --- /dev/null +++ b/federjs_old/FederView/index.js @@ -0,0 +1,97 @@ +import { INDEX_TYPE } from 'Types'; +import { initLoadingStyle, renderLoading } from './loading'; +import HnswView from './HnswView'; +import IvfflatView from './IvfflatView'; + +const viewHandlerMap = { + [INDEX_TYPE.hnsw]: HnswView, + [INDEX_TYPE.ivf_flat]: IvfflatView, +}; + +const defaultViewParams = { + width: 1000, + height: 600, + canvasScale: 3, +}; + +export default class FederView { + constructor({ domSelector, viewParams }) { + this.domSelector = domSelector; + this.viewParams = Object.assign({}, defaultViewParams, viewParams); + + this.viewHandler = null; + + // this.initDom(); + initLoadingStyle(); + } + initDom() { + const dom = document.createElement('div'); + dom.id = `feder-dom-${Math.floor(Math.random() * 100000)}`; + const { width, height } = this.viewParams; + const domStyle = { + position: 'relative', + width: `${width}px`, + height: `${height}px`, + // boxShadow: '0 0 5px #ccc', + // borderRadius: '10px', + }; + Object.assign(dom.style, domStyle); + renderLoading(dom, width, height); + + if (this.domSelector) { + const domContainer = document.querySelector(this.domSelector); + domContainer.innerHTML = ''; + domContainer.appendChild(dom); + } + + return dom; + } + initView({ indexType, indexMeta, getVectorById }) { + if (indexType in viewHandlerMap) { + this.view = new viewHandlerMap[indexType]({ + indexMeta, + viewParams: this.viewParams, + getVectorById, + }); + } else throw `No view handler for ${indexType}`; + } + overview(initCoreAndViewPromise) { + const dom = this.initDom(); + initCoreAndViewPromise.then(() => { + this.view.overview(dom); + }); + + return dom; + } + search({ + searchRes = null, + targetMediaUrl = null, + searchResPromise = null, + } = {}) { + const dom = this.initDom(); + + if (searchResPromise) { + searchResPromise.then(({ searchRes, targetMediaUrl }) => { + this.view.search(dom, { + searchRes, + targetMediaUrl, + }); + }); + } else { + this.view.search(dom, { + searchRes, + targetMediaUrl, + }); + } + + return dom; + } + + switchSearchView(searchViewType) { + try { + this.view.switchSearchView(searchViewType); + } catch (e) { + console.log('Not Support', e); + } + } +} diff --git a/federjs_old/FederView/loading.js b/federjs_old/FederView/loading.js new file mode 100644 index 0000000..3926aa7 --- /dev/null +++ b/federjs_old/FederView/loading.js @@ -0,0 +1,89 @@ +import * as d3 from 'd3'; + +const loadingSvgId = 'feder-loading'; +const loadingWidth = 30; +const loadingStrokeWidth = 6; + +export const initLoadingStyle = () => { + const style = document.createElement('style'); + style.type = 'text/css'; + style.innerHTML = ` + @keyframes rotation { + from { + transform: translate(${loadingWidth / 2}px,${ + loadingWidth / 2 + }px) rotate(0deg); + } + to { + transform: translate(${loadingWidth / 2}px,${ + loadingWidth / 2 + }px) rotate(359deg); + } + } + .rotate { + animation: rotation 2s infinite linear; + } + `; + document.getElementsByTagName('head').item(0).appendChild(style); +}; + +export const renderLoading = (domNode, width, height) => { + const dom = d3.select(domNode); + // const { width, height } = dom.node().getBoundingClientRect(); + if (!dom.select(`#${loadingSvgId}`).empty()) return; + const svg = dom + .append('svg') + .attr('id', loadingSvgId) + .attr('width', loadingWidth) + .attr('height', loadingWidth) + .style('position', 'absolute') + .style('left', width / 2 - loadingWidth / 2) + .style('bottom', height / 2 - loadingWidth / 2) + .style('overflow', 'visible'); + + const defsG = svg.append('defs'); + const linearGradientId = `feder-loading-gradient`; + const linearGradient = defsG + .append('linearGradient') + .attr('id', linearGradientId) + .attr('x1', 0) + .attr('y1', 0) + .attr('x2', 0) + .attr('y2', 1); + linearGradient + .append('stop') + .attr('offset', '0%') + .style('stop-color', '#1E64FF'); + linearGradient + .append('stop') + .attr('offset', '100%') + .style('stop-color', '#061982'); + + const loadingCircle = svg + .append('circle') + .attr('cx', loadingWidth / 2) + .attr('cy', loadingWidth / 2) + .attr('fill', 'none') + .attr('r', loadingWidth / 2) + .attr('stroke', '#1E64FF') + .attr('stroke-width', loadingStrokeWidth); + + const semiCircle = svg + .append('path') + .attr( + 'd', + `M0,${-loadingWidth / 2} a ${loadingWidth / 2} ${ + loadingWidth / 2 + } 0 1 1 ${0} ${loadingWidth}` + ) + .attr('fill', 'none') + // .style('transform', ``) + .attr('stroke', `url(#${linearGradientId})`) + .attr('stroke-width', loadingStrokeWidth) + .classed('rotate', true); +}; + +export const finishLoading = (domNode) => { + const dom = d3.select(domNode); + dom.selectAll(`#${loadingSvgId}`).remove(); +}; diff --git a/federjs_old/Types.js b/federjs_old/Types.js new file mode 100644 index 0000000..810251a --- /dev/null +++ b/federjs_old/Types.js @@ -0,0 +1,82 @@ +export const SOURCE_TYPE = { + hnswlib: 'hnswlib', + faiss: 'faiss', +}; + +export const INDEX_TYPE = { + hnsw: 'hnsw', + ivf_flat: 'ivf_flat', + flat: 'flat', +}; + +export const PROJECT_METHOD = { + umap: 'umap', + tsne: 'tsne', +} + +// faiss config +export const MetricType = { + METRIC_INNER_PRODUCT: 0, ///< maximum inner product search + METRIC_L2: 1, ///< squared L2 search + METRIC_L1: 2, ///< L1 (aka cityblock) + METRIC_Linf: 3, ///< infinity distance + METRIC_Lp: 4, ///< L_p distance, p is given by a faiss::Index + /// metric_arg + + /// some additional metrics defined in scipy.spatial.distance + METRIC_Canberra: 20, + METRIC_BrayCurtis: 21, + METRIC_JensenShannon: 22, +}; + +export const DirectMapType = { + NoMap: 0, // default + Array: 1, // sequential ids (only for add, no add_with_ids) + Hashtable: 2, // arbitrary ids +}; + +export const IndexHeader = { + IVFFlat: 'IwFl', + FlatL2: 'IxF2', + FlatIR: 'IxFI', +}; + +export const HNSW_NODE_TYPE = { + Coarse: 1, + Candidate: 2, + Fine: 3, + Target: 4, +}; + +export const HNSW_LINK_TYPE = { + None: 0, + Visited: 1, + Extended: 2, + Searched: 3, + Fine: 4, +}; + +export const VIEW_TYPE = { + overview: 'overview', + search: 'search', +} + +export const SEARCH_VIEW_TYPE = { + voronoi: 'voronoi', + polar: 'polar', + project: 'project', +} + +export const ANIMATION_TYPE = { + exit: 'exit', + enter: 'enter', +} + +export const FEDER_CORE_REQUEST = { + get_index_type: "get_index_type", + get_index_meta: "get_index_meta", + get_test_id_and_vector: "get_test_id_and_vector", + get_vector_by_id: "get_vector_by_id", + search: "search", + set_search_params: "set_search_params", +}; diff --git a/federjs_old/Utils/PriorityQueue.js b/federjs_old/Utils/PriorityQueue.js new file mode 100644 index 0000000..b95c76a --- /dev/null +++ b/federjs_old/Utils/PriorityQueue.js @@ -0,0 +1,78 @@ +//Minimum Heap +class PriorityQueue { + constructor(arr = [], key = null) { + if (typeof key == 'string') { + this._key = (item) => item[key]; + } else this._key = key; + this._tree = []; + arr.forEach((d) => this.add(d)); + } + add(item) { + this._tree.push(item); + let id = this._tree.length - 1; + while (id) { + const fatherId = Math.floor((id - 1) / 2); + if (this._getValue(id) >= this._getValue(fatherId)) break; + else { + this._swap(fatherId, id); + id = fatherId; + } + } + } + get top() { + return this._tree[0]; + } + pop() { + if (this.isEmpty) { + return 'empty'; + } + const item = this.top; + if (this._tree.length > 1) { + const lastItem = this._tree.pop(); + let id = 0; + this._tree[id] = lastItem; + while (!this._isLeaf(id)) { + const curValue = this._getValue(id); + const leftId = id * 2 + 1; + const leftValue = this._getValue(leftId); + const rightId = leftId >= this._tree.length - 1 ? leftId : id * 2 + 2; + const rightValue = this._getValue(rightId); + const minValue = Math.min(leftValue, rightValue); + if (curValue <= minValue) break; + else { + const minId = leftValue < rightValue ? leftId : rightId; + this._swap(minId, id); + id = minId; + } + } + } else { + this._tree = []; + } + return item; + } + get isEmpty() { + return this._tree.length === 0; + } + get size() { + return this._tree.length; + } + get _firstLeaf() { + return Math.floor(this._tree.length / 2); + } + _isLeaf(id) { + return id >= this._firstLeaf; + } + _getValue(id) { + if (this._key) { + return this._key(this._tree[id]); + } else { + return this._tree[id]; + } + } + _swap(id0, id1) { + const tree = this._tree; + [tree[id0], tree[id1]] = [tree[id1], tree[id0]]; + } +} + +export default PriorityQueue; diff --git a/federjs_old/Utils/index.js b/federjs_old/Utils/index.js new file mode 100644 index 0000000..6b8718c --- /dev/null +++ b/federjs_old/Utils/index.js @@ -0,0 +1,145 @@ +import * as d3 from 'd3'; +export const colorScheme = d3.schemeTableau10; + +import { MetricType } from 'Types'; + +export const getDisL2 = (vec1, vec2) => { + return Math.sqrt( + vec1 + .map((num, i) => num - vec2[i]) + .map((num) => num * num) + .reduce((a, c) => a + c, 0) + ); +}; + +export const getDisIR = (vec1, vec2) => { + return vec1.map((num, i) => num * vec2[i]).reduce((acc, cur) => acc + cur, 0); +}; + +export const getDisFunc = (metricType) => { + if (metricType === MetricType.METRIC_L2) { + return getDisL2; + } else if (metricType === MetricType.METRIC_INNER_PRODUCT) { + return getDisIR; + } + console.warn('[getDisFunc] wrong metric_type, use L2 (default).', metricType); + return getDisL2; +}; + +export default getDisFunc; + +export const getIvfListId = (listId) => `list-${listId}`; +export const uint8toChars = (data) => { + return String.fromCharCode(...data); +}; + +export const generateArray = (num) => { + return Array.from(new Array(Math.floor(num)).keys()); +}; + +export const polyPoints2path = (points, withZ = true) => { + return `M${points.join('L')}${withZ ? 'Z' : ''}`; +}; + +export const calAngle = (x, y) => { + let angle = (Math.atan(x / y) / Math.PI) * 180; + if (angle < 0) { + if (x < 0) { + angle += 360; + } else { + angle += 180; + } + } else { + if (x < 0) { + angle += 180; + } + } + return angle; +}; + +export const vecSort = (vecs, layoutKey, returnKey) => { + const center = { + x: vecs.reduce((acc, c) => acc + c[layoutKey][0], 0) / vecs.length, + y: vecs.reduce((acc, c) => acc + c[layoutKey][1], 0) / vecs.length, + }; + const angles = vecs.map((vec) => ({ + _vecSortAngle: calAngle( + vec[layoutKey][0] - center.x, + vec[layoutKey][1] - center.y + ), + _key: vec[returnKey], + })); + angles.sort((a, b) => a._vecSortAngle - b._vecSortAngle); + const res = angles.map((vec) => vec._key); + return res; +}; + +export const dist2 = (vec1, vec2) => + vec1.map((num, i) => num - vec2[i]).reduce((acc, cur) => acc + cur * cur, 0); + +export const dist = (vec1, vec2) => Math.sqrt(dist2(vec1, vec2)); + +export const inCircle = (x, y, x0, y0, r, bias = 0) => + dist2([x, y], [x0, y0]) < Math.pow(r + bias, 2); + +export const deDupLink = (links, source = 'source', target = 'target') => { + const linkStringSet = new Set(); + return links.filter((link) => { + const linkString = `${link[source]}---${link[target]}`; + const linkStringReverse = `${link[target]}---${link[source]}`; + if (linkStringSet.has(linkString) || linkStringSet.has(linkStringReverse)) { + return false; + } else { + linkStringSet.add(linkString); + return true; + } + }); +}; + +const connection = '---'; +export const getLinkId = (sourceId, targetId) => + `${sourceId}${connection}${targetId}`; +export const parseLinkId = (linkId) => linkId.split(connection).map((d) => +d); +export const getLinkIdWithLevel = (sourceId, targetId, level) => + `link-${level}-${sourceId}-${targetId}`; + +export const getNodeIdWithLevel = (nodeId, level) => `node-${level}-${nodeId}`; +export const getEntryLinkIdWithLevel = (nodeId, level) => + `inter-level-${level}-${nodeId}`; + +export const shortenLine = (point_0, point_1, d = 20) => { + const length = dist(point_0, point_1); + const t = Math.min(d / length, 0.4); + return [ + getInprocessPos(point_0, point_1, t), + getInprocessPos(point_0, point_1, 1 - t), + ]; +}; + +export const getInprocessPos = (point_0, point_1, t) => { + const x = point_0[0] * (1 - t) + point_1[0] * t; + const y = point_0[1] * (1 - t) + point_1[1] * t; + return [x, y]; +}; + +export const showVectors = (vec, precision = 6, maxLength = 20) => { + return ( + vec + .slice(0, maxLength) + .map((num) => num.toFixed(precision)) + .join(', ') + ', ...' + ); +}; + +export const randomSelect = (arr, k) => { + const res = new Set(); + k = Math.min(arr.length, k); + while (k > 0) { + const itemIndex = Math.floor(Math.random() * arr.length); + if (!res.has(itemIndex)) { + res.add(itemIndex); + k -= 1; + } + } + return Array.from(res).map((i) => arr[i]); +}; diff --git a/federjs_old/Utils/renderUtils.js b/federjs_old/Utils/renderUtils.js new file mode 100644 index 0000000..3e0ccdf --- /dev/null +++ b/federjs_old/Utils/renderUtils.js @@ -0,0 +1,293 @@ +import { polyPoints2path } from 'Utils'; +import * as d3 from 'd3'; + +export const colorScheme = d3.schemeTableau10; + +export const ZBlue = '#175FFF'; +export const ZLightBlue = '#91FDFF'; +export const ZYellow = '#FFFC85'; +export const ZOrange = '#F36E4B'; +export const ZLayerBorder = '#D9EAFF'; + +export const whiteColor = '#ffffff'; +export const blackColor = '#000000'; +export const backgroundColor = blackColor; +export const highLightColor = ZYellow; +export const voronoiHighlightColor = ZYellow; +export const selectedColor = '#FFC671'; +export const voronoiHoverColor = selectedColor; +export const hexWithOpacity = (color, opacity) => { + let opacityString = Math.round(opacity * 255).toString(16); + if (opacityString.length < 2) { + opacityString = '0' + opacityString; + } + return color + opacityString; +}; +export const voronoiStrokeWidth = 4; + +export const highLightGradientStopColors = [ + [0, hexWithOpacity(whiteColor, 0.2)], + [1, hexWithOpacity(ZYellow, 1)], +]; + +export const neighbourGradientStopColors = [ + [0, hexWithOpacity(whiteColor, 0)], + [1, hexWithOpacity(whiteColor, 0.8)], +]; + +export const targetLevelGradientStopColors = neighbourGradientStopColors; + +export const normalGradientStopColors = [ + [0, hexWithOpacity('#061982', 0.3)], + [1, hexWithOpacity('#1E64FF', 0.4)], +]; + +export const layerGradientStopColors = [ + [0.1, hexWithOpacity('#1E64FF', 0.4)], + [0.9, hexWithOpacity('#00234D', 0)], +]; + +const draw = ({ + ctx, + drawFunc = () => {}, + fillStyle = '', + strokeStyle = '', + lineWidth = 0, + lineCap = 'butt', + shadowColor = '', + shadowBlur = 0, + shadowOffsetX = 0, + shadowOffsetY = 0, + isFillLinearGradient = false, + isStrokeLinearGradient = false, + gradientPos = [0, 0, 100, 100], + gradientStopColors = [], +}) => { + ctx.save(); + + let gradient = null; + if (isFillLinearGradient || isStrokeLinearGradient) { + gradient = ctx.createLinearGradient(...gradientPos); + gradientStopColors.forEach((stopColor) => + gradient.addColorStop(...stopColor) + ); + } + ctx.fillStyle = isFillLinearGradient ? gradient : fillStyle; + ctx.strokeStyle = isStrokeLinearGradient ? gradient : strokeStyle; + ctx.lineWidth = lineWidth; + ctx.lineCap = lineCap; + + ctx.shadowColor = shadowColor; + ctx.shadowBlur = shadowBlur; + ctx.shadowOffsetX = shadowOffsetX; + ctx.shadowOffsetY = shadowOffsetY; + + drawFunc(); + + ctx.restore(); +}; + +export const drawVoronoi = ({ + ctx, + pointsList, + hasFill = false, + hasStroke = false, + ...styles +}) => { + const drawFunc = () => { + pointsList.forEach((points) => { + const path = new Path2D(polyPoints2path(points)); + hasFill && ctx.fill(path); + hasStroke && ctx.stroke(path); + }); + }; + draw({ ctx, drawFunc, ...styles }); +}; + +export const extraExtent = ([x0, x1], p = 0.5) => { + const length = x1 - x0; + return [x0 - length * p, x1 + length * p]; +}; + +export const drawVoronoiWithDots = ({ + ctx, + points, + hasFill = false, + hasStroke = false, + dotColor = hexWithOpacity('red', 0.6), + dotR = 1.5, + dotAngle = Math.PI / 6, + dotGap = 4, + fillStyle = 'blue', + strokeStyle = 'green', + lineWidth = 2, +}) => { + ctx.save(); + + ctx.fillStyle = fillStyle; + ctx.strokeStyle = strokeStyle; + ctx.lineWidth = lineWidth; + + path = new Path2D(polyPoints2path(points)); + hasFill && ctx.fill(path); + hasStroke && ctx.stroke(path); + + ctx.clip(path); + + const extentX = extraExtent(d3.extent(points, (point) => point[0])); + const extentY = extraExtent(d3.extent(points, (point) => point[1])); + + ctx.fillStyle = dotColor; + const step = (dotR + dotGap) * 2; + d3.range(extentX[0], extentX[1], step).forEach((x) => + d3.range(extentY[0], extentY[1], step).forEach((_y) => { + y = _y + (x - extentX[0]) * Math.tan(dotAngle); + ctx.beginPath(); + ctx.arc(x, y, dotR, 0, 2 * Math.PI); + ctx.fill(); + }) + ); + + ctx.strokeStyle = strokeStyle; + hasStroke && ctx.stroke(path); + + ctx.restore(); +}; + +export const drawCircle = ({ + ctx, + circles, + hasFill = false, + hasStroke = false, + ...styles +}) => { + const drawFunc = () => { + circles.forEach(([x, y, r]) => { + ctx.beginPath(); + ctx.arc(x, y, r, 0, 2 * Math.PI); + hasFill && ctx.fill(); + hasStroke && ctx.stroke(); + }); + }; + draw({ ctx, drawFunc, ...styles }); +}; + +export const drawEllipse = ({ + ctx, + circles, + hasFill = false, + hasStroke = false, + ...styles +}) => { + const drawFunc = () => { + circles.forEach(([x, y, rx, ry]) => { + ctx.beginPath(); + ctx.ellipse(x, y, rx, ry, 0, 0, 2 * Math.PI); + hasFill && ctx.fill(); + hasStroke && ctx.stroke(); + }); + }; + draw({ ctx, drawFunc, ...styles }); +}; + +export const drawRect = ({ + ctx, + x = 0, + y = 0, + width, + height, + hasFill = false, + hasStroke = false, + ...styles +}) => { + const drawFunc = () => { + hasFill && ctx.fillRect(0, 0, width, height); + hasStroke && ctx.strokeRect(0, 0, width, height); + }; + draw({ ctx, drawFunc, ...styles }); +}; + +export const drawPath = ({ + ctx, + points, + hasFill = false, + hasStroke = false, + withZ = true, + ...styles +}) => { + const drawFunc = () => { + const path = new Path2D(polyPoints2path(points, withZ)); + hasFill && ctx.fill(path); + hasStroke && ctx.stroke(path); + }; + draw({ ctx, drawFunc, ...styles }); +}; + +export const drawLine = ({ + ctx, + points, + hasFill = false, + hasStroke = false, + ...styles +}) => { + const drawFunc = () => { + const path = new Path2D(`M${points[0]}L${points[1]}`); + hasFill && ctx.fill(path); + hasStroke && ctx.stroke(path); + }; + draw({ ctx, drawFunc, ...styles }); +}; + +export const drawLines = ({ + ctx, + pointsList, + hasFill = false, + hasStroke = false, + ...styles +}) => { + const drawFunc = () => { + pointsList.forEach((points) => { + const path = new Path2D(`M${points[0]}L${points[1]}`); + hasFill && ctx.fill(path); + hasStroke && ctx.stroke(path); + }); + }; + draw({ ctx, drawFunc, ...styles }); +}; + +export const drawLinesWithLinearGradient = ({ + ctx, + pointsList, + hasFill = false, + hasStroke = false, + isStrokeLinearGradient = true, + ...styles +}) => { + pointsList.forEach((points) => { + const path = new Path2D(`M${points[0]}L${points[1]}`); + const gradientPos = [...points[0], ...points[1]]; + const drawFunc = () => { + hasFill && ctx.fill(path); + hasStroke && ctx.stroke(path); + }; + draw({ ctx, drawFunc, isStrokeLinearGradient, gradientPos, ...styles }); + }); +}; + +export const renderLoading = ({ dom, width, height }) => { + const _dom = d3.select(`#${dom.id}`); + const svg = _dom + .append('svg') + .attr('id', loadingSvgId) + .attr('width', loadingWidth) + .attr('height', loadingWidth) + .style('position', 'absolute') + .style('left', width / 2 - loadingWidth / 2) + .style('bottom', height / 2 - loadingWidth / 2) + .style('border', '1px solid red'); +}; + +export const finishLoading = ({ dom }) => { + const _dom = d3.select(`#${dom.id}`); + _dom.select(`#${loadingSvgId}`).remove(); +}; diff --git a/federjs_old/index.js b/federjs_old/index.js new file mode 100644 index 0000000..2914b6a --- /dev/null +++ b/federjs_old/index.js @@ -0,0 +1,6 @@ +import FederCore from './FederCore'; +import FederView from './FederView'; +import Feder from './Feder'; +import { FEDER_CORE_REQUEST } from 'Types'; + +export { Feder, FederCore, FederView, FEDER_CORE_REQUEST }; diff --git a/federpy/LICENSE b/federpy/LICENSE new file mode 100644 index 0000000..335ea9d --- /dev/null +++ b/federpy/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018 The Python Packaging Authority + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/federpy/README.md b/federpy/README.md new file mode 100644 index 0000000..65bb62b --- /dev/null +++ b/federpy/README.md @@ -0,0 +1,23 @@ +# Feder for Python + +## 0.6.0 + +Support search-by-vector + +``` +searchByVec(vector [, imgUrl=None, isDisplayed=True]) +``` + +## 0.7.0 + +Each action (search or overview) command generates a new div with a random id. + +Different actions will no longer share an output cell. + +## 0.8.0 + +Support chain functions. + +``` +federPy.setSearchParams(params).search() +``` \ No newline at end of file diff --git a/federpy/nodeServer/index.js b/federpy/nodeServer/index.js new file mode 100644 index 0000000..4eaa0b8 --- /dev/null +++ b/federpy/nodeServer/index.js @@ -0,0 +1,52 @@ +import express from 'express'; +import cors from 'cors'; +import getFederCore from './initFederCore.js'; + +import { coreNodePort } from '../test/config.js'; + +const app = express(); +app.use(cors()); + +const core = await getFederCore(); + +const successData = (data) => ({ code: 200, data }); + +app.get('/', (req, res) => { + console.log(req.query); + res.send(successData('get it~')); +}); + +app.get('/get_index_type', (_, res) => { + res.json(successData(core.indexType)); +}); + +app.get('/get_index_meta', (_, res) => { + res.json(successData(core.indexMeta)); +}); + +app.get('/get_test_id_and_vector', (_, res) => { + let [testId, testVec] = core.getTestIdAndVec(); + while (isNaN(testId)) { + [testId, testVec] = core.getTestIdAndVec(); + } + res.json(successData({ testId, testVec: Array.from(testVec) })); +}); + +app.get('/get_vector_by_id', (req, res) => { + const { id } = req.query; + res.json(successData(Array.from(core.id2vector[id] || []))); +}); + +app.get('/search', (req, res) => { + const { target } = req.query; + res.json(successData(core.search(target))); +}); + +app.get('/set_search_params', (req, res) => { + core.setSearchParams(req.query); + res.json(successData('ok')); +}); + +app.listen(coreNodePort, () => { + console.log('listening on port', coreNodePort); +}); diff --git a/federpy/pyproject.toml b/federpy/pyproject.toml new file mode 100644 index 0000000..a673a1f --- /dev/null +++ b/federpy/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools>=42", "ipython>=7"] +build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/federpy/setup.py b/federpy/setup.py new file mode 100644 index 0000000..f6d133e --- /dev/null +++ b/federpy/setup.py @@ -0,0 +1,23 @@ +import setuptools + +with open("README.md", "r", encoding="utf-8") as fh: + long_description = fh.read() + +setuptools.setup( + name="federpy", + version="0.8.0", + author="min.tian@zilliz", + author_email="min.tian@zilliz.com", + description="Feder for python", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://github.com/zilliztech/feder", + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], + package_dir={"": "src"}, + packages=setuptools.find_packages(where="src"), + python_requires=">=3.6", +) diff --git a/federpy/src/federpy/__init__.py b/federpy/src/federpy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/federpy/src/federpy/federpy.py b/federpy/src/federpy/federpy.py new file mode 100644 index 0000000..29ccdf7 --- /dev/null +++ b/federpy/src/federpy/federpy.py @@ -0,0 +1,106 @@ +from IPython.display import display, HTML +import random + + +class FederPy: + def __init__(self, indexFile, indexSource, mediaUrls=[], **viewParams): + self.indexFile = indexFile + self.indexSource = indexSource + + self.federjs = "https://unpkg.com/@zilliz/feder" + + self.actionJs = "" + self.searchParams = {} + self.mediaUrls = mediaUrls + self.viewParams = viewParams + + def getDiv(self): + self.container = "feder-container-%s" % random.randint(0, 10000000) + return '
' % self.container + + def getInitJs(self): + return """ +import { Feder } from "%s" +// console.log(Feder) + +const mediaUrls = [%s] +const mediaCallback = (rowId) => rowId in mediaUrls ? mediaUrls[rowId] : null + +const feder = new Feder({ + filePath: "%s", + source: "%s", + domSelector: "#%s", + viewParams: { + ...%s, + mediaCallback, + } +}) + """ % (self.federjs, ",".join(["'%s'" % url for url in self.mediaUrls]), self.indexFile, self.indexSource, self.container, self.viewParams) + + def overview(self, isDisplay=True): + self.actionJs = "feder.overview()" + if isDisplay: + self.showHtml() + else: + return self.getHtml() + + def searchById(self, targetId, isDisplay=True): + self.actionJs = "feder.setSearchParams(%s)\nfeder.searchById(%s)" % ( + self.searchParams, targetId) + if isDisplay: + self.showHtml() + else: + return self.getHtml() + + def searchByVec(self, targetVec, targetUrl=None, isDisplay=True): + targetVecString = "[" + ",".join([str(num) for num in targetVec]) + "]" + targetUrlString = "'%s'" % targetUrl if targetUrl else 'null' + self.actionJs = "feder.setSearchParams(%s)\nfeder.search(%s,%s)" % ( + self.searchParams, targetVecString, targetUrlString) + if isDisplay: + self.showHtml() + else: + return self.getHtml() + + def searchRandTestVec(self, isDisplay=True): + self.actionJs = "feder.setSearchParams(%s)\nfeder.searchRandTestVec()" % self.searchParams + if isDisplay: + self.showHtml() + else: + return self.getHtml() + + def setSearchParams(self, searchParams): + self.searchParams = searchParams + return self + + def getJs(self): + return """ +%s +%s + """ % (self.getInitJs(), self.actionJs) + + def getHtml(self): + return """ + + + + + + + + Feder + + + + %s + + + + + +""" % (self.getDiv(), self.getJs()) + + def showHtml(self): + display(HTML(self.getHtml())) diff --git a/federpy/test/test_searchById.ipynb b/federpy/test/test_searchById.ipynb new file mode 100644 index 0000000..1ebca0e --- /dev/null +++ b/federpy/test/test_searchById.ipynb @@ -0,0 +1,440 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 15, + "id": "2e0a8dce", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "import random\n", + "\n", + "\n", + "class FederPy:\n", + " def __init__(self, indexFile, indexSource, mediaUrls=[], **viewParams):\n", + " self.indexFile = indexFile\n", + " self.indexSource = indexSource\n", + "\n", + " self.federjs = \"https://unpkg.com/@zilliz/feder\"\n", + "\n", + " self.actionJs = \"\"\n", + " self.searchParams = {}\n", + " self.mediaUrls = mediaUrls\n", + " self.viewParams = viewParams\n", + "\n", + " def getDiv(self):\n", + " self.container = \"feder-container-%s\" % random.randint(0, 10000000)\n", + " return '
' % self.container\n", + "\n", + " def getInitJs(self):\n", + " return \"\"\"\n", + "import { Feder } from \"%s\"\n", + "// console.log(Feder)\n", + "\n", + "const mediaUrls = [%s]\n", + "const mediaCallback = (rowId) => rowId in mediaUrls ? mediaUrls[rowId] : null\n", + "\n", + "const feder = new Feder({\n", + " filePath: \"%s\",\n", + " source: \"%s\",\n", + " domSelector: \"#%s\",\n", + " viewParams: {\n", + " ...%s,\n", + " mediaCallback,\n", + " }\n", + "})\n", + " \"\"\" % (self.federjs, \",\".join([\"'%s'\" % url for url in self.mediaUrls]), self.indexFile, self.indexSource, self.container, self.viewParams)\n", + "\n", + " def overview(self, isDisplay=True):\n", + " self.actionJs = \"feder.overview()\"\n", + " if isDisplay:\n", + " self.showHtml()\n", + " else:\n", + " return self.getHtml()\n", + "\n", + " def searchById(self, targetId, isDisplay=True):\n", + " self.actionJs = \"feder.setSearchParams(%s)\\nfeder.searchById(%s)\" % (\n", + " self.searchParams, targetId)\n", + " if isDisplay:\n", + " self.showHtml()\n", + " else:\n", + " return self.getHtml()\n", + "\n", + " def searchByVec(self, targetVec, targetUrl=None, isDisplay=True):\n", + " targetVecString = \"[\" + \",\".join([str(num) for num in targetVec]) + \"]\"\n", + " targetUrlString = \"'%s'\" % targetUrl if targetUrl else 'null'\n", + " self.actionJs = \"feder.setSearchParams(%s)\\nfeder.search(%s,%s)\" % (\n", + " self.searchParams, targetVecString, targetUrlString)\n", + " if isDisplay:\n", + " self.showHtml()\n", + " else:\n", + " return self.getHtml()\n", + "\n", + " def searchRandTestVec(self, isDisplay=True):\n", + " self.actionJs = \"feder.setSearchParams(%s)\\nfeder.searchRandTestVec()\" % self.searchParams\n", + " if isDisplay:\n", + " self.showHtml()\n", + " else:\n", + " return self.getHtml()\n", + "\n", + " def setSearchParams(self, searchParams):\n", + " self.searchParams = searchParams\n", + "\n", + " def getJs(self):\n", + " return \"\"\"\n", + "%s\n", + "%s\n", + " \"\"\" % (self.getInitJs(), self.actionJs)\n", + "\n", + " def getHtml(self):\n", + " return \"\"\"\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " Feder\n", + "\n", + "\n", + "\n", + " %s\n", + "\n", + "\n", + "\n", + "\n", + " \n", + "\"\"\" % (self.getDiv(), self.getJs())\n", + "\n", + " def showHtml(self):\n", + " display(HTML(self.getHtml()))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "097125ac", + "metadata": {}, + "outputs": [], + "source": [ + "# IVFFlat - Search\n", + "import csv\n", + "import pandas as pd\n", + "# this csv includes 17,000+ items,each of which includes its filename.\n", + "namesFile = \"https://assets.zilliz.com/voc_names_4cee9440b1.csv\"\n", + "namesCsv = pd.read_csv(namesFile)\n", + "names = [row['name'] for index, row in namesCsv.iterrows()]\n", + "imageUrls = [\"https://assets.zilliz.com/voc2012/JPEGImages/%s\" % name for name in names]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "1f95dcdf", + "metadata": {}, + "outputs": [], + "source": [ + "indexFile = 'https://assets.zilliz.com/faiss_ivf_flat_voc_17k_ab112eec72.index'\n", + "indexSource = 'faiss'\n", + "\n", + "viewParams = {\n", + " \"width\": 800,\n", + " \"height\": 500,\n", + " \"mediaType\": \"img\",\n", + " \"mediaUrls\": imageUrls,\n", + " \"fineSearchWithProjection\": 1,\n", + " \"projectMethod\": \"umap\"\n", + "}\n", + "federPy = FederPy(indexFile, indexSource, **viewParams)\n", + "federPy.setSearchParams({\"k\": 15, \"nprobe\": 8})\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "88653ad0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " Feder\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + " \n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "federPy.searchById(1156)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "a4232ea2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " Feder\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + " \n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "federPy.searchById(665)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "7aef9547", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " Feder\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + " \n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "testId = 14486\n", + "testVec = [0.3180559277534485,1.8129287958145142,1.1755975484848022,0.7891319394111633,0.22350305318832397,2.516303300857544,1.1570743322372437,0.06357292830944061,0.943956196308136,0.6021895408630371,0.9676622748374939,0.6982965469360352,0.9805429577827454,0.5724471807479858,0.22905878722667694,0.09630092978477478,0.9583004713058472,1.0572623014450073,0.6430980563163757,1.3918004035949707,0.08578045666217804,1.5907948017120361,3.3321969509124756,1.3610285520553589,0.09104672074317932,0.10312048345804214,0.7651993632316589,1.3956501483917236,0.01969618909060955,0.6128015518188477,1.6002562046051025,0.43189698457717896,0.09782502800226212,0.44681864976882935,0.17383213341236115,1.540826439857483,1.3423514366149902,1.6673506498336792,0.5427879095077515,0.8117725849151611,1.1495232582092285,1.1069304943084717,0.1126856878399849,0.8899828791618347,2.41703724861145,0.8937768936157227,0.5728181004524231,0.5219349265098572,3.1016955375671387,1.0886644124984741,1.2785980701446533,1.5853283405303955,2.2631473541259766,0.9746670126914978,0.9295732378959656,0.2759018838405609,0.03575670346617699,1.1523011922836304,1.5381693840026855,2.675575017929077,0.12831033766269684,0.1481480449438095,0.971545934677124,0.5385479927062988,0.5174979567527771,0.2873912453651428,0.7357646226882935,0.4928179383277893,0.3909325897693634,1.1287131309509277,1.5709086656570435,1.692298412322998,0.9139777421951294,0,1.5500441789627075,0.7839444279670715,0.9178622364997864,0.2820394039154053,0.8132333755493164,3.5066189765930176,0.9958689212799072,1.1382688283920288,0.309495210647583,1.415186882019043,0.7401412725448608,0.8137246966362,1.7396281957626343,0.11588877439498901,1.7407218217849731,1.8080974817276,0.5819406509399414,1.4546641111373901,2.42268705368042,0.9622344970703125,1.2213270664215088,0.8828086256980896,0.6727229356765747,1.5722789764404297,1.4593628644943237,0.03921904042363167,1.090134859085083,2.0868043899536133,0.28828656673431396,0.13450616598129272,0.7206522226333618,0.8748136758804321,1.8188858032226562,0.26462316513061523,0.8555235862731934,1.7327840328216553,1.4438320398330688,0.5325329303741455,0.7508541941642761,1.339582920074463,1.70830500125885,1.0904120206832886,0.5070831775665283,0.5154015421867371,0.5790265798568726,1.773036003112793,0.5179463028907776,0.8528609871864319,1.0828299522399902,1.0559226274490356,1.0264568328857422,0.9711904525756836,0.2862222492694855,0.2566063702106476,0.0488421656191349,0.3808225095272064,0.6076082587242126,1.9010634422302246,1.3411893844604492,0.5852816700935364,1.391355276107788,2.265092134475708,0.08930734544992447,0.24246472120285034,0.3210437297821045,1.153865098953247,1.6873430013656616,0.13649778068065643,0.654911994934082,1.6923422813415527,0.5705053210258484,0.8343877792358398,0.6226603388786316,0.5277264714241028,1.5640935897827148,0.15445412695407867,0.5749205946922302,1.3574976921081543,1.0360305309295654,0.4930250644683838,0.20601044595241547,0.14740405976772308,0.458052396774292,0.9187849164009094,1.2116740942001343,0.23303964734077454,0.5805302262306213,0.5607320070266724,0.4117003083229065,2.465473175048828,1.6386477947235107,1.7031350135803223,0.7070876359939575,1.0024104118347168,0.8232477307319641,0.454339861869812,1.3948756456375122,0.3280218541622162,1.2151522636413574,0.003233200404793024,1.733725666999817,0.8428475260734558,0.22271889448165894,1.8416955471038818,0.7364838123321533,1.3723012208938599,0.5785627365112305,0.26418179273605347,0.9129582643508911,0.09611000120639801,1.287489891052246,0.11864835023880005,1.1257281303405762,0.2487281858921051,0.18080449104309082,1.7580831050872803,4.647215843200684,0.27495577931404114,0.9688863158226013,0.11473143100738525,0.5914319157600403,1.342428207397461,1.138437271118164,0.5523998737335205,0.7816208004951477,2.2148325443267822,1.0988376140594482,1.6005674600601196,1.1915910243988037,1.3269768953323364,0.378095418214798,0.4395700991153717,0.7779095768928528,0.830786943435669,0.054311707615852356,0.5461437702178955,0.5768404006958008,0.5111103653907776,0.909504771232605,0.601173460483551,0.1638777256011963,0.21263957023620605,1.3269394636154175,0.7092355489730835,0.23375484347343445,2.742825508117676,0.04263075068593025,1.0065308809280396,0.13075709342956543,0.5005173683166504,0.8138548135757446,0.06231844797730446,2.2059550285339355,0.06170327961444855,0.24481193721294403,0.9969230890274048,1.6500935554504395,0.55216383934021,1.2010104656219482,0.3328365385532379,0.6167313456535339,0.6265155076980591,0.1876257061958313,0.4984287619590759,0.6478190422058105,0.6275940537452698,1.99158775806427,0.817809522151947,0.6767558455467224,0.02413162961602211,0.8833544254302979,0.8482292294502258,0.3146904408931732,0.518939197063446,0.36384570598602295,0,0.9742975831031799,0.14988255500793457,0.43216198682785034,0.22757378220558167,0.4066866636276245,1.1298837661743164,0.9067808389663696,0.22455531358718872,0.05864056199789047,0.9304453730583191,0.9014017581939697,1.8137454986572266,0.0968548133969307,0.2409812957048416,0.6663099527359009,1.2130497694015503,0.24968497455120087,0.9161180853843689,0.353221595287323,0.8130157589912415,0.2987111806869507,0.6010563373565674,1.3867548704147339,2.9300880432128906,0.8085629343986511,0.40099242329597473,0.43244197964668274,0.5951328277587891,0.9391095638275146,0.26254960894584656,0.6959999203681946,0.1226467564702034,1.1226005554199219,0.4928096830844879,1.9354279041290283,0.3433109223842621,0.853999674320221,1.4863165616989136,1.118110179901123,1.1116055250167847,1.3586441278457642,1.268913745880127,0.3293173015117645,1.097061038017273,0.5706954002380371,1.133157730102539,0.08769454807043076,1.3840101957321167,3.1065492630004883,0.2939116060733795,0.2675859332084656,0.3103168308734894,0.4951390326023102,0.32175976037979126,0.6401526927947998,0.6554588079452515,0.6203683614730835,1.000016212463379,0.5004483461380005,1.860917329788208,1.376828908920288,0.7377114295959473,1.0946835279464722,0.7701189517974854,0.6361571550369263,0.6349006295204163,0.014083875343203545,0.12574534118175507,1.4780312776565552,0.684380054473877,0.26904618740081787,0.22538070380687714,0.00879308395087719,0.9298273921012878,1.9020938873291016,0.7884451150894165,0.07946275174617767,1.1165977716445923,0.30933812260627747,0.5403715372085571,1.1603479385375977,0.3008138835430145,1.3190054893493652,0.795007050037384,0.22366446256637573,0.7132651805877686,0.24945855140686035,1.3368955850601196,0.19791144132614136,0.3044207692146301,1.2946991920471191,2.172100067138672,0.0620955154299736,1.1856104135513306,1.050154209136963,0.22127188742160797,0.4226319491863251,0.6396470069885254,0.32624831795692444,0.6085342168807983,1.1651835441589355,0.16642792522907257,1.4138462543487549,1.297584056854248,1.6136043071746826,1.0782232284545898,0.6430231332778931,1.1396124362945557,0.3635297417640686,0.48967084288597107,0.46470028162002563,1.4600411653518677,0.4599548280239105,0.8528343439102173,0.14161142706871033,0.8258335590362549,0.582858145236969,0.9192168712615967,0.8009287118911743,0.6240752935409546,0.39849743247032166,0.7765495777130127,0.3709612488746643,2.652484893798828,0.8104533553123474,0.006185327190905809,0.35379570722579956,1.5678136348724365,0.6926767826080322,1.693477749824524,1.2875405550003052,0.6767603754997253,0.6120878458023071,2.0956668853759766,2.656432867050171,0.5108842253684998,2.3255038261413574,0.8390073180198669,2.5381956100463867,0.9664138555526733,0.6655454039573669,0.4604036509990692,0.4444624185562134,0.3776257634162903,2.2371013164520264,0.5808571577072144,0.31693392992019653,0.33319956064224243,0.8720987439155579,0.10681258141994476,0.6595206260681152,1.1067618131637573,1.2506458759307861,0.9226015210151672,0.8610519766807556,0.8589621782302856,0.4330337345600128,0.8203577995300293,0.2464151531457901,1.0172529220581055,0.3628329336643219,2.0844993591308594,0.6375234723091125,0.5927277207374573,1.312648892402649,0.37716561555862427,1.7252025604248047,0.45358338952064514,0.18682627379894257,0.0062152305617928505,0.6554352045059204,1.2754335403442383,0.8909009099006653,0.1972004622220993,1.9216731786727905,1.2920082807540894,0.13435210287570953,2.3624701499938965,0.22141511738300323,0.9661803245544434,1.1026030778884888,0.23505376279354095,0.030129481106996536,0.4950302243232727,0.4512035548686981,0.026624049991369247,1.4041651487350464,0.209356427192688,1.6079065799713135,2.164234161376953,1.5885684490203857,0.8960825204849243,1.886052131652832,0.2653025686740875,1.7950098514556885,0.6545081734657288,1.6967599391937256,0.03656003996729851,1.2098544836044312,3.3872408866882324,1.5322508811950684,0.19821853935718536,1.120884656906128,0.5186260938644409,0.7395733594894409,0.928455114364624,1.355623483657837,0.26370465755462646,1.2062020301818848,0.09249454736709595,0.5326693654060364,1.3141732215881348,0.2362804263830185,0.4778333008289337,0.22796191275119781,1.056803822517395,0.020549282431602478,0.33742931485176086,0.46185389161109924,2.4832324981689453,0.7287827134132385,0.36329227685928345,0.6522612571716309,0.3673896789550781,1.4581804275512695,0.6657092571258545,1.0051950216293335,1.2561205625534058,0.614002525806427,2.298558235168457,0.9794350266456604,0.48981261253356934,2.2125771045684814,0.2940179109573364,1.4562480449676514,0.9676485061645508,0.7187795639038086,0.6007862687110901,0.056436002254486084,1.2564529180526733,0.41692912578582764,0.7548884153366089,0.1753060221672058,1.8333464860916138,0.4114776849746704,0.42682477831840515,0.0785190537571907,1.204007863998413,0.16531716287136078,1.065880298614502,0.13906246423721313,0.4406368136405945,0.46826162934303284,1.468100666999817,1.7256641387939453,0.058478403836488724,0.3659725487232208,1.2905678749084473,1.2725436687469482,0.34850987792015076,0.22254829108715057,0.0393102802336216]\n", + "len(testVec)\n", + "federPy.searchByVec(testVec)\n", + "# federPy.searchByVec(testVec, imageUrls[testId])" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "5c7f9bb0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " Feder\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + " \n", + "\n" + ] + } + ], + "source": [ + "print(federPy.searchByVec(testVec, imageUrls[testId], False))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8484f838", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba0f7925", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/fig/hnsw_overview.png b/fig/hnsw_overview.png new file mode 100644 index 0000000..5201dfb Binary files /dev/null and b/fig/hnsw_overview.png differ diff --git a/fig/hnsw_search.png b/fig/hnsw_search.png new file mode 100644 index 0000000..e016d25 Binary files /dev/null and b/fig/hnsw_search.png differ diff --git a/fig/ivfflat_coarse.png b/fig/ivfflat_coarse.png new file mode 100644 index 0000000..231253e Binary files /dev/null and b/fig/ivfflat_coarse.png differ diff --git a/fig/ivfflat_fine_polar.png b/fig/ivfflat_fine_polar.png new file mode 100644 index 0000000..d3ebe72 Binary files /dev/null and b/fig/ivfflat_fine_polar.png differ diff --git a/fig/ivfflat_fine_project.png b/fig/ivfflat_fine_project.png new file mode 100644 index 0000000..611275d Binary files /dev/null and b/fig/ivfflat_fine_project.png differ diff --git a/fig/ivfflat_overview.png b/fig/ivfflat_overview.png new file mode 100644 index 0000000..d5204a1 Binary files /dev/null and b/fig/ivfflat_overview.png differ diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index c269617..0000000 --- a/package-lock.json +++ /dev/null @@ -1,1181 +0,0 @@ -{ - "name": "feder", - "version": "0.1.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "feder", - "version": "0.1.0", - "license": "Apache-2.0", - "devDependencies": { - "ascjs": "^5.0.1", - "c8": "^7.11.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz", - "integrity": "sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ascjs": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ascjs/-/ascjs-5.0.1.tgz", - "integrity": "sha512-1d/QdICzpywXiP53/Zz3fMdaC0/BB1ybLf+fK+QrqY8iyXNnWUHUrpmrowueXeswo+O+meJWm43TJSg2ClP3Sg==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.12.5" - }, - "bin": { - "ascjs": "bin.js" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/c8": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.11.0.tgz", - "integrity": "sha512-XqPyj1uvlHMr+Y1IeRndC2X5P7iJzJlEJwBpCdBbq2JocXOgJfr+JVfJkyNMGROke5LfKrhSFXGFXnwnRJAUJw==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.2", - "find-up": "^5.0.0", - "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.0.1", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.0.2", - "rimraf": "^3.0.0", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^8.0.0", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.7" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.3.tgz", - "integrity": "sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@babel/parser": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz", - "integrity": "sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw==", - "dev": true - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "ascjs": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ascjs/-/ascjs-5.0.1.tgz", - "integrity": "sha512-1d/QdICzpywXiP53/Zz3fMdaC0/BB1ybLf+fK+QrqY8iyXNnWUHUrpmrowueXeswo+O+meJWm43TJSg2ClP3Sg==", - "dev": true, - "requires": { - "@babel/parser": "^7.12.5" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "c8": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.11.0.tgz", - "integrity": "sha512-XqPyj1uvlHMr+Y1IeRndC2X5P7iJzJlEJwBpCdBbq2JocXOgJfr+JVfJkyNMGROke5LfKrhSFXGFXnwnRJAUJw==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.2", - "find-up": "^5.0.0", - "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.0.1", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.0.2", - "rimraf": "^3.0.0", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^8.0.0", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.7" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - } - }, - "istanbul-reports": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.3.tgz", - "integrity": "sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/package.json b/package.json index 2fc47a4..82f34e0 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,23 @@ { - "name": "feder", + "name": "@zilliz/feder", "author": "ued@zilliz.com", - "version": "0.1.0", + "version": "0.2.4", "description": "visualization packages for vector space", - "main": "./cjs/index.js", + "main": "dist/index.js", + "files": [ + "dist" + ], "scripts": { - "build": "npm run cjs && npm run test", + "build": "esbuild federjs/index.js --format=esm --bundle --outdir=dist", + "build_iife_global": "esbuild federjs/index.js --format=iife --global-name=Feder --bundle --outfile=test/feder_iife_global.js", + "build_esm": "esbuild federjs/index.js --format=esm --bundle --outfile=test/feder_esm.js --watch", "cjs": "ascjs --no-default esm cjs", "test": "c8 node test/index.js", - "coverage": "mkdir -p ./coverage; c8 report --reporter=text-lcov > ./coverage/lcov.info" + "coverage": "mkdir -p ./coverage; c8 report --reporter=text-lcov > ./coverage/lcov.info", + "dev": "esbuild test/index.js --bundle --outfile=test/bundle.js --watch", + "dev_core_browser": "esbuild test/test_core_browser.js --bundle --outfile=test/bundle.js --watch", + "dev_core_node": "esbuild test/test_core_node.js --bundle --outfile=test/bundle.js --watch", + "publish_py": "cd federpy && rm -rf dist && python -m build && twine upload dist/*" }, "repository": { "type": "git", @@ -21,17 +30,14 @@ "hnsw" ], "devDependencies": { + "@zilliz/feder": "^0.2.4", "ascjs": "^5.0.1", - "c8": "^7.11.0" + "c8": "^7.11.2", + "esbuild": "^0.14.38" }, "exports": { ".": { - "import": "./esm/index.js", - "default": "./cjs/index.js" - }, - "./utils": { - "import": "./esm/utils.js", - "default": "./cjs/utils.js" + "import": "./dist/index.js" }, "./package.json": "./package.json" }, @@ -47,5 +53,20 @@ }, "module": "./esm/index.js", "type": "module", - "homepage": "https://github.com/zilliztech/feder#readme" + "homepage": "https://github.com/zilliztech/feder#readme", + "dependencies": { + "@types/animejs": "^3.1.5", + "@types/three": "^0.143.2", + "animejs": "^3.2.1", + "d3": "^7.4.4", + "d3-fetch": "^3.0.1", + "seedrandom": "^3.0.5", + "three": "^0.143.0", + "three.meshline": "^1.4.0", + "tsne-js": "^1.0.3", + "umap-js": "^1.3.3" + }, + "publishConfig": { + "access": "public" + } } diff --git a/test/bundle.js b/test/bundle.js new file mode 100644 index 0000000..53cf06c --- /dev/null +++ b/test/bundle.js @@ -0,0 +1,54262 @@ +(() => { + var __create = Object.create; + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __getProtoOf = Object.getPrototypeOf; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __require = /* @__PURE__ */ ((x2) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x2, { + get: (a2, b) => (typeof require !== "undefined" ? require : a2)[b] + }) : x2)(function(x2) { + if (typeof require !== "undefined") + return require.apply(this, arguments); + throw new Error('Dynamic require of "' + x2 + '" is not supported'); + }); + var __commonJS = (cb, mod) => function __require2() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); + var __async = (__this, __arguments, generator) => { + return new Promise((resolve, reject) => { + var fulfilled = (value) => { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + }; + var rejected = (value) => { + try { + step(generator.throw(value)); + } catch (e) { + reject(e); + } + }; + var step = (x2) => x2.done ? resolve(x2.value) : Promise.resolve(x2.value).then(fulfilled, rejected); + step((generator = generator.apply(__this, __arguments)).next()); + }); + }; + + // node_modules/three/build/three.cjs + var require_three = __commonJS({ + "node_modules/three/build/three.cjs"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var REVISION2 = "143"; + var MOUSE2 = { + LEFT: 0, + MIDDLE: 1, + RIGHT: 2, + ROTATE: 0, + DOLLY: 1, + PAN: 2 + }; + var TOUCH2 = { + ROTATE: 0, + PAN: 1, + DOLLY_PAN: 2, + DOLLY_ROTATE: 3 + }; + var CullFaceNone2 = 0; + var CullFaceBack2 = 1; + var CullFaceFront2 = 2; + var CullFaceFrontBack = 3; + var BasicShadowMap = 0; + var PCFShadowMap2 = 1; + var PCFSoftShadowMap2 = 2; + var VSMShadowMap2 = 3; + var FrontSide2 = 0; + var BackSide2 = 1; + var DoubleSide2 = 2; + var FlatShading2 = 1; + var SmoothShading = 2; + var NoBlending2 = 0; + var NormalBlending2 = 1; + var AdditiveBlending2 = 2; + var SubtractiveBlending2 = 3; + var MultiplyBlending2 = 4; + var CustomBlending2 = 5; + var AddEquation2 = 100; + var SubtractEquation2 = 101; + var ReverseSubtractEquation2 = 102; + var MinEquation2 = 103; + var MaxEquation2 = 104; + var ZeroFactor2 = 200; + var OneFactor2 = 201; + var SrcColorFactor2 = 202; + var OneMinusSrcColorFactor2 = 203; + var SrcAlphaFactor2 = 204; + var OneMinusSrcAlphaFactor2 = 205; + var DstAlphaFactor2 = 206; + var OneMinusDstAlphaFactor2 = 207; + var DstColorFactor2 = 208; + var OneMinusDstColorFactor2 = 209; + var SrcAlphaSaturateFactor2 = 210; + var NeverDepth2 = 0; + var AlwaysDepth2 = 1; + var LessDepth2 = 2; + var LessEqualDepth2 = 3; + var EqualDepth2 = 4; + var GreaterEqualDepth2 = 5; + var GreaterDepth2 = 6; + var NotEqualDepth2 = 7; + var MultiplyOperation2 = 0; + var MixOperation2 = 1; + var AddOperation2 = 2; + var NoToneMapping2 = 0; + var LinearToneMapping2 = 1; + var ReinhardToneMapping2 = 2; + var CineonToneMapping2 = 3; + var ACESFilmicToneMapping2 = 4; + var CustomToneMapping2 = 5; + var UVMapping2 = 300; + var CubeReflectionMapping2 = 301; + var CubeRefractionMapping2 = 302; + var EquirectangularReflectionMapping2 = 303; + var EquirectangularRefractionMapping2 = 304; + var CubeUVReflectionMapping2 = 306; + var RepeatWrapping2 = 1e3; + var ClampToEdgeWrapping2 = 1001; + var MirroredRepeatWrapping2 = 1002; + var NearestFilter2 = 1003; + var NearestMipmapNearestFilter2 = 1004; + var NearestMipMapNearestFilter = 1004; + var NearestMipmapLinearFilter2 = 1005; + var NearestMipMapLinearFilter = 1005; + var LinearFilter2 = 1006; + var LinearMipmapNearestFilter2 = 1007; + var LinearMipMapNearestFilter = 1007; + var LinearMipmapLinearFilter2 = 1008; + var LinearMipMapLinearFilter = 1008; + var UnsignedByteType2 = 1009; + var ByteType2 = 1010; + var ShortType2 = 1011; + var UnsignedShortType2 = 1012; + var IntType2 = 1013; + var UnsignedIntType2 = 1014; + var FloatType2 = 1015; + var HalfFloatType2 = 1016; + var UnsignedShort4444Type2 = 1017; + var UnsignedShort5551Type2 = 1018; + var UnsignedInt248Type2 = 1020; + var AlphaFormat2 = 1021; + var RGBFormat2 = 1022; + var RGBAFormat2 = 1023; + var LuminanceFormat2 = 1024; + var LuminanceAlphaFormat2 = 1025; + var DepthFormat2 = 1026; + var DepthStencilFormat2 = 1027; + var RedFormat2 = 1028; + var RedIntegerFormat2 = 1029; + var RGFormat2 = 1030; + var RGIntegerFormat2 = 1031; + var RGBAIntegerFormat2 = 1033; + var RGB_S3TC_DXT1_Format2 = 33776; + var RGBA_S3TC_DXT1_Format2 = 33777; + var RGBA_S3TC_DXT3_Format2 = 33778; + var RGBA_S3TC_DXT5_Format2 = 33779; + var RGB_PVRTC_4BPPV1_Format2 = 35840; + var RGB_PVRTC_2BPPV1_Format2 = 35841; + var RGBA_PVRTC_4BPPV1_Format2 = 35842; + var RGBA_PVRTC_2BPPV1_Format2 = 35843; + var RGB_ETC1_Format2 = 36196; + var RGB_ETC2_Format2 = 37492; + var RGBA_ETC2_EAC_Format2 = 37496; + var RGBA_ASTC_4x4_Format2 = 37808; + var RGBA_ASTC_5x4_Format2 = 37809; + var RGBA_ASTC_5x5_Format2 = 37810; + var RGBA_ASTC_6x5_Format2 = 37811; + var RGBA_ASTC_6x6_Format2 = 37812; + var RGBA_ASTC_8x5_Format2 = 37813; + var RGBA_ASTC_8x6_Format2 = 37814; + var RGBA_ASTC_8x8_Format2 = 37815; + var RGBA_ASTC_10x5_Format2 = 37816; + var RGBA_ASTC_10x6_Format2 = 37817; + var RGBA_ASTC_10x8_Format2 = 37818; + var RGBA_ASTC_10x10_Format2 = 37819; + var RGBA_ASTC_12x10_Format2 = 37820; + var RGBA_ASTC_12x12_Format2 = 37821; + var RGBA_BPTC_Format2 = 36492; + var LoopOnce = 2200; + var LoopRepeat = 2201; + var LoopPingPong = 2202; + var InterpolateDiscrete2 = 2300; + var InterpolateLinear2 = 2301; + var InterpolateSmooth2 = 2302; + var ZeroCurvatureEnding2 = 2400; + var ZeroSlopeEnding2 = 2401; + var WrapAroundEnding2 = 2402; + var NormalAnimationBlendMode = 2500; + var AdditiveAnimationBlendMode = 2501; + var TrianglesDrawMode = 0; + var TriangleStripDrawMode = 1; + var TriangleFanDrawMode = 2; + var LinearEncoding2 = 3e3; + var sRGBEncoding2 = 3001; + var BasicDepthPacking2 = 3200; + var RGBADepthPacking2 = 3201; + var TangentSpaceNormalMap2 = 0; + var ObjectSpaceNormalMap2 = 1; + var NoColorSpace = ""; + var SRGBColorSpace2 = "srgb"; + var LinearSRGBColorSpace2 = "srgb-linear"; + var ZeroStencilOp = 0; + var KeepStencilOp2 = 7680; + var ReplaceStencilOp = 7681; + var IncrementStencilOp = 7682; + var DecrementStencilOp = 7683; + var IncrementWrapStencilOp = 34055; + var DecrementWrapStencilOp = 34056; + var InvertStencilOp = 5386; + var NeverStencilFunc = 512; + var LessStencilFunc = 513; + var EqualStencilFunc = 514; + var LessEqualStencilFunc = 515; + var GreaterStencilFunc = 516; + var NotEqualStencilFunc = 517; + var GreaterEqualStencilFunc = 518; + var AlwaysStencilFunc2 = 519; + var StaticDrawUsage2 = 35044; + var DynamicDrawUsage = 35048; + var StreamDrawUsage = 35040; + var StaticReadUsage = 35045; + var DynamicReadUsage = 35049; + var StreamReadUsage = 35041; + var StaticCopyUsage = 35046; + var DynamicCopyUsage = 35050; + var StreamCopyUsage = 35042; + var GLSL1 = "100"; + var GLSL32 = "300 es"; + var _SRGBAFormat2 = 1035; + var EventDispatcher2 = class { + addEventListener(type2, listener) { + if (this._listeners === void 0) + this._listeners = {}; + const listeners = this._listeners; + if (listeners[type2] === void 0) { + listeners[type2] = []; + } + if (listeners[type2].indexOf(listener) === -1) { + listeners[type2].push(listener); + } + } + hasEventListener(type2, listener) { + if (this._listeners === void 0) + return false; + const listeners = this._listeners; + return listeners[type2] !== void 0 && listeners[type2].indexOf(listener) !== -1; + } + removeEventListener(type2, listener) { + if (this._listeners === void 0) + return; + const listeners = this._listeners; + const listenerArray = listeners[type2]; + if (listenerArray !== void 0) { + const index2 = listenerArray.indexOf(listener); + if (index2 !== -1) { + listenerArray.splice(index2, 1); + } + } + } + dispatchEvent(event) { + if (this._listeners === void 0) + return; + const listeners = this._listeners; + const listenerArray = listeners[event.type]; + if (listenerArray !== void 0) { + event.target = this; + const array2 = listenerArray.slice(0); + for (let i = 0, l = array2.length; i < l; i++) { + array2[i].call(this, event); + } + event.target = null; + } + } + }; + var _lut2 = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"]; + var _seed = 1234567; + var DEG2RAD2 = Math.PI / 180; + var RAD2DEG2 = 180 / Math.PI; + function generateUUID2() { + const d0 = Math.random() * 4294967295 | 0; + const d1 = Math.random() * 4294967295 | 0; + const d2 = Math.random() * 4294967295 | 0; + const d3 = Math.random() * 4294967295 | 0; + const uuid = _lut2[d0 & 255] + _lut2[d0 >> 8 & 255] + _lut2[d0 >> 16 & 255] + _lut2[d0 >> 24 & 255] + "-" + _lut2[d1 & 255] + _lut2[d1 >> 8 & 255] + "-" + _lut2[d1 >> 16 & 15 | 64] + _lut2[d1 >> 24 & 255] + "-" + _lut2[d2 & 63 | 128] + _lut2[d2 >> 8 & 255] + "-" + _lut2[d2 >> 16 & 255] + _lut2[d2 >> 24 & 255] + _lut2[d3 & 255] + _lut2[d3 >> 8 & 255] + _lut2[d3 >> 16 & 255] + _lut2[d3 >> 24 & 255]; + return uuid.toLowerCase(); + } + function clamp2(value, min2, max2) { + return Math.max(min2, Math.min(max2, value)); + } + function euclideanModulo2(n, m2) { + return (n % m2 + m2) % m2; + } + function mapLinear(x2, a1, a2, b1, b2) { + return b1 + (x2 - a1) * (b2 - b1) / (a2 - a1); + } + function inverseLerp(x2, y2, value) { + if (x2 !== y2) { + return (value - x2) / (y2 - x2); + } else { + return 0; + } + } + function lerp2(x2, y2, t) { + return (1 - t) * x2 + t * y2; + } + function damp(x2, y2, lambda, dt) { + return lerp2(x2, y2, 1 - Math.exp(-lambda * dt)); + } + function pingpong(x2, length = 1) { + return length - Math.abs(euclideanModulo2(x2, length * 2) - length); + } + function smoothstep(x2, min2, max2) { + if (x2 <= min2) + return 0; + if (x2 >= max2) + return 1; + x2 = (x2 - min2) / (max2 - min2); + return x2 * x2 * (3 - 2 * x2); + } + function smootherstep(x2, min2, max2) { + if (x2 <= min2) + return 0; + if (x2 >= max2) + return 1; + x2 = (x2 - min2) / (max2 - min2); + return x2 * x2 * x2 * (x2 * (x2 * 6 - 15) + 10); + } + function randInt(low, high) { + return low + Math.floor(Math.random() * (high - low + 1)); + } + function randFloat(low, high) { + return low + Math.random() * (high - low); + } + function randFloatSpread(range2) { + return range2 * (0.5 - Math.random()); + } + function seededRandom(s) { + if (s !== void 0) + _seed = s; + let t = _seed += 1831565813; + t = Math.imul(t ^ t >>> 15, t | 1); + t ^= t + Math.imul(t ^ t >>> 7, t | 61); + return ((t ^ t >>> 14) >>> 0) / 4294967296; + } + function degToRad(degrees2) { + return degrees2 * DEG2RAD2; + } + function radToDeg(radians) { + return radians * RAD2DEG2; + } + function isPowerOfTwo2(value) { + return (value & value - 1) === 0 && value !== 0; + } + function ceilPowerOfTwo(value) { + return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2)); + } + function floorPowerOfTwo2(value) { + return Math.pow(2, Math.floor(Math.log(value) / Math.LN2)); + } + function setQuaternionFromProperEuler(q, a2, b, c2, order) { + const cos = Math.cos; + const sin = Math.sin; + const c22 = cos(b / 2); + const s2 = sin(b / 2); + const c13 = cos((a2 + c2) / 2); + const s13 = sin((a2 + c2) / 2); + const c1_3 = cos((a2 - c2) / 2); + const s1_3 = sin((a2 - c2) / 2); + const c3_1 = cos((c2 - a2) / 2); + const s3_1 = sin((c2 - a2) / 2); + switch (order) { + case "XYX": + q.set(c22 * s13, s2 * c1_3, s2 * s1_3, c22 * c13); + break; + case "YZY": + q.set(s2 * s1_3, c22 * s13, s2 * c1_3, c22 * c13); + break; + case "ZXZ": + q.set(s2 * c1_3, s2 * s1_3, c22 * s13, c22 * c13); + break; + case "XZX": + q.set(c22 * s13, s2 * s3_1, s2 * c3_1, c22 * c13); + break; + case "YXY": + q.set(s2 * c3_1, c22 * s13, s2 * s3_1, c22 * c13); + break; + case "ZYZ": + q.set(s2 * s3_1, s2 * c3_1, c22 * s13, c22 * c13); + break; + default: + console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: " + order); + } + } + function denormalize$1(value, array2) { + switch (array2.constructor) { + case Float32Array: + return value; + case Uint16Array: + return value / 65535; + case Uint8Array: + return value / 255; + case Int16Array: + return Math.max(value / 32767, -1); + case Int8Array: + return Math.max(value / 127, -1); + default: + throw new Error("Invalid component type."); + } + } + function normalize2(value, array2) { + switch (array2.constructor) { + case Float32Array: + return value; + case Uint16Array: + return Math.round(value * 65535); + case Uint8Array: + return Math.round(value * 255); + case Int16Array: + return Math.round(value * 32767); + case Int8Array: + return Math.round(value * 127); + default: + throw new Error("Invalid component type."); + } + } + var MathUtils = /* @__PURE__ */ Object.freeze({ + __proto__: null, + DEG2RAD: DEG2RAD2, + RAD2DEG: RAD2DEG2, + generateUUID: generateUUID2, + clamp: clamp2, + euclideanModulo: euclideanModulo2, + mapLinear, + inverseLerp, + lerp: lerp2, + damp, + pingpong, + smoothstep, + smootherstep, + randInt, + randFloat, + randFloatSpread, + seededRandom, + degToRad, + radToDeg, + isPowerOfTwo: isPowerOfTwo2, + ceilPowerOfTwo, + floorPowerOfTwo: floorPowerOfTwo2, + setQuaternionFromProperEuler, + normalize: normalize2, + denormalize: denormalize$1 + }); + var Vector22 = class { + constructor(x2 = 0, y2 = 0) { + Vector22.prototype.isVector2 = true; + this.x = x2; + this.y = y2; + } + get width() { + return this.x; + } + set width(value) { + this.x = value; + } + get height() { + return this.y; + } + set height(value) { + this.y = value; + } + set(x2, y2) { + this.x = x2; + this.y = y2; + return this; + } + setScalar(scalar) { + this.x = scalar; + this.y = scalar; + return this; + } + setX(x2) { + this.x = x2; + return this; + } + setY(y2) { + this.y = y2; + return this; + } + setComponent(index2, value) { + switch (index2) { + case 0: + this.x = value; + break; + case 1: + this.y = value; + break; + default: + throw new Error("index is out of range: " + index2); + } + return this; + } + getComponent(index2) { + switch (index2) { + case 0: + return this.x; + case 1: + return this.y; + default: + throw new Error("index is out of range: " + index2); + } + } + clone() { + return new this.constructor(this.x, this.y); + } + copy(v) { + this.x = v.x; + this.y = v.y; + return this; + } + add(v) { + this.x += v.x; + this.y += v.y; + return this; + } + addScalar(s) { + this.x += s; + this.y += s; + return this; + } + addVectors(a2, b) { + this.x = a2.x + b.x; + this.y = a2.y + b.y; + return this; + } + addScaledVector(v, s) { + this.x += v.x * s; + this.y += v.y * s; + return this; + } + sub(v) { + this.x -= v.x; + this.y -= v.y; + return this; + } + subScalar(s) { + this.x -= s; + this.y -= s; + return this; + } + subVectors(a2, b) { + this.x = a2.x - b.x; + this.y = a2.y - b.y; + return this; + } + multiply(v) { + this.x *= v.x; + this.y *= v.y; + return this; + } + multiplyScalar(scalar) { + this.x *= scalar; + this.y *= scalar; + return this; + } + divide(v) { + this.x /= v.x; + this.y /= v.y; + return this; + } + divideScalar(scalar) { + return this.multiplyScalar(1 / scalar); + } + applyMatrix3(m2) { + const x2 = this.x, y2 = this.y; + const e = m2.elements; + this.x = e[0] * x2 + e[3] * y2 + e[6]; + this.y = e[1] * x2 + e[4] * y2 + e[7]; + return this; + } + min(v) { + this.x = Math.min(this.x, v.x); + this.y = Math.min(this.y, v.y); + return this; + } + max(v) { + this.x = Math.max(this.x, v.x); + this.y = Math.max(this.y, v.y); + return this; + } + clamp(min2, max2) { + this.x = Math.max(min2.x, Math.min(max2.x, this.x)); + this.y = Math.max(min2.y, Math.min(max2.y, this.y)); + return this; + } + clampScalar(minVal, maxVal) { + this.x = Math.max(minVal, Math.min(maxVal, this.x)); + this.y = Math.max(minVal, Math.min(maxVal, this.y)); + return this; + } + clampLength(min2, max2) { + const length = this.length(); + return this.divideScalar(length || 1).multiplyScalar(Math.max(min2, Math.min(max2, length))); + } + floor() { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + return this; + } + ceil() { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + return this; + } + round() { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + return this; + } + roundToZero() { + this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x); + this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y); + return this; + } + negate() { + this.x = -this.x; + this.y = -this.y; + return this; + } + dot(v) { + return this.x * v.x + this.y * v.y; + } + cross(v) { + return this.x * v.y - this.y * v.x; + } + lengthSq() { + return this.x * this.x + this.y * this.y; + } + length() { + return Math.sqrt(this.x * this.x + this.y * this.y); + } + manhattanLength() { + return Math.abs(this.x) + Math.abs(this.y); + } + normalize() { + return this.divideScalar(this.length() || 1); + } + angle() { + const angle = Math.atan2(-this.y, -this.x) + Math.PI; + return angle; + } + distanceTo(v) { + return Math.sqrt(this.distanceToSquared(v)); + } + distanceToSquared(v) { + const dx = this.x - v.x, dy = this.y - v.y; + return dx * dx + dy * dy; + } + manhattanDistanceTo(v) { + return Math.abs(this.x - v.x) + Math.abs(this.y - v.y); + } + setLength(length) { + return this.normalize().multiplyScalar(length); + } + lerp(v, alpha) { + this.x += (v.x - this.x) * alpha; + this.y += (v.y - this.y) * alpha; + return this; + } + lerpVectors(v1, v2, alpha) { + this.x = v1.x + (v2.x - v1.x) * alpha; + this.y = v1.y + (v2.y - v1.y) * alpha; + return this; + } + equals(v) { + return v.x === this.x && v.y === this.y; + } + fromArray(array2, offset = 0) { + this.x = array2[offset]; + this.y = array2[offset + 1]; + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this.x; + array2[offset + 1] = this.y; + return array2; + } + fromBufferAttribute(attribute, index2) { + this.x = attribute.getX(index2); + this.y = attribute.getY(index2); + return this; + } + rotateAround(center, angle) { + const c2 = Math.cos(angle), s = Math.sin(angle); + const x2 = this.x - center.x; + const y2 = this.y - center.y; + this.x = x2 * c2 - y2 * s + center.x; + this.y = x2 * s + y2 * c2 + center.y; + return this; + } + random() { + this.x = Math.random(); + this.y = Math.random(); + return this; + } + *[Symbol.iterator]() { + yield this.x; + yield this.y; + } + }; + var Matrix32 = class { + constructor() { + Matrix32.prototype.isMatrix3 = true; + this.elements = [1, 0, 0, 0, 1, 0, 0, 0, 1]; + } + set(n11, n12, n13, n21, n22, n23, n31, n32, n33) { + const te = this.elements; + te[0] = n11; + te[1] = n21; + te[2] = n31; + te[3] = n12; + te[4] = n22; + te[5] = n32; + te[6] = n13; + te[7] = n23; + te[8] = n33; + return this; + } + identity() { + this.set(1, 0, 0, 0, 1, 0, 0, 0, 1); + return this; + } + copy(m2) { + const te = this.elements; + const me = m2.elements; + te[0] = me[0]; + te[1] = me[1]; + te[2] = me[2]; + te[3] = me[3]; + te[4] = me[4]; + te[5] = me[5]; + te[6] = me[6]; + te[7] = me[7]; + te[8] = me[8]; + return this; + } + extractBasis(xAxis, yAxis, zAxis) { + xAxis.setFromMatrix3Column(this, 0); + yAxis.setFromMatrix3Column(this, 1); + zAxis.setFromMatrix3Column(this, 2); + return this; + } + setFromMatrix4(m2) { + const me = m2.elements; + this.set(me[0], me[4], me[8], me[1], me[5], me[9], me[2], me[6], me[10]); + return this; + } + multiply(m2) { + return this.multiplyMatrices(this, m2); + } + premultiply(m2) { + return this.multiplyMatrices(m2, this); + } + multiplyMatrices(a2, b) { + const ae = a2.elements; + const be = b.elements; + const te = this.elements; + const a11 = ae[0], a12 = ae[3], a13 = ae[6]; + const a21 = ae[1], a22 = ae[4], a23 = ae[7]; + const a31 = ae[2], a32 = ae[5], a33 = ae[8]; + const b11 = be[0], b12 = be[3], b13 = be[6]; + const b21 = be[1], b22 = be[4], b23 = be[7]; + const b31 = be[2], b32 = be[5], b33 = be[8]; + te[0] = a11 * b11 + a12 * b21 + a13 * b31; + te[3] = a11 * b12 + a12 * b22 + a13 * b32; + te[6] = a11 * b13 + a12 * b23 + a13 * b33; + te[1] = a21 * b11 + a22 * b21 + a23 * b31; + te[4] = a21 * b12 + a22 * b22 + a23 * b32; + te[7] = a21 * b13 + a22 * b23 + a23 * b33; + te[2] = a31 * b11 + a32 * b21 + a33 * b31; + te[5] = a31 * b12 + a32 * b22 + a33 * b32; + te[8] = a31 * b13 + a32 * b23 + a33 * b33; + return this; + } + multiplyScalar(s) { + const te = this.elements; + te[0] *= s; + te[3] *= s; + te[6] *= s; + te[1] *= s; + te[4] *= s; + te[7] *= s; + te[2] *= s; + te[5] *= s; + te[8] *= s; + return this; + } + determinant() { + const te = this.elements; + const a2 = te[0], b = te[1], c2 = te[2], d = te[3], e = te[4], f = te[5], g = te[6], h = te[7], i = te[8]; + return a2 * e * i - a2 * f * h - b * d * i + b * f * g + c2 * d * h - c2 * e * g; + } + invert() { + const te = this.elements, n11 = te[0], n21 = te[1], n31 = te[2], n12 = te[3], n22 = te[4], n32 = te[5], n13 = te[6], n23 = te[7], n33 = te[8], t11 = n33 * n22 - n32 * n23, t12 = n32 * n13 - n33 * n12, t13 = n23 * n12 - n22 * n13, det = n11 * t11 + n21 * t12 + n31 * t13; + if (det === 0) + return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0); + const detInv = 1 / det; + te[0] = t11 * detInv; + te[1] = (n31 * n23 - n33 * n21) * detInv; + te[2] = (n32 * n21 - n31 * n22) * detInv; + te[3] = t12 * detInv; + te[4] = (n33 * n11 - n31 * n13) * detInv; + te[5] = (n31 * n12 - n32 * n11) * detInv; + te[6] = t13 * detInv; + te[7] = (n21 * n13 - n23 * n11) * detInv; + te[8] = (n22 * n11 - n21 * n12) * detInv; + return this; + } + transpose() { + let tmp2; + const m2 = this.elements; + tmp2 = m2[1]; + m2[1] = m2[3]; + m2[3] = tmp2; + tmp2 = m2[2]; + m2[2] = m2[6]; + m2[6] = tmp2; + tmp2 = m2[5]; + m2[5] = m2[7]; + m2[7] = tmp2; + return this; + } + getNormalMatrix(matrix4) { + return this.setFromMatrix4(matrix4).invert().transpose(); + } + transposeIntoArray(r) { + const m2 = this.elements; + r[0] = m2[0]; + r[1] = m2[3]; + r[2] = m2[6]; + r[3] = m2[1]; + r[4] = m2[4]; + r[5] = m2[7]; + r[6] = m2[2]; + r[7] = m2[5]; + r[8] = m2[8]; + return this; + } + setUvTransform(tx, ty, sx, sy, rotation, cx, cy) { + const c2 = Math.cos(rotation); + const s = Math.sin(rotation); + this.set(sx * c2, sx * s, -sx * (c2 * cx + s * cy) + cx + tx, -sy * s, sy * c2, -sy * (-s * cx + c2 * cy) + cy + ty, 0, 0, 1); + return this; + } + scale(sx, sy) { + const te = this.elements; + te[0] *= sx; + te[3] *= sx; + te[6] *= sx; + te[1] *= sy; + te[4] *= sy; + te[7] *= sy; + return this; + } + rotate(theta) { + const c2 = Math.cos(theta); + const s = Math.sin(theta); + const te = this.elements; + const a11 = te[0], a12 = te[3], a13 = te[6]; + const a21 = te[1], a22 = te[4], a23 = te[7]; + te[0] = c2 * a11 + s * a21; + te[3] = c2 * a12 + s * a22; + te[6] = c2 * a13 + s * a23; + te[1] = -s * a11 + c2 * a21; + te[4] = -s * a12 + c2 * a22; + te[7] = -s * a13 + c2 * a23; + return this; + } + translate(tx, ty) { + const te = this.elements; + te[0] += tx * te[2]; + te[3] += tx * te[5]; + te[6] += tx * te[8]; + te[1] += ty * te[2]; + te[4] += ty * te[5]; + te[7] += ty * te[8]; + return this; + } + equals(matrix) { + const te = this.elements; + const me = matrix.elements; + for (let i = 0; i < 9; i++) { + if (te[i] !== me[i]) + return false; + } + return true; + } + fromArray(array2, offset = 0) { + for (let i = 0; i < 9; i++) { + this.elements[i] = array2[i + offset]; + } + return this; + } + toArray(array2 = [], offset = 0) { + const te = this.elements; + array2[offset] = te[0]; + array2[offset + 1] = te[1]; + array2[offset + 2] = te[2]; + array2[offset + 3] = te[3]; + array2[offset + 4] = te[4]; + array2[offset + 5] = te[5]; + array2[offset + 6] = te[6]; + array2[offset + 7] = te[7]; + array2[offset + 8] = te[8]; + return array2; + } + clone() { + return new this.constructor().fromArray(this.elements); + } + }; + function arrayNeedsUint322(array2) { + for (let i = array2.length - 1; i >= 0; --i) { + if (array2[i] > 65535) + return true; + } + return false; + } + var TYPED_ARRAYS = { + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array + }; + function getTypedArray(type2, buffer) { + return new TYPED_ARRAYS[type2](buffer); + } + function createElementNS2(name) { + return document.createElementNS("http://www.w3.org/1999/xhtml", name); + } + function SRGBToLinear2(c2) { + return c2 < 0.04045 ? c2 * 0.0773993808 : Math.pow(c2 * 0.9478672986 + 0.0521327014, 2.4); + } + function LinearToSRGB2(c2) { + return c2 < 31308e-7 ? c2 * 12.92 : 1.055 * Math.pow(c2, 0.41666) - 0.055; + } + var FN2 = { + [SRGBColorSpace2]: { + [LinearSRGBColorSpace2]: SRGBToLinear2 + }, + [LinearSRGBColorSpace2]: { + [SRGBColorSpace2]: LinearToSRGB2 + } + }; + var ColorManagement2 = { + legacyMode: true, + get workingColorSpace() { + return LinearSRGBColorSpace2; + }, + set workingColorSpace(colorSpace) { + console.warn("THREE.ColorManagement: .workingColorSpace is readonly."); + }, + convert: function(color2, sourceColorSpace, targetColorSpace) { + if (this.legacyMode || sourceColorSpace === targetColorSpace || !sourceColorSpace || !targetColorSpace) { + return color2; + } + if (FN2[sourceColorSpace] && FN2[sourceColorSpace][targetColorSpace] !== void 0) { + const fn = FN2[sourceColorSpace][targetColorSpace]; + color2.r = fn(color2.r); + color2.g = fn(color2.g); + color2.b = fn(color2.b); + return color2; + } + throw new Error("Unsupported color space conversion."); + }, + fromWorkingColorSpace: function(color2, targetColorSpace) { + return this.convert(color2, this.workingColorSpace, targetColorSpace); + }, + toWorkingColorSpace: function(color2, sourceColorSpace) { + return this.convert(color2, sourceColorSpace, this.workingColorSpace); + } + }; + var _colorKeywords2 = { + "aliceblue": 15792383, + "antiquewhite": 16444375, + "aqua": 65535, + "aquamarine": 8388564, + "azure": 15794175, + "beige": 16119260, + "bisque": 16770244, + "black": 0, + "blanchedalmond": 16772045, + "blue": 255, + "blueviolet": 9055202, + "brown": 10824234, + "burlywood": 14596231, + "cadetblue": 6266528, + "chartreuse": 8388352, + "chocolate": 13789470, + "coral": 16744272, + "cornflowerblue": 6591981, + "cornsilk": 16775388, + "crimson": 14423100, + "cyan": 65535, + "darkblue": 139, + "darkcyan": 35723, + "darkgoldenrod": 12092939, + "darkgray": 11119017, + "darkgreen": 25600, + "darkgrey": 11119017, + "darkkhaki": 12433259, + "darkmagenta": 9109643, + "darkolivegreen": 5597999, + "darkorange": 16747520, + "darkorchid": 10040012, + "darkred": 9109504, + "darksalmon": 15308410, + "darkseagreen": 9419919, + "darkslateblue": 4734347, + "darkslategray": 3100495, + "darkslategrey": 3100495, + "darkturquoise": 52945, + "darkviolet": 9699539, + "deeppink": 16716947, + "deepskyblue": 49151, + "dimgray": 6908265, + "dimgrey": 6908265, + "dodgerblue": 2003199, + "firebrick": 11674146, + "floralwhite": 16775920, + "forestgreen": 2263842, + "fuchsia": 16711935, + "gainsboro": 14474460, + "ghostwhite": 16316671, + "gold": 16766720, + "goldenrod": 14329120, + "gray": 8421504, + "green": 32768, + "greenyellow": 11403055, + "grey": 8421504, + "honeydew": 15794160, + "hotpink": 16738740, + "indianred": 13458524, + "indigo": 4915330, + "ivory": 16777200, + "khaki": 15787660, + "lavender": 15132410, + "lavenderblush": 16773365, + "lawngreen": 8190976, + "lemonchiffon": 16775885, + "lightblue": 11393254, + "lightcoral": 15761536, + "lightcyan": 14745599, + "lightgoldenrodyellow": 16448210, + "lightgray": 13882323, + "lightgreen": 9498256, + "lightgrey": 13882323, + "lightpink": 16758465, + "lightsalmon": 16752762, + "lightseagreen": 2142890, + "lightskyblue": 8900346, + "lightslategray": 7833753, + "lightslategrey": 7833753, + "lightsteelblue": 11584734, + "lightyellow": 16777184, + "lime": 65280, + "limegreen": 3329330, + "linen": 16445670, + "magenta": 16711935, + "maroon": 8388608, + "mediumaquamarine": 6737322, + "mediumblue": 205, + "mediumorchid": 12211667, + "mediumpurple": 9662683, + "mediumseagreen": 3978097, + "mediumslateblue": 8087790, + "mediumspringgreen": 64154, + "mediumturquoise": 4772300, + "mediumvioletred": 13047173, + "midnightblue": 1644912, + "mintcream": 16121850, + "mistyrose": 16770273, + "moccasin": 16770229, + "navajowhite": 16768685, + "navy": 128, + "oldlace": 16643558, + "olive": 8421376, + "olivedrab": 7048739, + "orange": 16753920, + "orangered": 16729344, + "orchid": 14315734, + "palegoldenrod": 15657130, + "palegreen": 10025880, + "paleturquoise": 11529966, + "palevioletred": 14381203, + "papayawhip": 16773077, + "peachpuff": 16767673, + "peru": 13468991, + "pink": 16761035, + "plum": 14524637, + "powderblue": 11591910, + "purple": 8388736, + "rebeccapurple": 6697881, + "red": 16711680, + "rosybrown": 12357519, + "royalblue": 4286945, + "saddlebrown": 9127187, + "salmon": 16416882, + "sandybrown": 16032864, + "seagreen": 3050327, + "seashell": 16774638, + "sienna": 10506797, + "silver": 12632256, + "skyblue": 8900331, + "slateblue": 6970061, + "slategray": 7372944, + "slategrey": 7372944, + "snow": 16775930, + "springgreen": 65407, + "steelblue": 4620980, + "tan": 13808780, + "teal": 32896, + "thistle": 14204888, + "tomato": 16737095, + "turquoise": 4251856, + "violet": 15631086, + "wheat": 16113331, + "white": 16777215, + "whitesmoke": 16119285, + "yellow": 16776960, + "yellowgreen": 10145074 + }; + var _rgb2 = { + r: 0, + g: 0, + b: 0 + }; + var _hslA2 = { + h: 0, + s: 0, + l: 0 + }; + var _hslB2 = { + h: 0, + s: 0, + l: 0 + }; + function hue2rgb2(p, q, t) { + if (t < 0) + t += 1; + if (t > 1) + t -= 1; + if (t < 1 / 6) + return p + (q - p) * 6 * t; + if (t < 1 / 2) + return q; + if (t < 2 / 3) + return p + (q - p) * 6 * (2 / 3 - t); + return p; + } + function toComponents2(source, target) { + target.r = source.r; + target.g = source.g; + target.b = source.b; + return target; + } + var Color3 = class { + constructor(r, g, b) { + this.isColor = true; + this.r = 1; + this.g = 1; + this.b = 1; + if (g === void 0 && b === void 0) { + return this.set(r); + } + return this.setRGB(r, g, b); + } + set(value) { + if (value && value.isColor) { + this.copy(value); + } else if (typeof value === "number") { + this.setHex(value); + } else if (typeof value === "string") { + this.setStyle(value); + } + return this; + } + setScalar(scalar) { + this.r = scalar; + this.g = scalar; + this.b = scalar; + return this; + } + setHex(hex2, colorSpace = SRGBColorSpace2) { + hex2 = Math.floor(hex2); + this.r = (hex2 >> 16 & 255) / 255; + this.g = (hex2 >> 8 & 255) / 255; + this.b = (hex2 & 255) / 255; + ColorManagement2.toWorkingColorSpace(this, colorSpace); + return this; + } + setRGB(r, g, b, colorSpace = LinearSRGBColorSpace2) { + this.r = r; + this.g = g; + this.b = b; + ColorManagement2.toWorkingColorSpace(this, colorSpace); + return this; + } + setHSL(h, s, l, colorSpace = LinearSRGBColorSpace2) { + h = euclideanModulo2(h, 1); + s = clamp2(s, 0, 1); + l = clamp2(l, 0, 1); + if (s === 0) { + this.r = this.g = this.b = l; + } else { + const p = l <= 0.5 ? l * (1 + s) : l + s - l * s; + const q = 2 * l - p; + this.r = hue2rgb2(q, p, h + 1 / 3); + this.g = hue2rgb2(q, p, h); + this.b = hue2rgb2(q, p, h - 1 / 3); + } + ColorManagement2.toWorkingColorSpace(this, colorSpace); + return this; + } + setStyle(style, colorSpace = SRGBColorSpace2) { + function handleAlpha(string) { + if (string === void 0) + return; + if (parseFloat(string) < 1) { + console.warn("THREE.Color: Alpha component of " + style + " will be ignored."); + } + } + let m2; + if (m2 = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(style)) { + let color2; + const name = m2[1]; + const components = m2[2]; + switch (name) { + case "rgb": + case "rgba": + if (color2 = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) { + this.r = Math.min(255, parseInt(color2[1], 10)) / 255; + this.g = Math.min(255, parseInt(color2[2], 10)) / 255; + this.b = Math.min(255, parseInt(color2[3], 10)) / 255; + ColorManagement2.toWorkingColorSpace(this, colorSpace); + handleAlpha(color2[4]); + return this; + } + if (color2 = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) { + this.r = Math.min(100, parseInt(color2[1], 10)) / 100; + this.g = Math.min(100, parseInt(color2[2], 10)) / 100; + this.b = Math.min(100, parseInt(color2[3], 10)) / 100; + ColorManagement2.toWorkingColorSpace(this, colorSpace); + handleAlpha(color2[4]); + return this; + } + break; + case "hsl": + case "hsla": + if (color2 = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) { + const h = parseFloat(color2[1]) / 360; + const s = parseInt(color2[2], 10) / 100; + const l = parseInt(color2[3], 10) / 100; + handleAlpha(color2[4]); + return this.setHSL(h, s, l, colorSpace); + } + break; + } + } else if (m2 = /^\#([A-Fa-f\d]+)$/.exec(style)) { + const hex2 = m2[1]; + const size = hex2.length; + if (size === 3) { + this.r = parseInt(hex2.charAt(0) + hex2.charAt(0), 16) / 255; + this.g = parseInt(hex2.charAt(1) + hex2.charAt(1), 16) / 255; + this.b = parseInt(hex2.charAt(2) + hex2.charAt(2), 16) / 255; + ColorManagement2.toWorkingColorSpace(this, colorSpace); + return this; + } else if (size === 6) { + this.r = parseInt(hex2.charAt(0) + hex2.charAt(1), 16) / 255; + this.g = parseInt(hex2.charAt(2) + hex2.charAt(3), 16) / 255; + this.b = parseInt(hex2.charAt(4) + hex2.charAt(5), 16) / 255; + ColorManagement2.toWorkingColorSpace(this, colorSpace); + return this; + } + } + if (style && style.length > 0) { + return this.setColorName(style, colorSpace); + } + return this; + } + setColorName(style, colorSpace = SRGBColorSpace2) { + const hex2 = _colorKeywords2[style.toLowerCase()]; + if (hex2 !== void 0) { + this.setHex(hex2, colorSpace); + } else { + console.warn("THREE.Color: Unknown color " + style); + } + return this; + } + clone() { + return new this.constructor(this.r, this.g, this.b); + } + copy(color2) { + this.r = color2.r; + this.g = color2.g; + this.b = color2.b; + return this; + } + copySRGBToLinear(color2) { + this.r = SRGBToLinear2(color2.r); + this.g = SRGBToLinear2(color2.g); + this.b = SRGBToLinear2(color2.b); + return this; + } + copyLinearToSRGB(color2) { + this.r = LinearToSRGB2(color2.r); + this.g = LinearToSRGB2(color2.g); + this.b = LinearToSRGB2(color2.b); + return this; + } + convertSRGBToLinear() { + this.copySRGBToLinear(this); + return this; + } + convertLinearToSRGB() { + this.copyLinearToSRGB(this); + return this; + } + getHex(colorSpace = SRGBColorSpace2) { + ColorManagement2.fromWorkingColorSpace(toComponents2(this, _rgb2), colorSpace); + return clamp2(_rgb2.r * 255, 0, 255) << 16 ^ clamp2(_rgb2.g * 255, 0, 255) << 8 ^ clamp2(_rgb2.b * 255, 0, 255) << 0; + } + getHexString(colorSpace = SRGBColorSpace2) { + return ("000000" + this.getHex(colorSpace).toString(16)).slice(-6); + } + getHSL(target, colorSpace = LinearSRGBColorSpace2) { + ColorManagement2.fromWorkingColorSpace(toComponents2(this, _rgb2), colorSpace); + const r = _rgb2.r, g = _rgb2.g, b = _rgb2.b; + const max2 = Math.max(r, g, b); + const min2 = Math.min(r, g, b); + let hue, saturation; + const lightness = (min2 + max2) / 2; + if (min2 === max2) { + hue = 0; + saturation = 0; + } else { + const delta = max2 - min2; + saturation = lightness <= 0.5 ? delta / (max2 + min2) : delta / (2 - max2 - min2); + switch (max2) { + case r: + hue = (g - b) / delta + (g < b ? 6 : 0); + break; + case g: + hue = (b - r) / delta + 2; + break; + case b: + hue = (r - g) / delta + 4; + break; + } + hue /= 6; + } + target.h = hue; + target.s = saturation; + target.l = lightness; + return target; + } + getRGB(target, colorSpace = LinearSRGBColorSpace2) { + ColorManagement2.fromWorkingColorSpace(toComponents2(this, _rgb2), colorSpace); + target.r = _rgb2.r; + target.g = _rgb2.g; + target.b = _rgb2.b; + return target; + } + getStyle(colorSpace = SRGBColorSpace2) { + ColorManagement2.fromWorkingColorSpace(toComponents2(this, _rgb2), colorSpace); + if (colorSpace !== SRGBColorSpace2) { + return `color(${colorSpace} ${_rgb2.r} ${_rgb2.g} ${_rgb2.b})`; + } + return `rgb(${_rgb2.r * 255 | 0},${_rgb2.g * 255 | 0},${_rgb2.b * 255 | 0})`; + } + offsetHSL(h, s, l) { + this.getHSL(_hslA2); + _hslA2.h += h; + _hslA2.s += s; + _hslA2.l += l; + this.setHSL(_hslA2.h, _hslA2.s, _hslA2.l); + return this; + } + add(color2) { + this.r += color2.r; + this.g += color2.g; + this.b += color2.b; + return this; + } + addColors(color1, color2) { + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; + return this; + } + addScalar(s) { + this.r += s; + this.g += s; + this.b += s; + return this; + } + sub(color2) { + this.r = Math.max(0, this.r - color2.r); + this.g = Math.max(0, this.g - color2.g); + this.b = Math.max(0, this.b - color2.b); + return this; + } + multiply(color2) { + this.r *= color2.r; + this.g *= color2.g; + this.b *= color2.b; + return this; + } + multiplyScalar(s) { + this.r *= s; + this.g *= s; + this.b *= s; + return this; + } + lerp(color2, alpha) { + this.r += (color2.r - this.r) * alpha; + this.g += (color2.g - this.g) * alpha; + this.b += (color2.b - this.b) * alpha; + return this; + } + lerpColors(color1, color2, alpha) { + this.r = color1.r + (color2.r - color1.r) * alpha; + this.g = color1.g + (color2.g - color1.g) * alpha; + this.b = color1.b + (color2.b - color1.b) * alpha; + return this; + } + lerpHSL(color2, alpha) { + this.getHSL(_hslA2); + color2.getHSL(_hslB2); + const h = lerp2(_hslA2.h, _hslB2.h, alpha); + const s = lerp2(_hslA2.s, _hslB2.s, alpha); + const l = lerp2(_hslA2.l, _hslB2.l, alpha); + this.setHSL(h, s, l); + return this; + } + equals(c2) { + return c2.r === this.r && c2.g === this.g && c2.b === this.b; + } + fromArray(array2, offset = 0) { + this.r = array2[offset]; + this.g = array2[offset + 1]; + this.b = array2[offset + 2]; + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this.r; + array2[offset + 1] = this.g; + array2[offset + 2] = this.b; + return array2; + } + fromBufferAttribute(attribute, index2) { + this.r = attribute.getX(index2); + this.g = attribute.getY(index2); + this.b = attribute.getZ(index2); + if (attribute.normalized === true) { + this.r /= 255; + this.g /= 255; + this.b /= 255; + } + return this; + } + toJSON() { + return this.getHex(); + } + *[Symbol.iterator]() { + yield this.r; + yield this.g; + yield this.b; + } + }; + Color3.NAMES = _colorKeywords2; + var _canvas2; + var ImageUtils2 = class { + static getDataURL(image) { + if (/^data:/i.test(image.src)) { + return image.src; + } + if (typeof HTMLCanvasElement == "undefined") { + return image.src; + } + let canvas; + if (image instanceof HTMLCanvasElement) { + canvas = image; + } else { + if (_canvas2 === void 0) + _canvas2 = createElementNS2("canvas"); + _canvas2.width = image.width; + _canvas2.height = image.height; + const context = _canvas2.getContext("2d"); + if (image instanceof ImageData) { + context.putImageData(image, 0, 0); + } else { + context.drawImage(image, 0, 0, image.width, image.height); + } + canvas = _canvas2; + } + if (canvas.width > 2048 || canvas.height > 2048) { + console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons", image); + return canvas.toDataURL("image/jpeg", 0.6); + } else { + return canvas.toDataURL("image/png"); + } + } + static sRGBToLinear(image) { + if (typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && image instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) { + const canvas = createElementNS2("canvas"); + canvas.width = image.width; + canvas.height = image.height; + const context = canvas.getContext("2d"); + context.drawImage(image, 0, 0, image.width, image.height); + const imageData = context.getImageData(0, 0, image.width, image.height); + const data = imageData.data; + for (let i = 0; i < data.length; i++) { + data[i] = SRGBToLinear2(data[i] / 255) * 255; + } + context.putImageData(imageData, 0, 0); + return canvas; + } else if (image.data) { + const data = image.data.slice(0); + for (let i = 0; i < data.length; i++) { + if (data instanceof Uint8Array || data instanceof Uint8ClampedArray) { + data[i] = Math.floor(SRGBToLinear2(data[i] / 255) * 255); + } else { + data[i] = SRGBToLinear2(data[i]); + } + } + return { + data, + width: image.width, + height: image.height + }; + } else { + console.warn("THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied."); + return image; + } + } + }; + var Source2 = class { + constructor(data = null) { + this.isSource = true; + this.uuid = generateUUID2(); + this.data = data; + this.version = 0; + } + set needsUpdate(value) { + if (value === true) + this.version++; + } + toJSON(meta) { + const isRootObject = meta === void 0 || typeof meta === "string"; + if (!isRootObject && meta.images[this.uuid] !== void 0) { + return meta.images[this.uuid]; + } + const output = { + uuid: this.uuid, + url: "" + }; + const data = this.data; + if (data !== null) { + let url; + if (Array.isArray(data)) { + url = []; + for (let i = 0, l = data.length; i < l; i++) { + if (data[i].isDataTexture) { + url.push(serializeImage2(data[i].image)); + } else { + url.push(serializeImage2(data[i])); + } + } + } else { + url = serializeImage2(data); + } + output.url = url; + } + if (!isRootObject) { + meta.images[this.uuid] = output; + } + return output; + } + }; + function serializeImage2(image) { + if (typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && image instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) { + return ImageUtils2.getDataURL(image); + } else { + if (image.data) { + return { + data: Array.from(image.data), + width: image.width, + height: image.height, + type: image.data.constructor.name + }; + } else { + console.warn("THREE.Texture: Unable to serialize Texture."); + return {}; + } + } + } + var textureId2 = 0; + var Texture2 = class extends EventDispatcher2 { + constructor(image = Texture2.DEFAULT_IMAGE, mapping = Texture2.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping2, wrapT = ClampToEdgeWrapping2, magFilter = LinearFilter2, minFilter = LinearMipmapLinearFilter2, format2 = RGBAFormat2, type2 = UnsignedByteType2, anisotropy = 1, encoding = LinearEncoding2) { + super(); + this.isTexture = true; + Object.defineProperty(this, "id", { + value: textureId2++ + }); + this.uuid = generateUUID2(); + this.name = ""; + this.source = new Source2(image); + this.mipmaps = []; + this.mapping = mapping; + this.wrapS = wrapS; + this.wrapT = wrapT; + this.magFilter = magFilter; + this.minFilter = minFilter; + this.anisotropy = anisotropy; + this.format = format2; + this.internalFormat = null; + this.type = type2; + this.offset = new Vector22(0, 0); + this.repeat = new Vector22(1, 1); + this.center = new Vector22(0, 0); + this.rotation = 0; + this.matrixAutoUpdate = true; + this.matrix = new Matrix32(); + this.generateMipmaps = true; + this.premultiplyAlpha = false; + this.flipY = true; + this.unpackAlignment = 4; + this.encoding = encoding; + this.userData = {}; + this.version = 0; + this.onUpdate = null; + this.isRenderTargetTexture = false; + this.needsPMREMUpdate = false; + } + get image() { + return this.source.data; + } + set image(value) { + this.source.data = value; + } + updateMatrix() { + this.matrix.setUvTransform(this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y); + } + clone() { + return new this.constructor().copy(this); + } + copy(source) { + this.name = source.name; + this.source = source.source; + this.mipmaps = source.mipmaps.slice(0); + this.mapping = source.mapping; + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; + this.anisotropy = source.anisotropy; + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; + this.offset.copy(source.offset); + this.repeat.copy(source.repeat); + this.center.copy(source.center); + this.rotation = source.rotation; + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrix.copy(source.matrix); + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.encoding = source.encoding; + this.userData = JSON.parse(JSON.stringify(source.userData)); + this.needsUpdate = true; + return this; + } + toJSON(meta) { + const isRootObject = meta === void 0 || typeof meta === "string"; + if (!isRootObject && meta.textures[this.uuid] !== void 0) { + return meta.textures[this.uuid]; + } + const output = { + metadata: { + version: 4.5, + type: "Texture", + generator: "Texture.toJSON" + }, + uuid: this.uuid, + name: this.name, + image: this.source.toJSON(meta).uuid, + mapping: this.mapping, + repeat: [this.repeat.x, this.repeat.y], + offset: [this.offset.x, this.offset.y], + center: [this.center.x, this.center.y], + rotation: this.rotation, + wrap: [this.wrapS, this.wrapT], + format: this.format, + type: this.type, + encoding: this.encoding, + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, + flipY: this.flipY, + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment + }; + if (JSON.stringify(this.userData) !== "{}") + output.userData = this.userData; + if (!isRootObject) { + meta.textures[this.uuid] = output; + } + return output; + } + dispose() { + this.dispatchEvent({ + type: "dispose" + }); + } + transformUv(uv) { + if (this.mapping !== UVMapping2) + return uv; + uv.applyMatrix3(this.matrix); + if (uv.x < 0 || uv.x > 1) { + switch (this.wrapS) { + case RepeatWrapping2: + uv.x = uv.x - Math.floor(uv.x); + break; + case ClampToEdgeWrapping2: + uv.x = uv.x < 0 ? 0 : 1; + break; + case MirroredRepeatWrapping2: + if (Math.abs(Math.floor(uv.x) % 2) === 1) { + uv.x = Math.ceil(uv.x) - uv.x; + } else { + uv.x = uv.x - Math.floor(uv.x); + } + break; + } + } + if (uv.y < 0 || uv.y > 1) { + switch (this.wrapT) { + case RepeatWrapping2: + uv.y = uv.y - Math.floor(uv.y); + break; + case ClampToEdgeWrapping2: + uv.y = uv.y < 0 ? 0 : 1; + break; + case MirroredRepeatWrapping2: + if (Math.abs(Math.floor(uv.y) % 2) === 1) { + uv.y = Math.ceil(uv.y) - uv.y; + } else { + uv.y = uv.y - Math.floor(uv.y); + } + break; + } + } + if (this.flipY) { + uv.y = 1 - uv.y; + } + return uv; + } + set needsUpdate(value) { + if (value === true) { + this.version++; + this.source.needsUpdate = true; + } + } + }; + Texture2.DEFAULT_IMAGE = null; + Texture2.DEFAULT_MAPPING = UVMapping2; + var Vector42 = class { + constructor(x2 = 0, y2 = 0, z = 0, w = 1) { + Vector42.prototype.isVector4 = true; + this.x = x2; + this.y = y2; + this.z = z; + this.w = w; + } + get width() { + return this.z; + } + set width(value) { + this.z = value; + } + get height() { + return this.w; + } + set height(value) { + this.w = value; + } + set(x2, y2, z, w) { + this.x = x2; + this.y = y2; + this.z = z; + this.w = w; + return this; + } + setScalar(scalar) { + this.x = scalar; + this.y = scalar; + this.z = scalar; + this.w = scalar; + return this; + } + setX(x2) { + this.x = x2; + return this; + } + setY(y2) { + this.y = y2; + return this; + } + setZ(z) { + this.z = z; + return this; + } + setW(w) { + this.w = w; + return this; + } + setComponent(index2, value) { + switch (index2) { + case 0: + this.x = value; + break; + case 1: + this.y = value; + break; + case 2: + this.z = value; + break; + case 3: + this.w = value; + break; + default: + throw new Error("index is out of range: " + index2); + } + return this; + } + getComponent(index2) { + switch (index2) { + case 0: + return this.x; + case 1: + return this.y; + case 2: + return this.z; + case 3: + return this.w; + default: + throw new Error("index is out of range: " + index2); + } + } + clone() { + return new this.constructor(this.x, this.y, this.z, this.w); + } + copy(v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + this.w = v.w !== void 0 ? v.w : 1; + return this; + } + add(v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + this.w += v.w; + return this; + } + addScalar(s) { + this.x += s; + this.y += s; + this.z += s; + this.w += s; + return this; + } + addVectors(a2, b) { + this.x = a2.x + b.x; + this.y = a2.y + b.y; + this.z = a2.z + b.z; + this.w = a2.w + b.w; + return this; + } + addScaledVector(v, s) { + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + this.w += v.w * s; + return this; + } + sub(v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; + return this; + } + subScalar(s) { + this.x -= s; + this.y -= s; + this.z -= s; + this.w -= s; + return this; + } + subVectors(a2, b) { + this.x = a2.x - b.x; + this.y = a2.y - b.y; + this.z = a2.z - b.z; + this.w = a2.w - b.w; + return this; + } + multiply(v) { + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + this.w *= v.w; + return this; + } + multiplyScalar(scalar) { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + this.w *= scalar; + return this; + } + applyMatrix4(m2) { + const x2 = this.x, y2 = this.y, z = this.z, w = this.w; + const e = m2.elements; + this.x = e[0] * x2 + e[4] * y2 + e[8] * z + e[12] * w; + this.y = e[1] * x2 + e[5] * y2 + e[9] * z + e[13] * w; + this.z = e[2] * x2 + e[6] * y2 + e[10] * z + e[14] * w; + this.w = e[3] * x2 + e[7] * y2 + e[11] * z + e[15] * w; + return this; + } + divideScalar(scalar) { + return this.multiplyScalar(1 / scalar); + } + setAxisAngleFromQuaternion(q) { + this.w = 2 * Math.acos(q.w); + const s = Math.sqrt(1 - q.w * q.w); + if (s < 1e-4) { + this.x = 1; + this.y = 0; + this.z = 0; + } else { + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; + } + return this; + } + setAxisAngleFromRotationMatrix(m2) { + let angle, x2, y2, z; + const epsilon = 0.01, epsilon2 = 0.1, te = m2.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10]; + if (Math.abs(m12 - m21) < epsilon && Math.abs(m13 - m31) < epsilon && Math.abs(m23 - m32) < epsilon) { + if (Math.abs(m12 + m21) < epsilon2 && Math.abs(m13 + m31) < epsilon2 && Math.abs(m23 + m32) < epsilon2 && Math.abs(m11 + m22 + m33 - 3) < epsilon2) { + this.set(1, 0, 0, 0); + return this; + } + angle = Math.PI; + const xx = (m11 + 1) / 2; + const yy = (m22 + 1) / 2; + const zz = (m33 + 1) / 2; + const xy = (m12 + m21) / 4; + const xz = (m13 + m31) / 4; + const yz = (m23 + m32) / 4; + if (xx > yy && xx > zz) { + if (xx < epsilon) { + x2 = 0; + y2 = 0.707106781; + z = 0.707106781; + } else { + x2 = Math.sqrt(xx); + y2 = xy / x2; + z = xz / x2; + } + } else if (yy > zz) { + if (yy < epsilon) { + x2 = 0.707106781; + y2 = 0; + z = 0.707106781; + } else { + y2 = Math.sqrt(yy); + x2 = xy / y2; + z = yz / y2; + } + } else { + if (zz < epsilon) { + x2 = 0.707106781; + y2 = 0.707106781; + z = 0; + } else { + z = Math.sqrt(zz); + x2 = xz / z; + y2 = yz / z; + } + } + this.set(x2, y2, z, angle); + return this; + } + let s = Math.sqrt((m32 - m23) * (m32 - m23) + (m13 - m31) * (m13 - m31) + (m21 - m12) * (m21 - m12)); + if (Math.abs(s) < 1e-3) + s = 1; + this.x = (m32 - m23) / s; + this.y = (m13 - m31) / s; + this.z = (m21 - m12) / s; + this.w = Math.acos((m11 + m22 + m33 - 1) / 2); + return this; + } + min(v) { + this.x = Math.min(this.x, v.x); + this.y = Math.min(this.y, v.y); + this.z = Math.min(this.z, v.z); + this.w = Math.min(this.w, v.w); + return this; + } + max(v) { + this.x = Math.max(this.x, v.x); + this.y = Math.max(this.y, v.y); + this.z = Math.max(this.z, v.z); + this.w = Math.max(this.w, v.w); + return this; + } + clamp(min2, max2) { + this.x = Math.max(min2.x, Math.min(max2.x, this.x)); + this.y = Math.max(min2.y, Math.min(max2.y, this.y)); + this.z = Math.max(min2.z, Math.min(max2.z, this.z)); + this.w = Math.max(min2.w, Math.min(max2.w, this.w)); + return this; + } + clampScalar(minVal, maxVal) { + this.x = Math.max(minVal, Math.min(maxVal, this.x)); + this.y = Math.max(minVal, Math.min(maxVal, this.y)); + this.z = Math.max(minVal, Math.min(maxVal, this.z)); + this.w = Math.max(minVal, Math.min(maxVal, this.w)); + return this; + } + clampLength(min2, max2) { + const length = this.length(); + return this.divideScalar(length || 1).multiplyScalar(Math.max(min2, Math.min(max2, length))); + } + floor() { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + this.w = Math.floor(this.w); + return this; + } + ceil() { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + this.z = Math.ceil(this.z); + this.w = Math.ceil(this.w); + return this; + } + round() { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + this.z = Math.round(this.z); + this.w = Math.round(this.w); + return this; + } + roundToZero() { + this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x); + this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y); + this.z = this.z < 0 ? Math.ceil(this.z) : Math.floor(this.z); + this.w = this.w < 0 ? Math.ceil(this.w) : Math.floor(this.w); + return this; + } + negate() { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + this.w = -this.w; + return this; + } + dot(v) { + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + } + lengthSq() { + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + } + length() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w); + } + manhattanLength() { + return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) + Math.abs(this.w); + } + normalize() { + return this.divideScalar(this.length() || 1); + } + setLength(length) { + return this.normalize().multiplyScalar(length); + } + lerp(v, alpha) { + this.x += (v.x - this.x) * alpha; + this.y += (v.y - this.y) * alpha; + this.z += (v.z - this.z) * alpha; + this.w += (v.w - this.w) * alpha; + return this; + } + lerpVectors(v1, v2, alpha) { + this.x = v1.x + (v2.x - v1.x) * alpha; + this.y = v1.y + (v2.y - v1.y) * alpha; + this.z = v1.z + (v2.z - v1.z) * alpha; + this.w = v1.w + (v2.w - v1.w) * alpha; + return this; + } + equals(v) { + return v.x === this.x && v.y === this.y && v.z === this.z && v.w === this.w; + } + fromArray(array2, offset = 0) { + this.x = array2[offset]; + this.y = array2[offset + 1]; + this.z = array2[offset + 2]; + this.w = array2[offset + 3]; + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this.x; + array2[offset + 1] = this.y; + array2[offset + 2] = this.z; + array2[offset + 3] = this.w; + return array2; + } + fromBufferAttribute(attribute, index2) { + this.x = attribute.getX(index2); + this.y = attribute.getY(index2); + this.z = attribute.getZ(index2); + this.w = attribute.getW(index2); + return this; + } + random() { + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + this.w = Math.random(); + return this; + } + *[Symbol.iterator]() { + yield this.x; + yield this.y; + yield this.z; + yield this.w; + } + }; + var WebGLRenderTarget2 = class extends EventDispatcher2 { + constructor(width, height, options = {}) { + super(); + this.isWebGLRenderTarget = true; + this.width = width; + this.height = height; + this.depth = 1; + this.scissor = new Vector42(0, 0, width, height); + this.scissorTest = false; + this.viewport = new Vector42(0, 0, width, height); + const image = { + width, + height, + depth: 1 + }; + this.texture = new Texture2(image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding); + this.texture.isRenderTargetTexture = true; + this.texture.flipY = false; + this.texture.generateMipmaps = options.generateMipmaps !== void 0 ? options.generateMipmaps : false; + this.texture.internalFormat = options.internalFormat !== void 0 ? options.internalFormat : null; + this.texture.minFilter = options.minFilter !== void 0 ? options.minFilter : LinearFilter2; + this.depthBuffer = options.depthBuffer !== void 0 ? options.depthBuffer : true; + this.stencilBuffer = options.stencilBuffer !== void 0 ? options.stencilBuffer : false; + this.depthTexture = options.depthTexture !== void 0 ? options.depthTexture : null; + this.samples = options.samples !== void 0 ? options.samples : 0; + } + setSize(width, height, depth = 1) { + if (this.width !== width || this.height !== height || this.depth !== depth) { + this.width = width; + this.height = height; + this.depth = depth; + this.texture.image.width = width; + this.texture.image.height = height; + this.texture.image.depth = depth; + this.dispose(); + } + this.viewport.set(0, 0, width, height); + this.scissor.set(0, 0, width, height); + } + clone() { + return new this.constructor().copy(this); + } + copy(source) { + this.width = source.width; + this.height = source.height; + this.depth = source.depth; + this.viewport.copy(source.viewport); + this.texture = source.texture.clone(); + this.texture.isRenderTargetTexture = true; + const image = Object.assign({}, source.texture.image); + this.texture.source = new Source2(image); + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; + if (source.depthTexture !== null) + this.depthTexture = source.depthTexture.clone(); + this.samples = source.samples; + return this; + } + dispose() { + this.dispatchEvent({ + type: "dispose" + }); + } + }; + var DataArrayTexture2 = class extends Texture2 { + constructor(data = null, width = 1, height = 1, depth = 1) { + super(null); + this.isDataArrayTexture = true; + this.image = { + data, + width, + height, + depth + }; + this.magFilter = NearestFilter2; + this.minFilter = NearestFilter2; + this.wrapR = ClampToEdgeWrapping2; + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; + } + }; + var WebGLArrayRenderTarget = class extends WebGLRenderTarget2 { + constructor(width, height, depth) { + super(width, height); + this.isWebGLArrayRenderTarget = true; + this.depth = depth; + this.texture = new DataArrayTexture2(null, width, height, depth); + this.texture.isRenderTargetTexture = true; + } + }; + var Data3DTexture2 = class extends Texture2 { + constructor(data = null, width = 1, height = 1, depth = 1) { + super(null); + this.isData3DTexture = true; + this.image = { + data, + width, + height, + depth + }; + this.magFilter = NearestFilter2; + this.minFilter = NearestFilter2; + this.wrapR = ClampToEdgeWrapping2; + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; + } + }; + var WebGL3DRenderTarget = class extends WebGLRenderTarget2 { + constructor(width, height, depth) { + super(width, height); + this.isWebGL3DRenderTarget = true; + this.depth = depth; + this.texture = new Data3DTexture2(null, width, height, depth); + this.texture.isRenderTargetTexture = true; + } + }; + var WebGLMultipleRenderTargets = class extends WebGLRenderTarget2 { + constructor(width, height, count, options = {}) { + super(width, height, options); + this.isWebGLMultipleRenderTargets = true; + const texture = this.texture; + this.texture = []; + for (let i = 0; i < count; i++) { + this.texture[i] = texture.clone(); + this.texture[i].isRenderTargetTexture = true; + } + } + setSize(width, height, depth = 1) { + if (this.width !== width || this.height !== height || this.depth !== depth) { + this.width = width; + this.height = height; + this.depth = depth; + for (let i = 0, il = this.texture.length; i < il; i++) { + this.texture[i].image.width = width; + this.texture[i].image.height = height; + this.texture[i].image.depth = depth; + } + this.dispose(); + } + this.viewport.set(0, 0, width, height); + this.scissor.set(0, 0, width, height); + return this; + } + copy(source) { + this.dispose(); + this.width = source.width; + this.height = source.height; + this.depth = source.depth; + this.viewport.set(0, 0, this.width, this.height); + this.scissor.set(0, 0, this.width, this.height); + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; + if (source.depthTexture !== null) + this.depthTexture = source.depthTexture.clone(); + this.texture.length = 0; + for (let i = 0, il = source.texture.length; i < il; i++) { + this.texture[i] = source.texture[i].clone(); + this.texture[i].isRenderTargetTexture = true; + } + return this; + } + }; + var Quaternion2 = class { + constructor(x2 = 0, y2 = 0, z = 0, w = 1) { + this.isQuaternion = true; + this._x = x2; + this._y = y2; + this._z = z; + this._w = w; + } + static slerpFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t) { + let x0 = src0[srcOffset0 + 0], y0 = src0[srcOffset0 + 1], z0 = src0[srcOffset0 + 2], w0 = src0[srcOffset0 + 3]; + const x1 = src1[srcOffset1 + 0], y1 = src1[srcOffset1 + 1], z1 = src1[srcOffset1 + 2], w1 = src1[srcOffset1 + 3]; + if (t === 0) { + dst[dstOffset + 0] = x0; + dst[dstOffset + 1] = y0; + dst[dstOffset + 2] = z0; + dst[dstOffset + 3] = w0; + return; + } + if (t === 1) { + dst[dstOffset + 0] = x1; + dst[dstOffset + 1] = y1; + dst[dstOffset + 2] = z1; + dst[dstOffset + 3] = w1; + return; + } + if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) { + let s = 1 - t; + const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, dir = cos >= 0 ? 1 : -1, sqrSin = 1 - cos * cos; + if (sqrSin > Number.EPSILON) { + const sin = Math.sqrt(sqrSin), len = Math.atan2(sin, cos * dir); + s = Math.sin(s * len) / sin; + t = Math.sin(t * len) / sin; + } + const tDir = t * dir; + x0 = x0 * s + x1 * tDir; + y0 = y0 * s + y1 * tDir; + z0 = z0 * s + z1 * tDir; + w0 = w0 * s + w1 * tDir; + if (s === 1 - t) { + const f = 1 / Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0); + x0 *= f; + y0 *= f; + z0 *= f; + w0 *= f; + } + } + dst[dstOffset] = x0; + dst[dstOffset + 1] = y0; + dst[dstOffset + 2] = z0; + dst[dstOffset + 3] = w0; + } + static multiplyQuaternionsFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1) { + const x0 = src0[srcOffset0]; + const y0 = src0[srcOffset0 + 1]; + const z0 = src0[srcOffset0 + 2]; + const w0 = src0[srcOffset0 + 3]; + const x1 = src1[srcOffset1]; + const y1 = src1[srcOffset1 + 1]; + const z1 = src1[srcOffset1 + 2]; + const w1 = src1[srcOffset1 + 3]; + dst[dstOffset] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; + dst[dstOffset + 1] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; + dst[dstOffset + 2] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; + dst[dstOffset + 3] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; + return dst; + } + get x() { + return this._x; + } + set x(value) { + this._x = value; + this._onChangeCallback(); + } + get y() { + return this._y; + } + set y(value) { + this._y = value; + this._onChangeCallback(); + } + get z() { + return this._z; + } + set z(value) { + this._z = value; + this._onChangeCallback(); + } + get w() { + return this._w; + } + set w(value) { + this._w = value; + this._onChangeCallback(); + } + set(x2, y2, z, w) { + this._x = x2; + this._y = y2; + this._z = z; + this._w = w; + this._onChangeCallback(); + return this; + } + clone() { + return new this.constructor(this._x, this._y, this._z, this._w); + } + copy(quaternion) { + this._x = quaternion.x; + this._y = quaternion.y; + this._z = quaternion.z; + this._w = quaternion.w; + this._onChangeCallback(); + return this; + } + setFromEuler(euler, update) { + if (!(euler && euler.isEuler)) { + throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order."); + } + const x2 = euler._x, y2 = euler._y, z = euler._z, order = euler._order; + const cos = Math.cos; + const sin = Math.sin; + const c1 = cos(x2 / 2); + const c2 = cos(y2 / 2); + const c3 = cos(z / 2); + const s1 = sin(x2 / 2); + const s2 = sin(y2 / 2); + const s3 = sin(z / 2); + switch (order) { + case "XYZ": + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; + case "YXZ": + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; + case "ZXY": + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; + case "ZYX": + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; + case "YZX": + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; + case "XZY": + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; + default: + console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: " + order); + } + if (update !== false) + this._onChangeCallback(); + return this; + } + setFromAxisAngle(axis, angle) { + const halfAngle = angle / 2, s = Math.sin(halfAngle); + this._x = axis.x * s; + this._y = axis.y * s; + this._z = axis.z * s; + this._w = Math.cos(halfAngle); + this._onChangeCallback(); + return this; + } + setFromRotationMatrix(m2) { + const te = m2.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10], trace = m11 + m22 + m33; + if (trace > 0) { + const s = 0.5 / Math.sqrt(trace + 1); + this._w = 0.25 / s; + this._x = (m32 - m23) * s; + this._y = (m13 - m31) * s; + this._z = (m21 - m12) * s; + } else if (m11 > m22 && m11 > m33) { + const s = 2 * Math.sqrt(1 + m11 - m22 - m33); + this._w = (m32 - m23) / s; + this._x = 0.25 * s; + this._y = (m12 + m21) / s; + this._z = (m13 + m31) / s; + } else if (m22 > m33) { + const s = 2 * Math.sqrt(1 + m22 - m11 - m33); + this._w = (m13 - m31) / s; + this._x = (m12 + m21) / s; + this._y = 0.25 * s; + this._z = (m23 + m32) / s; + } else { + const s = 2 * Math.sqrt(1 + m33 - m11 - m22); + this._w = (m21 - m12) / s; + this._x = (m13 + m31) / s; + this._y = (m23 + m32) / s; + this._z = 0.25 * s; + } + this._onChangeCallback(); + return this; + } + setFromUnitVectors(vFrom, vTo) { + let r = vFrom.dot(vTo) + 1; + if (r < Number.EPSILON) { + r = 0; + if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) { + this._x = -vFrom.y; + this._y = vFrom.x; + this._z = 0; + this._w = r; + } else { + this._x = 0; + this._y = -vFrom.z; + this._z = vFrom.y; + this._w = r; + } + } else { + this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; + this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; + this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; + this._w = r; + } + return this.normalize(); + } + angleTo(q) { + return 2 * Math.acos(Math.abs(clamp2(this.dot(q), -1, 1))); + } + rotateTowards(q, step) { + const angle = this.angleTo(q); + if (angle === 0) + return this; + const t = Math.min(1, step / angle); + this.slerp(q, t); + return this; + } + identity() { + return this.set(0, 0, 0, 1); + } + invert() { + return this.conjugate(); + } + conjugate() { + this._x *= -1; + this._y *= -1; + this._z *= -1; + this._onChangeCallback(); + return this; + } + dot(v) { + return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; + } + lengthSq() { + return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; + } + length() { + return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w); + } + normalize() { + let l = this.length(); + if (l === 0) { + this._x = 0; + this._y = 0; + this._z = 0; + this._w = 1; + } else { + l = 1 / l; + this._x = this._x * l; + this._y = this._y * l; + this._z = this._z * l; + this._w = this._w * l; + } + this._onChangeCallback(); + return this; + } + multiply(q) { + return this.multiplyQuaternions(this, q); + } + premultiply(q) { + return this.multiplyQuaternions(q, this); + } + multiplyQuaternions(a2, b) { + const qax = a2._x, qay = a2._y, qaz = a2._z, qaw = a2._w; + const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; + this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; + this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; + this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; + this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; + this._onChangeCallback(); + return this; + } + slerp(qb, t) { + if (t === 0) + return this; + if (t === 1) + return this.copy(qb); + const x2 = this._x, y2 = this._y, z = this._z, w = this._w; + let cosHalfTheta = w * qb._w + x2 * qb._x + y2 * qb._y + z * qb._z; + if (cosHalfTheta < 0) { + this._w = -qb._w; + this._x = -qb._x; + this._y = -qb._y; + this._z = -qb._z; + cosHalfTheta = -cosHalfTheta; + } else { + this.copy(qb); + } + if (cosHalfTheta >= 1) { + this._w = w; + this._x = x2; + this._y = y2; + this._z = z; + return this; + } + const sqrSinHalfTheta = 1 - cosHalfTheta * cosHalfTheta; + if (sqrSinHalfTheta <= Number.EPSILON) { + const s = 1 - t; + this._w = s * w + t * this._w; + this._x = s * x2 + t * this._x; + this._y = s * y2 + t * this._y; + this._z = s * z + t * this._z; + this.normalize(); + this._onChangeCallback(); + return this; + } + const sinHalfTheta = Math.sqrt(sqrSinHalfTheta); + const halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta); + const ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta, ratioB = Math.sin(t * halfTheta) / sinHalfTheta; + this._w = w * ratioA + this._w * ratioB; + this._x = x2 * ratioA + this._x * ratioB; + this._y = y2 * ratioA + this._y * ratioB; + this._z = z * ratioA + this._z * ratioB; + this._onChangeCallback(); + return this; + } + slerpQuaternions(qa, qb, t) { + return this.copy(qa).slerp(qb, t); + } + random() { + const u1 = Math.random(); + const sqrt1u1 = Math.sqrt(1 - u1); + const sqrtu1 = Math.sqrt(u1); + const u2 = 2 * Math.PI * Math.random(); + const u3 = 2 * Math.PI * Math.random(); + return this.set(sqrt1u1 * Math.cos(u2), sqrtu1 * Math.sin(u3), sqrtu1 * Math.cos(u3), sqrt1u1 * Math.sin(u2)); + } + equals(quaternion) { + return quaternion._x === this._x && quaternion._y === this._y && quaternion._z === this._z && quaternion._w === this._w; + } + fromArray(array2, offset = 0) { + this._x = array2[offset]; + this._y = array2[offset + 1]; + this._z = array2[offset + 2]; + this._w = array2[offset + 3]; + this._onChangeCallback(); + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this._x; + array2[offset + 1] = this._y; + array2[offset + 2] = this._z; + array2[offset + 3] = this._w; + return array2; + } + fromBufferAttribute(attribute, index2) { + this._x = attribute.getX(index2); + this._y = attribute.getY(index2); + this._z = attribute.getZ(index2); + this._w = attribute.getW(index2); + return this; + } + _onChange(callback) { + this._onChangeCallback = callback; + return this; + } + _onChangeCallback() { + } + *[Symbol.iterator]() { + yield this._x; + yield this._y; + yield this._z; + yield this._w; + } + }; + var Vector32 = class { + constructor(x2 = 0, y2 = 0, z = 0) { + Vector32.prototype.isVector3 = true; + this.x = x2; + this.y = y2; + this.z = z; + } + set(x2, y2, z) { + if (z === void 0) + z = this.z; + this.x = x2; + this.y = y2; + this.z = z; + return this; + } + setScalar(scalar) { + this.x = scalar; + this.y = scalar; + this.z = scalar; + return this; + } + setX(x2) { + this.x = x2; + return this; + } + setY(y2) { + this.y = y2; + return this; + } + setZ(z) { + this.z = z; + return this; + } + setComponent(index2, value) { + switch (index2) { + case 0: + this.x = value; + break; + case 1: + this.y = value; + break; + case 2: + this.z = value; + break; + default: + throw new Error("index is out of range: " + index2); + } + return this; + } + getComponent(index2) { + switch (index2) { + case 0: + return this.x; + case 1: + return this.y; + case 2: + return this.z; + default: + throw new Error("index is out of range: " + index2); + } + } + clone() { + return new this.constructor(this.x, this.y, this.z); + } + copy(v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + return this; + } + add(v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; + } + addScalar(s) { + this.x += s; + this.y += s; + this.z += s; + return this; + } + addVectors(a2, b) { + this.x = a2.x + b.x; + this.y = a2.y + b.y; + this.z = a2.z + b.z; + return this; + } + addScaledVector(v, s) { + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + return this; + } + sub(v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + return this; + } + subScalar(s) { + this.x -= s; + this.y -= s; + this.z -= s; + return this; + } + subVectors(a2, b) { + this.x = a2.x - b.x; + this.y = a2.y - b.y; + this.z = a2.z - b.z; + return this; + } + multiply(v) { + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + return this; + } + multiplyScalar(scalar) { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + return this; + } + multiplyVectors(a2, b) { + this.x = a2.x * b.x; + this.y = a2.y * b.y; + this.z = a2.z * b.z; + return this; + } + applyEuler(euler) { + return this.applyQuaternion(_quaternion$42.setFromEuler(euler)); + } + applyAxisAngle(axis, angle) { + return this.applyQuaternion(_quaternion$42.setFromAxisAngle(axis, angle)); + } + applyMatrix3(m2) { + const x2 = this.x, y2 = this.y, z = this.z; + const e = m2.elements; + this.x = e[0] * x2 + e[3] * y2 + e[6] * z; + this.y = e[1] * x2 + e[4] * y2 + e[7] * z; + this.z = e[2] * x2 + e[5] * y2 + e[8] * z; + return this; + } + applyNormalMatrix(m2) { + return this.applyMatrix3(m2).normalize(); + } + applyMatrix4(m2) { + const x2 = this.x, y2 = this.y, z = this.z; + const e = m2.elements; + const w = 1 / (e[3] * x2 + e[7] * y2 + e[11] * z + e[15]); + this.x = (e[0] * x2 + e[4] * y2 + e[8] * z + e[12]) * w; + this.y = (e[1] * x2 + e[5] * y2 + e[9] * z + e[13]) * w; + this.z = (e[2] * x2 + e[6] * y2 + e[10] * z + e[14]) * w; + return this; + } + applyQuaternion(q) { + const x2 = this.x, y2 = this.y, z = this.z; + const qx = q.x, qy = q.y, qz = q.z, qw = q.w; + const ix = qw * x2 + qy * z - qz * y2; + const iy = qw * y2 + qz * x2 - qx * z; + const iz = qw * z + qx * y2 - qy * x2; + const iw = -qx * x2 - qy * y2 - qz * z; + this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; + this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; + this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; + return this; + } + project(camera) { + return this.applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix); + } + unproject(camera) { + return this.applyMatrix4(camera.projectionMatrixInverse).applyMatrix4(camera.matrixWorld); + } + transformDirection(m2) { + const x2 = this.x, y2 = this.y, z = this.z; + const e = m2.elements; + this.x = e[0] * x2 + e[4] * y2 + e[8] * z; + this.y = e[1] * x2 + e[5] * y2 + e[9] * z; + this.z = e[2] * x2 + e[6] * y2 + e[10] * z; + return this.normalize(); + } + divide(v) { + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; + return this; + } + divideScalar(scalar) { + return this.multiplyScalar(1 / scalar); + } + min(v) { + this.x = Math.min(this.x, v.x); + this.y = Math.min(this.y, v.y); + this.z = Math.min(this.z, v.z); + return this; + } + max(v) { + this.x = Math.max(this.x, v.x); + this.y = Math.max(this.y, v.y); + this.z = Math.max(this.z, v.z); + return this; + } + clamp(min2, max2) { + this.x = Math.max(min2.x, Math.min(max2.x, this.x)); + this.y = Math.max(min2.y, Math.min(max2.y, this.y)); + this.z = Math.max(min2.z, Math.min(max2.z, this.z)); + return this; + } + clampScalar(minVal, maxVal) { + this.x = Math.max(minVal, Math.min(maxVal, this.x)); + this.y = Math.max(minVal, Math.min(maxVal, this.y)); + this.z = Math.max(minVal, Math.min(maxVal, this.z)); + return this; + } + clampLength(min2, max2) { + const length = this.length(); + return this.divideScalar(length || 1).multiplyScalar(Math.max(min2, Math.min(max2, length))); + } + floor() { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + return this; + } + ceil() { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + this.z = Math.ceil(this.z); + return this; + } + round() { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + this.z = Math.round(this.z); + return this; + } + roundToZero() { + this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x); + this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y); + this.z = this.z < 0 ? Math.ceil(this.z) : Math.floor(this.z); + return this; + } + negate() { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + return this; + } + dot(v) { + return this.x * v.x + this.y * v.y + this.z * v.z; + } + lengthSq() { + return this.x * this.x + this.y * this.y + this.z * this.z; + } + length() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + } + manhattanLength() { + return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z); + } + normalize() { + return this.divideScalar(this.length() || 1); + } + setLength(length) { + return this.normalize().multiplyScalar(length); + } + lerp(v, alpha) { + this.x += (v.x - this.x) * alpha; + this.y += (v.y - this.y) * alpha; + this.z += (v.z - this.z) * alpha; + return this; + } + lerpVectors(v1, v2, alpha) { + this.x = v1.x + (v2.x - v1.x) * alpha; + this.y = v1.y + (v2.y - v1.y) * alpha; + this.z = v1.z + (v2.z - v1.z) * alpha; + return this; + } + cross(v) { + return this.crossVectors(this, v); + } + crossVectors(a2, b) { + const ax = a2.x, ay = a2.y, az = a2.z; + const bx = b.x, by = b.y, bz = b.z; + this.x = ay * bz - az * by; + this.y = az * bx - ax * bz; + this.z = ax * by - ay * bx; + return this; + } + projectOnVector(v) { + const denominator = v.lengthSq(); + if (denominator === 0) + return this.set(0, 0, 0); + const scalar = v.dot(this) / denominator; + return this.copy(v).multiplyScalar(scalar); + } + projectOnPlane(planeNormal) { + _vector$c2.copy(this).projectOnVector(planeNormal); + return this.sub(_vector$c2); + } + reflect(normal) { + return this.sub(_vector$c2.copy(normal).multiplyScalar(2 * this.dot(normal))); + } + angleTo(v) { + const denominator = Math.sqrt(this.lengthSq() * v.lengthSq()); + if (denominator === 0) + return Math.PI / 2; + const theta = this.dot(v) / denominator; + return Math.acos(clamp2(theta, -1, 1)); + } + distanceTo(v) { + return Math.sqrt(this.distanceToSquared(v)); + } + distanceToSquared(v) { + const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; + return dx * dx + dy * dy + dz * dz; + } + manhattanDistanceTo(v) { + return Math.abs(this.x - v.x) + Math.abs(this.y - v.y) + Math.abs(this.z - v.z); + } + setFromSpherical(s) { + return this.setFromSphericalCoords(s.radius, s.phi, s.theta); + } + setFromSphericalCoords(radius, phi, theta) { + const sinPhiRadius = Math.sin(phi) * radius; + this.x = sinPhiRadius * Math.sin(theta); + this.y = Math.cos(phi) * radius; + this.z = sinPhiRadius * Math.cos(theta); + return this; + } + setFromCylindrical(c2) { + return this.setFromCylindricalCoords(c2.radius, c2.theta, c2.y); + } + setFromCylindricalCoords(radius, theta, y2) { + this.x = radius * Math.sin(theta); + this.y = y2; + this.z = radius * Math.cos(theta); + return this; + } + setFromMatrixPosition(m2) { + const e = m2.elements; + this.x = e[12]; + this.y = e[13]; + this.z = e[14]; + return this; + } + setFromMatrixScale(m2) { + const sx = this.setFromMatrixColumn(m2, 0).length(); + const sy = this.setFromMatrixColumn(m2, 1).length(); + const sz = this.setFromMatrixColumn(m2, 2).length(); + this.x = sx; + this.y = sy; + this.z = sz; + return this; + } + setFromMatrixColumn(m2, index2) { + return this.fromArray(m2.elements, index2 * 4); + } + setFromMatrix3Column(m2, index2) { + return this.fromArray(m2.elements, index2 * 3); + } + setFromEuler(e) { + this.x = e._x; + this.y = e._y; + this.z = e._z; + return this; + } + equals(v) { + return v.x === this.x && v.y === this.y && v.z === this.z; + } + fromArray(array2, offset = 0) { + this.x = array2[offset]; + this.y = array2[offset + 1]; + this.z = array2[offset + 2]; + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this.x; + array2[offset + 1] = this.y; + array2[offset + 2] = this.z; + return array2; + } + fromBufferAttribute(attribute, index2) { + this.x = attribute.getX(index2); + this.y = attribute.getY(index2); + this.z = attribute.getZ(index2); + return this; + } + random() { + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + return this; + } + randomDirection() { + const u = (Math.random() - 0.5) * 2; + const t = Math.random() * Math.PI * 2; + const f = Math.sqrt(1 - u ** 2); + this.x = f * Math.cos(t); + this.y = f * Math.sin(t); + this.z = u; + return this; + } + *[Symbol.iterator]() { + yield this.x; + yield this.y; + yield this.z; + } + }; + var _vector$c2 = /* @__PURE__ */ new Vector32(); + var _quaternion$42 = /* @__PURE__ */ new Quaternion2(); + var Box32 = class { + constructor(min2 = new Vector32(Infinity, Infinity, Infinity), max2 = new Vector32(-Infinity, -Infinity, -Infinity)) { + this.isBox3 = true; + this.min = min2; + this.max = max2; + } + set(min2, max2) { + this.min.copy(min2); + this.max.copy(max2); + return this; + } + setFromArray(array2) { + let minX = Infinity; + let minY = Infinity; + let minZ = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + let maxZ = -Infinity; + for (let i = 0, l = array2.length; i < l; i += 3) { + const x2 = array2[i]; + const y2 = array2[i + 1]; + const z = array2[i + 2]; + if (x2 < minX) + minX = x2; + if (y2 < minY) + minY = y2; + if (z < minZ) + minZ = z; + if (x2 > maxX) + maxX = x2; + if (y2 > maxY) + maxY = y2; + if (z > maxZ) + maxZ = z; + } + this.min.set(minX, minY, minZ); + this.max.set(maxX, maxY, maxZ); + return this; + } + setFromBufferAttribute(attribute) { + let minX = Infinity; + let minY = Infinity; + let minZ = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + let maxZ = -Infinity; + for (let i = 0, l = attribute.count; i < l; i++) { + const x2 = attribute.getX(i); + const y2 = attribute.getY(i); + const z = attribute.getZ(i); + if (x2 < minX) + minX = x2; + if (y2 < minY) + minY = y2; + if (z < minZ) + minZ = z; + if (x2 > maxX) + maxX = x2; + if (y2 > maxY) + maxY = y2; + if (z > maxZ) + maxZ = z; + } + this.min.set(minX, minY, minZ); + this.max.set(maxX, maxY, maxZ); + return this; + } + setFromPoints(points) { + this.makeEmpty(); + for (let i = 0, il = points.length; i < il; i++) { + this.expandByPoint(points[i]); + } + return this; + } + setFromCenterAndSize(center, size) { + const halfSize = _vector$b2.copy(size).multiplyScalar(0.5); + this.min.copy(center).sub(halfSize); + this.max.copy(center).add(halfSize); + return this; + } + setFromObject(object, precise = false) { + this.makeEmpty(); + return this.expandByObject(object, precise); + } + clone() { + return new this.constructor().copy(this); + } + copy(box) { + this.min.copy(box.min); + this.max.copy(box.max); + return this; + } + makeEmpty() { + this.min.x = this.min.y = this.min.z = Infinity; + this.max.x = this.max.y = this.max.z = -Infinity; + return this; + } + isEmpty() { + return this.max.x < this.min.x || this.max.y < this.min.y || this.max.z < this.min.z; + } + getCenter(target) { + return this.isEmpty() ? target.set(0, 0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5); + } + getSize(target) { + return this.isEmpty() ? target.set(0, 0, 0) : target.subVectors(this.max, this.min); + } + expandByPoint(point) { + this.min.min(point); + this.max.max(point); + return this; + } + expandByVector(vector) { + this.min.sub(vector); + this.max.add(vector); + return this; + } + expandByScalar(scalar) { + this.min.addScalar(-scalar); + this.max.addScalar(scalar); + return this; + } + expandByObject(object, precise = false) { + object.updateWorldMatrix(false, false); + const geometry = object.geometry; + if (geometry !== void 0) { + if (precise && geometry.attributes != void 0 && geometry.attributes.position !== void 0) { + const position = geometry.attributes.position; + for (let i = 0, l = position.count; i < l; i++) { + _vector$b2.fromBufferAttribute(position, i).applyMatrix4(object.matrixWorld); + this.expandByPoint(_vector$b2); + } + } else { + if (geometry.boundingBox === null) { + geometry.computeBoundingBox(); + } + _box$32.copy(geometry.boundingBox); + _box$32.applyMatrix4(object.matrixWorld); + this.union(_box$32); + } + } + const children2 = object.children; + for (let i = 0, l = children2.length; i < l; i++) { + this.expandByObject(children2[i], precise); + } + return this; + } + containsPoint(point) { + return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y || point.z < this.min.z || point.z > this.max.z ? false : true; + } + containsBox(box) { + return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y && this.min.z <= box.min.z && box.max.z <= this.max.z; + } + getParameter(point, target) { + return target.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y), (point.z - this.min.z) / (this.max.z - this.min.z)); + } + intersectsBox(box) { + return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y || box.max.z < this.min.z || box.min.z > this.max.z ? false : true; + } + intersectsSphere(sphere) { + this.clampPoint(sphere.center, _vector$b2); + return _vector$b2.distanceToSquared(sphere.center) <= sphere.radius * sphere.radius; + } + intersectsPlane(plane) { + let min2, max2; + if (plane.normal.x > 0) { + min2 = plane.normal.x * this.min.x; + max2 = plane.normal.x * this.max.x; + } else { + min2 = plane.normal.x * this.max.x; + max2 = plane.normal.x * this.min.x; + } + if (plane.normal.y > 0) { + min2 += plane.normal.y * this.min.y; + max2 += plane.normal.y * this.max.y; + } else { + min2 += plane.normal.y * this.max.y; + max2 += plane.normal.y * this.min.y; + } + if (plane.normal.z > 0) { + min2 += plane.normal.z * this.min.z; + max2 += plane.normal.z * this.max.z; + } else { + min2 += plane.normal.z * this.max.z; + max2 += plane.normal.z * this.min.z; + } + return min2 <= -plane.constant && max2 >= -plane.constant; + } + intersectsTriangle(triangle) { + if (this.isEmpty()) { + return false; + } + this.getCenter(_center2); + _extents2.subVectors(this.max, _center2); + _v0$22.subVectors(triangle.a, _center2); + _v1$72.subVectors(triangle.b, _center2); + _v2$32.subVectors(triangle.c, _center2); + _f02.subVectors(_v1$72, _v0$22); + _f12.subVectors(_v2$32, _v1$72); + _f22.subVectors(_v0$22, _v2$32); + let axes = [0, -_f02.z, _f02.y, 0, -_f12.z, _f12.y, 0, -_f22.z, _f22.y, _f02.z, 0, -_f02.x, _f12.z, 0, -_f12.x, _f22.z, 0, -_f22.x, -_f02.y, _f02.x, 0, -_f12.y, _f12.x, 0, -_f22.y, _f22.x, 0]; + if (!satForAxes2(axes, _v0$22, _v1$72, _v2$32, _extents2)) { + return false; + } + axes = [1, 0, 0, 0, 1, 0, 0, 0, 1]; + if (!satForAxes2(axes, _v0$22, _v1$72, _v2$32, _extents2)) { + return false; + } + _triangleNormal2.crossVectors(_f02, _f12); + axes = [_triangleNormal2.x, _triangleNormal2.y, _triangleNormal2.z]; + return satForAxes2(axes, _v0$22, _v1$72, _v2$32, _extents2); + } + clampPoint(point, target) { + return target.copy(point).clamp(this.min, this.max); + } + distanceToPoint(point) { + const clampedPoint = _vector$b2.copy(point).clamp(this.min, this.max); + return clampedPoint.sub(point).length(); + } + getBoundingSphere(target) { + this.getCenter(target.center); + target.radius = this.getSize(_vector$b2).length() * 0.5; + return target; + } + intersect(box) { + this.min.max(box.min); + this.max.min(box.max); + if (this.isEmpty()) + this.makeEmpty(); + return this; + } + union(box) { + this.min.min(box.min); + this.max.max(box.max); + return this; + } + applyMatrix4(matrix) { + if (this.isEmpty()) + return this; + _points2[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix); + _points2[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix); + _points2[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix); + _points2[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix); + _points2[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix); + _points2[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix); + _points2[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix); + _points2[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix); + this.setFromPoints(_points2); + return this; + } + translate(offset) { + this.min.add(offset); + this.max.add(offset); + return this; + } + equals(box) { + return box.min.equals(this.min) && box.max.equals(this.max); + } + }; + var _points2 = [/* @__PURE__ */ new Vector32(), /* @__PURE__ */ new Vector32(), /* @__PURE__ */ new Vector32(), /* @__PURE__ */ new Vector32(), /* @__PURE__ */ new Vector32(), /* @__PURE__ */ new Vector32(), /* @__PURE__ */ new Vector32(), /* @__PURE__ */ new Vector32()]; + var _vector$b2 = /* @__PURE__ */ new Vector32(); + var _box$32 = /* @__PURE__ */ new Box32(); + var _v0$22 = /* @__PURE__ */ new Vector32(); + var _v1$72 = /* @__PURE__ */ new Vector32(); + var _v2$32 = /* @__PURE__ */ new Vector32(); + var _f02 = /* @__PURE__ */ new Vector32(); + var _f12 = /* @__PURE__ */ new Vector32(); + var _f22 = /* @__PURE__ */ new Vector32(); + var _center2 = /* @__PURE__ */ new Vector32(); + var _extents2 = /* @__PURE__ */ new Vector32(); + var _triangleNormal2 = /* @__PURE__ */ new Vector32(); + var _testAxis2 = /* @__PURE__ */ new Vector32(); + function satForAxes2(axes, v0, v1, v2, extents) { + for (let i = 0, j = axes.length - 3; i <= j; i += 3) { + _testAxis2.fromArray(axes, i); + const r = extents.x * Math.abs(_testAxis2.x) + extents.y * Math.abs(_testAxis2.y) + extents.z * Math.abs(_testAxis2.z); + const p0 = v0.dot(_testAxis2); + const p1 = v1.dot(_testAxis2); + const p2 = v2.dot(_testAxis2); + if (Math.max(-Math.max(p0, p1, p2), Math.min(p0, p1, p2)) > r) { + return false; + } + } + return true; + } + var _box$22 = /* @__PURE__ */ new Box32(); + var _v1$62 = /* @__PURE__ */ new Vector32(); + var _toFarthestPoint2 = /* @__PURE__ */ new Vector32(); + var _toPoint2 = /* @__PURE__ */ new Vector32(); + var Sphere2 = class { + constructor(center = new Vector32(), radius = -1) { + this.center = center; + this.radius = radius; + } + set(center, radius) { + this.center.copy(center); + this.radius = radius; + return this; + } + setFromPoints(points, optionalCenter) { + const center = this.center; + if (optionalCenter !== void 0) { + center.copy(optionalCenter); + } else { + _box$22.setFromPoints(points).getCenter(center); + } + let maxRadiusSq = 0; + for (let i = 0, il = points.length; i < il; i++) { + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(points[i])); + } + this.radius = Math.sqrt(maxRadiusSq); + return this; + } + copy(sphere) { + this.center.copy(sphere.center); + this.radius = sphere.radius; + return this; + } + isEmpty() { + return this.radius < 0; + } + makeEmpty() { + this.center.set(0, 0, 0); + this.radius = -1; + return this; + } + containsPoint(point) { + return point.distanceToSquared(this.center) <= this.radius * this.radius; + } + distanceToPoint(point) { + return point.distanceTo(this.center) - this.radius; + } + intersectsSphere(sphere) { + const radiusSum = this.radius + sphere.radius; + return sphere.center.distanceToSquared(this.center) <= radiusSum * radiusSum; + } + intersectsBox(box) { + return box.intersectsSphere(this); + } + intersectsPlane(plane) { + return Math.abs(plane.distanceToPoint(this.center)) <= this.radius; + } + clampPoint(point, target) { + const deltaLengthSq = this.center.distanceToSquared(point); + target.copy(point); + if (deltaLengthSq > this.radius * this.radius) { + target.sub(this.center).normalize(); + target.multiplyScalar(this.radius).add(this.center); + } + return target; + } + getBoundingBox(target) { + if (this.isEmpty()) { + target.makeEmpty(); + return target; + } + target.set(this.center, this.center); + target.expandByScalar(this.radius); + return target; + } + applyMatrix4(matrix) { + this.center.applyMatrix4(matrix); + this.radius = this.radius * matrix.getMaxScaleOnAxis(); + return this; + } + translate(offset) { + this.center.add(offset); + return this; + } + expandByPoint(point) { + _toPoint2.subVectors(point, this.center); + const lengthSq = _toPoint2.lengthSq(); + if (lengthSq > this.radius * this.radius) { + const length = Math.sqrt(lengthSq); + const missingRadiusHalf = (length - this.radius) * 0.5; + this.center.add(_toPoint2.multiplyScalar(missingRadiusHalf / length)); + this.radius += missingRadiusHalf; + } + return this; + } + union(sphere) { + if (this.center.equals(sphere.center) === true) { + _toFarthestPoint2.set(0, 0, 1).multiplyScalar(sphere.radius); + } else { + _toFarthestPoint2.subVectors(sphere.center, this.center).normalize().multiplyScalar(sphere.radius); + } + this.expandByPoint(_v1$62.copy(sphere.center).add(_toFarthestPoint2)); + this.expandByPoint(_v1$62.copy(sphere.center).sub(_toFarthestPoint2)); + return this; + } + equals(sphere) { + return sphere.center.equals(this.center) && sphere.radius === this.radius; + } + clone() { + return new this.constructor().copy(this); + } + }; + var _vector$a2 = /* @__PURE__ */ new Vector32(); + var _segCenter2 = /* @__PURE__ */ new Vector32(); + var _segDir2 = /* @__PURE__ */ new Vector32(); + var _diff2 = /* @__PURE__ */ new Vector32(); + var _edge12 = /* @__PURE__ */ new Vector32(); + var _edge22 = /* @__PURE__ */ new Vector32(); + var _normal$12 = /* @__PURE__ */ new Vector32(); + var Ray2 = class { + constructor(origin = new Vector32(), direction = new Vector32(0, 0, -1)) { + this.origin = origin; + this.direction = direction; + } + set(origin, direction) { + this.origin.copy(origin); + this.direction.copy(direction); + return this; + } + copy(ray) { + this.origin.copy(ray.origin); + this.direction.copy(ray.direction); + return this; + } + at(t, target) { + return target.copy(this.direction).multiplyScalar(t).add(this.origin); + } + lookAt(v) { + this.direction.copy(v).sub(this.origin).normalize(); + return this; + } + recast(t) { + this.origin.copy(this.at(t, _vector$a2)); + return this; + } + closestPointToPoint(point, target) { + target.subVectors(point, this.origin); + const directionDistance = target.dot(this.direction); + if (directionDistance < 0) { + return target.copy(this.origin); + } + return target.copy(this.direction).multiplyScalar(directionDistance).add(this.origin); + } + distanceToPoint(point) { + return Math.sqrt(this.distanceSqToPoint(point)); + } + distanceSqToPoint(point) { + const directionDistance = _vector$a2.subVectors(point, this.origin).dot(this.direction); + if (directionDistance < 0) { + return this.origin.distanceToSquared(point); + } + _vector$a2.copy(this.direction).multiplyScalar(directionDistance).add(this.origin); + return _vector$a2.distanceToSquared(point); + } + distanceSqToSegment(v0, v1, optionalPointOnRay, optionalPointOnSegment) { + _segCenter2.copy(v0).add(v1).multiplyScalar(0.5); + _segDir2.copy(v1).sub(v0).normalize(); + _diff2.copy(this.origin).sub(_segCenter2); + const segExtent = v0.distanceTo(v1) * 0.5; + const a01 = -this.direction.dot(_segDir2); + const b0 = _diff2.dot(this.direction); + const b1 = -_diff2.dot(_segDir2); + const c2 = _diff2.lengthSq(); + const det = Math.abs(1 - a01 * a01); + let s0, s1, sqrDist, extDet; + if (det > 0) { + s0 = a01 * b1 - b0; + s1 = a01 * b0 - b1; + extDet = segExtent * det; + if (s0 >= 0) { + if (s1 >= -extDet) { + if (s1 <= extDet) { + const invDet = 1 / det; + s0 *= invDet; + s1 *= invDet; + sqrDist = s0 * (s0 + a01 * s1 + 2 * b0) + s1 * (a01 * s0 + s1 + 2 * b1) + c2; + } else { + s1 = segExtent; + s0 = Math.max(0, -(a01 * s1 + b0)); + sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2; + } + } else { + s1 = -segExtent; + s0 = Math.max(0, -(a01 * s1 + b0)); + sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2; + } + } else { + if (s1 <= -extDet) { + s0 = Math.max(0, -(-a01 * segExtent + b0)); + s1 = s0 > 0 ? -segExtent : Math.min(Math.max(-segExtent, -b1), segExtent); + sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2; + } else if (s1 <= extDet) { + s0 = 0; + s1 = Math.min(Math.max(-segExtent, -b1), segExtent); + sqrDist = s1 * (s1 + 2 * b1) + c2; + } else { + s0 = Math.max(0, -(a01 * segExtent + b0)); + s1 = s0 > 0 ? segExtent : Math.min(Math.max(-segExtent, -b1), segExtent); + sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2; + } + } + } else { + s1 = a01 > 0 ? -segExtent : segExtent; + s0 = Math.max(0, -(a01 * s1 + b0)); + sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2; + } + if (optionalPointOnRay) { + optionalPointOnRay.copy(this.direction).multiplyScalar(s0).add(this.origin); + } + if (optionalPointOnSegment) { + optionalPointOnSegment.copy(_segDir2).multiplyScalar(s1).add(_segCenter2); + } + return sqrDist; + } + intersectSphere(sphere, target) { + _vector$a2.subVectors(sphere.center, this.origin); + const tca = _vector$a2.dot(this.direction); + const d2 = _vector$a2.dot(_vector$a2) - tca * tca; + const radius2 = sphere.radius * sphere.radius; + if (d2 > radius2) + return null; + const thc = Math.sqrt(radius2 - d2); + const t0 = tca - thc; + const t1 = tca + thc; + if (t0 < 0 && t1 < 0) + return null; + if (t0 < 0) + return this.at(t1, target); + return this.at(t0, target); + } + intersectsSphere(sphere) { + return this.distanceSqToPoint(sphere.center) <= sphere.radius * sphere.radius; + } + distanceToPlane(plane) { + const denominator = plane.normal.dot(this.direction); + if (denominator === 0) { + if (plane.distanceToPoint(this.origin) === 0) { + return 0; + } + return null; + } + const t = -(this.origin.dot(plane.normal) + plane.constant) / denominator; + return t >= 0 ? t : null; + } + intersectPlane(plane, target) { + const t = this.distanceToPlane(plane); + if (t === null) { + return null; + } + return this.at(t, target); + } + intersectsPlane(plane) { + const distToPoint = plane.distanceToPoint(this.origin); + if (distToPoint === 0) { + return true; + } + const denominator = plane.normal.dot(this.direction); + if (denominator * distToPoint < 0) { + return true; + } + return false; + } + intersectBox(box, target) { + let tmin, tmax, tymin, tymax, tzmin, tzmax; + const invdirx = 1 / this.direction.x, invdiry = 1 / this.direction.y, invdirz = 1 / this.direction.z; + const origin = this.origin; + if (invdirx >= 0) { + tmin = (box.min.x - origin.x) * invdirx; + tmax = (box.max.x - origin.x) * invdirx; + } else { + tmin = (box.max.x - origin.x) * invdirx; + tmax = (box.min.x - origin.x) * invdirx; + } + if (invdiry >= 0) { + tymin = (box.min.y - origin.y) * invdiry; + tymax = (box.max.y - origin.y) * invdiry; + } else { + tymin = (box.max.y - origin.y) * invdiry; + tymax = (box.min.y - origin.y) * invdiry; + } + if (tmin > tymax || tymin > tmax) + return null; + if (tymin > tmin || tmin !== tmin) + tmin = tymin; + if (tymax < tmax || tmax !== tmax) + tmax = tymax; + if (invdirz >= 0) { + tzmin = (box.min.z - origin.z) * invdirz; + tzmax = (box.max.z - origin.z) * invdirz; + } else { + tzmin = (box.max.z - origin.z) * invdirz; + tzmax = (box.min.z - origin.z) * invdirz; + } + if (tmin > tzmax || tzmin > tmax) + return null; + if (tzmin > tmin || tmin !== tmin) + tmin = tzmin; + if (tzmax < tmax || tmax !== tmax) + tmax = tzmax; + if (tmax < 0) + return null; + return this.at(tmin >= 0 ? tmin : tmax, target); + } + intersectsBox(box) { + return this.intersectBox(box, _vector$a2) !== null; + } + intersectTriangle(a2, b, c2, backfaceCulling, target) { + _edge12.subVectors(b, a2); + _edge22.subVectors(c2, a2); + _normal$12.crossVectors(_edge12, _edge22); + let DdN = this.direction.dot(_normal$12); + let sign2; + if (DdN > 0) { + if (backfaceCulling) + return null; + sign2 = 1; + } else if (DdN < 0) { + sign2 = -1; + DdN = -DdN; + } else { + return null; + } + _diff2.subVectors(this.origin, a2); + const DdQxE2 = sign2 * this.direction.dot(_edge22.crossVectors(_diff2, _edge22)); + if (DdQxE2 < 0) { + return null; + } + const DdE1xQ = sign2 * this.direction.dot(_edge12.cross(_diff2)); + if (DdE1xQ < 0) { + return null; + } + if (DdQxE2 + DdE1xQ > DdN) { + return null; + } + const QdN = -sign2 * _diff2.dot(_normal$12); + if (QdN < 0) { + return null; + } + return this.at(QdN / DdN, target); + } + applyMatrix4(matrix4) { + this.origin.applyMatrix4(matrix4); + this.direction.transformDirection(matrix4); + return this; + } + equals(ray) { + return ray.origin.equals(this.origin) && ray.direction.equals(this.direction); + } + clone() { + return new this.constructor().copy(this); + } + }; + var Matrix42 = class { + constructor() { + Matrix42.prototype.isMatrix4 = true; + this.elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; + } + set(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) { + const te = this.elements; + te[0] = n11; + te[4] = n12; + te[8] = n13; + te[12] = n14; + te[1] = n21; + te[5] = n22; + te[9] = n23; + te[13] = n24; + te[2] = n31; + te[6] = n32; + te[10] = n33; + te[14] = n34; + te[3] = n41; + te[7] = n42; + te[11] = n43; + te[15] = n44; + return this; + } + identity() { + this.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + return this; + } + clone() { + return new Matrix42().fromArray(this.elements); + } + copy(m2) { + const te = this.elements; + const me = m2.elements; + te[0] = me[0]; + te[1] = me[1]; + te[2] = me[2]; + te[3] = me[3]; + te[4] = me[4]; + te[5] = me[5]; + te[6] = me[6]; + te[7] = me[7]; + te[8] = me[8]; + te[9] = me[9]; + te[10] = me[10]; + te[11] = me[11]; + te[12] = me[12]; + te[13] = me[13]; + te[14] = me[14]; + te[15] = me[15]; + return this; + } + copyPosition(m2) { + const te = this.elements, me = m2.elements; + te[12] = me[12]; + te[13] = me[13]; + te[14] = me[14]; + return this; + } + setFromMatrix3(m2) { + const me = m2.elements; + this.set(me[0], me[3], me[6], 0, me[1], me[4], me[7], 0, me[2], me[5], me[8], 0, 0, 0, 0, 1); + return this; + } + extractBasis(xAxis, yAxis, zAxis) { + xAxis.setFromMatrixColumn(this, 0); + yAxis.setFromMatrixColumn(this, 1); + zAxis.setFromMatrixColumn(this, 2); + return this; + } + makeBasis(xAxis, yAxis, zAxis) { + this.set(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, 0, 0, 0, 1); + return this; + } + extractRotation(m2) { + const te = this.elements; + const me = m2.elements; + const scaleX = 1 / _v1$52.setFromMatrixColumn(m2, 0).length(); + const scaleY = 1 / _v1$52.setFromMatrixColumn(m2, 1).length(); + const scaleZ = 1 / _v1$52.setFromMatrixColumn(m2, 2).length(); + te[0] = me[0] * scaleX; + te[1] = me[1] * scaleX; + te[2] = me[2] * scaleX; + te[3] = 0; + te[4] = me[4] * scaleY; + te[5] = me[5] * scaleY; + te[6] = me[6] * scaleY; + te[7] = 0; + te[8] = me[8] * scaleZ; + te[9] = me[9] * scaleZ; + te[10] = me[10] * scaleZ; + te[11] = 0; + te[12] = 0; + te[13] = 0; + te[14] = 0; + te[15] = 1; + return this; + } + makeRotationFromEuler(euler) { + const te = this.elements; + const x2 = euler.x, y2 = euler.y, z = euler.z; + const a2 = Math.cos(x2), b = Math.sin(x2); + const c2 = Math.cos(y2), d = Math.sin(y2); + const e = Math.cos(z), f = Math.sin(z); + if (euler.order === "XYZ") { + const ae = a2 * e, af = a2 * f, be = b * e, bf = b * f; + te[0] = c2 * e; + te[4] = -c2 * f; + te[8] = d; + te[1] = af + be * d; + te[5] = ae - bf * d; + te[9] = -b * c2; + te[2] = bf - ae * d; + te[6] = be + af * d; + te[10] = a2 * c2; + } else if (euler.order === "YXZ") { + const ce = c2 * e, cf = c2 * f, de = d * e, df = d * f; + te[0] = ce + df * b; + te[4] = de * b - cf; + te[8] = a2 * d; + te[1] = a2 * f; + te[5] = a2 * e; + te[9] = -b; + te[2] = cf * b - de; + te[6] = df + ce * b; + te[10] = a2 * c2; + } else if (euler.order === "ZXY") { + const ce = c2 * e, cf = c2 * f, de = d * e, df = d * f; + te[0] = ce - df * b; + te[4] = -a2 * f; + te[8] = de + cf * b; + te[1] = cf + de * b; + te[5] = a2 * e; + te[9] = df - ce * b; + te[2] = -a2 * d; + te[6] = b; + te[10] = a2 * c2; + } else if (euler.order === "ZYX") { + const ae = a2 * e, af = a2 * f, be = b * e, bf = b * f; + te[0] = c2 * e; + te[4] = be * d - af; + te[8] = ae * d + bf; + te[1] = c2 * f; + te[5] = bf * d + ae; + te[9] = af * d - be; + te[2] = -d; + te[6] = b * c2; + te[10] = a2 * c2; + } else if (euler.order === "YZX") { + const ac = a2 * c2, ad = a2 * d, bc = b * c2, bd = b * d; + te[0] = c2 * e; + te[4] = bd - ac * f; + te[8] = bc * f + ad; + te[1] = f; + te[5] = a2 * e; + te[9] = -b * e; + te[2] = -d * e; + te[6] = ad * f + bc; + te[10] = ac - bd * f; + } else if (euler.order === "XZY") { + const ac = a2 * c2, ad = a2 * d, bc = b * c2, bd = b * d; + te[0] = c2 * e; + te[4] = -f; + te[8] = d * e; + te[1] = ac * f + bd; + te[5] = a2 * e; + te[9] = ad * f - bc; + te[2] = bc * f - ad; + te[6] = b * e; + te[10] = bd * f + ac; + } + te[3] = 0; + te[7] = 0; + te[11] = 0; + te[12] = 0; + te[13] = 0; + te[14] = 0; + te[15] = 1; + return this; + } + makeRotationFromQuaternion(q) { + return this.compose(_zero2, q, _one2); + } + lookAt(eye, target, up) { + const te = this.elements; + _z2.subVectors(eye, target); + if (_z2.lengthSq() === 0) { + _z2.z = 1; + } + _z2.normalize(); + _x2.crossVectors(up, _z2); + if (_x2.lengthSq() === 0) { + if (Math.abs(up.z) === 1) { + _z2.x += 1e-4; + } else { + _z2.z += 1e-4; + } + _z2.normalize(); + _x2.crossVectors(up, _z2); + } + _x2.normalize(); + _y2.crossVectors(_z2, _x2); + te[0] = _x2.x; + te[4] = _y2.x; + te[8] = _z2.x; + te[1] = _x2.y; + te[5] = _y2.y; + te[9] = _z2.y; + te[2] = _x2.z; + te[6] = _y2.z; + te[10] = _z2.z; + return this; + } + multiply(m2) { + return this.multiplyMatrices(this, m2); + } + premultiply(m2) { + return this.multiplyMatrices(m2, this); + } + multiplyMatrices(a2, b) { + const ae = a2.elements; + const be = b.elements; + const te = this.elements; + const a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12]; + const a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13]; + const a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14]; + const a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15]; + const b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12]; + const b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13]; + const b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14]; + const b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15]; + te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; + te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; + te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; + te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; + te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; + te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; + te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; + te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; + te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; + te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; + te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; + te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; + te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; + te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; + te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; + te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; + return this; + } + multiplyScalar(s) { + const te = this.elements; + te[0] *= s; + te[4] *= s; + te[8] *= s; + te[12] *= s; + te[1] *= s; + te[5] *= s; + te[9] *= s; + te[13] *= s; + te[2] *= s; + te[6] *= s; + te[10] *= s; + te[14] *= s; + te[3] *= s; + te[7] *= s; + te[11] *= s; + te[15] *= s; + return this; + } + determinant() { + const te = this.elements; + const n11 = te[0], n12 = te[4], n13 = te[8], n14 = te[12]; + const n21 = te[1], n22 = te[5], n23 = te[9], n24 = te[13]; + const n31 = te[2], n32 = te[6], n33 = te[10], n34 = te[14]; + const n41 = te[3], n42 = te[7], n43 = te[11], n44 = te[15]; + return n41 * (+n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34) + n42 * (+n11 * n23 * n34 - n11 * n24 * n33 + n14 * n21 * n33 - n13 * n21 * n34 + n13 * n24 * n31 - n14 * n23 * n31) + n43 * (+n11 * n24 * n32 - n11 * n22 * n34 - n14 * n21 * n32 + n12 * n21 * n34 + n14 * n22 * n31 - n12 * n24 * n31) + n44 * (-n13 * n22 * n31 - n11 * n23 * n32 + n11 * n22 * n33 + n13 * n21 * n32 - n12 * n21 * n33 + n12 * n23 * n31); + } + transpose() { + const te = this.elements; + let tmp2; + tmp2 = te[1]; + te[1] = te[4]; + te[4] = tmp2; + tmp2 = te[2]; + te[2] = te[8]; + te[8] = tmp2; + tmp2 = te[6]; + te[6] = te[9]; + te[9] = tmp2; + tmp2 = te[3]; + te[3] = te[12]; + te[12] = tmp2; + tmp2 = te[7]; + te[7] = te[13]; + te[13] = tmp2; + tmp2 = te[11]; + te[11] = te[14]; + te[14] = tmp2; + return this; + } + setPosition(x2, y2, z) { + const te = this.elements; + if (x2.isVector3) { + te[12] = x2.x; + te[13] = x2.y; + te[14] = x2.z; + } else { + te[12] = x2; + te[13] = y2; + te[14] = z; + } + return this; + } + invert() { + const te = this.elements, n11 = te[0], n21 = te[1], n31 = te[2], n41 = te[3], n12 = te[4], n22 = te[5], n32 = te[6], n42 = te[7], n13 = te[8], n23 = te[9], n33 = te[10], n43 = te[11], n14 = te[12], n24 = te[13], n34 = te[14], n44 = te[15], t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; + const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; + if (det === 0) + return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + const detInv = 1 / det; + te[0] = t11 * detInv; + te[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv; + te[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv; + te[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv; + te[4] = t12 * detInv; + te[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv; + te[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv; + te[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv; + te[8] = t13 * detInv; + te[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv; + te[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv; + te[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv; + te[12] = t14 * detInv; + te[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv; + te[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv; + te[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv; + return this; + } + scale(v) { + const te = this.elements; + const x2 = v.x, y2 = v.y, z = v.z; + te[0] *= x2; + te[4] *= y2; + te[8] *= z; + te[1] *= x2; + te[5] *= y2; + te[9] *= z; + te[2] *= x2; + te[6] *= y2; + te[10] *= z; + te[3] *= x2; + te[7] *= y2; + te[11] *= z; + return this; + } + getMaxScaleOnAxis() { + const te = this.elements; + const scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2]; + const scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6]; + const scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10]; + return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq)); + } + makeTranslation(x2, y2, z) { + this.set(1, 0, 0, x2, 0, 1, 0, y2, 0, 0, 1, z, 0, 0, 0, 1); + return this; + } + makeRotationX(theta) { + const c2 = Math.cos(theta), s = Math.sin(theta); + this.set(1, 0, 0, 0, 0, c2, -s, 0, 0, s, c2, 0, 0, 0, 0, 1); + return this; + } + makeRotationY(theta) { + const c2 = Math.cos(theta), s = Math.sin(theta); + this.set(c2, 0, s, 0, 0, 1, 0, 0, -s, 0, c2, 0, 0, 0, 0, 1); + return this; + } + makeRotationZ(theta) { + const c2 = Math.cos(theta), s = Math.sin(theta); + this.set(c2, -s, 0, 0, s, c2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + return this; + } + makeRotationAxis(axis, angle) { + const c2 = Math.cos(angle); + const s = Math.sin(angle); + const t = 1 - c2; + const x2 = axis.x, y2 = axis.y, z = axis.z; + const tx = t * x2, ty = t * y2; + this.set(tx * x2 + c2, tx * y2 - s * z, tx * z + s * y2, 0, tx * y2 + s * z, ty * y2 + c2, ty * z - s * x2, 0, tx * z - s * y2, ty * z + s * x2, t * z * z + c2, 0, 0, 0, 0, 1); + return this; + } + makeScale(x2, y2, z) { + this.set(x2, 0, 0, 0, 0, y2, 0, 0, 0, 0, z, 0, 0, 0, 0, 1); + return this; + } + makeShear(xy, xz, yx, yz, zx, zy) { + this.set(1, yx, zx, 0, xy, 1, zy, 0, xz, yz, 1, 0, 0, 0, 0, 1); + return this; + } + compose(position, quaternion, scale) { + const te = this.elements; + const x2 = quaternion._x, y2 = quaternion._y, z = quaternion._z, w = quaternion._w; + const x22 = x2 + x2, y22 = y2 + y2, z2 = z + z; + const xx = x2 * x22, xy = x2 * y22, xz = x2 * z2; + const yy = y2 * y22, yz = y2 * z2, zz = z * z2; + const wx = w * x22, wy = w * y22, wz = w * z2; + const sx = scale.x, sy = scale.y, sz = scale.z; + te[0] = (1 - (yy + zz)) * sx; + te[1] = (xy + wz) * sx; + te[2] = (xz - wy) * sx; + te[3] = 0; + te[4] = (xy - wz) * sy; + te[5] = (1 - (xx + zz)) * sy; + te[6] = (yz + wx) * sy; + te[7] = 0; + te[8] = (xz + wy) * sz; + te[9] = (yz - wx) * sz; + te[10] = (1 - (xx + yy)) * sz; + te[11] = 0; + te[12] = position.x; + te[13] = position.y; + te[14] = position.z; + te[15] = 1; + return this; + } + decompose(position, quaternion, scale) { + const te = this.elements; + let sx = _v1$52.set(te[0], te[1], te[2]).length(); + const sy = _v1$52.set(te[4], te[5], te[6]).length(); + const sz = _v1$52.set(te[8], te[9], te[10]).length(); + const det = this.determinant(); + if (det < 0) + sx = -sx; + position.x = te[12]; + position.y = te[13]; + position.z = te[14]; + _m1$22.copy(this); + const invSX = 1 / sx; + const invSY = 1 / sy; + const invSZ = 1 / sz; + _m1$22.elements[0] *= invSX; + _m1$22.elements[1] *= invSX; + _m1$22.elements[2] *= invSX; + _m1$22.elements[4] *= invSY; + _m1$22.elements[5] *= invSY; + _m1$22.elements[6] *= invSY; + _m1$22.elements[8] *= invSZ; + _m1$22.elements[9] *= invSZ; + _m1$22.elements[10] *= invSZ; + quaternion.setFromRotationMatrix(_m1$22); + scale.x = sx; + scale.y = sy; + scale.z = sz; + return this; + } + makePerspective(left, right, top, bottom, near, far) { + const te = this.elements; + const x2 = 2 * near / (right - left); + const y2 = 2 * near / (top - bottom); + const a2 = (right + left) / (right - left); + const b = (top + bottom) / (top - bottom); + const c2 = -(far + near) / (far - near); + const d = -2 * far * near / (far - near); + te[0] = x2; + te[4] = 0; + te[8] = a2; + te[12] = 0; + te[1] = 0; + te[5] = y2; + te[9] = b; + te[13] = 0; + te[2] = 0; + te[6] = 0; + te[10] = c2; + te[14] = d; + te[3] = 0; + te[7] = 0; + te[11] = -1; + te[15] = 0; + return this; + } + makeOrthographic(left, right, top, bottom, near, far) { + const te = this.elements; + const w = 1 / (right - left); + const h = 1 / (top - bottom); + const p = 1 / (far - near); + const x2 = (right + left) * w; + const y2 = (top + bottom) * h; + const z = (far + near) * p; + te[0] = 2 * w; + te[4] = 0; + te[8] = 0; + te[12] = -x2; + te[1] = 0; + te[5] = 2 * h; + te[9] = 0; + te[13] = -y2; + te[2] = 0; + te[6] = 0; + te[10] = -2 * p; + te[14] = -z; + te[3] = 0; + te[7] = 0; + te[11] = 0; + te[15] = 1; + return this; + } + equals(matrix) { + const te = this.elements; + const me = matrix.elements; + for (let i = 0; i < 16; i++) { + if (te[i] !== me[i]) + return false; + } + return true; + } + fromArray(array2, offset = 0) { + for (let i = 0; i < 16; i++) { + this.elements[i] = array2[i + offset]; + } + return this; + } + toArray(array2 = [], offset = 0) { + const te = this.elements; + array2[offset] = te[0]; + array2[offset + 1] = te[1]; + array2[offset + 2] = te[2]; + array2[offset + 3] = te[3]; + array2[offset + 4] = te[4]; + array2[offset + 5] = te[5]; + array2[offset + 6] = te[6]; + array2[offset + 7] = te[7]; + array2[offset + 8] = te[8]; + array2[offset + 9] = te[9]; + array2[offset + 10] = te[10]; + array2[offset + 11] = te[11]; + array2[offset + 12] = te[12]; + array2[offset + 13] = te[13]; + array2[offset + 14] = te[14]; + array2[offset + 15] = te[15]; + return array2; + } + }; + var _v1$52 = /* @__PURE__ */ new Vector32(); + var _m1$22 = /* @__PURE__ */ new Matrix42(); + var _zero2 = /* @__PURE__ */ new Vector32(0, 0, 0); + var _one2 = /* @__PURE__ */ new Vector32(1, 1, 1); + var _x2 = /* @__PURE__ */ new Vector32(); + var _y2 = /* @__PURE__ */ new Vector32(); + var _z2 = /* @__PURE__ */ new Vector32(); + var _matrix$12 = /* @__PURE__ */ new Matrix42(); + var _quaternion$32 = /* @__PURE__ */ new Quaternion2(); + var Euler2 = class { + constructor(x2 = 0, y2 = 0, z = 0, order = Euler2.DefaultOrder) { + this.isEuler = true; + this._x = x2; + this._y = y2; + this._z = z; + this._order = order; + } + get x() { + return this._x; + } + set x(value) { + this._x = value; + this._onChangeCallback(); + } + get y() { + return this._y; + } + set y(value) { + this._y = value; + this._onChangeCallback(); + } + get z() { + return this._z; + } + set z(value) { + this._z = value; + this._onChangeCallback(); + } + get order() { + return this._order; + } + set order(value) { + this._order = value; + this._onChangeCallback(); + } + set(x2, y2, z, order = this._order) { + this._x = x2; + this._y = y2; + this._z = z; + this._order = order; + this._onChangeCallback(); + return this; + } + clone() { + return new this.constructor(this._x, this._y, this._z, this._order); + } + copy(euler) { + this._x = euler._x; + this._y = euler._y; + this._z = euler._z; + this._order = euler._order; + this._onChangeCallback(); + return this; + } + setFromRotationMatrix(m2, order = this._order, update = true) { + const te = m2.elements; + const m11 = te[0], m12 = te[4], m13 = te[8]; + const m21 = te[1], m22 = te[5], m23 = te[9]; + const m31 = te[2], m32 = te[6], m33 = te[10]; + switch (order) { + case "XYZ": + this._y = Math.asin(clamp2(m13, -1, 1)); + if (Math.abs(m13) < 0.9999999) { + this._x = Math.atan2(-m23, m33); + this._z = Math.atan2(-m12, m11); + } else { + this._x = Math.atan2(m32, m22); + this._z = 0; + } + break; + case "YXZ": + this._x = Math.asin(-clamp2(m23, -1, 1)); + if (Math.abs(m23) < 0.9999999) { + this._y = Math.atan2(m13, m33); + this._z = Math.atan2(m21, m22); + } else { + this._y = Math.atan2(-m31, m11); + this._z = 0; + } + break; + case "ZXY": + this._x = Math.asin(clamp2(m32, -1, 1)); + if (Math.abs(m32) < 0.9999999) { + this._y = Math.atan2(-m31, m33); + this._z = Math.atan2(-m12, m22); + } else { + this._y = 0; + this._z = Math.atan2(m21, m11); + } + break; + case "ZYX": + this._y = Math.asin(-clamp2(m31, -1, 1)); + if (Math.abs(m31) < 0.9999999) { + this._x = Math.atan2(m32, m33); + this._z = Math.atan2(m21, m11); + } else { + this._x = 0; + this._z = Math.atan2(-m12, m22); + } + break; + case "YZX": + this._z = Math.asin(clamp2(m21, -1, 1)); + if (Math.abs(m21) < 0.9999999) { + this._x = Math.atan2(-m23, m22); + this._y = Math.atan2(-m31, m11); + } else { + this._x = 0; + this._y = Math.atan2(m13, m33); + } + break; + case "XZY": + this._z = Math.asin(-clamp2(m12, -1, 1)); + if (Math.abs(m12) < 0.9999999) { + this._x = Math.atan2(m32, m22); + this._y = Math.atan2(m13, m11); + } else { + this._x = Math.atan2(-m23, m33); + this._y = 0; + } + break; + default: + console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: " + order); + } + this._order = order; + if (update === true) + this._onChangeCallback(); + return this; + } + setFromQuaternion(q, order, update) { + _matrix$12.makeRotationFromQuaternion(q); + return this.setFromRotationMatrix(_matrix$12, order, update); + } + setFromVector3(v, order = this._order) { + return this.set(v.x, v.y, v.z, order); + } + reorder(newOrder) { + _quaternion$32.setFromEuler(this); + return this.setFromQuaternion(_quaternion$32, newOrder); + } + equals(euler) { + return euler._x === this._x && euler._y === this._y && euler._z === this._z && euler._order === this._order; + } + fromArray(array2) { + this._x = array2[0]; + this._y = array2[1]; + this._z = array2[2]; + if (array2[3] !== void 0) + this._order = array2[3]; + this._onChangeCallback(); + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this._x; + array2[offset + 1] = this._y; + array2[offset + 2] = this._z; + array2[offset + 3] = this._order; + return array2; + } + _onChange(callback) { + this._onChangeCallback = callback; + return this; + } + _onChangeCallback() { + } + *[Symbol.iterator]() { + yield this._x; + yield this._y; + yield this._z; + yield this._order; + } + toVector3() { + console.error("THREE.Euler: .toVector3() has been removed. Use Vector3.setFromEuler() instead"); + } + }; + Euler2.DefaultOrder = "XYZ"; + Euler2.RotationOrders = ["XYZ", "YZX", "ZXY", "XZY", "YXZ", "ZYX"]; + var Layers2 = class { + constructor() { + this.mask = 1 | 0; + } + set(channel) { + this.mask = (1 << channel | 0) >>> 0; + } + enable(channel) { + this.mask |= 1 << channel | 0; + } + enableAll() { + this.mask = 4294967295 | 0; + } + toggle(channel) { + this.mask ^= 1 << channel | 0; + } + disable(channel) { + this.mask &= ~(1 << channel | 0); + } + disableAll() { + this.mask = 0; + } + test(layers) { + return (this.mask & layers.mask) !== 0; + } + isEnabled(channel) { + return (this.mask & (1 << channel | 0)) !== 0; + } + }; + var _object3DId2 = 0; + var _v1$42 = /* @__PURE__ */ new Vector32(); + var _q12 = /* @__PURE__ */ new Quaternion2(); + var _m1$12 = /* @__PURE__ */ new Matrix42(); + var _target2 = /* @__PURE__ */ new Vector32(); + var _position$32 = /* @__PURE__ */ new Vector32(); + var _scale$22 = /* @__PURE__ */ new Vector32(); + var _quaternion$22 = /* @__PURE__ */ new Quaternion2(); + var _xAxis2 = /* @__PURE__ */ new Vector32(1, 0, 0); + var _yAxis2 = /* @__PURE__ */ new Vector32(0, 1, 0); + var _zAxis2 = /* @__PURE__ */ new Vector32(0, 0, 1); + var _addedEvent2 = { + type: "added" + }; + var _removedEvent2 = { + type: "removed" + }; + var Object3D2 = class extends EventDispatcher2 { + constructor() { + super(); + this.isObject3D = true; + Object.defineProperty(this, "id", { + value: _object3DId2++ + }); + this.uuid = generateUUID2(); + this.name = ""; + this.type = "Object3D"; + this.parent = null; + this.children = []; + this.up = Object3D2.DefaultUp.clone(); + const position = new Vector32(); + const rotation = new Euler2(); + const quaternion = new Quaternion2(); + const scale = new Vector32(1, 1, 1); + function onRotationChange() { + quaternion.setFromEuler(rotation, false); + } + function onQuaternionChange() { + rotation.setFromQuaternion(quaternion, void 0, false); + } + rotation._onChange(onRotationChange); + quaternion._onChange(onQuaternionChange); + Object.defineProperties(this, { + position: { + configurable: true, + enumerable: true, + value: position + }, + rotation: { + configurable: true, + enumerable: true, + value: rotation + }, + quaternion: { + configurable: true, + enumerable: true, + value: quaternion + }, + scale: { + configurable: true, + enumerable: true, + value: scale + }, + modelViewMatrix: { + value: new Matrix42() + }, + normalMatrix: { + value: new Matrix32() + } + }); + this.matrix = new Matrix42(); + this.matrixWorld = new Matrix42(); + this.matrixAutoUpdate = Object3D2.DefaultMatrixAutoUpdate; + this.matrixWorldNeedsUpdate = false; + this.layers = new Layers2(); + this.visible = true; + this.castShadow = false; + this.receiveShadow = false; + this.frustumCulled = true; + this.renderOrder = 0; + this.animations = []; + this.userData = {}; + } + onBeforeRender() { + } + onAfterRender() { + } + applyMatrix4(matrix) { + if (this.matrixAutoUpdate) + this.updateMatrix(); + this.matrix.premultiply(matrix); + this.matrix.decompose(this.position, this.quaternion, this.scale); + } + applyQuaternion(q) { + this.quaternion.premultiply(q); + return this; + } + setRotationFromAxisAngle(axis, angle) { + this.quaternion.setFromAxisAngle(axis, angle); + } + setRotationFromEuler(euler) { + this.quaternion.setFromEuler(euler, true); + } + setRotationFromMatrix(m2) { + this.quaternion.setFromRotationMatrix(m2); + } + setRotationFromQuaternion(q) { + this.quaternion.copy(q); + } + rotateOnAxis(axis, angle) { + _q12.setFromAxisAngle(axis, angle); + this.quaternion.multiply(_q12); + return this; + } + rotateOnWorldAxis(axis, angle) { + _q12.setFromAxisAngle(axis, angle); + this.quaternion.premultiply(_q12); + return this; + } + rotateX(angle) { + return this.rotateOnAxis(_xAxis2, angle); + } + rotateY(angle) { + return this.rotateOnAxis(_yAxis2, angle); + } + rotateZ(angle) { + return this.rotateOnAxis(_zAxis2, angle); + } + translateOnAxis(axis, distance) { + _v1$42.copy(axis).applyQuaternion(this.quaternion); + this.position.add(_v1$42.multiplyScalar(distance)); + return this; + } + translateX(distance) { + return this.translateOnAxis(_xAxis2, distance); + } + translateY(distance) { + return this.translateOnAxis(_yAxis2, distance); + } + translateZ(distance) { + return this.translateOnAxis(_zAxis2, distance); + } + localToWorld(vector) { + return vector.applyMatrix4(this.matrixWorld); + } + worldToLocal(vector) { + return vector.applyMatrix4(_m1$12.copy(this.matrixWorld).invert()); + } + lookAt(x2, y2, z) { + if (x2.isVector3) { + _target2.copy(x2); + } else { + _target2.set(x2, y2, z); + } + const parent = this.parent; + this.updateWorldMatrix(true, false); + _position$32.setFromMatrixPosition(this.matrixWorld); + if (this.isCamera || this.isLight) { + _m1$12.lookAt(_position$32, _target2, this.up); + } else { + _m1$12.lookAt(_target2, _position$32, this.up); + } + this.quaternion.setFromRotationMatrix(_m1$12); + if (parent) { + _m1$12.extractRotation(parent.matrixWorld); + _q12.setFromRotationMatrix(_m1$12); + this.quaternion.premultiply(_q12.invert()); + } + } + add(object) { + if (arguments.length > 1) { + for (let i = 0; i < arguments.length; i++) { + this.add(arguments[i]); + } + return this; + } + if (object === this) { + console.error("THREE.Object3D.add: object can't be added as a child of itself.", object); + return this; + } + if (object && object.isObject3D) { + if (object.parent !== null) { + object.parent.remove(object); + } + object.parent = this; + this.children.push(object); + object.dispatchEvent(_addedEvent2); + } else { + console.error("THREE.Object3D.add: object not an instance of THREE.Object3D.", object); + } + return this; + } + remove(object) { + if (arguments.length > 1) { + for (let i = 0; i < arguments.length; i++) { + this.remove(arguments[i]); + } + return this; + } + const index2 = this.children.indexOf(object); + if (index2 !== -1) { + object.parent = null; + this.children.splice(index2, 1); + object.dispatchEvent(_removedEvent2); + } + return this; + } + removeFromParent() { + const parent = this.parent; + if (parent !== null) { + parent.remove(this); + } + return this; + } + clear() { + for (let i = 0; i < this.children.length; i++) { + const object = this.children[i]; + object.parent = null; + object.dispatchEvent(_removedEvent2); + } + this.children.length = 0; + return this; + } + attach(object) { + this.updateWorldMatrix(true, false); + _m1$12.copy(this.matrixWorld).invert(); + if (object.parent !== null) { + object.parent.updateWorldMatrix(true, false); + _m1$12.multiply(object.parent.matrixWorld); + } + object.applyMatrix4(_m1$12); + this.add(object); + object.updateWorldMatrix(false, true); + return this; + } + getObjectById(id3) { + return this.getObjectByProperty("id", id3); + } + getObjectByName(name) { + return this.getObjectByProperty("name", name); + } + getObjectByProperty(name, value) { + if (this[name] === value) + return this; + for (let i = 0, l = this.children.length; i < l; i++) { + const child = this.children[i]; + const object = child.getObjectByProperty(name, value); + if (object !== void 0) { + return object; + } + } + return void 0; + } + getWorldPosition(target) { + this.updateWorldMatrix(true, false); + return target.setFromMatrixPosition(this.matrixWorld); + } + getWorldQuaternion(target) { + this.updateWorldMatrix(true, false); + this.matrixWorld.decompose(_position$32, target, _scale$22); + return target; + } + getWorldScale(target) { + this.updateWorldMatrix(true, false); + this.matrixWorld.decompose(_position$32, _quaternion$22, target); + return target; + } + getWorldDirection(target) { + this.updateWorldMatrix(true, false); + const e = this.matrixWorld.elements; + return target.set(e[8], e[9], e[10]).normalize(); + } + raycast() { + } + traverse(callback) { + callback(this); + const children2 = this.children; + for (let i = 0, l = children2.length; i < l; i++) { + children2[i].traverse(callback); + } + } + traverseVisible(callback) { + if (this.visible === false) + return; + callback(this); + const children2 = this.children; + for (let i = 0, l = children2.length; i < l; i++) { + children2[i].traverseVisible(callback); + } + } + traverseAncestors(callback) { + const parent = this.parent; + if (parent !== null) { + callback(parent); + parent.traverseAncestors(callback); + } + } + updateMatrix() { + this.matrix.compose(this.position, this.quaternion, this.scale); + this.matrixWorldNeedsUpdate = true; + } + updateMatrixWorld(force) { + if (this.matrixAutoUpdate) + this.updateMatrix(); + if (this.matrixWorldNeedsUpdate || force) { + if (this.parent === null) { + this.matrixWorld.copy(this.matrix); + } else { + this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix); + } + this.matrixWorldNeedsUpdate = false; + force = true; + } + const children2 = this.children; + for (let i = 0, l = children2.length; i < l; i++) { + children2[i].updateMatrixWorld(force); + } + } + updateWorldMatrix(updateParents, updateChildren) { + const parent = this.parent; + if (updateParents === true && parent !== null) { + parent.updateWorldMatrix(true, false); + } + if (this.matrixAutoUpdate) + this.updateMatrix(); + if (this.parent === null) { + this.matrixWorld.copy(this.matrix); + } else { + this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix); + } + if (updateChildren === true) { + const children2 = this.children; + for (let i = 0, l = children2.length; i < l; i++) { + children2[i].updateWorldMatrix(false, true); + } + } + } + toJSON(meta) { + const isRootObject = meta === void 0 || typeof meta === "string"; + const output = {}; + if (isRootObject) { + meta = { + geometries: {}, + materials: {}, + textures: {}, + images: {}, + shapes: {}, + skeletons: {}, + animations: {}, + nodes: {} + }; + output.metadata = { + version: 4.5, + type: "Object", + generator: "Object3D.toJSON" + }; + } + const object = {}; + object.uuid = this.uuid; + object.type = this.type; + if (this.name !== "") + object.name = this.name; + if (this.castShadow === true) + object.castShadow = true; + if (this.receiveShadow === true) + object.receiveShadow = true; + if (this.visible === false) + object.visible = false; + if (this.frustumCulled === false) + object.frustumCulled = false; + if (this.renderOrder !== 0) + object.renderOrder = this.renderOrder; + if (JSON.stringify(this.userData) !== "{}") + object.userData = this.userData; + object.layers = this.layers.mask; + object.matrix = this.matrix.toArray(); + if (this.matrixAutoUpdate === false) + object.matrixAutoUpdate = false; + if (this.isInstancedMesh) { + object.type = "InstancedMesh"; + object.count = this.count; + object.instanceMatrix = this.instanceMatrix.toJSON(); + if (this.instanceColor !== null) + object.instanceColor = this.instanceColor.toJSON(); + } + function serialize(library, element) { + if (library[element.uuid] === void 0) { + library[element.uuid] = element.toJSON(meta); + } + return element.uuid; + } + if (this.isScene) { + if (this.background) { + if (this.background.isColor) { + object.background = this.background.toJSON(); + } else if (this.background.isTexture) { + object.background = this.background.toJSON(meta).uuid; + } + } + if (this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true) { + object.environment = this.environment.toJSON(meta).uuid; + } + } else if (this.isMesh || this.isLine || this.isPoints) { + object.geometry = serialize(meta.geometries, this.geometry); + const parameters = this.geometry.parameters; + if (parameters !== void 0 && parameters.shapes !== void 0) { + const shapes = parameters.shapes; + if (Array.isArray(shapes)) { + for (let i = 0, l = shapes.length; i < l; i++) { + const shape = shapes[i]; + serialize(meta.shapes, shape); + } + } else { + serialize(meta.shapes, shapes); + } + } + } + if (this.isSkinnedMesh) { + object.bindMode = this.bindMode; + object.bindMatrix = this.bindMatrix.toArray(); + if (this.skeleton !== void 0) { + serialize(meta.skeletons, this.skeleton); + object.skeleton = this.skeleton.uuid; + } + } + if (this.material !== void 0) { + if (Array.isArray(this.material)) { + const uuids = []; + for (let i = 0, l = this.material.length; i < l; i++) { + uuids.push(serialize(meta.materials, this.material[i])); + } + object.material = uuids; + } else { + object.material = serialize(meta.materials, this.material); + } + } + if (this.children.length > 0) { + object.children = []; + for (let i = 0; i < this.children.length; i++) { + object.children.push(this.children[i].toJSON(meta).object); + } + } + if (this.animations.length > 0) { + object.animations = []; + for (let i = 0; i < this.animations.length; i++) { + const animation = this.animations[i]; + object.animations.push(serialize(meta.animations, animation)); + } + } + if (isRootObject) { + const geometries = extractFromCache(meta.geometries); + const materials = extractFromCache(meta.materials); + const textures = extractFromCache(meta.textures); + const images = extractFromCache(meta.images); + const shapes = extractFromCache(meta.shapes); + const skeletons = extractFromCache(meta.skeletons); + const animations = extractFromCache(meta.animations); + const nodes = extractFromCache(meta.nodes); + if (geometries.length > 0) + output.geometries = geometries; + if (materials.length > 0) + output.materials = materials; + if (textures.length > 0) + output.textures = textures; + if (images.length > 0) + output.images = images; + if (shapes.length > 0) + output.shapes = shapes; + if (skeletons.length > 0) + output.skeletons = skeletons; + if (animations.length > 0) + output.animations = animations; + if (nodes.length > 0) + output.nodes = nodes; + } + output.object = object; + return output; + function extractFromCache(cache2) { + const values = []; + for (const key in cache2) { + const data = cache2[key]; + delete data.metadata; + values.push(data); + } + return values; + } + } + clone(recursive) { + return new this.constructor().copy(this, recursive); + } + copy(source, recursive = true) { + this.name = source.name; + this.up.copy(source.up); + this.position.copy(source.position); + this.rotation.order = source.rotation.order; + this.quaternion.copy(source.quaternion); + this.scale.copy(source.scale); + this.matrix.copy(source.matrix); + this.matrixWorld.copy(source.matrixWorld); + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; + this.layers.mask = source.layers.mask; + this.visible = source.visible; + this.castShadow = source.castShadow; + this.receiveShadow = source.receiveShadow; + this.frustumCulled = source.frustumCulled; + this.renderOrder = source.renderOrder; + this.userData = JSON.parse(JSON.stringify(source.userData)); + if (recursive === true) { + for (let i = 0; i < source.children.length; i++) { + const child = source.children[i]; + this.add(child.clone()); + } + } + return this; + } + }; + Object3D2.DefaultUp = /* @__PURE__ */ new Vector32(0, 1, 0); + Object3D2.DefaultMatrixAutoUpdate = true; + var _v0$12 = /* @__PURE__ */ new Vector32(); + var _v1$32 = /* @__PURE__ */ new Vector32(); + var _v2$22 = /* @__PURE__ */ new Vector32(); + var _v3$12 = /* @__PURE__ */ new Vector32(); + var _vab2 = /* @__PURE__ */ new Vector32(); + var _vac2 = /* @__PURE__ */ new Vector32(); + var _vbc2 = /* @__PURE__ */ new Vector32(); + var _vap2 = /* @__PURE__ */ new Vector32(); + var _vbp2 = /* @__PURE__ */ new Vector32(); + var _vcp2 = /* @__PURE__ */ new Vector32(); + var Triangle2 = class { + constructor(a2 = new Vector32(), b = new Vector32(), c2 = new Vector32()) { + this.a = a2; + this.b = b; + this.c = c2; + } + static getNormal(a2, b, c2, target) { + target.subVectors(c2, b); + _v0$12.subVectors(a2, b); + target.cross(_v0$12); + const targetLengthSq = target.lengthSq(); + if (targetLengthSq > 0) { + return target.multiplyScalar(1 / Math.sqrt(targetLengthSq)); + } + return target.set(0, 0, 0); + } + static getBarycoord(point, a2, b, c2, target) { + _v0$12.subVectors(c2, a2); + _v1$32.subVectors(b, a2); + _v2$22.subVectors(point, a2); + const dot00 = _v0$12.dot(_v0$12); + const dot01 = _v0$12.dot(_v1$32); + const dot02 = _v0$12.dot(_v2$22); + const dot11 = _v1$32.dot(_v1$32); + const dot12 = _v1$32.dot(_v2$22); + const denom = dot00 * dot11 - dot01 * dot01; + if (denom === 0) { + return target.set(-2, -1, -1); + } + const invDenom = 1 / denom; + const u = (dot11 * dot02 - dot01 * dot12) * invDenom; + const v = (dot00 * dot12 - dot01 * dot02) * invDenom; + return target.set(1 - u - v, v, u); + } + static containsPoint(point, a2, b, c2) { + this.getBarycoord(point, a2, b, c2, _v3$12); + return _v3$12.x >= 0 && _v3$12.y >= 0 && _v3$12.x + _v3$12.y <= 1; + } + static getUV(point, p1, p2, p3, uv1, uv2, uv3, target) { + this.getBarycoord(point, p1, p2, p3, _v3$12); + target.set(0, 0); + target.addScaledVector(uv1, _v3$12.x); + target.addScaledVector(uv2, _v3$12.y); + target.addScaledVector(uv3, _v3$12.z); + return target; + } + static isFrontFacing(a2, b, c2, direction) { + _v0$12.subVectors(c2, b); + _v1$32.subVectors(a2, b); + return _v0$12.cross(_v1$32).dot(direction) < 0 ? true : false; + } + set(a2, b, c2) { + this.a.copy(a2); + this.b.copy(b); + this.c.copy(c2); + return this; + } + setFromPointsAndIndices(points, i0, i1, i2) { + this.a.copy(points[i0]); + this.b.copy(points[i1]); + this.c.copy(points[i2]); + return this; + } + setFromAttributeAndIndices(attribute, i0, i1, i2) { + this.a.fromBufferAttribute(attribute, i0); + this.b.fromBufferAttribute(attribute, i1); + this.c.fromBufferAttribute(attribute, i2); + return this; + } + clone() { + return new this.constructor().copy(this); + } + copy(triangle) { + this.a.copy(triangle.a); + this.b.copy(triangle.b); + this.c.copy(triangle.c); + return this; + } + getArea() { + _v0$12.subVectors(this.c, this.b); + _v1$32.subVectors(this.a, this.b); + return _v0$12.cross(_v1$32).length() * 0.5; + } + getMidpoint(target) { + return target.addVectors(this.a, this.b).add(this.c).multiplyScalar(1 / 3); + } + getNormal(target) { + return Triangle2.getNormal(this.a, this.b, this.c, target); + } + getPlane(target) { + return target.setFromCoplanarPoints(this.a, this.b, this.c); + } + getBarycoord(point, target) { + return Triangle2.getBarycoord(point, this.a, this.b, this.c, target); + } + getUV(point, uv1, uv2, uv3, target) { + return Triangle2.getUV(point, this.a, this.b, this.c, uv1, uv2, uv3, target); + } + containsPoint(point) { + return Triangle2.containsPoint(point, this.a, this.b, this.c); + } + isFrontFacing(direction) { + return Triangle2.isFrontFacing(this.a, this.b, this.c, direction); + } + intersectsBox(box) { + return box.intersectsTriangle(this); + } + closestPointToPoint(p, target) { + const a2 = this.a, b = this.b, c2 = this.c; + let v, w; + _vab2.subVectors(b, a2); + _vac2.subVectors(c2, a2); + _vap2.subVectors(p, a2); + const d1 = _vab2.dot(_vap2); + const d2 = _vac2.dot(_vap2); + if (d1 <= 0 && d2 <= 0) { + return target.copy(a2); + } + _vbp2.subVectors(p, b); + const d3 = _vab2.dot(_vbp2); + const d4 = _vac2.dot(_vbp2); + if (d3 >= 0 && d4 <= d3) { + return target.copy(b); + } + const vc = d1 * d4 - d3 * d2; + if (vc <= 0 && d1 >= 0 && d3 <= 0) { + v = d1 / (d1 - d3); + return target.copy(a2).addScaledVector(_vab2, v); + } + _vcp2.subVectors(p, c2); + const d5 = _vab2.dot(_vcp2); + const d6 = _vac2.dot(_vcp2); + if (d6 >= 0 && d5 <= d6) { + return target.copy(c2); + } + const vb = d5 * d2 - d1 * d6; + if (vb <= 0 && d2 >= 0 && d6 <= 0) { + w = d2 / (d2 - d6); + return target.copy(a2).addScaledVector(_vac2, w); + } + const va = d3 * d6 - d5 * d4; + if (va <= 0 && d4 - d3 >= 0 && d5 - d6 >= 0) { + _vbc2.subVectors(c2, b); + w = (d4 - d3) / (d4 - d3 + (d5 - d6)); + return target.copy(b).addScaledVector(_vbc2, w); + } + const denom = 1 / (va + vb + vc); + v = vb * denom; + w = vc * denom; + return target.copy(a2).addScaledVector(_vab2, v).addScaledVector(_vac2, w); + } + equals(triangle) { + return triangle.a.equals(this.a) && triangle.b.equals(this.b) && triangle.c.equals(this.c); + } + }; + var materialId2 = 0; + var Material2 = class extends EventDispatcher2 { + constructor() { + super(); + this.isMaterial = true; + Object.defineProperty(this, "id", { + value: materialId2++ + }); + this.uuid = generateUUID2(); + this.name = ""; + this.type = "Material"; + this.blending = NormalBlending2; + this.side = FrontSide2; + this.vertexColors = false; + this.opacity = 1; + this.transparent = false; + this.blendSrc = SrcAlphaFactor2; + this.blendDst = OneMinusSrcAlphaFactor2; + this.blendEquation = AddEquation2; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; + this.depthFunc = LessEqualDepth2; + this.depthTest = true; + this.depthWrite = true; + this.stencilWriteMask = 255; + this.stencilFunc = AlwaysStencilFunc2; + this.stencilRef = 0; + this.stencilFuncMask = 255; + this.stencilFail = KeepStencilOp2; + this.stencilZFail = KeepStencilOp2; + this.stencilZPass = KeepStencilOp2; + this.stencilWrite = false; + this.clippingPlanes = null; + this.clipIntersection = false; + this.clipShadows = false; + this.shadowSide = null; + this.colorWrite = true; + this.precision = null; + this.polygonOffset = false; + this.polygonOffsetFactor = 0; + this.polygonOffsetUnits = 0; + this.dithering = false; + this.alphaToCoverage = false; + this.premultipliedAlpha = false; + this.visible = true; + this.toneMapped = true; + this.userData = {}; + this.version = 0; + this._alphaTest = 0; + } + get alphaTest() { + return this._alphaTest; + } + set alphaTest(value) { + if (this._alphaTest > 0 !== value > 0) { + this.version++; + } + this._alphaTest = value; + } + onBuild() { + } + onBeforeRender() { + } + onBeforeCompile() { + } + customProgramCacheKey() { + return this.onBeforeCompile.toString(); + } + setValues(values) { + if (values === void 0) + return; + for (const key in values) { + const newValue = values[key]; + if (newValue === void 0) { + console.warn("THREE.Material: '" + key + "' parameter is undefined."); + continue; + } + if (key === "shading") { + console.warn("THREE." + this.type + ": .shading has been removed. Use the boolean .flatShading instead."); + this.flatShading = newValue === FlatShading2 ? true : false; + continue; + } + const currentValue = this[key]; + if (currentValue === void 0) { + console.warn("THREE." + this.type + ": '" + key + "' is not a property of this material."); + continue; + } + if (currentValue && currentValue.isColor) { + currentValue.set(newValue); + } else if (currentValue && currentValue.isVector3 && newValue && newValue.isVector3) { + currentValue.copy(newValue); + } else { + this[key] = newValue; + } + } + } + toJSON(meta) { + const isRootObject = meta === void 0 || typeof meta === "string"; + if (isRootObject) { + meta = { + textures: {}, + images: {} + }; + } + const data = { + metadata: { + version: 4.5, + type: "Material", + generator: "Material.toJSON" + } + }; + data.uuid = this.uuid; + data.type = this.type; + if (this.name !== "") + data.name = this.name; + if (this.color && this.color.isColor) + data.color = this.color.getHex(); + if (this.roughness !== void 0) + data.roughness = this.roughness; + if (this.metalness !== void 0) + data.metalness = this.metalness; + if (this.sheen !== void 0) + data.sheen = this.sheen; + if (this.sheenColor && this.sheenColor.isColor) + data.sheenColor = this.sheenColor.getHex(); + if (this.sheenRoughness !== void 0) + data.sheenRoughness = this.sheenRoughness; + if (this.emissive && this.emissive.isColor) + data.emissive = this.emissive.getHex(); + if (this.emissiveIntensity && this.emissiveIntensity !== 1) + data.emissiveIntensity = this.emissiveIntensity; + if (this.specular && this.specular.isColor) + data.specular = this.specular.getHex(); + if (this.specularIntensity !== void 0) + data.specularIntensity = this.specularIntensity; + if (this.specularColor && this.specularColor.isColor) + data.specularColor = this.specularColor.getHex(); + if (this.shininess !== void 0) + data.shininess = this.shininess; + if (this.clearcoat !== void 0) + data.clearcoat = this.clearcoat; + if (this.clearcoatRoughness !== void 0) + data.clearcoatRoughness = this.clearcoatRoughness; + if (this.clearcoatMap && this.clearcoatMap.isTexture) { + data.clearcoatMap = this.clearcoatMap.toJSON(meta).uuid; + } + if (this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture) { + data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON(meta).uuid; + } + if (this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture) { + data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON(meta).uuid; + data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); + } + if (this.iridescence !== void 0) + data.iridescence = this.iridescence; + if (this.iridescenceIOR !== void 0) + data.iridescenceIOR = this.iridescenceIOR; + if (this.iridescenceThicknessRange !== void 0) + data.iridescenceThicknessRange = this.iridescenceThicknessRange; + if (this.iridescenceMap && this.iridescenceMap.isTexture) { + data.iridescenceMap = this.iridescenceMap.toJSON(meta).uuid; + } + if (this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture) { + data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON(meta).uuid; + } + if (this.map && this.map.isTexture) + data.map = this.map.toJSON(meta).uuid; + if (this.matcap && this.matcap.isTexture) + data.matcap = this.matcap.toJSON(meta).uuid; + if (this.alphaMap && this.alphaMap.isTexture) + data.alphaMap = this.alphaMap.toJSON(meta).uuid; + if (this.lightMap && this.lightMap.isTexture) { + data.lightMap = this.lightMap.toJSON(meta).uuid; + data.lightMapIntensity = this.lightMapIntensity; + } + if (this.aoMap && this.aoMap.isTexture) { + data.aoMap = this.aoMap.toJSON(meta).uuid; + data.aoMapIntensity = this.aoMapIntensity; + } + if (this.bumpMap && this.bumpMap.isTexture) { + data.bumpMap = this.bumpMap.toJSON(meta).uuid; + data.bumpScale = this.bumpScale; + } + if (this.normalMap && this.normalMap.isTexture) { + data.normalMap = this.normalMap.toJSON(meta).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); + } + if (this.displacementMap && this.displacementMap.isTexture) { + data.displacementMap = this.displacementMap.toJSON(meta).uuid; + data.displacementScale = this.displacementScale; + data.displacementBias = this.displacementBias; + } + if (this.roughnessMap && this.roughnessMap.isTexture) + data.roughnessMap = this.roughnessMap.toJSON(meta).uuid; + if (this.metalnessMap && this.metalnessMap.isTexture) + data.metalnessMap = this.metalnessMap.toJSON(meta).uuid; + if (this.emissiveMap && this.emissiveMap.isTexture) + data.emissiveMap = this.emissiveMap.toJSON(meta).uuid; + if (this.specularMap && this.specularMap.isTexture) + data.specularMap = this.specularMap.toJSON(meta).uuid; + if (this.specularIntensityMap && this.specularIntensityMap.isTexture) + data.specularIntensityMap = this.specularIntensityMap.toJSON(meta).uuid; + if (this.specularColorMap && this.specularColorMap.isTexture) + data.specularColorMap = this.specularColorMap.toJSON(meta).uuid; + if (this.envMap && this.envMap.isTexture) { + data.envMap = this.envMap.toJSON(meta).uuid; + if (this.combine !== void 0) + data.combine = this.combine; + } + if (this.envMapIntensity !== void 0) + data.envMapIntensity = this.envMapIntensity; + if (this.reflectivity !== void 0) + data.reflectivity = this.reflectivity; + if (this.refractionRatio !== void 0) + data.refractionRatio = this.refractionRatio; + if (this.gradientMap && this.gradientMap.isTexture) { + data.gradientMap = this.gradientMap.toJSON(meta).uuid; + } + if (this.transmission !== void 0) + data.transmission = this.transmission; + if (this.transmissionMap && this.transmissionMap.isTexture) + data.transmissionMap = this.transmissionMap.toJSON(meta).uuid; + if (this.thickness !== void 0) + data.thickness = this.thickness; + if (this.thicknessMap && this.thicknessMap.isTexture) + data.thicknessMap = this.thicknessMap.toJSON(meta).uuid; + if (this.attenuationDistance !== void 0) + data.attenuationDistance = this.attenuationDistance; + if (this.attenuationColor !== void 0) + data.attenuationColor = this.attenuationColor.getHex(); + if (this.size !== void 0) + data.size = this.size; + if (this.shadowSide !== null) + data.shadowSide = this.shadowSide; + if (this.sizeAttenuation !== void 0) + data.sizeAttenuation = this.sizeAttenuation; + if (this.blending !== NormalBlending2) + data.blending = this.blending; + if (this.side !== FrontSide2) + data.side = this.side; + if (this.vertexColors) + data.vertexColors = true; + if (this.opacity < 1) + data.opacity = this.opacity; + if (this.transparent === true) + data.transparent = this.transparent; + data.depthFunc = this.depthFunc; + data.depthTest = this.depthTest; + data.depthWrite = this.depthWrite; + data.colorWrite = this.colorWrite; + data.stencilWrite = this.stencilWrite; + data.stencilWriteMask = this.stencilWriteMask; + data.stencilFunc = this.stencilFunc; + data.stencilRef = this.stencilRef; + data.stencilFuncMask = this.stencilFuncMask; + data.stencilFail = this.stencilFail; + data.stencilZFail = this.stencilZFail; + data.stencilZPass = this.stencilZPass; + if (this.rotation !== void 0 && this.rotation !== 0) + data.rotation = this.rotation; + if (this.polygonOffset === true) + data.polygonOffset = true; + if (this.polygonOffsetFactor !== 0) + data.polygonOffsetFactor = this.polygonOffsetFactor; + if (this.polygonOffsetUnits !== 0) + data.polygonOffsetUnits = this.polygonOffsetUnits; + if (this.linewidth !== void 0 && this.linewidth !== 1) + data.linewidth = this.linewidth; + if (this.dashSize !== void 0) + data.dashSize = this.dashSize; + if (this.gapSize !== void 0) + data.gapSize = this.gapSize; + if (this.scale !== void 0) + data.scale = this.scale; + if (this.dithering === true) + data.dithering = true; + if (this.alphaTest > 0) + data.alphaTest = this.alphaTest; + if (this.alphaToCoverage === true) + data.alphaToCoverage = this.alphaToCoverage; + if (this.premultipliedAlpha === true) + data.premultipliedAlpha = this.premultipliedAlpha; + if (this.wireframe === true) + data.wireframe = this.wireframe; + if (this.wireframeLinewidth > 1) + data.wireframeLinewidth = this.wireframeLinewidth; + if (this.wireframeLinecap !== "round") + data.wireframeLinecap = this.wireframeLinecap; + if (this.wireframeLinejoin !== "round") + data.wireframeLinejoin = this.wireframeLinejoin; + if (this.flatShading === true) + data.flatShading = this.flatShading; + if (this.visible === false) + data.visible = false; + if (this.toneMapped === false) + data.toneMapped = false; + if (this.fog === false) + data.fog = false; + if (JSON.stringify(this.userData) !== "{}") + data.userData = this.userData; + function extractFromCache(cache2) { + const values = []; + for (const key in cache2) { + const data2 = cache2[key]; + delete data2.metadata; + values.push(data2); + } + return values; + } + if (isRootObject) { + const textures = extractFromCache(meta.textures); + const images = extractFromCache(meta.images); + if (textures.length > 0) + data.textures = textures; + if (images.length > 0) + data.images = images; + } + return data; + } + clone() { + return new this.constructor().copy(this); + } + copy(source) { + this.name = source.name; + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; + this.opacity = source.opacity; + this.transparent = source.transparent; + this.blendSrc = source.blendSrc; + this.blendDst = source.blendDst; + this.blendEquation = source.blendEquation; + this.blendSrcAlpha = source.blendSrcAlpha; + this.blendDstAlpha = source.blendDstAlpha; + this.blendEquationAlpha = source.blendEquationAlpha; + this.depthFunc = source.depthFunc; + this.depthTest = source.depthTest; + this.depthWrite = source.depthWrite; + this.stencilWriteMask = source.stencilWriteMask; + this.stencilFunc = source.stencilFunc; + this.stencilRef = source.stencilRef; + this.stencilFuncMask = source.stencilFuncMask; + this.stencilFail = source.stencilFail; + this.stencilZFail = source.stencilZFail; + this.stencilZPass = source.stencilZPass; + this.stencilWrite = source.stencilWrite; + const srcPlanes = source.clippingPlanes; + let dstPlanes = null; + if (srcPlanes !== null) { + const n = srcPlanes.length; + dstPlanes = new Array(n); + for (let i = 0; i !== n; ++i) { + dstPlanes[i] = srcPlanes[i].clone(); + } + } + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; + this.shadowSide = source.shadowSide; + this.colorWrite = source.colorWrite; + this.precision = source.precision; + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; + this.dithering = source.dithering; + this.alphaTest = source.alphaTest; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; + this.visible = source.visible; + this.toneMapped = source.toneMapped; + this.userData = JSON.parse(JSON.stringify(source.userData)); + return this; + } + dispose() { + this.dispatchEvent({ + type: "dispose" + }); + } + set needsUpdate(value) { + if (value === true) + this.version++; + } + }; + var MeshBasicMaterial2 = class extends Material2 { + constructor(parameters) { + super(); + this.isMeshBasicMaterial = true; + this.type = "MeshBasicMaterial"; + this.color = new Color3(16777215); + this.map = null; + this.lightMap = null; + this.lightMapIntensity = 1; + this.aoMap = null; + this.aoMapIntensity = 1; + this.specularMap = null; + this.alphaMap = null; + this.envMap = null; + this.combine = MultiplyOperation2; + this.reflectivity = 1; + this.refractionRatio = 0.98; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = "round"; + this.wireframeLinejoin = "round"; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.color.copy(source.color); + this.map = source.map; + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + this.specularMap = source.specularMap; + this.alphaMap = source.alphaMap; + this.envMap = source.envMap; + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + this.fog = source.fog; + return this; + } + }; + var _vector$92 = /* @__PURE__ */ new Vector32(); + var _vector2$12 = /* @__PURE__ */ new Vector22(); + var BufferAttribute2 = class { + constructor(array2, itemSize, normalized) { + if (Array.isArray(array2)) { + throw new TypeError("THREE.BufferAttribute: array should be a Typed Array."); + } + this.isBufferAttribute = true; + this.name = ""; + this.array = array2; + this.itemSize = itemSize; + this.count = array2 !== void 0 ? array2.length / itemSize : 0; + this.normalized = normalized === true; + this.usage = StaticDrawUsage2; + this.updateRange = { + offset: 0, + count: -1 + }; + this.version = 0; + } + onUploadCallback() { + } + set needsUpdate(value) { + if (value === true) + this.version++; + } + setUsage(value) { + this.usage = value; + return this; + } + copy(source) { + this.name = source.name; + this.array = new source.array.constructor(source.array); + this.itemSize = source.itemSize; + this.count = source.count; + this.normalized = source.normalized; + this.usage = source.usage; + return this; + } + copyAt(index1, attribute, index2) { + index1 *= this.itemSize; + index2 *= attribute.itemSize; + for (let i = 0, l = this.itemSize; i < l; i++) { + this.array[index1 + i] = attribute.array[index2 + i]; + } + return this; + } + copyArray(array2) { + this.array.set(array2); + return this; + } + copyColorsArray(colors) { + const array2 = this.array; + let offset = 0; + for (let i = 0, l = colors.length; i < l; i++) { + let color2 = colors[i]; + if (color2 === void 0) { + console.warn("THREE.BufferAttribute.copyColorsArray(): color is undefined", i); + color2 = new Color3(); + } + array2[offset++] = color2.r; + array2[offset++] = color2.g; + array2[offset++] = color2.b; + } + return this; + } + copyVector2sArray(vectors) { + const array2 = this.array; + let offset = 0; + for (let i = 0, l = vectors.length; i < l; i++) { + let vector = vectors[i]; + if (vector === void 0) { + console.warn("THREE.BufferAttribute.copyVector2sArray(): vector is undefined", i); + vector = new Vector22(); + } + array2[offset++] = vector.x; + array2[offset++] = vector.y; + } + return this; + } + copyVector3sArray(vectors) { + const array2 = this.array; + let offset = 0; + for (let i = 0, l = vectors.length; i < l; i++) { + let vector = vectors[i]; + if (vector === void 0) { + console.warn("THREE.BufferAttribute.copyVector3sArray(): vector is undefined", i); + vector = new Vector32(); + } + array2[offset++] = vector.x; + array2[offset++] = vector.y; + array2[offset++] = vector.z; + } + return this; + } + copyVector4sArray(vectors) { + const array2 = this.array; + let offset = 0; + for (let i = 0, l = vectors.length; i < l; i++) { + let vector = vectors[i]; + if (vector === void 0) { + console.warn("THREE.BufferAttribute.copyVector4sArray(): vector is undefined", i); + vector = new Vector42(); + } + array2[offset++] = vector.x; + array2[offset++] = vector.y; + array2[offset++] = vector.z; + array2[offset++] = vector.w; + } + return this; + } + applyMatrix3(m2) { + if (this.itemSize === 2) { + for (let i = 0, l = this.count; i < l; i++) { + _vector2$12.fromBufferAttribute(this, i); + _vector2$12.applyMatrix3(m2); + this.setXY(i, _vector2$12.x, _vector2$12.y); + } + } else if (this.itemSize === 3) { + for (let i = 0, l = this.count; i < l; i++) { + _vector$92.fromBufferAttribute(this, i); + _vector$92.applyMatrix3(m2); + this.setXYZ(i, _vector$92.x, _vector$92.y, _vector$92.z); + } + } + return this; + } + applyMatrix4(m2) { + for (let i = 0, l = this.count; i < l; i++) { + _vector$92.fromBufferAttribute(this, i); + _vector$92.applyMatrix4(m2); + this.setXYZ(i, _vector$92.x, _vector$92.y, _vector$92.z); + } + return this; + } + applyNormalMatrix(m2) { + for (let i = 0, l = this.count; i < l; i++) { + _vector$92.fromBufferAttribute(this, i); + _vector$92.applyNormalMatrix(m2); + this.setXYZ(i, _vector$92.x, _vector$92.y, _vector$92.z); + } + return this; + } + transformDirection(m2) { + for (let i = 0, l = this.count; i < l; i++) { + _vector$92.fromBufferAttribute(this, i); + _vector$92.transformDirection(m2); + this.setXYZ(i, _vector$92.x, _vector$92.y, _vector$92.z); + } + return this; + } + set(value, offset = 0) { + this.array.set(value, offset); + return this; + } + getX(index2) { + return this.array[index2 * this.itemSize]; + } + setX(index2, x2) { + this.array[index2 * this.itemSize] = x2; + return this; + } + getY(index2) { + return this.array[index2 * this.itemSize + 1]; + } + setY(index2, y2) { + this.array[index2 * this.itemSize + 1] = y2; + return this; + } + getZ(index2) { + return this.array[index2 * this.itemSize + 2]; + } + setZ(index2, z) { + this.array[index2 * this.itemSize + 2] = z; + return this; + } + getW(index2) { + return this.array[index2 * this.itemSize + 3]; + } + setW(index2, w) { + this.array[index2 * this.itemSize + 3] = w; + return this; + } + setXY(index2, x2, y2) { + index2 *= this.itemSize; + this.array[index2 + 0] = x2; + this.array[index2 + 1] = y2; + return this; + } + setXYZ(index2, x2, y2, z) { + index2 *= this.itemSize; + this.array[index2 + 0] = x2; + this.array[index2 + 1] = y2; + this.array[index2 + 2] = z; + return this; + } + setXYZW(index2, x2, y2, z, w) { + index2 *= this.itemSize; + this.array[index2 + 0] = x2; + this.array[index2 + 1] = y2; + this.array[index2 + 2] = z; + this.array[index2 + 3] = w; + return this; + } + onUpload(callback) { + this.onUploadCallback = callback; + return this; + } + clone() { + return new this.constructor(this.array, this.itemSize).copy(this); + } + toJSON() { + const data = { + itemSize: this.itemSize, + type: this.array.constructor.name, + array: Array.from(this.array), + normalized: this.normalized + }; + if (this.name !== "") + data.name = this.name; + if (this.usage !== StaticDrawUsage2) + data.usage = this.usage; + if (this.updateRange.offset !== 0 || this.updateRange.count !== -1) + data.updateRange = this.updateRange; + return data; + } + }; + var Int8BufferAttribute = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized) { + super(new Int8Array(array2), itemSize, normalized); + } + }; + var Uint8BufferAttribute = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized) { + super(new Uint8Array(array2), itemSize, normalized); + } + }; + var Uint8ClampedBufferAttribute = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized) { + super(new Uint8ClampedArray(array2), itemSize, normalized); + } + }; + var Int16BufferAttribute = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized) { + super(new Int16Array(array2), itemSize, normalized); + } + }; + var Uint16BufferAttribute2 = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized) { + super(new Uint16Array(array2), itemSize, normalized); + } + }; + var Int32BufferAttribute = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized) { + super(new Int32Array(array2), itemSize, normalized); + } + }; + var Uint32BufferAttribute2 = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized) { + super(new Uint32Array(array2), itemSize, normalized); + } + }; + var Float16BufferAttribute = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized) { + super(new Uint16Array(array2), itemSize, normalized); + this.isFloat16BufferAttribute = true; + } + }; + var Float32BufferAttribute2 = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized) { + super(new Float32Array(array2), itemSize, normalized); + } + }; + var Float64BufferAttribute = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized) { + super(new Float64Array(array2), itemSize, normalized); + } + }; + var _id$12 = 0; + var _m12 = /* @__PURE__ */ new Matrix42(); + var _obj2 = /* @__PURE__ */ new Object3D2(); + var _offset2 = /* @__PURE__ */ new Vector32(); + var _box$12 = /* @__PURE__ */ new Box32(); + var _boxMorphTargets2 = /* @__PURE__ */ new Box32(); + var _vector$82 = /* @__PURE__ */ new Vector32(); + var BufferGeometry2 = class extends EventDispatcher2 { + constructor() { + super(); + this.isBufferGeometry = true; + Object.defineProperty(this, "id", { + value: _id$12++ + }); + this.uuid = generateUUID2(); + this.name = ""; + this.type = "BufferGeometry"; + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.morphTargetsRelative = false; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; + this.drawRange = { + start: 0, + count: Infinity + }; + this.userData = {}; + } + getIndex() { + return this.index; + } + setIndex(index2) { + if (Array.isArray(index2)) { + this.index = new (arrayNeedsUint322(index2) ? Uint32BufferAttribute2 : Uint16BufferAttribute2)(index2, 1); + } else { + this.index = index2; + } + return this; + } + getAttribute(name) { + return this.attributes[name]; + } + setAttribute(name, attribute) { + this.attributes[name] = attribute; + return this; + } + deleteAttribute(name) { + delete this.attributes[name]; + return this; + } + hasAttribute(name) { + return this.attributes[name] !== void 0; + } + addGroup(start2, count, materialIndex = 0) { + this.groups.push({ + start: start2, + count, + materialIndex + }); + } + clearGroups() { + this.groups = []; + } + setDrawRange(start2, count) { + this.drawRange.start = start2; + this.drawRange.count = count; + } + applyMatrix4(matrix) { + const position = this.attributes.position; + if (position !== void 0) { + position.applyMatrix4(matrix); + position.needsUpdate = true; + } + const normal = this.attributes.normal; + if (normal !== void 0) { + const normalMatrix = new Matrix32().getNormalMatrix(matrix); + normal.applyNormalMatrix(normalMatrix); + normal.needsUpdate = true; + } + const tangent = this.attributes.tangent; + if (tangent !== void 0) { + tangent.transformDirection(matrix); + tangent.needsUpdate = true; + } + if (this.boundingBox !== null) { + this.computeBoundingBox(); + } + if (this.boundingSphere !== null) { + this.computeBoundingSphere(); + } + return this; + } + applyQuaternion(q) { + _m12.makeRotationFromQuaternion(q); + this.applyMatrix4(_m12); + return this; + } + rotateX(angle) { + _m12.makeRotationX(angle); + this.applyMatrix4(_m12); + return this; + } + rotateY(angle) { + _m12.makeRotationY(angle); + this.applyMatrix4(_m12); + return this; + } + rotateZ(angle) { + _m12.makeRotationZ(angle); + this.applyMatrix4(_m12); + return this; + } + translate(x2, y2, z) { + _m12.makeTranslation(x2, y2, z); + this.applyMatrix4(_m12); + return this; + } + scale(x2, y2, z) { + _m12.makeScale(x2, y2, z); + this.applyMatrix4(_m12); + return this; + } + lookAt(vector) { + _obj2.lookAt(vector); + _obj2.updateMatrix(); + this.applyMatrix4(_obj2.matrix); + return this; + } + center() { + this.computeBoundingBox(); + this.boundingBox.getCenter(_offset2).negate(); + this.translate(_offset2.x, _offset2.y, _offset2.z); + return this; + } + setFromPoints(points) { + const position = []; + for (let i = 0, l = points.length; i < l; i++) { + const point = points[i]; + position.push(point.x, point.y, point.z || 0); + } + this.setAttribute("position", new Float32BufferAttribute2(position, 3)); + return this; + } + computeBoundingBox() { + if (this.boundingBox === null) { + this.boundingBox = new Box32(); + } + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; + if (position && position.isGLBufferAttribute) { + console.error('THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this); + this.boundingBox.set(new Vector32(-Infinity, -Infinity, -Infinity), new Vector32(Infinity, Infinity, Infinity)); + return; + } + if (position !== void 0) { + this.boundingBox.setFromBufferAttribute(position); + if (morphAttributesPosition) { + for (let i = 0, il = morphAttributesPosition.length; i < il; i++) { + const morphAttribute = morphAttributesPosition[i]; + _box$12.setFromBufferAttribute(morphAttribute); + if (this.morphTargetsRelative) { + _vector$82.addVectors(this.boundingBox.min, _box$12.min); + this.boundingBox.expandByPoint(_vector$82); + _vector$82.addVectors(this.boundingBox.max, _box$12.max); + this.boundingBox.expandByPoint(_vector$82); + } else { + this.boundingBox.expandByPoint(_box$12.min); + this.boundingBox.expandByPoint(_box$12.max); + } + } + } + } else { + this.boundingBox.makeEmpty(); + } + if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) { + console.error('THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this); + } + } + computeBoundingSphere() { + if (this.boundingSphere === null) { + this.boundingSphere = new Sphere2(); + } + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; + if (position && position.isGLBufferAttribute) { + console.error('THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this); + this.boundingSphere.set(new Vector32(), Infinity); + return; + } + if (position) { + const center = this.boundingSphere.center; + _box$12.setFromBufferAttribute(position); + if (morphAttributesPosition) { + for (let i = 0, il = morphAttributesPosition.length; i < il; i++) { + const morphAttribute = morphAttributesPosition[i]; + _boxMorphTargets2.setFromBufferAttribute(morphAttribute); + if (this.morphTargetsRelative) { + _vector$82.addVectors(_box$12.min, _boxMorphTargets2.min); + _box$12.expandByPoint(_vector$82); + _vector$82.addVectors(_box$12.max, _boxMorphTargets2.max); + _box$12.expandByPoint(_vector$82); + } else { + _box$12.expandByPoint(_boxMorphTargets2.min); + _box$12.expandByPoint(_boxMorphTargets2.max); + } + } + } + _box$12.getCenter(center); + let maxRadiusSq = 0; + for (let i = 0, il = position.count; i < il; i++) { + _vector$82.fromBufferAttribute(position, i); + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$82)); + } + if (morphAttributesPosition) { + for (let i = 0, il = morphAttributesPosition.length; i < il; i++) { + const morphAttribute = morphAttributesPosition[i]; + const morphTargetsRelative = this.morphTargetsRelative; + for (let j = 0, jl = morphAttribute.count; j < jl; j++) { + _vector$82.fromBufferAttribute(morphAttribute, j); + if (morphTargetsRelative) { + _offset2.fromBufferAttribute(position, j); + _vector$82.add(_offset2); + } + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$82)); + } + } + } + this.boundingSphere.radius = Math.sqrt(maxRadiusSq); + if (isNaN(this.boundingSphere.radius)) { + console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this); + } + } + } + computeTangents() { + const index2 = this.index; + const attributes = this.attributes; + if (index2 === null || attributes.position === void 0 || attributes.normal === void 0 || attributes.uv === void 0) { + console.error("THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)"); + return; + } + const indices = index2.array; + const positions = attributes.position.array; + const normals = attributes.normal.array; + const uvs = attributes.uv.array; + const nVertices = positions.length / 3; + if (this.hasAttribute("tangent") === false) { + this.setAttribute("tangent", new BufferAttribute2(new Float32Array(4 * nVertices), 4)); + } + const tangents = this.getAttribute("tangent").array; + const tan1 = [], tan2 = []; + for (let i = 0; i < nVertices; i++) { + tan1[i] = new Vector32(); + tan2[i] = new Vector32(); + } + const vA = new Vector32(), vB = new Vector32(), vC = new Vector32(), uvA = new Vector22(), uvB = new Vector22(), uvC = new Vector22(), sdir = new Vector32(), tdir = new Vector32(); + function handleTriangle(a2, b, c2) { + vA.fromArray(positions, a2 * 3); + vB.fromArray(positions, b * 3); + vC.fromArray(positions, c2 * 3); + uvA.fromArray(uvs, a2 * 2); + uvB.fromArray(uvs, b * 2); + uvC.fromArray(uvs, c2 * 2); + vB.sub(vA); + vC.sub(vA); + uvB.sub(uvA); + uvC.sub(uvA); + const r = 1 / (uvB.x * uvC.y - uvC.x * uvB.y); + if (!isFinite(r)) + return; + sdir.copy(vB).multiplyScalar(uvC.y).addScaledVector(vC, -uvB.y).multiplyScalar(r); + tdir.copy(vC).multiplyScalar(uvB.x).addScaledVector(vB, -uvC.x).multiplyScalar(r); + tan1[a2].add(sdir); + tan1[b].add(sdir); + tan1[c2].add(sdir); + tan2[a2].add(tdir); + tan2[b].add(tdir); + tan2[c2].add(tdir); + } + let groups = this.groups; + if (groups.length === 0) { + groups = [{ + start: 0, + count: indices.length + }]; + } + for (let i = 0, il = groups.length; i < il; ++i) { + const group = groups[i]; + const start2 = group.start; + const count = group.count; + for (let j = start2, jl = start2 + count; j < jl; j += 3) { + handleTriangle(indices[j + 0], indices[j + 1], indices[j + 2]); + } + } + const tmp2 = new Vector32(), tmp22 = new Vector32(); + const n = new Vector32(), n2 = new Vector32(); + function handleVertex(v) { + n.fromArray(normals, v * 3); + n2.copy(n); + const t = tan1[v]; + tmp2.copy(t); + tmp2.sub(n.multiplyScalar(n.dot(t))).normalize(); + tmp22.crossVectors(n2, t); + const test = tmp22.dot(tan2[v]); + const w = test < 0 ? -1 : 1; + tangents[v * 4] = tmp2.x; + tangents[v * 4 + 1] = tmp2.y; + tangents[v * 4 + 2] = tmp2.z; + tangents[v * 4 + 3] = w; + } + for (let i = 0, il = groups.length; i < il; ++i) { + const group = groups[i]; + const start2 = group.start; + const count = group.count; + for (let j = start2, jl = start2 + count; j < jl; j += 3) { + handleVertex(indices[j + 0]); + handleVertex(indices[j + 1]); + handleVertex(indices[j + 2]); + } + } + } + computeVertexNormals() { + const index2 = this.index; + const positionAttribute = this.getAttribute("position"); + if (positionAttribute !== void 0) { + let normalAttribute = this.getAttribute("normal"); + if (normalAttribute === void 0) { + normalAttribute = new BufferAttribute2(new Float32Array(positionAttribute.count * 3), 3); + this.setAttribute("normal", normalAttribute); + } else { + for (let i = 0, il = normalAttribute.count; i < il; i++) { + normalAttribute.setXYZ(i, 0, 0, 0); + } + } + const pA = new Vector32(), pB = new Vector32(), pC = new Vector32(); + const nA = new Vector32(), nB = new Vector32(), nC = new Vector32(); + const cb = new Vector32(), ab = new Vector32(); + if (index2) { + for (let i = 0, il = index2.count; i < il; i += 3) { + const vA = index2.getX(i + 0); + const vB = index2.getX(i + 1); + const vC = index2.getX(i + 2); + pA.fromBufferAttribute(positionAttribute, vA); + pB.fromBufferAttribute(positionAttribute, vB); + pC.fromBufferAttribute(positionAttribute, vC); + cb.subVectors(pC, pB); + ab.subVectors(pA, pB); + cb.cross(ab); + nA.fromBufferAttribute(normalAttribute, vA); + nB.fromBufferAttribute(normalAttribute, vB); + nC.fromBufferAttribute(normalAttribute, vC); + nA.add(cb); + nB.add(cb); + nC.add(cb); + normalAttribute.setXYZ(vA, nA.x, nA.y, nA.z); + normalAttribute.setXYZ(vB, nB.x, nB.y, nB.z); + normalAttribute.setXYZ(vC, nC.x, nC.y, nC.z); + } + } else { + for (let i = 0, il = positionAttribute.count; i < il; i += 3) { + pA.fromBufferAttribute(positionAttribute, i + 0); + pB.fromBufferAttribute(positionAttribute, i + 1); + pC.fromBufferAttribute(positionAttribute, i + 2); + cb.subVectors(pC, pB); + ab.subVectors(pA, pB); + cb.cross(ab); + normalAttribute.setXYZ(i + 0, cb.x, cb.y, cb.z); + normalAttribute.setXYZ(i + 1, cb.x, cb.y, cb.z); + normalAttribute.setXYZ(i + 2, cb.x, cb.y, cb.z); + } + } + this.normalizeNormals(); + normalAttribute.needsUpdate = true; + } + } + merge(geometry, offset) { + if (!(geometry && geometry.isBufferGeometry)) { + console.error("THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.", geometry); + return; + } + if (offset === void 0) { + offset = 0; + console.warn("THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge."); + } + const attributes = this.attributes; + for (const key in attributes) { + if (geometry.attributes[key] === void 0) + continue; + const attribute1 = attributes[key]; + const attributeArray1 = attribute1.array; + const attribute2 = geometry.attributes[key]; + const attributeArray2 = attribute2.array; + const attributeOffset = attribute2.itemSize * offset; + const length = Math.min(attributeArray2.length, attributeArray1.length - attributeOffset); + for (let i = 0, j = attributeOffset; i < length; i++, j++) { + attributeArray1[j] = attributeArray2[i]; + } + } + return this; + } + normalizeNormals() { + const normals = this.attributes.normal; + for (let i = 0, il = normals.count; i < il; i++) { + _vector$82.fromBufferAttribute(normals, i); + _vector$82.normalize(); + normals.setXYZ(i, _vector$82.x, _vector$82.y, _vector$82.z); + } + } + toNonIndexed() { + function convertBufferAttribute(attribute, indices2) { + const array2 = attribute.array; + const itemSize = attribute.itemSize; + const normalized = attribute.normalized; + const array22 = new array2.constructor(indices2.length * itemSize); + let index2 = 0, index22 = 0; + for (let i = 0, l = indices2.length; i < l; i++) { + if (attribute.isInterleavedBufferAttribute) { + index2 = indices2[i] * attribute.data.stride + attribute.offset; + } else { + index2 = indices2[i] * itemSize; + } + for (let j = 0; j < itemSize; j++) { + array22[index22++] = array2[index2++]; + } + } + return new BufferAttribute2(array22, itemSize, normalized); + } + if (this.index === null) { + console.warn("THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed."); + return this; + } + const geometry2 = new BufferGeometry2(); + const indices = this.index.array; + const attributes = this.attributes; + for (const name in attributes) { + const attribute = attributes[name]; + const newAttribute = convertBufferAttribute(attribute, indices); + geometry2.setAttribute(name, newAttribute); + } + const morphAttributes = this.morphAttributes; + for (const name in morphAttributes) { + const morphArray = []; + const morphAttribute = morphAttributes[name]; + for (let i = 0, il = morphAttribute.length; i < il; i++) { + const attribute = morphAttribute[i]; + const newAttribute = convertBufferAttribute(attribute, indices); + morphArray.push(newAttribute); + } + geometry2.morphAttributes[name] = morphArray; + } + geometry2.morphTargetsRelative = this.morphTargetsRelative; + const groups = this.groups; + for (let i = 0, l = groups.length; i < l; i++) { + const group = groups[i]; + geometry2.addGroup(group.start, group.count, group.materialIndex); + } + return geometry2; + } + toJSON() { + const data = { + metadata: { + version: 4.5, + type: "BufferGeometry", + generator: "BufferGeometry.toJSON" + } + }; + data.uuid = this.uuid; + data.type = this.type; + if (this.name !== "") + data.name = this.name; + if (Object.keys(this.userData).length > 0) + data.userData = this.userData; + if (this.parameters !== void 0) { + const parameters = this.parameters; + for (const key in parameters) { + if (parameters[key] !== void 0) + data[key] = parameters[key]; + } + return data; + } + data.data = { + attributes: {} + }; + const index2 = this.index; + if (index2 !== null) { + data.data.index = { + type: index2.array.constructor.name, + array: Array.prototype.slice.call(index2.array) + }; + } + const attributes = this.attributes; + for (const key in attributes) { + const attribute = attributes[key]; + data.data.attributes[key] = attribute.toJSON(data.data); + } + const morphAttributes = {}; + let hasMorphAttributes = false; + for (const key in this.morphAttributes) { + const attributeArray = this.morphAttributes[key]; + const array2 = []; + for (let i = 0, il = attributeArray.length; i < il; i++) { + const attribute = attributeArray[i]; + array2.push(attribute.toJSON(data.data)); + } + if (array2.length > 0) { + morphAttributes[key] = array2; + hasMorphAttributes = true; + } + } + if (hasMorphAttributes) { + data.data.morphAttributes = morphAttributes; + data.data.morphTargetsRelative = this.morphTargetsRelative; + } + const groups = this.groups; + if (groups.length > 0) { + data.data.groups = JSON.parse(JSON.stringify(groups)); + } + const boundingSphere = this.boundingSphere; + if (boundingSphere !== null) { + data.data.boundingSphere = { + center: boundingSphere.center.toArray(), + radius: boundingSphere.radius + }; + } + return data; + } + clone() { + return new this.constructor().copy(this); + } + copy(source) { + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; + const data = {}; + this.name = source.name; + const index2 = source.index; + if (index2 !== null) { + this.setIndex(index2.clone(data)); + } + const attributes = source.attributes; + for (const name in attributes) { + const attribute = attributes[name]; + this.setAttribute(name, attribute.clone(data)); + } + const morphAttributes = source.morphAttributes; + for (const name in morphAttributes) { + const array2 = []; + const morphAttribute = morphAttributes[name]; + for (let i = 0, l = morphAttribute.length; i < l; i++) { + array2.push(morphAttribute[i].clone(data)); + } + this.morphAttributes[name] = array2; + } + this.morphTargetsRelative = source.morphTargetsRelative; + const groups = source.groups; + for (let i = 0, l = groups.length; i < l; i++) { + const group = groups[i]; + this.addGroup(group.start, group.count, group.materialIndex); + } + const boundingBox = source.boundingBox; + if (boundingBox !== null) { + this.boundingBox = boundingBox.clone(); + } + const boundingSphere = source.boundingSphere; + if (boundingSphere !== null) { + this.boundingSphere = boundingSphere.clone(); + } + this.drawRange.start = source.drawRange.start; + this.drawRange.count = source.drawRange.count; + this.userData = source.userData; + if (source.parameters !== void 0) + this.parameters = Object.assign({}, source.parameters); + return this; + } + dispose() { + this.dispatchEvent({ + type: "dispose" + }); + } + }; + var _inverseMatrix$22 = /* @__PURE__ */ new Matrix42(); + var _ray$22 = /* @__PURE__ */ new Ray2(); + var _sphere$32 = /* @__PURE__ */ new Sphere2(); + var _vA$12 = /* @__PURE__ */ new Vector32(); + var _vB$12 = /* @__PURE__ */ new Vector32(); + var _vC$12 = /* @__PURE__ */ new Vector32(); + var _tempA2 = /* @__PURE__ */ new Vector32(); + var _tempB2 = /* @__PURE__ */ new Vector32(); + var _tempC2 = /* @__PURE__ */ new Vector32(); + var _morphA2 = /* @__PURE__ */ new Vector32(); + var _morphB2 = /* @__PURE__ */ new Vector32(); + var _morphC2 = /* @__PURE__ */ new Vector32(); + var _uvA$12 = /* @__PURE__ */ new Vector22(); + var _uvB$12 = /* @__PURE__ */ new Vector22(); + var _uvC$12 = /* @__PURE__ */ new Vector22(); + var _intersectionPoint2 = /* @__PURE__ */ new Vector32(); + var _intersectionPointWorld2 = /* @__PURE__ */ new Vector32(); + var Mesh2 = class extends Object3D2 { + constructor(geometry = new BufferGeometry2(), material = new MeshBasicMaterial2()) { + super(); + this.isMesh = true; + this.type = "Mesh"; + this.geometry = geometry; + this.material = material; + this.updateMorphTargets(); + } + copy(source, recursive) { + super.copy(source, recursive); + if (source.morphTargetInfluences !== void 0) { + this.morphTargetInfluences = source.morphTargetInfluences.slice(); + } + if (source.morphTargetDictionary !== void 0) { + this.morphTargetDictionary = Object.assign({}, source.morphTargetDictionary); + } + this.material = source.material; + this.geometry = source.geometry; + return this; + } + updateMorphTargets() { + const geometry = this.geometry; + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys(morphAttributes); + if (keys.length > 0) { + const morphAttribute = morphAttributes[keys[0]]; + if (morphAttribute !== void 0) { + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; + for (let m2 = 0, ml = morphAttribute.length; m2 < ml; m2++) { + const name = morphAttribute[m2].name || String(m2); + this.morphTargetInfluences.push(0); + this.morphTargetDictionary[name] = m2; + } + } + } + } + raycast(raycaster, intersects2) { + const geometry = this.geometry; + const material = this.material; + const matrixWorld = this.matrixWorld; + if (material === void 0) + return; + if (geometry.boundingSphere === null) + geometry.computeBoundingSphere(); + _sphere$32.copy(geometry.boundingSphere); + _sphere$32.applyMatrix4(matrixWorld); + if (raycaster.ray.intersectsSphere(_sphere$32) === false) + return; + _inverseMatrix$22.copy(matrixWorld).invert(); + _ray$22.copy(raycaster.ray).applyMatrix4(_inverseMatrix$22); + if (geometry.boundingBox !== null) { + if (_ray$22.intersectsBox(geometry.boundingBox) === false) + return; + } + let intersection; + const index2 = geometry.index; + const position = geometry.attributes.position; + const morphPosition = geometry.morphAttributes.position; + const morphTargetsRelative = geometry.morphTargetsRelative; + const uv = geometry.attributes.uv; + const uv2 = geometry.attributes.uv2; + const groups = geometry.groups; + const drawRange = geometry.drawRange; + if (index2 !== null) { + if (Array.isArray(material)) { + for (let i = 0, il = groups.length; i < il; i++) { + const group = groups[i]; + const groupMaterial = material[group.materialIndex]; + const start2 = Math.max(group.start, drawRange.start); + const end = Math.min(index2.count, Math.min(group.start + group.count, drawRange.start + drawRange.count)); + for (let j = start2, jl = end; j < jl; j += 3) { + const a2 = index2.getX(j); + const b = index2.getX(j + 1); + const c2 = index2.getX(j + 2); + intersection = checkBufferGeometryIntersection2(this, groupMaterial, raycaster, _ray$22, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b, c2); + if (intersection) { + intersection.faceIndex = Math.floor(j / 3); + intersection.face.materialIndex = group.materialIndex; + intersects2.push(intersection); + } + } + } + } else { + const start2 = Math.max(0, drawRange.start); + const end = Math.min(index2.count, drawRange.start + drawRange.count); + for (let i = start2, il = end; i < il; i += 3) { + const a2 = index2.getX(i); + const b = index2.getX(i + 1); + const c2 = index2.getX(i + 2); + intersection = checkBufferGeometryIntersection2(this, material, raycaster, _ray$22, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b, c2); + if (intersection) { + intersection.faceIndex = Math.floor(i / 3); + intersects2.push(intersection); + } + } + } + } else if (position !== void 0) { + if (Array.isArray(material)) { + for (let i = 0, il = groups.length; i < il; i++) { + const group = groups[i]; + const groupMaterial = material[group.materialIndex]; + const start2 = Math.max(group.start, drawRange.start); + const end = Math.min(position.count, Math.min(group.start + group.count, drawRange.start + drawRange.count)); + for (let j = start2, jl = end; j < jl; j += 3) { + const a2 = j; + const b = j + 1; + const c2 = j + 2; + intersection = checkBufferGeometryIntersection2(this, groupMaterial, raycaster, _ray$22, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b, c2); + if (intersection) { + intersection.faceIndex = Math.floor(j / 3); + intersection.face.materialIndex = group.materialIndex; + intersects2.push(intersection); + } + } + } + } else { + const start2 = Math.max(0, drawRange.start); + const end = Math.min(position.count, drawRange.start + drawRange.count); + for (let i = start2, il = end; i < il; i += 3) { + const a2 = i; + const b = i + 1; + const c2 = i + 2; + intersection = checkBufferGeometryIntersection2(this, material, raycaster, _ray$22, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b, c2); + if (intersection) { + intersection.faceIndex = Math.floor(i / 3); + intersects2.push(intersection); + } + } + } + } + } + }; + function checkIntersection2(object, material, raycaster, ray, pA, pB, pC, point) { + let intersect; + if (material.side === BackSide2) { + intersect = ray.intersectTriangle(pC, pB, pA, true, point); + } else { + intersect = ray.intersectTriangle(pA, pB, pC, material.side !== DoubleSide2, point); + } + if (intersect === null) + return null; + _intersectionPointWorld2.copy(point); + _intersectionPointWorld2.applyMatrix4(object.matrixWorld); + const distance = raycaster.ray.origin.distanceTo(_intersectionPointWorld2); + if (distance < raycaster.near || distance > raycaster.far) + return null; + return { + distance, + point: _intersectionPointWorld2.clone(), + object + }; + } + function checkBufferGeometryIntersection2(object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b, c2) { + _vA$12.fromBufferAttribute(position, a2); + _vB$12.fromBufferAttribute(position, b); + _vC$12.fromBufferAttribute(position, c2); + const morphInfluences = object.morphTargetInfluences; + if (morphPosition && morphInfluences) { + _morphA2.set(0, 0, 0); + _morphB2.set(0, 0, 0); + _morphC2.set(0, 0, 0); + for (let i = 0, il = morphPosition.length; i < il; i++) { + const influence = morphInfluences[i]; + const morphAttribute = morphPosition[i]; + if (influence === 0) + continue; + _tempA2.fromBufferAttribute(morphAttribute, a2); + _tempB2.fromBufferAttribute(morphAttribute, b); + _tempC2.fromBufferAttribute(morphAttribute, c2); + if (morphTargetsRelative) { + _morphA2.addScaledVector(_tempA2, influence); + _morphB2.addScaledVector(_tempB2, influence); + _morphC2.addScaledVector(_tempC2, influence); + } else { + _morphA2.addScaledVector(_tempA2.sub(_vA$12), influence); + _morphB2.addScaledVector(_tempB2.sub(_vB$12), influence); + _morphC2.addScaledVector(_tempC2.sub(_vC$12), influence); + } + } + _vA$12.add(_morphA2); + _vB$12.add(_morphB2); + _vC$12.add(_morphC2); + } + if (object.isSkinnedMesh) { + object.boneTransform(a2, _vA$12); + object.boneTransform(b, _vB$12); + object.boneTransform(c2, _vC$12); + } + const intersection = checkIntersection2(object, material, raycaster, ray, _vA$12, _vB$12, _vC$12, _intersectionPoint2); + if (intersection) { + if (uv) { + _uvA$12.fromBufferAttribute(uv, a2); + _uvB$12.fromBufferAttribute(uv, b); + _uvC$12.fromBufferAttribute(uv, c2); + intersection.uv = Triangle2.getUV(_intersectionPoint2, _vA$12, _vB$12, _vC$12, _uvA$12, _uvB$12, _uvC$12, new Vector22()); + } + if (uv2) { + _uvA$12.fromBufferAttribute(uv2, a2); + _uvB$12.fromBufferAttribute(uv2, b); + _uvC$12.fromBufferAttribute(uv2, c2); + intersection.uv2 = Triangle2.getUV(_intersectionPoint2, _vA$12, _vB$12, _vC$12, _uvA$12, _uvB$12, _uvC$12, new Vector22()); + } + const face = { + a: a2, + b, + c: c2, + normal: new Vector32(), + materialIndex: 0 + }; + Triangle2.getNormal(_vA$12, _vB$12, _vC$12, face.normal); + intersection.face = face; + } + return intersection; + } + var BoxGeometry2 = class extends BufferGeometry2 { + constructor(width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1) { + super(); + this.type = "BoxGeometry"; + this.parameters = { + width, + height, + depth, + widthSegments, + heightSegments, + depthSegments + }; + const scope = this; + widthSegments = Math.floor(widthSegments); + heightSegments = Math.floor(heightSegments); + depthSegments = Math.floor(depthSegments); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + let numberOfVertices = 0; + let groupStart = 0; + buildPlane("z", "y", "x", -1, -1, depth, height, width, depthSegments, heightSegments, 0); + buildPlane("z", "y", "x", 1, -1, depth, height, -width, depthSegments, heightSegments, 1); + buildPlane("x", "z", "y", 1, 1, width, depth, height, widthSegments, depthSegments, 2); + buildPlane("x", "z", "y", 1, -1, width, depth, -height, widthSegments, depthSegments, 3); + buildPlane("x", "y", "z", 1, -1, width, height, depth, widthSegments, heightSegments, 4); + buildPlane("x", "y", "z", -1, -1, width, height, -depth, widthSegments, heightSegments, 5); + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + function buildPlane(u, v, w, udir, vdir, width2, height2, depth2, gridX, gridY, materialIndex) { + const segmentWidth = width2 / gridX; + const segmentHeight = height2 / gridY; + const widthHalf = width2 / 2; + const heightHalf = height2 / 2; + const depthHalf = depth2 / 2; + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; + let vertexCounter = 0; + let groupCount = 0; + const vector = new Vector32(); + for (let iy = 0; iy < gridY1; iy++) { + const y2 = iy * segmentHeight - heightHalf; + for (let ix = 0; ix < gridX1; ix++) { + const x2 = ix * segmentWidth - widthHalf; + vector[u] = x2 * udir; + vector[v] = y2 * vdir; + vector[w] = depthHalf; + vertices.push(vector.x, vector.y, vector.z); + vector[u] = 0; + vector[v] = 0; + vector[w] = depth2 > 0 ? 1 : -1; + normals.push(vector.x, vector.y, vector.z); + uvs.push(ix / gridX); + uvs.push(1 - iy / gridY); + vertexCounter += 1; + } + } + for (let iy = 0; iy < gridY; iy++) { + for (let ix = 0; ix < gridX; ix++) { + const a2 = numberOfVertices + ix + gridX1 * iy; + const b = numberOfVertices + ix + gridX1 * (iy + 1); + const c2 = numberOfVertices + (ix + 1) + gridX1 * (iy + 1); + const d = numberOfVertices + (ix + 1) + gridX1 * iy; + indices.push(a2, b, d); + indices.push(b, c2, d); + groupCount += 6; + } + } + scope.addGroup(groupStart, groupCount, materialIndex); + groupStart += groupCount; + numberOfVertices += vertexCounter; + } + } + static fromJSON(data) { + return new BoxGeometry2(data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments); + } + }; + function cloneUniforms2(src) { + const dst = {}; + for (const u in src) { + dst[u] = {}; + for (const p in src[u]) { + const property = src[u][p]; + if (property && (property.isColor || property.isMatrix3 || property.isMatrix4 || property.isVector2 || property.isVector3 || property.isVector4 || property.isTexture || property.isQuaternion)) { + dst[u][p] = property.clone(); + } else if (Array.isArray(property)) { + dst[u][p] = property.slice(); + } else { + dst[u][p] = property; + } + } + } + return dst; + } + function mergeUniforms2(uniforms) { + const merged = {}; + for (let u = 0; u < uniforms.length; u++) { + const tmp2 = cloneUniforms2(uniforms[u]); + for (const p in tmp2) { + merged[p] = tmp2[p]; + } + } + return merged; + } + function cloneUniformsGroups2(src) { + const dst = []; + for (let u = 0; u < src.length; u++) { + dst.push(src[u].clone()); + } + return dst; + } + var UniformsUtils2 = { + clone: cloneUniforms2, + merge: mergeUniforms2 + }; + var default_vertex2 = "void main() {\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"; + var default_fragment2 = "void main() {\n gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}"; + var ShaderMaterial2 = class extends Material2 { + constructor(parameters) { + super(); + this.isShaderMaterial = true; + this.type = "ShaderMaterial"; + this.defines = {}; + this.uniforms = {}; + this.uniformsGroups = []; + this.vertexShader = default_vertex2; + this.fragmentShader = default_fragment2; + this.linewidth = 1; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.fog = false; + this.lights = false; + this.clipping = false; + this.extensions = { + derivatives: false, + fragDepth: false, + drawBuffers: false, + shaderTextureLOD: false + }; + this.defaultAttributeValues = { + "color": [1, 1, 1], + "uv": [0, 0], + "uv2": [0, 0] + }; + this.index0AttributeName = void 0; + this.uniformsNeedUpdate = false; + this.glslVersion = null; + if (parameters !== void 0) { + if (parameters.attributes !== void 0) { + console.error("THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead."); + } + this.setValues(parameters); + } + } + copy(source) { + super.copy(source); + this.fragmentShader = source.fragmentShader; + this.vertexShader = source.vertexShader; + this.uniforms = cloneUniforms2(source.uniforms); + this.uniformsGroups = cloneUniformsGroups2(source.uniformsGroups); + this.defines = Object.assign({}, source.defines); + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.fog = source.fog; + this.lights = source.lights; + this.clipping = source.clipping; + this.extensions = Object.assign({}, source.extensions); + this.glslVersion = source.glslVersion; + return this; + } + toJSON(meta) { + const data = super.toJSON(meta); + data.glslVersion = this.glslVersion; + data.uniforms = {}; + for (const name in this.uniforms) { + const uniform = this.uniforms[name]; + const value = uniform.value; + if (value && value.isTexture) { + data.uniforms[name] = { + type: "t", + value: value.toJSON(meta).uuid + }; + } else if (value && value.isColor) { + data.uniforms[name] = { + type: "c", + value: value.getHex() + }; + } else if (value && value.isVector2) { + data.uniforms[name] = { + type: "v2", + value: value.toArray() + }; + } else if (value && value.isVector3) { + data.uniforms[name] = { + type: "v3", + value: value.toArray() + }; + } else if (value && value.isVector4) { + data.uniforms[name] = { + type: "v4", + value: value.toArray() + }; + } else if (value && value.isMatrix3) { + data.uniforms[name] = { + type: "m3", + value: value.toArray() + }; + } else if (value && value.isMatrix4) { + data.uniforms[name] = { + type: "m4", + value: value.toArray() + }; + } else { + data.uniforms[name] = { + value + }; + } + } + if (Object.keys(this.defines).length > 0) + data.defines = this.defines; + data.vertexShader = this.vertexShader; + data.fragmentShader = this.fragmentShader; + const extensions = {}; + for (const key in this.extensions) { + if (this.extensions[key] === true) + extensions[key] = true; + } + if (Object.keys(extensions).length > 0) + data.extensions = extensions; + return data; + } + }; + var Camera2 = class extends Object3D2 { + constructor() { + super(); + this.isCamera = true; + this.type = "Camera"; + this.matrixWorldInverse = new Matrix42(); + this.projectionMatrix = new Matrix42(); + this.projectionMatrixInverse = new Matrix42(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.matrixWorldInverse.copy(source.matrixWorldInverse); + this.projectionMatrix.copy(source.projectionMatrix); + this.projectionMatrixInverse.copy(source.projectionMatrixInverse); + return this; + } + getWorldDirection(target) { + this.updateWorldMatrix(true, false); + const e = this.matrixWorld.elements; + return target.set(-e[8], -e[9], -e[10]).normalize(); + } + updateMatrixWorld(force) { + super.updateMatrixWorld(force); + this.matrixWorldInverse.copy(this.matrixWorld).invert(); + } + updateWorldMatrix(updateParents, updateChildren) { + super.updateWorldMatrix(updateParents, updateChildren); + this.matrixWorldInverse.copy(this.matrixWorld).invert(); + } + clone() { + return new this.constructor().copy(this); + } + }; + var PerspectiveCamera2 = class extends Camera2 { + constructor(fov3 = 50, aspect3 = 1, near = 0.1, far = 2e3) { + super(); + this.isPerspectiveCamera = true; + this.type = "PerspectiveCamera"; + this.fov = fov3; + this.zoom = 1; + this.near = near; + this.far = far; + this.focus = 10; + this.aspect = aspect3; + this.view = null; + this.filmGauge = 35; + this.filmOffset = 0; + this.updateProjectionMatrix(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.fov = source.fov; + this.zoom = source.zoom; + this.near = source.near; + this.far = source.far; + this.focus = source.focus; + this.aspect = source.aspect; + this.view = source.view === null ? null : Object.assign({}, source.view); + this.filmGauge = source.filmGauge; + this.filmOffset = source.filmOffset; + return this; + } + setFocalLength(focalLength) { + const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; + this.fov = RAD2DEG2 * 2 * Math.atan(vExtentSlope); + this.updateProjectionMatrix(); + } + getFocalLength() { + const vExtentSlope = Math.tan(DEG2RAD2 * 0.5 * this.fov); + return 0.5 * this.getFilmHeight() / vExtentSlope; + } + getEffectiveFOV() { + return RAD2DEG2 * 2 * Math.atan(Math.tan(DEG2RAD2 * 0.5 * this.fov) / this.zoom); + } + getFilmWidth() { + return this.filmGauge * Math.min(this.aspect, 1); + } + getFilmHeight() { + return this.filmGauge / Math.max(this.aspect, 1); + } + setViewOffset(fullWidth, fullHeight, x2, y2, width, height) { + this.aspect = fullWidth / fullHeight; + if (this.view === null) { + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; + } + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x2; + this.view.offsetY = y2; + this.view.width = width; + this.view.height = height; + this.updateProjectionMatrix(); + } + clearViewOffset() { + if (this.view !== null) { + this.view.enabled = false; + } + this.updateProjectionMatrix(); + } + updateProjectionMatrix() { + const near = this.near; + let top = near * Math.tan(DEG2RAD2 * 0.5 * this.fov) / this.zoom; + let height = 2 * top; + let width = this.aspect * height; + let left = -0.5 * width; + const view = this.view; + if (this.view !== null && this.view.enabled) { + const fullWidth = view.fullWidth, fullHeight = view.fullHeight; + left += view.offsetX * width / fullWidth; + top -= view.offsetY * height / fullHeight; + width *= view.width / fullWidth; + height *= view.height / fullHeight; + } + const skew = this.filmOffset; + if (skew !== 0) + left += near * skew / this.getFilmWidth(); + this.projectionMatrix.makePerspective(left, left + width, top, top - height, near, this.far); + this.projectionMatrixInverse.copy(this.projectionMatrix).invert(); + } + toJSON(meta) { + const data = super.toJSON(meta); + data.object.fov = this.fov; + data.object.zoom = this.zoom; + data.object.near = this.near; + data.object.far = this.far; + data.object.focus = this.focus; + data.object.aspect = this.aspect; + if (this.view !== null) + data.object.view = Object.assign({}, this.view); + data.object.filmGauge = this.filmGauge; + data.object.filmOffset = this.filmOffset; + return data; + } + }; + var fov2 = 90; + var aspect2 = 1; + var CubeCamera2 = class extends Object3D2 { + constructor(near, far, renderTarget) { + super(); + this.type = "CubeCamera"; + if (renderTarget.isWebGLCubeRenderTarget !== true) { + console.error("THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter."); + return; + } + this.renderTarget = renderTarget; + const cameraPX = new PerspectiveCamera2(fov2, aspect2, near, far); + cameraPX.layers = this.layers; + cameraPX.up.set(0, -1, 0); + cameraPX.lookAt(new Vector32(1, 0, 0)); + this.add(cameraPX); + const cameraNX = new PerspectiveCamera2(fov2, aspect2, near, far); + cameraNX.layers = this.layers; + cameraNX.up.set(0, -1, 0); + cameraNX.lookAt(new Vector32(-1, 0, 0)); + this.add(cameraNX); + const cameraPY = new PerspectiveCamera2(fov2, aspect2, near, far); + cameraPY.layers = this.layers; + cameraPY.up.set(0, 0, 1); + cameraPY.lookAt(new Vector32(0, 1, 0)); + this.add(cameraPY); + const cameraNY = new PerspectiveCamera2(fov2, aspect2, near, far); + cameraNY.layers = this.layers; + cameraNY.up.set(0, 0, -1); + cameraNY.lookAt(new Vector32(0, -1, 0)); + this.add(cameraNY); + const cameraPZ = new PerspectiveCamera2(fov2, aspect2, near, far); + cameraPZ.layers = this.layers; + cameraPZ.up.set(0, -1, 0); + cameraPZ.lookAt(new Vector32(0, 0, 1)); + this.add(cameraPZ); + const cameraNZ = new PerspectiveCamera2(fov2, aspect2, near, far); + cameraNZ.layers = this.layers; + cameraNZ.up.set(0, -1, 0); + cameraNZ.lookAt(new Vector32(0, 0, -1)); + this.add(cameraNZ); + } + update(renderer, scene) { + if (this.parent === null) + this.updateMatrixWorld(); + const renderTarget = this.renderTarget; + const [cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ] = this.children; + const currentRenderTarget = renderer.getRenderTarget(); + const currentToneMapping = renderer.toneMapping; + const currentXrEnabled = renderer.xr.enabled; + renderer.toneMapping = NoToneMapping2; + renderer.xr.enabled = false; + const generateMipmaps = renderTarget.texture.generateMipmaps; + renderTarget.texture.generateMipmaps = false; + renderer.setRenderTarget(renderTarget, 0); + renderer.render(scene, cameraPX); + renderer.setRenderTarget(renderTarget, 1); + renderer.render(scene, cameraNX); + renderer.setRenderTarget(renderTarget, 2); + renderer.render(scene, cameraPY); + renderer.setRenderTarget(renderTarget, 3); + renderer.render(scene, cameraNY); + renderer.setRenderTarget(renderTarget, 4); + renderer.render(scene, cameraPZ); + renderTarget.texture.generateMipmaps = generateMipmaps; + renderer.setRenderTarget(renderTarget, 5); + renderer.render(scene, cameraNZ); + renderer.setRenderTarget(currentRenderTarget); + renderer.toneMapping = currentToneMapping; + renderer.xr.enabled = currentXrEnabled; + renderTarget.texture.needsPMREMUpdate = true; + } + }; + var CubeTexture2 = class extends Texture2 { + constructor(images, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy, encoding) { + images = images !== void 0 ? images : []; + mapping = mapping !== void 0 ? mapping : CubeReflectionMapping2; + super(images, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy, encoding); + this.isCubeTexture = true; + this.flipY = false; + } + get images() { + return this.image; + } + set images(value) { + this.image = value; + } + }; + var WebGLCubeRenderTarget2 = class extends WebGLRenderTarget2 { + constructor(size, options = {}) { + super(size, size, options); + this.isWebGLCubeRenderTarget = true; + const image = { + width: size, + height: size, + depth: 1 + }; + const images = [image, image, image, image, image, image]; + this.texture = new CubeTexture2(images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding); + this.texture.isRenderTargetTexture = true; + this.texture.generateMipmaps = options.generateMipmaps !== void 0 ? options.generateMipmaps : false; + this.texture.minFilter = options.minFilter !== void 0 ? options.minFilter : LinearFilter2; + } + fromEquirectangularTexture(renderer, texture) { + this.texture.type = texture.type; + this.texture.encoding = texture.encoding; + this.texture.generateMipmaps = texture.generateMipmaps; + this.texture.minFilter = texture.minFilter; + this.texture.magFilter = texture.magFilter; + const shader = { + uniforms: { + tEquirect: { + value: null + } + }, + vertexShader: ` + + varying vec3 vWorldDirection; + + vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); + + } + + void main() { + + vWorldDirection = transformDirection( position, modelMatrix ); + + #include + #include + + } + `, + fragmentShader: ` + + uniform sampler2D tEquirect; + + varying vec3 vWorldDirection; + + #include + + void main() { + + vec3 direction = normalize( vWorldDirection ); + + vec2 sampleUV = equirectUv( direction ); + + gl_FragColor = texture2D( tEquirect, sampleUV ); + + } + ` + }; + const geometry = new BoxGeometry2(5, 5, 5); + const material = new ShaderMaterial2({ + name: "CubemapFromEquirect", + uniforms: cloneUniforms2(shader.uniforms), + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + side: BackSide2, + blending: NoBlending2 + }); + material.uniforms.tEquirect.value = texture; + const mesh = new Mesh2(geometry, material); + const currentMinFilter = texture.minFilter; + if (texture.minFilter === LinearMipmapLinearFilter2) + texture.minFilter = LinearFilter2; + const camera = new CubeCamera2(1, 10, this); + camera.update(renderer, mesh); + texture.minFilter = currentMinFilter; + mesh.geometry.dispose(); + mesh.material.dispose(); + return this; + } + clear(renderer, color2, depth, stencil) { + const currentRenderTarget = renderer.getRenderTarget(); + for (let i = 0; i < 6; i++) { + renderer.setRenderTarget(this, i); + renderer.clear(color2, depth, stencil); + } + renderer.setRenderTarget(currentRenderTarget); + } + }; + var _vector12 = /* @__PURE__ */ new Vector32(); + var _vector22 = /* @__PURE__ */ new Vector32(); + var _normalMatrix2 = /* @__PURE__ */ new Matrix32(); + var Plane2 = class { + constructor(normal = new Vector32(1, 0, 0), constant = 0) { + this.isPlane = true; + this.normal = normal; + this.constant = constant; + } + set(normal, constant) { + this.normal.copy(normal); + this.constant = constant; + return this; + } + setComponents(x2, y2, z, w) { + this.normal.set(x2, y2, z); + this.constant = w; + return this; + } + setFromNormalAndCoplanarPoint(normal, point) { + this.normal.copy(normal); + this.constant = -point.dot(this.normal); + return this; + } + setFromCoplanarPoints(a2, b, c2) { + const normal = _vector12.subVectors(c2, b).cross(_vector22.subVectors(a2, b)).normalize(); + this.setFromNormalAndCoplanarPoint(normal, a2); + return this; + } + copy(plane) { + this.normal.copy(plane.normal); + this.constant = plane.constant; + return this; + } + normalize() { + const inverseNormalLength = 1 / this.normal.length(); + this.normal.multiplyScalar(inverseNormalLength); + this.constant *= inverseNormalLength; + return this; + } + negate() { + this.constant *= -1; + this.normal.negate(); + return this; + } + distanceToPoint(point) { + return this.normal.dot(point) + this.constant; + } + distanceToSphere(sphere) { + return this.distanceToPoint(sphere.center) - sphere.radius; + } + projectPoint(point, target) { + return target.copy(this.normal).multiplyScalar(-this.distanceToPoint(point)).add(point); + } + intersectLine(line, target) { + const direction = line.delta(_vector12); + const denominator = this.normal.dot(direction); + if (denominator === 0) { + if (this.distanceToPoint(line.start) === 0) { + return target.copy(line.start); + } + return null; + } + const t = -(line.start.dot(this.normal) + this.constant) / denominator; + if (t < 0 || t > 1) { + return null; + } + return target.copy(direction).multiplyScalar(t).add(line.start); + } + intersectsLine(line) { + const startSign = this.distanceToPoint(line.start); + const endSign = this.distanceToPoint(line.end); + return startSign < 0 && endSign > 0 || endSign < 0 && startSign > 0; + } + intersectsBox(box) { + return box.intersectsPlane(this); + } + intersectsSphere(sphere) { + return sphere.intersectsPlane(this); + } + coplanarPoint(target) { + return target.copy(this.normal).multiplyScalar(-this.constant); + } + applyMatrix4(matrix, optionalNormalMatrix) { + const normalMatrix = optionalNormalMatrix || _normalMatrix2.getNormalMatrix(matrix); + const referencePoint = this.coplanarPoint(_vector12).applyMatrix4(matrix); + const normal = this.normal.applyMatrix3(normalMatrix).normalize(); + this.constant = -referencePoint.dot(normal); + return this; + } + translate(offset) { + this.constant -= offset.dot(this.normal); + return this; + } + equals(plane) { + return plane.normal.equals(this.normal) && plane.constant === this.constant; + } + clone() { + return new this.constructor().copy(this); + } + }; + var _sphere$22 = /* @__PURE__ */ new Sphere2(); + var _vector$72 = /* @__PURE__ */ new Vector32(); + var Frustum2 = class { + constructor(p0 = new Plane2(), p1 = new Plane2(), p2 = new Plane2(), p3 = new Plane2(), p4 = new Plane2(), p5 = new Plane2()) { + this.planes = [p0, p1, p2, p3, p4, p5]; + } + set(p0, p1, p2, p3, p4, p5) { + const planes = this.planes; + planes[0].copy(p0); + planes[1].copy(p1); + planes[2].copy(p2); + planes[3].copy(p3); + planes[4].copy(p4); + planes[5].copy(p5); + return this; + } + copy(frustum) { + const planes = this.planes; + for (let i = 0; i < 6; i++) { + planes[i].copy(frustum.planes[i]); + } + return this; + } + setFromProjectionMatrix(m2) { + const planes = this.planes; + const me = m2.elements; + const me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3]; + const me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7]; + const me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11]; + const me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15]; + planes[0].setComponents(me3 - me0, me7 - me4, me11 - me8, me15 - me12).normalize(); + planes[1].setComponents(me3 + me0, me7 + me4, me11 + me8, me15 + me12).normalize(); + planes[2].setComponents(me3 + me1, me7 + me5, me11 + me9, me15 + me13).normalize(); + planes[3].setComponents(me3 - me1, me7 - me5, me11 - me9, me15 - me13).normalize(); + planes[4].setComponents(me3 - me2, me7 - me6, me11 - me10, me15 - me14).normalize(); + planes[5].setComponents(me3 + me2, me7 + me6, me11 + me10, me15 + me14).normalize(); + return this; + } + intersectsObject(object) { + const geometry = object.geometry; + if (geometry.boundingSphere === null) + geometry.computeBoundingSphere(); + _sphere$22.copy(geometry.boundingSphere).applyMatrix4(object.matrixWorld); + return this.intersectsSphere(_sphere$22); + } + intersectsSprite(sprite) { + _sphere$22.center.set(0, 0, 0); + _sphere$22.radius = 0.7071067811865476; + _sphere$22.applyMatrix4(sprite.matrixWorld); + return this.intersectsSphere(_sphere$22); + } + intersectsSphere(sphere) { + const planes = this.planes; + const center = sphere.center; + const negRadius = -sphere.radius; + for (let i = 0; i < 6; i++) { + const distance = planes[i].distanceToPoint(center); + if (distance < negRadius) { + return false; + } + } + return true; + } + intersectsBox(box) { + const planes = this.planes; + for (let i = 0; i < 6; i++) { + const plane = planes[i]; + _vector$72.x = plane.normal.x > 0 ? box.max.x : box.min.x; + _vector$72.y = plane.normal.y > 0 ? box.max.y : box.min.y; + _vector$72.z = plane.normal.z > 0 ? box.max.z : box.min.z; + if (plane.distanceToPoint(_vector$72) < 0) { + return false; + } + } + return true; + } + containsPoint(point) { + const planes = this.planes; + for (let i = 0; i < 6; i++) { + if (planes[i].distanceToPoint(point) < 0) { + return false; + } + } + return true; + } + clone() { + return new this.constructor().copy(this); + } + }; + function WebGLAnimation2() { + let context = null; + let isAnimating = false; + let animationLoop = null; + let requestId = null; + function onAnimationFrame(time, frame2) { + animationLoop(time, frame2); + requestId = context.requestAnimationFrame(onAnimationFrame); + } + return { + start: function() { + if (isAnimating === true) + return; + if (animationLoop === null) + return; + requestId = context.requestAnimationFrame(onAnimationFrame); + isAnimating = true; + }, + stop: function() { + context.cancelAnimationFrame(requestId); + isAnimating = false; + }, + setAnimationLoop: function(callback) { + animationLoop = callback; + }, + setContext: function(value) { + context = value; + } + }; + } + function WebGLAttributes2(gl, capabilities) { + const isWebGL2 = capabilities.isWebGL2; + const buffers = /* @__PURE__ */ new WeakMap(); + function createBuffer(attribute, bufferType) { + const array2 = attribute.array; + const usage = attribute.usage; + const buffer = gl.createBuffer(); + gl.bindBuffer(bufferType, buffer); + gl.bufferData(bufferType, array2, usage); + attribute.onUploadCallback(); + let type2; + if (array2 instanceof Float32Array) { + type2 = gl.FLOAT; + } else if (array2 instanceof Uint16Array) { + if (attribute.isFloat16BufferAttribute) { + if (isWebGL2) { + type2 = gl.HALF_FLOAT; + } else { + throw new Error("THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2."); + } + } else { + type2 = gl.UNSIGNED_SHORT; + } + } else if (array2 instanceof Int16Array) { + type2 = gl.SHORT; + } else if (array2 instanceof Uint32Array) { + type2 = gl.UNSIGNED_INT; + } else if (array2 instanceof Int32Array) { + type2 = gl.INT; + } else if (array2 instanceof Int8Array) { + type2 = gl.BYTE; + } else if (array2 instanceof Uint8Array) { + type2 = gl.UNSIGNED_BYTE; + } else if (array2 instanceof Uint8ClampedArray) { + type2 = gl.UNSIGNED_BYTE; + } else { + throw new Error("THREE.WebGLAttributes: Unsupported buffer data format: " + array2); + } + return { + buffer, + type: type2, + bytesPerElement: array2.BYTES_PER_ELEMENT, + version: attribute.version + }; + } + function updateBuffer(buffer, attribute, bufferType) { + const array2 = attribute.array; + const updateRange = attribute.updateRange; + gl.bindBuffer(bufferType, buffer); + if (updateRange.count === -1) { + gl.bufferSubData(bufferType, 0, array2); + } else { + if (isWebGL2) { + gl.bufferSubData(bufferType, updateRange.offset * array2.BYTES_PER_ELEMENT, array2, updateRange.offset, updateRange.count); + } else { + gl.bufferSubData(bufferType, updateRange.offset * array2.BYTES_PER_ELEMENT, array2.subarray(updateRange.offset, updateRange.offset + updateRange.count)); + } + updateRange.count = -1; + } + } + function get3(attribute) { + if (attribute.isInterleavedBufferAttribute) + attribute = attribute.data; + return buffers.get(attribute); + } + function remove2(attribute) { + if (attribute.isInterleavedBufferAttribute) + attribute = attribute.data; + const data = buffers.get(attribute); + if (data) { + gl.deleteBuffer(data.buffer); + buffers.delete(attribute); + } + } + function update(attribute, bufferType) { + if (attribute.isGLBufferAttribute) { + const cached = buffers.get(attribute); + if (!cached || cached.version < attribute.version) { + buffers.set(attribute, { + buffer: attribute.buffer, + type: attribute.type, + bytesPerElement: attribute.elementSize, + version: attribute.version + }); + } + return; + } + if (attribute.isInterleavedBufferAttribute) + attribute = attribute.data; + const data = buffers.get(attribute); + if (data === void 0) { + buffers.set(attribute, createBuffer(attribute, bufferType)); + } else if (data.version < attribute.version) { + updateBuffer(data.buffer, attribute, bufferType); + data.version = attribute.version; + } + } + return { + get: get3, + remove: remove2, + update + }; + } + var PlaneGeometry2 = class extends BufferGeometry2 { + constructor(width = 1, height = 1, widthSegments = 1, heightSegments = 1) { + super(); + this.type = "PlaneGeometry"; + this.parameters = { + width, + height, + widthSegments, + heightSegments + }; + const width_half = width / 2; + const height_half = height / 2; + const gridX = Math.floor(widthSegments); + const gridY = Math.floor(heightSegments); + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; + const segment_width = width / gridX; + const segment_height = height / gridY; + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + for (let iy = 0; iy < gridY1; iy++) { + const y2 = iy * segment_height - height_half; + for (let ix = 0; ix < gridX1; ix++) { + const x2 = ix * segment_width - width_half; + vertices.push(x2, -y2, 0); + normals.push(0, 0, 1); + uvs.push(ix / gridX); + uvs.push(1 - iy / gridY); + } + } + for (let iy = 0; iy < gridY; iy++) { + for (let ix = 0; ix < gridX; ix++) { + const a2 = ix + gridX1 * iy; + const b = ix + gridX1 * (iy + 1); + const c2 = ix + 1 + gridX1 * (iy + 1); + const d = ix + 1 + gridX1 * iy; + indices.push(a2, b, d); + indices.push(b, c2, d); + } + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + } + static fromJSON(data) { + return new PlaneGeometry2(data.width, data.height, data.widthSegments, data.heightSegments); + } + }; + var alphamap_fragment2 = "#ifdef USE_ALPHAMAP\n diffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif"; + var alphamap_pars_fragment2 = "#ifdef USE_ALPHAMAP\n uniform sampler2D alphaMap;\n#endif"; + var alphatest_fragment2 = "#ifdef USE_ALPHATEST\n if ( diffuseColor.a < alphaTest ) discard;\n#endif"; + var alphatest_pars_fragment2 = "#ifdef USE_ALPHATEST\n uniform float alphaTest;\n#endif"; + var aomap_fragment2 = "#ifdef USE_AOMAP\n float ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n reflectedLight.indirectDiffuse *= ambientOcclusion;\n #if defined( USE_ENVMAP ) && defined( STANDARD )\n float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n reflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n #endif\n#endif"; + var aomap_pars_fragment2 = "#ifdef USE_AOMAP\n uniform sampler2D aoMap;\n uniform float aoMapIntensity;\n#endif"; + var begin_vertex2 = "vec3 transformed = vec3( position );"; + var beginnormal_vertex2 = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n vec3 objectTangent = vec3( tangent.xyz );\n#endif"; + var bsdfs2 = "vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n return RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n float a2 = pow2( alpha );\n float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n return 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n float a2 = pow2( alpha );\n float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n return RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) {\n float alpha = pow2( roughness );\n vec3 halfDir = normalize( lightDir + viewDir );\n float dotNL = saturate( dot( normal, lightDir ) );\n float dotNV = saturate( dot( normal, viewDir ) );\n float dotNH = saturate( dot( normal, halfDir ) );\n float dotVH = saturate( dot( viewDir, halfDir ) );\n vec3 F = F_Schlick( f0, f90, dotVH );\n float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n float D = D_GGX( alpha, dotNH );\n return F * ( V * D );\n}\n#ifdef USE_IRIDESCENCE\n vec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) {\n float alpha = pow2( roughness );\n vec3 halfDir = normalize( lightDir + viewDir );\n float dotNL = saturate( dot( normal, lightDir ) );\n float dotNV = saturate( dot( normal, viewDir ) );\n float dotNH = saturate( dot( normal, halfDir ) );\n float dotVH = saturate( dot( viewDir, halfDir ) );\n vec3 F = mix( F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence );\n float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n float D = D_GGX( alpha, dotNH );\n return F * ( V * D );\n }\n#endif\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n const float LUT_SIZE = 64.0;\n const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n const float LUT_BIAS = 0.5 / LUT_SIZE;\n float dotNV = saturate( dot( N, V ) );\n vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n uv = uv * LUT_SCALE + LUT_BIAS;\n return uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n float l = length( f );\n return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n float x = dot( v1, v2 );\n float y = abs( x );\n float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n float b = 3.4175940 + ( 4.1616724 + y ) * y;\n float v = a / b;\n float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n return cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n vec3 lightNormal = cross( v1, v2 );\n if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n vec3 T1, T2;\n T1 = normalize( V - N * dot( V, N ) );\n T2 = - cross( N, T1 );\n mat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n vec3 coords[ 4 ];\n coords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n coords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n coords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n coords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n coords[ 0 ] = normalize( coords[ 0 ] );\n coords[ 1 ] = normalize( coords[ 1 ] );\n coords[ 2 ] = normalize( coords[ 2 ] );\n coords[ 3 ] = normalize( coords[ 3 ] );\n vec3 vectorFormFactor = vec3( 0.0 );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n float result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n return vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n return 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n vec3 halfDir = normalize( lightDir + viewDir );\n float dotNH = saturate( dot( normal, halfDir ) );\n float dotVH = saturate( dot( viewDir, halfDir ) );\n vec3 F = F_Schlick( specularColor, 1.0, dotVH );\n float G = G_BlinnPhong_Implicit( );\n float D = D_BlinnPhong( shininess, dotNH );\n return F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n float alpha = pow2( roughness );\n float invAlpha = 1.0 / alpha;\n float cos2h = dotNH * dotNH;\n float sin2h = max( 1.0 - cos2h, 0.0078125 );\n return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n return saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n vec3 halfDir = normalize( lightDir + viewDir );\n float dotNL = saturate( dot( normal, lightDir ) );\n float dotNV = saturate( dot( normal, viewDir ) );\n float dotNH = saturate( dot( normal, halfDir ) );\n float D = D_Charlie( sheenRoughness, dotNH );\n float V = V_Neubelt( dotNV, dotNL );\n return sheenColor * ( D * V );\n}\n#endif"; + var iridescence_fragment2 = "#ifdef USE_IRIDESCENCE\n const mat3 XYZ_TO_REC709 = mat3(\n 3.2404542, -0.9692660, 0.0556434,\n -1.5371385, 1.8760108, -0.2040259,\n -0.4985314, 0.0415560, 1.0572252\n );\n vec3 Fresnel0ToIor( vec3 fresnel0 ) {\n vec3 sqrtF0 = sqrt( fresnel0 );\n return ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n }\n vec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n return pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n }\n float IorToFresnel0( float transmittedIor, float incidentIor ) {\n return pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n }\n vec3 evalSensitivity( float OPD, vec3 shift ) {\n float phase = 2.0 * PI * OPD * 1.0e-9;\n vec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n vec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n vec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n vec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n xyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n xyz /= 1.0685e-7;\n vec3 rgb = XYZ_TO_REC709 * xyz;\n return rgb;\n }\n vec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n vec3 I;\n float iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n float sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n float cosTheta2Sq = 1.0 - sinTheta2Sq;\n if ( cosTheta2Sq < 0.0 ) {\n return vec3( 1.0 );\n }\n float cosTheta2 = sqrt( cosTheta2Sq );\n float R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n float R12 = F_Schlick( R0, 1.0, cosTheta1 );\n float R21 = R12;\n float T121 = 1.0 - R12;\n float phi12 = 0.0;\n if ( iridescenceIOR < outsideIOR ) phi12 = PI;\n float phi21 = PI - phi12;\n vec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) ); vec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n vec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n vec3 phi23 = vec3( 0.0 );\n if ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n if ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n if ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n float OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n vec3 phi = vec3( phi21 ) + phi23;\n vec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n vec3 r123 = sqrt( R123 );\n vec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n vec3 C0 = R12 + Rs;\n I = C0;\n vec3 Cm = Rs - T121;\n for ( int m = 1; m <= 2; ++ m ) {\n Cm *= r123;\n vec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n I += Cm * Sm;\n }\n return max( I, vec3( 0.0 ) );\n }\n#endif"; + var bumpmap_pars_fragment2 = "#ifdef USE_BUMPMAP\n uniform sampler2D bumpMap;\n uniform float bumpScale;\n vec2 dHdxy_fwd() {\n vec2 dSTdx = dFdx( vUv );\n vec2 dSTdy = dFdy( vUv );\n float Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n return vec2( dBx, dBy );\n }\n vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n vec3 vSigmaX = dFdx( surf_pos.xyz );\n vec3 vSigmaY = dFdy( surf_pos.xyz );\n vec3 vN = surf_norm;\n vec3 R1 = cross( vSigmaY, vN );\n vec3 R2 = cross( vN, vSigmaX );\n float fDet = dot( vSigmaX, R1 ) * faceDirection;\n vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n return normalize( abs( fDet ) * surf_norm - vGrad );\n }\n#endif"; + var clipping_planes_fragment2 = "#if NUM_CLIPPING_PLANES > 0\n vec4 plane;\n #pragma unroll_loop_start\n for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n plane = clippingPlanes[ i ];\n if ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n }\n #pragma unroll_loop_end\n #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n bool clipped = true;\n #pragma unroll_loop_start\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n plane = clippingPlanes[ i ];\n clipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n }\n #pragma unroll_loop_end\n if ( clipped ) discard;\n #endif\n#endif"; + var clipping_planes_pars_fragment2 = "#if NUM_CLIPPING_PLANES > 0\n varying vec3 vClipPosition;\n uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif"; + var clipping_planes_pars_vertex2 = "#if NUM_CLIPPING_PLANES > 0\n varying vec3 vClipPosition;\n#endif"; + var clipping_planes_vertex2 = "#if NUM_CLIPPING_PLANES > 0\n vClipPosition = - mvPosition.xyz;\n#endif"; + var color_fragment2 = "#if defined( USE_COLOR_ALPHA )\n diffuseColor *= vColor;\n#elif defined( USE_COLOR )\n diffuseColor.rgb *= vColor;\n#endif"; + var color_pars_fragment2 = "#if defined( USE_COLOR_ALPHA )\n varying vec4 vColor;\n#elif defined( USE_COLOR )\n varying vec3 vColor;\n#endif"; + var color_pars_vertex2 = "#if defined( USE_COLOR_ALPHA )\n varying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n varying vec3 vColor;\n#endif"; + var color_vertex2 = "#if defined( USE_COLOR_ALPHA )\n vColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n vColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n vColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n vColor.xyz *= instanceColor.xyz;\n#endif"; + var common2 = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n const highp float a = 12.9898, b = 78.233, c = 43758.5453;\n highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n return fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n float precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n float precisionSafeLength( vec3 v ) {\n float maxComponent = max3( abs( v ) );\n return length( v / maxComponent ) * maxComponent;\n }\n#endif\nstruct IncidentLight {\n vec3 color;\n vec3 direction;\n bool visible;\n};\nstruct ReflectedLight {\n vec3 directDiffuse;\n vec3 directSpecular;\n vec3 indirectDiffuse;\n vec3 indirectSpecular;\n};\nstruct GeometricContext {\n vec3 position;\n vec3 normal;\n vec3 viewDir;\n#ifdef USE_CLEARCOAT\n vec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n mat3 tmp;\n tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n return tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n const vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n return dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n return m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n return vec2( u, v );\n}"; + var cube_uv_reflection_fragment2 = "#ifdef ENVMAP_TYPE_CUBE_UV\n #define cubeUV_minMipLevel 4.0\n #define cubeUV_minTileSize 16.0\n float getFace( vec3 direction ) {\n vec3 absDirection = abs( direction );\n float face = - 1.0;\n if ( absDirection.x > absDirection.z ) {\n if ( absDirection.x > absDirection.y )\n face = direction.x > 0.0 ? 0.0 : 3.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n } else {\n if ( absDirection.z > absDirection.y )\n face = direction.z > 0.0 ? 2.0 : 5.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n }\n return face;\n }\n vec2 getUV( vec3 direction, float face ) {\n vec2 uv;\n if ( face == 0.0 ) {\n uv = vec2( direction.z, direction.y ) / abs( direction.x );\n } else if ( face == 1.0 ) {\n uv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n } else if ( face == 2.0 ) {\n uv = vec2( - direction.x, direction.y ) / abs( direction.z );\n } else if ( face == 3.0 ) {\n uv = vec2( - direction.z, direction.y ) / abs( direction.x );\n } else if ( face == 4.0 ) {\n uv = vec2( - direction.x, direction.z ) / abs( direction.y );\n } else {\n uv = vec2( direction.x, direction.y ) / abs( direction.z );\n }\n return 0.5 * ( uv + 1.0 );\n }\n vec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n float face = getFace( direction );\n float filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n mipInt = max( mipInt, cubeUV_minMipLevel );\n float faceSize = exp2( mipInt );\n vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n if ( face > 2.0 ) {\n uv.y += faceSize;\n face -= 3.0;\n }\n uv.x += face * faceSize;\n uv.x += filterInt * 3.0 * cubeUV_minTileSize;\n uv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n uv.x *= CUBEUV_TEXEL_WIDTH;\n uv.y *= CUBEUV_TEXEL_HEIGHT;\n #ifdef texture2DGradEXT\n return texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n #else\n return texture2D( envMap, uv ).rgb;\n #endif\n }\n #define r0 1.0\n #define v0 0.339\n #define m0 - 2.0\n #define r1 0.8\n #define v1 0.276\n #define m1 - 1.0\n #define r4 0.4\n #define v4 0.046\n #define m4 2.0\n #define r5 0.305\n #define v5 0.016\n #define m5 3.0\n #define r6 0.21\n #define v6 0.0038\n #define m6 4.0\n float roughnessToMip( float roughness ) {\n float mip = 0.0;\n if ( roughness >= r1 ) {\n mip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n } else if ( roughness >= r4 ) {\n mip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n } else if ( roughness >= r5 ) {\n mip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n } else if ( roughness >= r6 ) {\n mip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n } else {\n mip = - 2.0 * log2( 1.16 * roughness ); }\n return mip;\n }\n vec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n float mip = clamp( roughnessToMip( roughness ), m0, CUBEUV_MAX_MIP );\n float mipF = fract( mip );\n float mipInt = floor( mip );\n vec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n if ( mipF == 0.0 ) {\n return vec4( color0, 1.0 );\n } else {\n vec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n return vec4( mix( color0, color1, mipF ), 1.0 );\n }\n }\n#endif"; + var defaultnormal_vertex2 = "vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n mat3 m = mat3( instanceMatrix );\n transformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n transformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n transformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n vec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n #ifdef FLIP_SIDED\n transformedTangent = - transformedTangent;\n #endif\n#endif"; + var displacementmap_pars_vertex2 = "#ifdef USE_DISPLACEMENTMAP\n uniform sampler2D displacementMap;\n uniform float displacementScale;\n uniform float displacementBias;\n#endif"; + var displacementmap_vertex2 = "#ifdef USE_DISPLACEMENTMAP\n transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif"; + var emissivemap_fragment2 = "#ifdef USE_EMISSIVEMAP\n vec4 emissiveColor = texture2D( emissiveMap, vUv );\n totalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; + var emissivemap_pars_fragment2 = "#ifdef USE_EMISSIVEMAP\n uniform sampler2D emissiveMap;\n#endif"; + var encodings_fragment2 = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; + var encodings_pars_fragment2 = "vec4 LinearToLinear( in vec4 value ) {\n return value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}"; + var envmap_fragment2 = "#ifdef USE_ENVMAP\n #ifdef ENV_WORLDPOS\n vec3 cameraToFrag;\n if ( isOrthographic ) {\n cameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n } else {\n cameraToFrag = normalize( vWorldPosition - cameraPosition );\n }\n vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n #ifdef ENVMAP_MODE_REFLECTION\n vec3 reflectVec = reflect( cameraToFrag, worldNormal );\n #else\n vec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n #endif\n #else\n vec3 reflectVec = vReflect;\n #endif\n #ifdef ENVMAP_TYPE_CUBE\n vec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n #elif defined( ENVMAP_TYPE_CUBE_UV )\n vec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n #else\n vec4 envColor = vec4( 0.0 );\n #endif\n #ifdef ENVMAP_BLENDING_MULTIPLY\n outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n #elif defined( ENVMAP_BLENDING_MIX )\n outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n #elif defined( ENVMAP_BLENDING_ADD )\n outgoingLight += envColor.xyz * specularStrength * reflectivity;\n #endif\n#endif"; + var envmap_common_pars_fragment2 = "#ifdef USE_ENVMAP\n uniform float envMapIntensity;\n uniform float flipEnvMap;\n #ifdef ENVMAP_TYPE_CUBE\n uniform samplerCube envMap;\n #else\n uniform sampler2D envMap;\n #endif\n \n#endif"; + var envmap_pars_fragment2 = "#ifdef USE_ENVMAP\n uniform float reflectivity;\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n #define ENV_WORLDPOS\n #endif\n #ifdef ENV_WORLDPOS\n varying vec3 vWorldPosition;\n uniform float refractionRatio;\n #else\n varying vec3 vReflect;\n #endif\n#endif"; + var envmap_pars_vertex2 = "#ifdef USE_ENVMAP\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n #define ENV_WORLDPOS\n #endif\n #ifdef ENV_WORLDPOS\n \n varying vec3 vWorldPosition;\n #else\n varying vec3 vReflect;\n uniform float refractionRatio;\n #endif\n#endif"; + var envmap_vertex2 = "#ifdef USE_ENVMAP\n #ifdef ENV_WORLDPOS\n vWorldPosition = worldPosition.xyz;\n #else\n vec3 cameraToVertex;\n if ( isOrthographic ) {\n cameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n } else {\n cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n }\n vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n #ifdef ENVMAP_MODE_REFLECTION\n vReflect = reflect( cameraToVertex, worldNormal );\n #else\n vReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n #endif\n #endif\n#endif"; + var fog_vertex2 = "#ifdef USE_FOG\n vFogDepth = - mvPosition.z;\n#endif"; + var fog_pars_vertex2 = "#ifdef USE_FOG\n varying float vFogDepth;\n#endif"; + var fog_fragment2 = "#ifdef USE_FOG\n #ifdef FOG_EXP2\n float fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n #else\n float fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n #endif\n gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif"; + var fog_pars_fragment2 = "#ifdef USE_FOG\n uniform vec3 fogColor;\n varying float vFogDepth;\n #ifdef FOG_EXP2\n uniform float fogDensity;\n #else\n uniform float fogNear;\n uniform float fogFar;\n #endif\n#endif"; + var gradientmap_pars_fragment2 = "#ifdef USE_GRADIENTMAP\n uniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n float dotNL = dot( normal, lightDirection );\n vec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n #ifdef USE_GRADIENTMAP\n return vec3( texture2D( gradientMap, coord ).r );\n #else\n return ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n #endif\n}"; + var lightmap_fragment2 = "#ifdef USE_LIGHTMAP\n vec4 lightMapTexel = texture2D( lightMap, vUv2 );\n vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n reflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; + var lightmap_pars_fragment2 = "#ifdef USE_LIGHTMAP\n uniform sampler2D lightMap;\n uniform float lightMapIntensity;\n#endif"; + var lights_lambert_vertex2 = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n vLightBack = vec3( 0.0 );\n vIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry.normal );\n#ifdef DOUBLE_SIDED\n vIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n vIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry.normal );\n#endif\n#if NUM_POINT_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n getPointLightInfo( pointLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n #endif\n }\n #pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n getSpotLightInfo( spotLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n #endif\n }\n #pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n getDirectionalLightInfo( directionalLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n #endif\n }\n #pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n vIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n #ifdef DOUBLE_SIDED\n vIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry.normal );\n #endif\n }\n #pragma unroll_loop_end\n#endif"; + var lights_pars_begin2 = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n float x = normal.x, y = normal.y, z = normal.z;\n vec3 result = shCoefficients[ 0 ] * 0.886227;\n result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n return result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n vec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n return irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n vec3 irradiance = ambientLightColor;\n return irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n #if defined ( PHYSICALLY_CORRECT_LIGHTS )\n float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n if ( cutoffDistance > 0.0 ) {\n distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n }\n return distanceFalloff;\n #else\n if ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n return pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n }\n return 1.0;\n #endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n return smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n struct DirectionalLight {\n vec3 direction;\n vec3 color;\n };\n uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n void getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n light.color = directionalLight.color;\n light.direction = directionalLight.direction;\n light.visible = true;\n }\n#endif\n#if NUM_POINT_LIGHTS > 0\n struct PointLight {\n vec3 position;\n vec3 color;\n float distance;\n float decay;\n };\n uniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n void getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n vec3 lVector = pointLight.position - geometry.position;\n light.direction = normalize( lVector );\n float lightDistance = length( lVector );\n light.color = pointLight.color;\n light.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n light.visible = ( light.color != vec3( 0.0 ) );\n }\n#endif\n#if NUM_SPOT_LIGHTS > 0\n struct SpotLight {\n vec3 position;\n vec3 direction;\n vec3 color;\n float distance;\n float decay;\n float coneCos;\n float penumbraCos;\n };\n uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n void getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n vec3 lVector = spotLight.position - geometry.position;\n light.direction = normalize( lVector );\n float angleCos = dot( light.direction, spotLight.direction );\n float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n if ( spotAttenuation > 0.0 ) {\n float lightDistance = length( lVector );\n light.color = spotLight.color * spotAttenuation;\n light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n light.visible = ( light.color != vec3( 0.0 ) );\n } else {\n light.color = vec3( 0.0 );\n light.visible = false;\n }\n }\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n struct RectAreaLight {\n vec3 color;\n vec3 position;\n vec3 halfWidth;\n vec3 halfHeight;\n };\n uniform sampler2D ltc_1; uniform sampler2D ltc_2;\n uniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n struct HemisphereLight {\n vec3 direction;\n vec3 skyColor;\n vec3 groundColor;\n };\n uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n float dotNL = dot( normal, hemiLight.direction );\n float hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n return irradiance;\n }\n#endif"; + var envmap_physical_pars_fragment2 = "#if defined( USE_ENVMAP )\n vec3 getIBLIrradiance( const in vec3 normal ) {\n #if defined( ENVMAP_TYPE_CUBE_UV )\n vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n vec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n return PI * envMapColor.rgb * envMapIntensity;\n #else\n return vec3( 0.0 );\n #endif\n }\n vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n #if defined( ENVMAP_TYPE_CUBE_UV )\n vec3 reflectVec = reflect( - viewDir, normal );\n reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n reflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n vec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n return envMapColor.rgb * envMapIntensity;\n #else\n return vec3( 0.0 );\n #endif\n }\n#endif"; + var lights_toon_fragment2 = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; + var lights_toon_pars_fragment2 = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n vec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n vec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct RE_Direct_Toon\n#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material ) (0)"; + var lights_phong_fragment2 = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;"; + var lights_phong_pars_fragment2 = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n vec3 diffuseColor;\n vec3 specularColor;\n float specularShininess;\n float specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n vec3 irradiance = dotNL * directLight.color;\n reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n reflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct RE_Direct_BlinnPhong\n#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material ) (0)"; + var lights_physical_fragment2 = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n #ifdef SPECULAR\n float specularIntensityFactor = specularIntensity;\n vec3 specularColorFactor = specularColor;\n #ifdef USE_SPECULARINTENSITYMAP\n specularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n #endif\n #ifdef USE_SPECULARCOLORMAP\n specularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n #endif\n material.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n #else\n float specularIntensityFactor = 1.0;\n vec3 specularColorFactor = vec3( 1.0 );\n material.specularF90 = 1.0;\n #endif\n material.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n material.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n material.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n material.clearcoat = clearcoat;\n material.clearcoatRoughness = clearcoatRoughness;\n material.clearcoatF0 = vec3( 0.04 );\n material.clearcoatF90 = 1.0;\n #ifdef USE_CLEARCOATMAP\n material.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n #endif\n #ifdef USE_CLEARCOAT_ROUGHNESSMAP\n material.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n #endif\n material.clearcoat = saturate( material.clearcoat ); material.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n material.clearcoatRoughness += geometryRoughness;\n material.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n material.iridescence = iridescence;\n material.iridescenceIOR = iridescenceIOR;\n #ifdef USE_IRIDESCENCEMAP\n material.iridescence *= texture2D( iridescenceMap, vUv ).r;\n #endif\n #ifdef USE_IRIDESCENCE_THICKNESSMAP\n material.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n #else\n material.iridescenceThickness = iridescenceThicknessMaximum;\n #endif\n#endif\n#ifdef USE_SHEEN\n material.sheenColor = sheenColor;\n #ifdef USE_SHEENCOLORMAP\n material.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n #endif\n material.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n #ifdef USE_SHEENROUGHNESSMAP\n material.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n #endif\n#endif"; + var lights_physical_pars_fragment2 = "struct PhysicalMaterial {\n vec3 diffuseColor;\n float roughness;\n vec3 specularColor;\n float specularF90;\n #ifdef USE_CLEARCOAT\n float clearcoat;\n float clearcoatRoughness;\n vec3 clearcoatF0;\n float clearcoatF90;\n #endif\n #ifdef USE_IRIDESCENCE\n float iridescence;\n float iridescenceIOR;\n float iridescenceThickness;\n vec3 iridescenceFresnel;\n vec3 iridescenceF0;\n #endif\n #ifdef USE_SHEEN\n vec3 sheenColor;\n float sheenRoughness;\n #endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness) {\n float dotNV = saturate( dot( normal, viewDir ) );\n float r2 = roughness * roughness;\n float a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n float b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n float DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n return saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n float dotNV = saturate( dot( normal, viewDir ) );\n const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n vec4 r = roughness * c0 + c1;\n float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n vec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n return fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n vec2 fab = DFGApprox( normal, viewDir, roughness );\n return specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n vec2 fab = DFGApprox( normal, viewDir, roughness );\n #ifdef USE_IRIDESCENCE\n vec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n #else\n vec3 Fr = specularColor;\n #endif\n vec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n float Ess = fab.x + fab.y;\n float Ems = 1.0 - Ess;\n vec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619; vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n singleScatter += FssEss;\n multiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n void RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n vec3 normal = geometry.normal;\n vec3 viewDir = geometry.viewDir;\n vec3 position = geometry.position;\n vec3 lightPos = rectAreaLight.position;\n vec3 halfWidth = rectAreaLight.halfWidth;\n vec3 halfHeight = rectAreaLight.halfHeight;\n vec3 lightColor = rectAreaLight.color;\n float roughness = material.roughness;\n vec3 rectCoords[ 4 ];\n rectCoords[ 0 ] = lightPos + halfWidth - halfHeight; rectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n rectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n rectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n vec2 uv = LTC_Uv( normal, viewDir, roughness );\n vec4 t1 = texture2D( ltc_1, uv );\n vec4 t2 = texture2D( ltc_2, uv );\n mat3 mInv = mat3(\n vec3( t1.x, 0, t1.y ),\n vec3( 0, 1, 0 ),\n vec3( t1.z, 0, t1.w )\n );\n vec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n reflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n reflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n }\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n vec3 irradiance = dotNL * directLight.color;\n #ifdef USE_CLEARCOAT\n float dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n vec3 ccIrradiance = dotNLcc * directLight.color;\n clearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n #endif\n #ifdef USE_SHEEN\n sheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n #endif\n #ifdef USE_IRIDESCENCE\n reflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n #else\n reflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n #endif\n reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n #ifdef USE_CLEARCOAT\n clearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n #endif\n #ifdef USE_SHEEN\n sheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n #endif\n vec3 singleScattering = vec3( 0.0 );\n vec3 multiScattering = vec3( 0.0 );\n vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n #ifdef USE_IRIDESCENCE\n computeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n #else\n computeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n #endif\n vec3 totalScattering = singleScattering + multiScattering;\n vec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n reflectedLight.indirectSpecular += radiance * singleScattering;\n reflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct RE_Direct_Physical\n#define RE_Direct_RectArea RE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular RE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; + var lights_fragment_begin2 = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n geometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n float dotNVi = saturate( dot( normal, geometry.viewDir ) );\n if ( material.iridescenceThickness == 0.0 ) {\n material.iridescence = 0.0;\n } else {\n material.iridescence = saturate( material.iridescence );\n }\n if ( material.iridescence > 0.0 ) {\n material.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n material.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n }\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n PointLight pointLight;\n #if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n PointLightShadow pointLightShadow;\n #endif\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n pointLight = pointLights[ i ];\n getPointLightInfo( pointLight, geometry, directLight );\n #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n pointLightShadow = pointLightShadows[ i ];\n directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n SpotLight spotLight;\n #if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n SpotLightShadow spotLightShadow;\n #endif\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n spotLight = spotLights[ i ];\n getSpotLightInfo( spotLight, geometry, directLight );\n #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n spotLightShadow = spotLightShadows[ i ];\n directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n DirectionalLight directionalLight;\n #if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n DirectionalLightShadow directionalLightShadow;\n #endif\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n directionalLight = directionalLights[ i ];\n getDirectionalLightInfo( directionalLight, geometry, directLight );\n #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n directionalLightShadow = directionalLightShadows[ i ];\n directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n RectAreaLight rectAreaLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n rectAreaLight = rectAreaLights[ i ];\n RE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n vec3 iblIrradiance = vec3( 0.0 );\n vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n irradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n #if ( NUM_HEMI_LIGHTS > 0 )\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n }\n #pragma unroll_loop_end\n #endif\n#endif\n#if defined( RE_IndirectSpecular )\n vec3 radiance = vec3( 0.0 );\n vec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; + var lights_fragment_maps2 = "#if defined( RE_IndirectDiffuse )\n #ifdef USE_LIGHTMAP\n vec4 lightMapTexel = texture2D( lightMap, vUv2 );\n vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n irradiance += lightMapIrradiance;\n #endif\n #if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n iblIrradiance += getIBLIrradiance( geometry.normal );\n #endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n radiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n #ifdef USE_CLEARCOAT\n clearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n #endif\n#endif"; + var lights_fragment_end2 = "#if defined( RE_IndirectDiffuse )\n RE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n RE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif"; + var logdepthbuf_fragment2 = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n gl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; + var logdepthbuf_pars_fragment2 = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n uniform float logDepthBufFC;\n varying float vFragDepth;\n varying float vIsPerspective;\n#endif"; + var logdepthbuf_pars_vertex2 = "#ifdef USE_LOGDEPTHBUF\n #ifdef USE_LOGDEPTHBUF_EXT\n varying float vFragDepth;\n varying float vIsPerspective;\n #else\n uniform float logDepthBufFC;\n #endif\n#endif"; + var logdepthbuf_vertex2 = "#ifdef USE_LOGDEPTHBUF\n #ifdef USE_LOGDEPTHBUF_EXT\n vFragDepth = 1.0 + gl_Position.w;\n vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n #else\n if ( isPerspectiveMatrix( projectionMatrix ) ) {\n gl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n gl_Position.z *= gl_Position.w;\n }\n #endif\n#endif"; + var map_fragment2 = "#ifdef USE_MAP\n vec4 sampledDiffuseColor = texture2D( map, vUv );\n #ifdef DECODE_VIDEO_TEXTURE\n sampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n #endif\n diffuseColor *= sampledDiffuseColor;\n#endif"; + var map_pars_fragment2 = "#ifdef USE_MAP\n uniform sampler2D map;\n#endif"; + var map_particle_fragment2 = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n diffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n diffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; + var map_particle_pars_fragment2 = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n uniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n uniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n uniform sampler2D alphaMap;\n#endif"; + var metalnessmap_fragment2 = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n vec4 texelMetalness = texture2D( metalnessMap, vUv );\n metalnessFactor *= texelMetalness.b;\n#endif"; + var metalnessmap_pars_fragment2 = "#ifdef USE_METALNESSMAP\n uniform sampler2D metalnessMap;\n#endif"; + var morphcolor_vertex2 = "#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n vColor *= morphTargetBaseInfluence;\n for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n #if defined( USE_COLOR_ALPHA )\n if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n #elif defined( USE_COLOR )\n if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n #endif\n }\n#endif"; + var morphnormal_vertex2 = "#ifdef USE_MORPHNORMALS\n objectNormal *= morphTargetBaseInfluence;\n #ifdef MORPHTARGETS_TEXTURE\n for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n if ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n }\n #else\n objectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n objectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n objectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n objectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n #endif\n#endif"; + var morphtarget_pars_vertex2 = "#ifdef USE_MORPHTARGETS\n uniform float morphTargetBaseInfluence;\n #ifdef MORPHTARGETS_TEXTURE\n uniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n uniform sampler2DArray morphTargetsTexture;\n uniform ivec2 morphTargetsTextureSize;\n vec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n int texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n int y = texelIndex / morphTargetsTextureSize.x;\n int x = texelIndex - y * morphTargetsTextureSize.x;\n ivec3 morphUV = ivec3( x, y, morphTargetIndex );\n return texelFetch( morphTargetsTexture, morphUV, 0 );\n }\n #else\n #ifndef USE_MORPHNORMALS\n uniform float morphTargetInfluences[ 8 ];\n #else\n uniform float morphTargetInfluences[ 4 ];\n #endif\n #endif\n#endif"; + var morphtarget_vertex2 = "#ifdef USE_MORPHTARGETS\n transformed *= morphTargetBaseInfluence;\n #ifdef MORPHTARGETS_TEXTURE\n for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n if ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n }\n #else\n transformed += morphTarget0 * morphTargetInfluences[ 0 ];\n transformed += morphTarget1 * morphTargetInfluences[ 1 ];\n transformed += morphTarget2 * morphTargetInfluences[ 2 ];\n transformed += morphTarget3 * morphTargetInfluences[ 3 ];\n #ifndef USE_MORPHNORMALS\n transformed += morphTarget4 * morphTargetInfluences[ 4 ];\n transformed += morphTarget5 * morphTargetInfluences[ 5 ];\n transformed += morphTarget6 * morphTargetInfluences[ 6 ];\n transformed += morphTarget7 * morphTargetInfluences[ 7 ];\n #endif\n #endif\n#endif"; + var normal_fragment_begin2 = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n vec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n vec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n vec3 normal = normalize( cross( fdx, fdy ) );\n#else\n vec3 normal = normalize( vNormal );\n #ifdef DOUBLE_SIDED\n normal = normal * faceDirection;\n #endif\n #ifdef USE_TANGENT\n vec3 tangent = normalize( vTangent );\n vec3 bitangent = normalize( vBitangent );\n #ifdef DOUBLE_SIDED\n tangent = tangent * faceDirection;\n bitangent = bitangent * faceDirection;\n #endif\n #if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n mat3 vTBN = mat3( tangent, bitangent, normal );\n #endif\n #endif\n#endif\nvec3 geometryNormal = normal;"; + var normal_fragment_maps2 = "#ifdef OBJECTSPACE_NORMALMAP\n normal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n #ifdef FLIP_SIDED\n normal = - normal;\n #endif\n #ifdef DOUBLE_SIDED\n normal = normal * faceDirection;\n #endif\n normal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n mapN.xy *= normalScale;\n #ifdef USE_TANGENT\n normal = normalize( vTBN * mapN );\n #else\n normal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n #endif\n#elif defined( USE_BUMPMAP )\n normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; + var normal_pars_fragment2 = "#ifndef FLAT_SHADED\n varying vec3 vNormal;\n #ifdef USE_TANGENT\n varying vec3 vTangent;\n varying vec3 vBitangent;\n #endif\n#endif"; + var normal_pars_vertex2 = "#ifndef FLAT_SHADED\n varying vec3 vNormal;\n #ifdef USE_TANGENT\n varying vec3 vTangent;\n varying vec3 vBitangent;\n #endif\n#endif"; + var normal_vertex2 = "#ifndef FLAT_SHADED\n vNormal = normalize( transformedNormal );\n #ifdef USE_TANGENT\n vTangent = normalize( transformedTangent );\n vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n #endif\n#endif"; + var normalmap_pars_fragment2 = "#ifdef USE_NORMALMAP\n uniform sampler2D normalMap;\n uniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n uniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n vec3 q0 = dFdx( eye_pos.xyz );\n vec3 q1 = dFdy( eye_pos.xyz );\n vec2 st0 = dFdx( vUv.st );\n vec2 st1 = dFdy( vUv.st );\n vec3 N = surf_norm;\n vec3 q1perp = cross( q1, N );\n vec3 q0perp = cross( N, q0 );\n vec3 T = q1perp * st0.x + q0perp * st1.x;\n vec3 B = q1perp * st0.y + q0perp * st1.y;\n float det = max( dot( T, T ), dot( B, B ) );\n float scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n return normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n }\n#endif"; + var clearcoat_normal_fragment_begin2 = "#ifdef USE_CLEARCOAT\n vec3 clearcoatNormal = geometryNormal;\n#endif"; + var clearcoat_normal_fragment_maps2 = "#ifdef USE_CLEARCOAT_NORMALMAP\n vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n clearcoatMapN.xy *= clearcoatNormalScale;\n #ifdef USE_TANGENT\n clearcoatNormal = normalize( vTBN * clearcoatMapN );\n #else\n clearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n #endif\n#endif"; + var clearcoat_pars_fragment2 = "#ifdef USE_CLEARCOATMAP\n uniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n uniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n uniform sampler2D clearcoatNormalMap;\n uniform vec2 clearcoatNormalScale;\n#endif"; + var iridescence_pars_fragment2 = "#ifdef USE_IRIDESCENCEMAP\n uniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n uniform sampler2D iridescenceThicknessMap;\n#endif"; + var output_fragment2 = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; + var packing2 = "vec3 packNormalToRGB( const in vec3 normal ) {\n return normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n return 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n vec4 r = vec4( fract( v * PackFactors ), v );\n r.yzw -= r.xyz * ShiftRight8; return r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n return dot( v, UnpackFactors );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n vec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n return vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n return ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n return linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n return ( near * far ) / ( ( far - near ) * invClipZ - far );\n}"; + var premultiplied_alpha_fragment2 = "#ifdef PREMULTIPLIED_ALPHA\n gl_FragColor.rgb *= gl_FragColor.a;\n#endif"; + var project_vertex2 = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n mvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;"; + var dithering_fragment2 = "#ifdef DITHERING\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif"; + var dithering_pars_fragment2 = "#ifdef DITHERING\n vec3 dithering( vec3 color ) {\n float grid_position = rand( gl_FragCoord.xy );\n vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n return color + dither_shift_RGB;\n }\n#endif"; + var roughnessmap_fragment2 = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n vec4 texelRoughness = texture2D( roughnessMap, vUv );\n roughnessFactor *= texelRoughness.g;\n#endif"; + var roughnessmap_pars_fragment2 = "#ifdef USE_ROUGHNESSMAP\n uniform sampler2D roughnessMap;\n#endif"; + var shadowmap_pars_fragment2 = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0\n uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n struct DirectionalLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n struct SpotLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n uniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n struct PointLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n float shadowCameraNear;\n float shadowCameraFar;\n };\n uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n #endif\n float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n }\n vec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n return unpackRGBATo2Half( texture2D( shadow, uv ) );\n }\n float VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n float occlusion = 1.0;\n vec2 distribution = texture2DDistribution( shadow, uv );\n float hard_shadow = step( compare , distribution.x );\n if (hard_shadow != 1.0 ) {\n float distance = compare - distribution.x ;\n float variance = max( 0.00000, distribution.y * distribution.y );\n float softness_probability = variance / (variance + distance * distance ); softness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); occlusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n }\n return occlusion;\n }\n float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n float shadow = 1.0;\n shadowCoord.xyz /= shadowCoord.w;\n shadowCoord.z += shadowBias;\n bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n bool inFrustum = all( inFrustumVec );\n bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n bool frustumTest = all( frustumTestVec );\n if ( frustumTest ) {\n #if defined( SHADOWMAP_TYPE_PCF )\n vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n float dx0 = - texelSize.x * shadowRadius;\n float dy0 = - texelSize.y * shadowRadius;\n float dx1 = + texelSize.x * shadowRadius;\n float dy1 = + texelSize.y * shadowRadius;\n float dx2 = dx0 / 2.0;\n float dy2 = dy0 / 2.0;\n float dx3 = dx1 / 2.0;\n float dy3 = dy1 / 2.0;\n shadow = (\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n ) * ( 1.0 / 17.0 );\n #elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n float dx = texelSize.x;\n float dy = texelSize.y;\n vec2 uv = shadowCoord.xy;\n vec2 f = fract( uv * shadowMapSize + 0.5 );\n uv -= f * texelSize;\n shadow = (\n texture2DCompare( shadowMap, uv, shadowCoord.z ) +\n texture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n texture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n mix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n f.x ) +\n mix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n f.x ) +\n mix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n f.y ) +\n mix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n f.y ) +\n mix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n f.x ),\n mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n f.x ),\n f.y )\n ) * ( 1.0 / 9.0 );\n #elif defined( SHADOWMAP_TYPE_VSM )\n shadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n #else\n shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n #endif\n }\n return shadow;\n }\n vec2 cubeToUV( vec3 v, float texelSizeY ) {\n vec3 absV = abs( v );\n float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n absV *= scaleToCube;\n v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n vec2 planar = v.xy;\n float almostATexel = 1.5 * texelSizeY;\n float almostOne = 1.0 - almostATexel;\n if ( absV.z >= almostOne ) {\n if ( v.z > 0.0 )\n planar.x = 4.0 - v.x;\n } else if ( absV.x >= almostOne ) {\n float signX = sign( v.x );\n planar.x = v.z * signX + 2.0 * signX;\n } else if ( absV.y >= almostOne ) {\n float signY = sign( v.y );\n planar.x = v.x + 2.0 * signY + 2.0;\n planar.y = v.z * signY - 2.0;\n }\n return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n }\n float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n vec3 lightToPosition = shadowCoord.xyz;\n float dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); dp += shadowBias;\n vec3 bd3D = normalize( lightToPosition );\n #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n return (\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n ) * ( 1.0 / 9.0 );\n #else\n return texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n #endif\n }\n#endif"; + var shadowmap_pars_vertex2 = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0\n uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n struct DirectionalLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n uniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n struct SpotLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n struct PointLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n float shadowCameraNear;\n float shadowCameraFar;\n };\n uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n #endif\n#endif"; + var shadowmap_vertex2 = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0\n vec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n vec4 shadowWorldPosition;\n #endif\n #if NUM_DIR_LIGHT_SHADOWS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias, 0 );\n vSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * shadowWorldPosition;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n }\n #pragma unroll_loop_end\n #endif\n#endif"; + var shadowmask_pars_fragment2 = "float getShadowMask() {\n float shadow = 1.0;\n #ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0\n DirectionalLightShadow directionalLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n directionalLight = directionalLightShadows[ i ];\n shadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n SpotLightShadow spotLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n spotLight = spotLightShadows[ i ];\n shadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n PointLightShadow pointLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n pointLight = pointLightShadows[ i ];\n shadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n }\n #pragma unroll_loop_end\n #endif\n #endif\n return shadow;\n}"; + var skinbase_vertex2 = "#ifdef USE_SKINNING\n mat4 boneMatX = getBoneMatrix( skinIndex.x );\n mat4 boneMatY = getBoneMatrix( skinIndex.y );\n mat4 boneMatZ = getBoneMatrix( skinIndex.z );\n mat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; + var skinning_pars_vertex2 = "#ifdef USE_SKINNING\n uniform mat4 bindMatrix;\n uniform mat4 bindMatrixInverse;\n uniform highp sampler2D boneTexture;\n uniform int boneTextureSize;\n mat4 getBoneMatrix( const in float i ) {\n float j = i * 4.0;\n float x = mod( j, float( boneTextureSize ) );\n float y = floor( j / float( boneTextureSize ) );\n float dx = 1.0 / float( boneTextureSize );\n float dy = 1.0 / float( boneTextureSize );\n y = dy * ( y + 0.5 );\n vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n mat4 bone = mat4( v1, v2, v3, v4 );\n return bone;\n }\n#endif"; + var skinning_vertex2 = "#ifdef USE_SKINNING\n vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n vec4 skinned = vec4( 0.0 );\n skinned += boneMatX * skinVertex * skinWeight.x;\n skinned += boneMatY * skinVertex * skinWeight.y;\n skinned += boneMatZ * skinVertex * skinWeight.z;\n skinned += boneMatW * skinVertex * skinWeight.w;\n transformed = ( bindMatrixInverse * skinned ).xyz;\n#endif"; + var skinnormal_vertex2 = "#ifdef USE_SKINNING\n mat4 skinMatrix = mat4( 0.0 );\n skinMatrix += skinWeight.x * boneMatX;\n skinMatrix += skinWeight.y * boneMatY;\n skinMatrix += skinWeight.z * boneMatZ;\n skinMatrix += skinWeight.w * boneMatW;\n skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n #ifdef USE_TANGENT\n objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n #endif\n#endif"; + var specularmap_fragment2 = "float specularStrength;\n#ifdef USE_SPECULARMAP\n vec4 texelSpecular = texture2D( specularMap, vUv );\n specularStrength = texelSpecular.r;\n#else\n specularStrength = 1.0;\n#endif"; + var specularmap_pars_fragment2 = "#ifdef USE_SPECULARMAP\n uniform sampler2D specularMap;\n#endif"; + var tonemapping_fragment2 = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif"; + var tonemapping_pars_fragment2 = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n return toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n color *= toneMappingExposure;\n return saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n color *= toneMappingExposure;\n color = max( vec3( 0.0 ), color - 0.004 );\n return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n vec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n return a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n const mat3 ACESInputMat = mat3(\n vec3( 0.59719, 0.07600, 0.02840 ), vec3( 0.35458, 0.90834, 0.13383 ),\n vec3( 0.04823, 0.01566, 0.83777 )\n );\n const mat3 ACESOutputMat = mat3(\n vec3( 1.60475, -0.10208, -0.00327 ), vec3( -0.53108, 1.10813, -0.07276 ),\n vec3( -0.07367, -0.00605, 1.07602 )\n );\n color *= toneMappingExposure / 0.6;\n color = ACESInputMat * color;\n color = RRTAndODTFit( color );\n color = ACESOutputMat * color;\n return saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; + var transmission_fragment2 = "#ifdef USE_TRANSMISSION\n float transmissionAlpha = 1.0;\n float transmissionFactor = transmission;\n float thicknessFactor = thickness;\n #ifdef USE_TRANSMISSIONMAP\n transmissionFactor *= texture2D( transmissionMap, vUv ).r;\n #endif\n #ifdef USE_THICKNESSMAP\n thicknessFactor *= texture2D( thicknessMap, vUv ).g;\n #endif\n vec3 pos = vWorldPosition;\n vec3 v = normalize( cameraPosition - pos );\n vec3 n = inverseTransformDirection( normal, viewMatrix );\n vec4 transmission = getIBLVolumeRefraction(\n n, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,\n pos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,\n attenuationColor, attenuationDistance );\n totalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );\n transmissionAlpha = mix( transmissionAlpha, transmission.a, transmissionFactor );\n#endif"; + var transmission_pars_fragment2 = "#ifdef USE_TRANSMISSION\n uniform float transmission;\n uniform float thickness;\n uniform float attenuationDistance;\n uniform vec3 attenuationColor;\n #ifdef USE_TRANSMISSIONMAP\n uniform sampler2D transmissionMap;\n #endif\n #ifdef USE_THICKNESSMAP\n uniform sampler2D thicknessMap;\n #endif\n uniform vec2 transmissionSamplerSize;\n uniform sampler2D transmissionSamplerMap;\n uniform mat4 modelMatrix;\n uniform mat4 projectionMatrix;\n varying vec3 vWorldPosition;\n vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n vec3 modelScale;\n modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n return normalize( refractionVector ) * thickness * modelScale;\n }\n float applyIorToRoughness( const in float roughness, const in float ior ) {\n return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n }\n vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n float framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n #ifdef texture2DLodEXT\n return texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n #else\n return texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n #endif\n }\n vec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n if ( attenuationDistance == 0.0 ) {\n return radiance;\n } else {\n vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); return transmittance * radiance;\n }\n }\n vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n const in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n const in vec3 attenuationColor, const in float attenuationDistance ) {\n vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n vec3 refractedRayExit = position + transmissionRay;\n vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n vec2 refractionCoords = ndcPos.xy / ndcPos.w;\n refractionCoords += 1.0;\n refractionCoords /= 2.0;\n vec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n vec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n return vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n }\n#endif"; + var uv_pars_fragment2 = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n varying vec2 vUv;\n#endif"; + var uv_pars_vertex2 = "#ifdef USE_UV\n #ifdef UVS_VERTEX_ONLY\n vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n uniform mat3 uvTransform;\n#endif"; + var uv_vertex2 = "#ifdef USE_UV\n vUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; + var uv2_pars_fragment2 = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n varying vec2 vUv2;\n#endif"; + var uv2_pars_vertex2 = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n attribute vec2 uv2;\n varying vec2 vUv2;\n uniform mat3 uv2Transform;\n#endif"; + var uv2_vertex2 = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n vUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif"; + var worldpos_vertex2 = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION )\n vec4 worldPosition = vec4( transformed, 1.0 );\n #ifdef USE_INSTANCING\n worldPosition = instanceMatrix * worldPosition;\n #endif\n worldPosition = modelMatrix * worldPosition;\n#endif"; + var vertex$g2 = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n vUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n gl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; + var fragment$g2 = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n gl_FragColor = texture2D( t2D, vUv );\n #ifdef DECODE_VIDEO_TEXTURE\n gl_FragColor = vec4( mix( pow( gl_FragColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), gl_FragColor.rgb * 0.0773993808, vec3( lessThanEqual( gl_FragColor.rgb, vec3( 0.04045 ) ) ) ), gl_FragColor.w );\n #endif\n #include \n #include \n}"; + var vertex$f2 = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n vWorldDirection = transformDirection( position, modelMatrix );\n #include \n #include \n gl_Position.z = gl_Position.w;\n}"; + var fragment$f2 = "#include \nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n vec3 vReflect = vWorldDirection;\n #include \n gl_FragColor = envColor;\n gl_FragColor.a *= opacity;\n #include \n #include \n}"; + var vertex$e2 = "#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n #include \n #include \n #ifdef USE_DISPLACEMENTMAP\n #include \n #include \n #include \n #endif\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vHighPrecisionZW = gl_Position.zw;\n}"; + var fragment$e2 = "#if DEPTH_PACKING == 3200\n uniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n #include \n vec4 diffuseColor = vec4( 1.0 );\n #if DEPTH_PACKING == 3200\n diffuseColor.a = opacity;\n #endif\n #include \n #include \n #include \n #include \n float fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n #if DEPTH_PACKING == 3200\n gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n #elif DEPTH_PACKING == 3201\n gl_FragColor = packDepthToRGBA( fragCoordZ );\n #endif\n}"; + var vertex$d2 = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #ifdef USE_DISPLACEMENTMAP\n #include \n #include \n #include \n #endif\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vWorldPosition = worldPosition.xyz;\n}"; + var fragment$d2 = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n #include \n vec4 diffuseColor = vec4( 1.0 );\n #include \n #include \n #include \n float dist = length( vWorldPosition - referencePosition );\n dist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n dist = saturate( dist );\n gl_FragColor = packDepthToRGBA( dist );\n}"; + var vertex$c2 = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n vWorldDirection = transformDirection( position, modelMatrix );\n #include \n #include \n}"; + var fragment$c2 = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n vec3 direction = normalize( vWorldDirection );\n vec2 sampleUV = equirectUv( direction );\n gl_FragColor = texture2D( tEquirect, sampleUV );\n #include \n #include \n}"; + var vertex$b2 = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n vLineDistance = scale * lineDistance;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var fragment$b2 = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n if ( mod( vLineDistance, totalSize ) > dashSize ) {\n discard;\n }\n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n outgoingLight = diffuseColor.rgb;\n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$a2 = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n #include \n #include \n #include \n #include \n #include \n #endif\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var fragment$a2 = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n varying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n #include \n #include \n #include \n #include \n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n #ifdef USE_LIGHTMAP\n vec4 lightMapTexel = texture2D( lightMap, vUv2 );\n reflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n #else\n reflectedLight.indirectDiffuse += vec3( 1.0 );\n #endif\n #include \n reflectedLight.indirectDiffuse *= diffuseColor.rgb;\n vec3 outgoingLight = reflectedLight.indirectDiffuse;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$92 = "#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n varying vec3 vLightBack;\n varying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var fragment$92 = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n varying vec3 vLightBack;\n varying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #ifdef DOUBLE_SIDED\n reflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n #else\n reflectedLight.indirectDiffuse += vIndirectFront;\n #endif\n #include \n reflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb );\n #ifdef DOUBLE_SIDED\n reflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n #else\n reflectedLight.directDiffuse = vLightFront;\n #endif\n reflectedLight.directDiffuse *= BRDF_Lambert( diffuseColor.rgb ) * getShadowMask();\n #include \n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$82 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vViewPosition = - mvPosition.xyz;\n}"; + var fragment$82 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vec3 viewDir = normalize( vViewPosition );\n vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n vec3 y = cross( viewDir, x );\n vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n #ifdef USE_MATCAP\n vec4 matcapColor = texture2D( matcap, uv );\n #else\n vec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n #endif\n vec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$72 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n varying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n vViewPosition = - mvPosition.xyz;\n#endif\n}"; + var fragment$72 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n varying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n gl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n #ifdef OPAQUE\n gl_FragColor.a = 1.0;\n #endif\n}"; + var vertex$62 = "#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vViewPosition = - mvPosition.xyz;\n #include \n #include \n #include \n #include \n}"; + var fragment$62 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$52 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n varying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vViewPosition = - mvPosition.xyz;\n #include \n #include \n #include \n#ifdef USE_TRANSMISSION\n vWorldPosition = worldPosition.xyz;\n#endif\n}"; + var fragment$52 = "#define STANDARD\n#ifdef PHYSICAL\n #define IOR\n #define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n uniform float ior;\n#endif\n#ifdef SPECULAR\n uniform float specularIntensity;\n uniform vec3 specularColor;\n #ifdef USE_SPECULARINTENSITYMAP\n uniform sampler2D specularIntensityMap;\n #endif\n #ifdef USE_SPECULARCOLORMAP\n uniform sampler2D specularColorMap;\n #endif\n#endif\n#ifdef USE_CLEARCOAT\n uniform float clearcoat;\n uniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n uniform float iridescence;\n uniform float iridescenceIOR;\n uniform float iridescenceThicknessMinimum;\n uniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n uniform vec3 sheenColor;\n uniform float sheenRoughness;\n #ifdef USE_SHEENCOLORMAP\n uniform sampler2D sheenColorMap;\n #endif\n #ifdef USE_SHEENROUGHNESSMAP\n uniform sampler2D sheenRoughnessMap;\n #endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n #include \n vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n #ifdef USE_SHEEN\n float sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n #endif\n #ifdef USE_CLEARCOAT\n float dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n #endif\n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$42 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vViewPosition = - mvPosition.xyz;\n #include \n #include \n #include \n}"; + var fragment$42 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$32 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n gl_PointSize = size;\n #ifdef USE_SIZEATTENUATION\n bool isPerspective = isPerspectiveMatrix( projectionMatrix );\n if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n #endif\n #include \n #include \n #include \n #include \n}"; + var fragment$32 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n #include \n #include \n outgoingLight = diffuseColor.rgb;\n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$22 = "#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var fragment$22 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n gl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n #include \n #include \n #include \n}"; + var vertex$12 = "uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n vec2 scale;\n scale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n scale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n #ifndef USE_SIZEATTENUATION\n bool isPerspective = isPerspectiveMatrix( projectionMatrix );\n if ( isPerspective ) scale *= - mvPosition.z;\n #endif\n vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n vec2 rotatedPosition;\n rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n mvPosition.xy += rotatedPosition;\n gl_Position = projectionMatrix * mvPosition;\n #include \n #include \n #include \n}"; + var fragment$12 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n #include \n #include \n outgoingLight = diffuseColor.rgb;\n #include \n #include \n #include \n #include \n}"; + var ShaderChunk2 = { + alphamap_fragment: alphamap_fragment2, + alphamap_pars_fragment: alphamap_pars_fragment2, + alphatest_fragment: alphatest_fragment2, + alphatest_pars_fragment: alphatest_pars_fragment2, + aomap_fragment: aomap_fragment2, + aomap_pars_fragment: aomap_pars_fragment2, + begin_vertex: begin_vertex2, + beginnormal_vertex: beginnormal_vertex2, + bsdfs: bsdfs2, + iridescence_fragment: iridescence_fragment2, + bumpmap_pars_fragment: bumpmap_pars_fragment2, + clipping_planes_fragment: clipping_planes_fragment2, + clipping_planes_pars_fragment: clipping_planes_pars_fragment2, + clipping_planes_pars_vertex: clipping_planes_pars_vertex2, + clipping_planes_vertex: clipping_planes_vertex2, + color_fragment: color_fragment2, + color_pars_fragment: color_pars_fragment2, + color_pars_vertex: color_pars_vertex2, + color_vertex: color_vertex2, + common: common2, + cube_uv_reflection_fragment: cube_uv_reflection_fragment2, + defaultnormal_vertex: defaultnormal_vertex2, + displacementmap_pars_vertex: displacementmap_pars_vertex2, + displacementmap_vertex: displacementmap_vertex2, + emissivemap_fragment: emissivemap_fragment2, + emissivemap_pars_fragment: emissivemap_pars_fragment2, + encodings_fragment: encodings_fragment2, + encodings_pars_fragment: encodings_pars_fragment2, + envmap_fragment: envmap_fragment2, + envmap_common_pars_fragment: envmap_common_pars_fragment2, + envmap_pars_fragment: envmap_pars_fragment2, + envmap_pars_vertex: envmap_pars_vertex2, + envmap_physical_pars_fragment: envmap_physical_pars_fragment2, + envmap_vertex: envmap_vertex2, + fog_vertex: fog_vertex2, + fog_pars_vertex: fog_pars_vertex2, + fog_fragment: fog_fragment2, + fog_pars_fragment: fog_pars_fragment2, + gradientmap_pars_fragment: gradientmap_pars_fragment2, + lightmap_fragment: lightmap_fragment2, + lightmap_pars_fragment: lightmap_pars_fragment2, + lights_lambert_vertex: lights_lambert_vertex2, + lights_pars_begin: lights_pars_begin2, + lights_toon_fragment: lights_toon_fragment2, + lights_toon_pars_fragment: lights_toon_pars_fragment2, + lights_phong_fragment: lights_phong_fragment2, + lights_phong_pars_fragment: lights_phong_pars_fragment2, + lights_physical_fragment: lights_physical_fragment2, + lights_physical_pars_fragment: lights_physical_pars_fragment2, + lights_fragment_begin: lights_fragment_begin2, + lights_fragment_maps: lights_fragment_maps2, + lights_fragment_end: lights_fragment_end2, + logdepthbuf_fragment: logdepthbuf_fragment2, + logdepthbuf_pars_fragment: logdepthbuf_pars_fragment2, + logdepthbuf_pars_vertex: logdepthbuf_pars_vertex2, + logdepthbuf_vertex: logdepthbuf_vertex2, + map_fragment: map_fragment2, + map_pars_fragment: map_pars_fragment2, + map_particle_fragment: map_particle_fragment2, + map_particle_pars_fragment: map_particle_pars_fragment2, + metalnessmap_fragment: metalnessmap_fragment2, + metalnessmap_pars_fragment: metalnessmap_pars_fragment2, + morphcolor_vertex: morphcolor_vertex2, + morphnormal_vertex: morphnormal_vertex2, + morphtarget_pars_vertex: morphtarget_pars_vertex2, + morphtarget_vertex: morphtarget_vertex2, + normal_fragment_begin: normal_fragment_begin2, + normal_fragment_maps: normal_fragment_maps2, + normal_pars_fragment: normal_pars_fragment2, + normal_pars_vertex: normal_pars_vertex2, + normal_vertex: normal_vertex2, + normalmap_pars_fragment: normalmap_pars_fragment2, + clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin2, + clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps2, + clearcoat_pars_fragment: clearcoat_pars_fragment2, + iridescence_pars_fragment: iridescence_pars_fragment2, + output_fragment: output_fragment2, + packing: packing2, + premultiplied_alpha_fragment: premultiplied_alpha_fragment2, + project_vertex: project_vertex2, + dithering_fragment: dithering_fragment2, + dithering_pars_fragment: dithering_pars_fragment2, + roughnessmap_fragment: roughnessmap_fragment2, + roughnessmap_pars_fragment: roughnessmap_pars_fragment2, + shadowmap_pars_fragment: shadowmap_pars_fragment2, + shadowmap_pars_vertex: shadowmap_pars_vertex2, + shadowmap_vertex: shadowmap_vertex2, + shadowmask_pars_fragment: shadowmask_pars_fragment2, + skinbase_vertex: skinbase_vertex2, + skinning_pars_vertex: skinning_pars_vertex2, + skinning_vertex: skinning_vertex2, + skinnormal_vertex: skinnormal_vertex2, + specularmap_fragment: specularmap_fragment2, + specularmap_pars_fragment: specularmap_pars_fragment2, + tonemapping_fragment: tonemapping_fragment2, + tonemapping_pars_fragment: tonemapping_pars_fragment2, + transmission_fragment: transmission_fragment2, + transmission_pars_fragment: transmission_pars_fragment2, + uv_pars_fragment: uv_pars_fragment2, + uv_pars_vertex: uv_pars_vertex2, + uv_vertex: uv_vertex2, + uv2_pars_fragment: uv2_pars_fragment2, + uv2_pars_vertex: uv2_pars_vertex2, + uv2_vertex: uv2_vertex2, + worldpos_vertex: worldpos_vertex2, + background_vert: vertex$g2, + background_frag: fragment$g2, + cube_vert: vertex$f2, + cube_frag: fragment$f2, + depth_vert: vertex$e2, + depth_frag: fragment$e2, + distanceRGBA_vert: vertex$d2, + distanceRGBA_frag: fragment$d2, + equirect_vert: vertex$c2, + equirect_frag: fragment$c2, + linedashed_vert: vertex$b2, + linedashed_frag: fragment$b2, + meshbasic_vert: vertex$a2, + meshbasic_frag: fragment$a2, + meshlambert_vert: vertex$92, + meshlambert_frag: fragment$92, + meshmatcap_vert: vertex$82, + meshmatcap_frag: fragment$82, + meshnormal_vert: vertex$72, + meshnormal_frag: fragment$72, + meshphong_vert: vertex$62, + meshphong_frag: fragment$62, + meshphysical_vert: vertex$52, + meshphysical_frag: fragment$52, + meshtoon_vert: vertex$42, + meshtoon_frag: fragment$42, + points_vert: vertex$32, + points_frag: fragment$32, + shadow_vert: vertex$22, + shadow_frag: fragment$22, + sprite_vert: vertex$12, + sprite_frag: fragment$12 + }; + var UniformsLib2 = { + common: { + diffuse: { + value: /* @__PURE__ */ new Color3(16777215) + }, + opacity: { + value: 1 + }, + map: { + value: null + }, + uvTransform: { + value: /* @__PURE__ */ new Matrix32() + }, + uv2Transform: { + value: /* @__PURE__ */ new Matrix32() + }, + alphaMap: { + value: null + }, + alphaTest: { + value: 0 + } + }, + specularmap: { + specularMap: { + value: null + } + }, + envmap: { + envMap: { + value: null + }, + flipEnvMap: { + value: -1 + }, + reflectivity: { + value: 1 + }, + ior: { + value: 1.5 + }, + refractionRatio: { + value: 0.98 + } + }, + aomap: { + aoMap: { + value: null + }, + aoMapIntensity: { + value: 1 + } + }, + lightmap: { + lightMap: { + value: null + }, + lightMapIntensity: { + value: 1 + } + }, + emissivemap: { + emissiveMap: { + value: null + } + }, + bumpmap: { + bumpMap: { + value: null + }, + bumpScale: { + value: 1 + } + }, + normalmap: { + normalMap: { + value: null + }, + normalScale: { + value: /* @__PURE__ */ new Vector22(1, 1) + } + }, + displacementmap: { + displacementMap: { + value: null + }, + displacementScale: { + value: 1 + }, + displacementBias: { + value: 0 + } + }, + roughnessmap: { + roughnessMap: { + value: null + } + }, + metalnessmap: { + metalnessMap: { + value: null + } + }, + gradientmap: { + gradientMap: { + value: null + } + }, + fog: { + fogDensity: { + value: 25e-5 + }, + fogNear: { + value: 1 + }, + fogFar: { + value: 2e3 + }, + fogColor: { + value: /* @__PURE__ */ new Color3(16777215) + } + }, + lights: { + ambientLightColor: { + value: [] + }, + lightProbe: { + value: [] + }, + directionalLights: { + value: [], + properties: { + direction: {}, + color: {} + } + }, + directionalLightShadows: { + value: [], + properties: { + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {} + } + }, + directionalShadowMap: { + value: [] + }, + directionalShadowMatrix: { + value: [] + }, + spotLights: { + value: [], + properties: { + color: {}, + position: {}, + direction: {}, + distance: {}, + coneCos: {}, + penumbraCos: {}, + decay: {} + } + }, + spotLightShadows: { + value: [], + properties: { + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {} + } + }, + spotShadowMap: { + value: [] + }, + spotShadowMatrix: { + value: [] + }, + pointLights: { + value: [], + properties: { + color: {}, + position: {}, + decay: {}, + distance: {} + } + }, + pointLightShadows: { + value: [], + properties: { + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {}, + shadowCameraNear: {}, + shadowCameraFar: {} + } + }, + pointShadowMap: { + value: [] + }, + pointShadowMatrix: { + value: [] + }, + hemisphereLights: { + value: [], + properties: { + direction: {}, + skyColor: {}, + groundColor: {} + } + }, + rectAreaLights: { + value: [], + properties: { + color: {}, + position: {}, + width: {}, + height: {} + } + }, + ltc_1: { + value: null + }, + ltc_2: { + value: null + } + }, + points: { + diffuse: { + value: /* @__PURE__ */ new Color3(16777215) + }, + opacity: { + value: 1 + }, + size: { + value: 1 + }, + scale: { + value: 1 + }, + map: { + value: null + }, + alphaMap: { + value: null + }, + alphaTest: { + value: 0 + }, + uvTransform: { + value: /* @__PURE__ */ new Matrix32() + } + }, + sprite: { + diffuse: { + value: /* @__PURE__ */ new Color3(16777215) + }, + opacity: { + value: 1 + }, + center: { + value: /* @__PURE__ */ new Vector22(0.5, 0.5) + }, + rotation: { + value: 0 + }, + map: { + value: null + }, + alphaMap: { + value: null + }, + alphaTest: { + value: 0 + }, + uvTransform: { + value: /* @__PURE__ */ new Matrix32() + } + } + }; + var ShaderLib2 = { + basic: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.common, UniformsLib2.specularmap, UniformsLib2.envmap, UniformsLib2.aomap, UniformsLib2.lightmap, UniformsLib2.fog]), + vertexShader: ShaderChunk2.meshbasic_vert, + fragmentShader: ShaderChunk2.meshbasic_frag + }, + lambert: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.common, UniformsLib2.specularmap, UniformsLib2.envmap, UniformsLib2.aomap, UniformsLib2.lightmap, UniformsLib2.emissivemap, UniformsLib2.fog, UniformsLib2.lights, { + emissive: { + value: /* @__PURE__ */ new Color3(0) + } + }]), + vertexShader: ShaderChunk2.meshlambert_vert, + fragmentShader: ShaderChunk2.meshlambert_frag + }, + phong: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.common, UniformsLib2.specularmap, UniformsLib2.envmap, UniformsLib2.aomap, UniformsLib2.lightmap, UniformsLib2.emissivemap, UniformsLib2.bumpmap, UniformsLib2.normalmap, UniformsLib2.displacementmap, UniformsLib2.fog, UniformsLib2.lights, { + emissive: { + value: /* @__PURE__ */ new Color3(0) + }, + specular: { + value: /* @__PURE__ */ new Color3(1118481) + }, + shininess: { + value: 30 + } + }]), + vertexShader: ShaderChunk2.meshphong_vert, + fragmentShader: ShaderChunk2.meshphong_frag + }, + standard: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.common, UniformsLib2.envmap, UniformsLib2.aomap, UniformsLib2.lightmap, UniformsLib2.emissivemap, UniformsLib2.bumpmap, UniformsLib2.normalmap, UniformsLib2.displacementmap, UniformsLib2.roughnessmap, UniformsLib2.metalnessmap, UniformsLib2.fog, UniformsLib2.lights, { + emissive: { + value: /* @__PURE__ */ new Color3(0) + }, + roughness: { + value: 1 + }, + metalness: { + value: 0 + }, + envMapIntensity: { + value: 1 + } + }]), + vertexShader: ShaderChunk2.meshphysical_vert, + fragmentShader: ShaderChunk2.meshphysical_frag + }, + toon: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.common, UniformsLib2.aomap, UniformsLib2.lightmap, UniformsLib2.emissivemap, UniformsLib2.bumpmap, UniformsLib2.normalmap, UniformsLib2.displacementmap, UniformsLib2.gradientmap, UniformsLib2.fog, UniformsLib2.lights, { + emissive: { + value: /* @__PURE__ */ new Color3(0) + } + }]), + vertexShader: ShaderChunk2.meshtoon_vert, + fragmentShader: ShaderChunk2.meshtoon_frag + }, + matcap: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.common, UniformsLib2.bumpmap, UniformsLib2.normalmap, UniformsLib2.displacementmap, UniformsLib2.fog, { + matcap: { + value: null + } + }]), + vertexShader: ShaderChunk2.meshmatcap_vert, + fragmentShader: ShaderChunk2.meshmatcap_frag + }, + points: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.points, UniformsLib2.fog]), + vertexShader: ShaderChunk2.points_vert, + fragmentShader: ShaderChunk2.points_frag + }, + dashed: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.common, UniformsLib2.fog, { + scale: { + value: 1 + }, + dashSize: { + value: 1 + }, + totalSize: { + value: 2 + } + }]), + vertexShader: ShaderChunk2.linedashed_vert, + fragmentShader: ShaderChunk2.linedashed_frag + }, + depth: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.common, UniformsLib2.displacementmap]), + vertexShader: ShaderChunk2.depth_vert, + fragmentShader: ShaderChunk2.depth_frag + }, + normal: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.common, UniformsLib2.bumpmap, UniformsLib2.normalmap, UniformsLib2.displacementmap, { + opacity: { + value: 1 + } + }]), + vertexShader: ShaderChunk2.meshnormal_vert, + fragmentShader: ShaderChunk2.meshnormal_frag + }, + sprite: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.sprite, UniformsLib2.fog]), + vertexShader: ShaderChunk2.sprite_vert, + fragmentShader: ShaderChunk2.sprite_frag + }, + background: { + uniforms: { + uvTransform: { + value: /* @__PURE__ */ new Matrix32() + }, + t2D: { + value: null + } + }, + vertexShader: ShaderChunk2.background_vert, + fragmentShader: ShaderChunk2.background_frag + }, + cube: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.envmap, { + opacity: { + value: 1 + } + }]), + vertexShader: ShaderChunk2.cube_vert, + fragmentShader: ShaderChunk2.cube_frag + }, + equirect: { + uniforms: { + tEquirect: { + value: null + } + }, + vertexShader: ShaderChunk2.equirect_vert, + fragmentShader: ShaderChunk2.equirect_frag + }, + distanceRGBA: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.common, UniformsLib2.displacementmap, { + referencePosition: { + value: /* @__PURE__ */ new Vector32() + }, + nearDistance: { + value: 1 + }, + farDistance: { + value: 1e3 + } + }]), + vertexShader: ShaderChunk2.distanceRGBA_vert, + fragmentShader: ShaderChunk2.distanceRGBA_frag + }, + shadow: { + uniforms: /* @__PURE__ */ mergeUniforms2([UniformsLib2.lights, UniformsLib2.fog, { + color: { + value: /* @__PURE__ */ new Color3(0) + }, + opacity: { + value: 1 + } + }]), + vertexShader: ShaderChunk2.shadow_vert, + fragmentShader: ShaderChunk2.shadow_frag + } + }; + ShaderLib2.physical = { + uniforms: /* @__PURE__ */ mergeUniforms2([ShaderLib2.standard.uniforms, { + clearcoat: { + value: 0 + }, + clearcoatMap: { + value: null + }, + clearcoatRoughness: { + value: 0 + }, + clearcoatRoughnessMap: { + value: null + }, + clearcoatNormalScale: { + value: /* @__PURE__ */ new Vector22(1, 1) + }, + clearcoatNormalMap: { + value: null + }, + iridescence: { + value: 0 + }, + iridescenceMap: { + value: null + }, + iridescenceIOR: { + value: 1.3 + }, + iridescenceThicknessMinimum: { + value: 100 + }, + iridescenceThicknessMaximum: { + value: 400 + }, + iridescenceThicknessMap: { + value: null + }, + sheen: { + value: 0 + }, + sheenColor: { + value: /* @__PURE__ */ new Color3(0) + }, + sheenColorMap: { + value: null + }, + sheenRoughness: { + value: 1 + }, + sheenRoughnessMap: { + value: null + }, + transmission: { + value: 0 + }, + transmissionMap: { + value: null + }, + transmissionSamplerSize: { + value: /* @__PURE__ */ new Vector22() + }, + transmissionSamplerMap: { + value: null + }, + thickness: { + value: 0 + }, + thicknessMap: { + value: null + }, + attenuationDistance: { + value: 0 + }, + attenuationColor: { + value: /* @__PURE__ */ new Color3(0) + }, + specularIntensity: { + value: 1 + }, + specularIntensityMap: { + value: null + }, + specularColor: { + value: /* @__PURE__ */ new Color3(1, 1, 1) + }, + specularColorMap: { + value: null + } + }]), + vertexShader: ShaderChunk2.meshphysical_vert, + fragmentShader: ShaderChunk2.meshphysical_frag + }; + function WebGLBackground2(renderer, cubemaps, state, objects, alpha, premultipliedAlpha) { + const clearColor = new Color3(0); + let clearAlpha = alpha === true ? 0 : 1; + let planeMesh; + let boxMesh; + let currentBackground = null; + let currentBackgroundVersion = 0; + let currentTonemapping = null; + function render(renderList, scene) { + let forceClear = false; + let background = scene.isScene === true ? scene.background : null; + if (background && background.isTexture) { + background = cubemaps.get(background); + } + const xr = renderer.xr; + const session = xr.getSession && xr.getSession(); + if (session && session.environmentBlendMode === "additive") { + background = null; + } + if (background === null) { + setClear(clearColor, clearAlpha); + } else if (background && background.isColor) { + setClear(background, 1); + forceClear = true; + } + if (renderer.autoClear || forceClear) { + renderer.clear(renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil); + } + if (background && (background.isCubeTexture || background.mapping === CubeUVReflectionMapping2)) { + if (boxMesh === void 0) { + boxMesh = new Mesh2(new BoxGeometry2(1, 1, 1), new ShaderMaterial2({ + name: "BackgroundCubeMaterial", + uniforms: cloneUniforms2(ShaderLib2.cube.uniforms), + vertexShader: ShaderLib2.cube.vertexShader, + fragmentShader: ShaderLib2.cube.fragmentShader, + side: BackSide2, + depthTest: false, + depthWrite: false, + fog: false + })); + boxMesh.geometry.deleteAttribute("normal"); + boxMesh.geometry.deleteAttribute("uv"); + boxMesh.onBeforeRender = function(renderer2, scene2, camera) { + this.matrixWorld.copyPosition(camera.matrixWorld); + }; + Object.defineProperty(boxMesh.material, "envMap", { + get: function() { + return this.uniforms.envMap.value; + } + }); + objects.update(boxMesh); + } + boxMesh.material.uniforms.envMap.value = background; + boxMesh.material.uniforms.flipEnvMap.value = background.isCubeTexture && background.isRenderTargetTexture === false ? -1 : 1; + if (currentBackground !== background || currentBackgroundVersion !== background.version || currentTonemapping !== renderer.toneMapping) { + boxMesh.material.needsUpdate = true; + currentBackground = background; + currentBackgroundVersion = background.version; + currentTonemapping = renderer.toneMapping; + } + boxMesh.layers.enableAll(); + renderList.unshift(boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null); + } else if (background && background.isTexture) { + if (planeMesh === void 0) { + planeMesh = new Mesh2(new PlaneGeometry2(2, 2), new ShaderMaterial2({ + name: "BackgroundMaterial", + uniforms: cloneUniforms2(ShaderLib2.background.uniforms), + vertexShader: ShaderLib2.background.vertexShader, + fragmentShader: ShaderLib2.background.fragmentShader, + side: FrontSide2, + depthTest: false, + depthWrite: false, + fog: false + })); + planeMesh.geometry.deleteAttribute("normal"); + Object.defineProperty(planeMesh.material, "map", { + get: function() { + return this.uniforms.t2D.value; + } + }); + objects.update(planeMesh); + } + planeMesh.material.uniforms.t2D.value = background; + if (background.matrixAutoUpdate === true) { + background.updateMatrix(); + } + planeMesh.material.uniforms.uvTransform.value.copy(background.matrix); + if (currentBackground !== background || currentBackgroundVersion !== background.version || currentTonemapping !== renderer.toneMapping) { + planeMesh.material.needsUpdate = true; + currentBackground = background; + currentBackgroundVersion = background.version; + currentTonemapping = renderer.toneMapping; + } + planeMesh.layers.enableAll(); + renderList.unshift(planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null); + } + } + function setClear(color2, alpha2) { + state.buffers.color.setClear(color2.r, color2.g, color2.b, alpha2, premultipliedAlpha); + } + return { + getClearColor: function() { + return clearColor; + }, + setClearColor: function(color2, alpha2 = 1) { + clearColor.set(color2); + clearAlpha = alpha2; + setClear(clearColor, clearAlpha); + }, + getClearAlpha: function() { + return clearAlpha; + }, + setClearAlpha: function(alpha2) { + clearAlpha = alpha2; + setClear(clearColor, clearAlpha); + }, + render + }; + } + function WebGLBindingStates2(gl, extensions, attributes, capabilities) { + const maxVertexAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + const extension = capabilities.isWebGL2 ? null : extensions.get("OES_vertex_array_object"); + const vaoAvailable = capabilities.isWebGL2 || extension !== null; + const bindingStates = {}; + const defaultState = createBindingState(null); + let currentState = defaultState; + let forceUpdate = false; + function setup(object, material, program, geometry, index2) { + let updateBuffers = false; + if (vaoAvailable) { + const state = getBindingState(geometry, program, material); + if (currentState !== state) { + currentState = state; + bindVertexArrayObject(currentState.object); + } + updateBuffers = needsUpdate(object, geometry, program, index2); + if (updateBuffers) + saveCache(object, geometry, program, index2); + } else { + const wireframe = material.wireframe === true; + if (currentState.geometry !== geometry.id || currentState.program !== program.id || currentState.wireframe !== wireframe) { + currentState.geometry = geometry.id; + currentState.program = program.id; + currentState.wireframe = wireframe; + updateBuffers = true; + } + } + if (index2 !== null) { + attributes.update(index2, gl.ELEMENT_ARRAY_BUFFER); + } + if (updateBuffers || forceUpdate) { + forceUpdate = false; + setupVertexAttributes(object, material, program, geometry); + if (index2 !== null) { + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, attributes.get(index2).buffer); + } + } + } + function createVertexArrayObject() { + if (capabilities.isWebGL2) + return gl.createVertexArray(); + return extension.createVertexArrayOES(); + } + function bindVertexArrayObject(vao) { + if (capabilities.isWebGL2) + return gl.bindVertexArray(vao); + return extension.bindVertexArrayOES(vao); + } + function deleteVertexArrayObject(vao) { + if (capabilities.isWebGL2) + return gl.deleteVertexArray(vao); + return extension.deleteVertexArrayOES(vao); + } + function getBindingState(geometry, program, material) { + const wireframe = material.wireframe === true; + let programMap = bindingStates[geometry.id]; + if (programMap === void 0) { + programMap = {}; + bindingStates[geometry.id] = programMap; + } + let stateMap = programMap[program.id]; + if (stateMap === void 0) { + stateMap = {}; + programMap[program.id] = stateMap; + } + let state = stateMap[wireframe]; + if (state === void 0) { + state = createBindingState(createVertexArrayObject()); + stateMap[wireframe] = state; + } + return state; + } + function createBindingState(vao) { + const newAttributes = []; + const enabledAttributes = []; + const attributeDivisors = []; + for (let i = 0; i < maxVertexAttributes; i++) { + newAttributes[i] = 0; + enabledAttributes[i] = 0; + attributeDivisors[i] = 0; + } + return { + geometry: null, + program: null, + wireframe: false, + newAttributes, + enabledAttributes, + attributeDivisors, + object: vao, + attributes: {}, + index: null + }; + } + function needsUpdate(object, geometry, program, index2) { + const cachedAttributes = currentState.attributes; + const geometryAttributes = geometry.attributes; + let attributesNum = 0; + const programAttributes = program.getAttributes(); + for (const name in programAttributes) { + const programAttribute = programAttributes[name]; + if (programAttribute.location >= 0) { + const cachedAttribute = cachedAttributes[name]; + let geometryAttribute = geometryAttributes[name]; + if (geometryAttribute === void 0) { + if (name === "instanceMatrix" && object.instanceMatrix) + geometryAttribute = object.instanceMatrix; + if (name === "instanceColor" && object.instanceColor) + geometryAttribute = object.instanceColor; + } + if (cachedAttribute === void 0) + return true; + if (cachedAttribute.attribute !== geometryAttribute) + return true; + if (geometryAttribute && cachedAttribute.data !== geometryAttribute.data) + return true; + attributesNum++; + } + } + if (currentState.attributesNum !== attributesNum) + return true; + if (currentState.index !== index2) + return true; + return false; + } + function saveCache(object, geometry, program, index2) { + const cache2 = {}; + const attributes2 = geometry.attributes; + let attributesNum = 0; + const programAttributes = program.getAttributes(); + for (const name in programAttributes) { + const programAttribute = programAttributes[name]; + if (programAttribute.location >= 0) { + let attribute = attributes2[name]; + if (attribute === void 0) { + if (name === "instanceMatrix" && object.instanceMatrix) + attribute = object.instanceMatrix; + if (name === "instanceColor" && object.instanceColor) + attribute = object.instanceColor; + } + const data = {}; + data.attribute = attribute; + if (attribute && attribute.data) { + data.data = attribute.data; + } + cache2[name] = data; + attributesNum++; + } + } + currentState.attributes = cache2; + currentState.attributesNum = attributesNum; + currentState.index = index2; + } + function initAttributes() { + const newAttributes = currentState.newAttributes; + for (let i = 0, il = newAttributes.length; i < il; i++) { + newAttributes[i] = 0; + } + } + function enableAttribute(attribute) { + enableAttributeAndDivisor(attribute, 0); + } + function enableAttributeAndDivisor(attribute, meshPerAttribute) { + const newAttributes = currentState.newAttributes; + const enabledAttributes = currentState.enabledAttributes; + const attributeDivisors = currentState.attributeDivisors; + newAttributes[attribute] = 1; + if (enabledAttributes[attribute] === 0) { + gl.enableVertexAttribArray(attribute); + enabledAttributes[attribute] = 1; + } + if (attributeDivisors[attribute] !== meshPerAttribute) { + const extension2 = capabilities.isWebGL2 ? gl : extensions.get("ANGLE_instanced_arrays"); + extension2[capabilities.isWebGL2 ? "vertexAttribDivisor" : "vertexAttribDivisorANGLE"](attribute, meshPerAttribute); + attributeDivisors[attribute] = meshPerAttribute; + } + } + function disableUnusedAttributes() { + const newAttributes = currentState.newAttributes; + const enabledAttributes = currentState.enabledAttributes; + for (let i = 0, il = enabledAttributes.length; i < il; i++) { + if (enabledAttributes[i] !== newAttributes[i]) { + gl.disableVertexAttribArray(i); + enabledAttributes[i] = 0; + } + } + } + function vertexAttribPointer(index2, size, type2, normalized, stride, offset) { + if (capabilities.isWebGL2 === true && (type2 === gl.INT || type2 === gl.UNSIGNED_INT)) { + gl.vertexAttribIPointer(index2, size, type2, stride, offset); + } else { + gl.vertexAttribPointer(index2, size, type2, normalized, stride, offset); + } + } + function setupVertexAttributes(object, material, program, geometry) { + if (capabilities.isWebGL2 === false && (object.isInstancedMesh || geometry.isInstancedBufferGeometry)) { + if (extensions.get("ANGLE_instanced_arrays") === null) + return; + } + initAttributes(); + const geometryAttributes = geometry.attributes; + const programAttributes = program.getAttributes(); + const materialDefaultAttributeValues = material.defaultAttributeValues; + for (const name in programAttributes) { + const programAttribute = programAttributes[name]; + if (programAttribute.location >= 0) { + let geometryAttribute = geometryAttributes[name]; + if (geometryAttribute === void 0) { + if (name === "instanceMatrix" && object.instanceMatrix) + geometryAttribute = object.instanceMatrix; + if (name === "instanceColor" && object.instanceColor) + geometryAttribute = object.instanceColor; + } + if (geometryAttribute !== void 0) { + const normalized = geometryAttribute.normalized; + const size = geometryAttribute.itemSize; + const attribute = attributes.get(geometryAttribute); + if (attribute === void 0) + continue; + const buffer = attribute.buffer; + const type2 = attribute.type; + const bytesPerElement = attribute.bytesPerElement; + if (geometryAttribute.isInterleavedBufferAttribute) { + const data = geometryAttribute.data; + const stride = data.stride; + const offset = geometryAttribute.offset; + if (data.isInstancedInterleavedBuffer) { + for (let i = 0; i < programAttribute.locationSize; i++) { + enableAttributeAndDivisor(programAttribute.location + i, data.meshPerAttribute); + } + if (object.isInstancedMesh !== true && geometry._maxInstanceCount === void 0) { + geometry._maxInstanceCount = data.meshPerAttribute * data.count; + } + } else { + for (let i = 0; i < programAttribute.locationSize; i++) { + enableAttribute(programAttribute.location + i); + } + } + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + for (let i = 0; i < programAttribute.locationSize; i++) { + vertexAttribPointer(programAttribute.location + i, size / programAttribute.locationSize, type2, normalized, stride * bytesPerElement, (offset + size / programAttribute.locationSize * i) * bytesPerElement); + } + } else { + if (geometryAttribute.isInstancedBufferAttribute) { + for (let i = 0; i < programAttribute.locationSize; i++) { + enableAttributeAndDivisor(programAttribute.location + i, geometryAttribute.meshPerAttribute); + } + if (object.isInstancedMesh !== true && geometry._maxInstanceCount === void 0) { + geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; + } + } else { + for (let i = 0; i < programAttribute.locationSize; i++) { + enableAttribute(programAttribute.location + i); + } + } + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + for (let i = 0; i < programAttribute.locationSize; i++) { + vertexAttribPointer(programAttribute.location + i, size / programAttribute.locationSize, type2, normalized, size * bytesPerElement, size / programAttribute.locationSize * i * bytesPerElement); + } + } + } else if (materialDefaultAttributeValues !== void 0) { + const value = materialDefaultAttributeValues[name]; + if (value !== void 0) { + switch (value.length) { + case 2: + gl.vertexAttrib2fv(programAttribute.location, value); + break; + case 3: + gl.vertexAttrib3fv(programAttribute.location, value); + break; + case 4: + gl.vertexAttrib4fv(programAttribute.location, value); + break; + default: + gl.vertexAttrib1fv(programAttribute.location, value); + } + } + } + } + } + disableUnusedAttributes(); + } + function dispose() { + reset(); + for (const geometryId in bindingStates) { + const programMap = bindingStates[geometryId]; + for (const programId in programMap) { + const stateMap = programMap[programId]; + for (const wireframe in stateMap) { + deleteVertexArrayObject(stateMap[wireframe].object); + delete stateMap[wireframe]; + } + delete programMap[programId]; + } + delete bindingStates[geometryId]; + } + } + function releaseStatesOfGeometry(geometry) { + if (bindingStates[geometry.id] === void 0) + return; + const programMap = bindingStates[geometry.id]; + for (const programId in programMap) { + const stateMap = programMap[programId]; + for (const wireframe in stateMap) { + deleteVertexArrayObject(stateMap[wireframe].object); + delete stateMap[wireframe]; + } + delete programMap[programId]; + } + delete bindingStates[geometry.id]; + } + function releaseStatesOfProgram(program) { + for (const geometryId in bindingStates) { + const programMap = bindingStates[geometryId]; + if (programMap[program.id] === void 0) + continue; + const stateMap = programMap[program.id]; + for (const wireframe in stateMap) { + deleteVertexArrayObject(stateMap[wireframe].object); + delete stateMap[wireframe]; + } + delete programMap[program.id]; + } + } + function reset() { + resetDefaultState(); + forceUpdate = true; + if (currentState === defaultState) + return; + currentState = defaultState; + bindVertexArrayObject(currentState.object); + } + function resetDefaultState() { + defaultState.geometry = null; + defaultState.program = null; + defaultState.wireframe = false; + } + return { + setup, + reset, + resetDefaultState, + dispose, + releaseStatesOfGeometry, + releaseStatesOfProgram, + initAttributes, + enableAttribute, + disableUnusedAttributes + }; + } + function WebGLBufferRenderer2(gl, extensions, info, capabilities) { + const isWebGL2 = capabilities.isWebGL2; + let mode; + function setMode(value) { + mode = value; + } + function render(start2, count) { + gl.drawArrays(mode, start2, count); + info.update(count, mode, 1); + } + function renderInstances(start2, count, primcount) { + if (primcount === 0) + return; + let extension, methodName; + if (isWebGL2) { + extension = gl; + methodName = "drawArraysInstanced"; + } else { + extension = extensions.get("ANGLE_instanced_arrays"); + methodName = "drawArraysInstancedANGLE"; + if (extension === null) { + console.error("THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays."); + return; + } + } + extension[methodName](mode, start2, count, primcount); + info.update(count, mode, primcount); + } + this.setMode = setMode; + this.render = render; + this.renderInstances = renderInstances; + } + function WebGLCapabilities2(gl, extensions, parameters) { + let maxAnisotropy; + function getMaxAnisotropy() { + if (maxAnisotropy !== void 0) + return maxAnisotropy; + if (extensions.has("EXT_texture_filter_anisotropic") === true) { + const extension = extensions.get("EXT_texture_filter_anisotropic"); + maxAnisotropy = gl.getParameter(extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT); + } else { + maxAnisotropy = 0; + } + return maxAnisotropy; + } + function getMaxPrecision(precision2) { + if (precision2 === "highp") { + if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision > 0) { + return "highp"; + } + precision2 = "mediump"; + } + if (precision2 === "mediump") { + if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT).precision > 0) { + return "mediump"; + } + } + return "lowp"; + } + const isWebGL2 = typeof WebGL2RenderingContext !== "undefined" && gl instanceof WebGL2RenderingContext || typeof WebGL2ComputeRenderingContext !== "undefined" && gl instanceof WebGL2ComputeRenderingContext; + let precision = parameters.precision !== void 0 ? parameters.precision : "highp"; + const maxPrecision = getMaxPrecision(precision); + if (maxPrecision !== precision) { + console.warn("THREE.WebGLRenderer:", precision, "not supported, using", maxPrecision, "instead."); + precision = maxPrecision; + } + const drawBuffers = isWebGL2 || extensions.has("WEBGL_draw_buffers"); + const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; + const maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + const maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS); + const maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); + const maxCubemapSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE); + const maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + const maxVertexUniforms = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS); + const maxVaryings = gl.getParameter(gl.MAX_VARYING_VECTORS); + const maxFragmentUniforms = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS); + const vertexTextures = maxVertexTextures > 0; + const floatFragmentTextures = isWebGL2 || extensions.has("OES_texture_float"); + const floatVertexTextures = vertexTextures && floatFragmentTextures; + const maxSamples = isWebGL2 ? gl.getParameter(gl.MAX_SAMPLES) : 0; + return { + isWebGL2, + drawBuffers, + getMaxAnisotropy, + getMaxPrecision, + precision, + logarithmicDepthBuffer, + maxTextures, + maxVertexTextures, + maxTextureSize, + maxCubemapSize, + maxAttributes, + maxVertexUniforms, + maxVaryings, + maxFragmentUniforms, + vertexTextures, + floatFragmentTextures, + floatVertexTextures, + maxSamples + }; + } + function WebGLClipping2(properties) { + const scope = this; + let globalState = null, numGlobalPlanes = 0, localClippingEnabled = false, renderingShadows = false; + const plane = new Plane2(), viewNormalMatrix = new Matrix32(), uniform = { + value: null, + needsUpdate: false + }; + this.uniform = uniform; + this.numPlanes = 0; + this.numIntersection = 0; + this.init = function(planes, enableLocalClipping, camera) { + const enabled = planes.length !== 0 || enableLocalClipping || numGlobalPlanes !== 0 || localClippingEnabled; + localClippingEnabled = enableLocalClipping; + globalState = projectPlanes(planes, camera, 0); + numGlobalPlanes = planes.length; + return enabled; + }; + this.beginShadows = function() { + renderingShadows = true; + projectPlanes(null); + }; + this.endShadows = function() { + renderingShadows = false; + resetGlobalState(); + }; + this.setState = function(material, camera, useCache) { + const planes = material.clippingPlanes, clipIntersection = material.clipIntersection, clipShadows = material.clipShadows; + const materialProperties = properties.get(material); + if (!localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && !clipShadows) { + if (renderingShadows) { + projectPlanes(null); + } else { + resetGlobalState(); + } + } else { + const nGlobal = renderingShadows ? 0 : numGlobalPlanes, lGlobal = nGlobal * 4; + let dstArray = materialProperties.clippingState || null; + uniform.value = dstArray; + dstArray = projectPlanes(planes, camera, lGlobal, useCache); + for (let i = 0; i !== lGlobal; ++i) { + dstArray[i] = globalState[i]; + } + materialProperties.clippingState = dstArray; + this.numIntersection = clipIntersection ? this.numPlanes : 0; + this.numPlanes += nGlobal; + } + }; + function resetGlobalState() { + if (uniform.value !== globalState) { + uniform.value = globalState; + uniform.needsUpdate = numGlobalPlanes > 0; + } + scope.numPlanes = numGlobalPlanes; + scope.numIntersection = 0; + } + function projectPlanes(planes, camera, dstOffset, skipTransform) { + const nPlanes = planes !== null ? planes.length : 0; + let dstArray = null; + if (nPlanes !== 0) { + dstArray = uniform.value; + if (skipTransform !== true || dstArray === null) { + const flatSize = dstOffset + nPlanes * 4, viewMatrix = camera.matrixWorldInverse; + viewNormalMatrix.getNormalMatrix(viewMatrix); + if (dstArray === null || dstArray.length < flatSize) { + dstArray = new Float32Array(flatSize); + } + for (let i = 0, i4 = dstOffset; i !== nPlanes; ++i, i4 += 4) { + plane.copy(planes[i]).applyMatrix4(viewMatrix, viewNormalMatrix); + plane.normal.toArray(dstArray, i4); + dstArray[i4 + 3] = plane.constant; + } + } + uniform.value = dstArray; + uniform.needsUpdate = true; + } + scope.numPlanes = nPlanes; + scope.numIntersection = 0; + return dstArray; + } + } + function WebGLCubeMaps2(renderer) { + let cubemaps = /* @__PURE__ */ new WeakMap(); + function mapTextureMapping(texture, mapping) { + if (mapping === EquirectangularReflectionMapping2) { + texture.mapping = CubeReflectionMapping2; + } else if (mapping === EquirectangularRefractionMapping2) { + texture.mapping = CubeRefractionMapping2; + } + return texture; + } + function get3(texture) { + if (texture && texture.isTexture && texture.isRenderTargetTexture === false) { + const mapping = texture.mapping; + if (mapping === EquirectangularReflectionMapping2 || mapping === EquirectangularRefractionMapping2) { + if (cubemaps.has(texture)) { + const cubemap = cubemaps.get(texture).texture; + return mapTextureMapping(cubemap, texture.mapping); + } else { + const image = texture.image; + if (image && image.height > 0) { + const renderTarget = new WebGLCubeRenderTarget2(image.height / 2); + renderTarget.fromEquirectangularTexture(renderer, texture); + cubemaps.set(texture, renderTarget); + texture.addEventListener("dispose", onTextureDispose); + return mapTextureMapping(renderTarget.texture, texture.mapping); + } else { + return null; + } + } + } + } + return texture; + } + function onTextureDispose(event) { + const texture = event.target; + texture.removeEventListener("dispose", onTextureDispose); + const cubemap = cubemaps.get(texture); + if (cubemap !== void 0) { + cubemaps.delete(texture); + cubemap.dispose(); + } + } + function dispose() { + cubemaps = /* @__PURE__ */ new WeakMap(); + } + return { + get: get3, + dispose + }; + } + var OrthographicCamera2 = class extends Camera2 { + constructor(left = -1, right = 1, top = 1, bottom = -1, near = 0.1, far = 2e3) { + super(); + this.isOrthographicCamera = true; + this.type = "OrthographicCamera"; + this.zoom = 1; + this.view = null; + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; + this.near = near; + this.far = far; + this.updateProjectionMatrix(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.left = source.left; + this.right = source.right; + this.top = source.top; + this.bottom = source.bottom; + this.near = source.near; + this.far = source.far; + this.zoom = source.zoom; + this.view = source.view === null ? null : Object.assign({}, source.view); + return this; + } + setViewOffset(fullWidth, fullHeight, x2, y2, width, height) { + if (this.view === null) { + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; + } + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x2; + this.view.offsetY = y2; + this.view.width = width; + this.view.height = height; + this.updateProjectionMatrix(); + } + clearViewOffset() { + if (this.view !== null) { + this.view.enabled = false; + } + this.updateProjectionMatrix(); + } + updateProjectionMatrix() { + const dx = (this.right - this.left) / (2 * this.zoom); + const dy = (this.top - this.bottom) / (2 * this.zoom); + const cx = (this.right + this.left) / 2; + const cy = (this.top + this.bottom) / 2; + let left = cx - dx; + let right = cx + dx; + let top = cy + dy; + let bottom = cy - dy; + if (this.view !== null && this.view.enabled) { + const scaleW = (this.right - this.left) / this.view.fullWidth / this.zoom; + const scaleH = (this.top - this.bottom) / this.view.fullHeight / this.zoom; + left += scaleW * this.view.offsetX; + right = left + scaleW * this.view.width; + top -= scaleH * this.view.offsetY; + bottom = top - scaleH * this.view.height; + } + this.projectionMatrix.makeOrthographic(left, right, top, bottom, this.near, this.far); + this.projectionMatrixInverse.copy(this.projectionMatrix).invert(); + } + toJSON(meta) { + const data = super.toJSON(meta); + data.object.zoom = this.zoom; + data.object.left = this.left; + data.object.right = this.right; + data.object.top = this.top; + data.object.bottom = this.bottom; + data.object.near = this.near; + data.object.far = this.far; + if (this.view !== null) + data.object.view = Object.assign({}, this.view); + return data; + } + }; + var LOD_MIN2 = 4; + var EXTRA_LOD_SIGMA2 = [0.125, 0.215, 0.35, 0.446, 0.526, 0.582]; + var MAX_SAMPLES2 = 20; + var _flatCamera2 = /* @__PURE__ */ new OrthographicCamera2(); + var _clearColor2 = /* @__PURE__ */ new Color3(); + var _oldTarget2 = null; + var PHI2 = (1 + Math.sqrt(5)) / 2; + var INV_PHI2 = 1 / PHI2; + var _axisDirections2 = [/* @__PURE__ */ new Vector32(1, 1, 1), /* @__PURE__ */ new Vector32(-1, 1, 1), /* @__PURE__ */ new Vector32(1, 1, -1), /* @__PURE__ */ new Vector32(-1, 1, -1), /* @__PURE__ */ new Vector32(0, PHI2, INV_PHI2), /* @__PURE__ */ new Vector32(0, PHI2, -INV_PHI2), /* @__PURE__ */ new Vector32(INV_PHI2, 0, PHI2), /* @__PURE__ */ new Vector32(-INV_PHI2, 0, PHI2), /* @__PURE__ */ new Vector32(PHI2, INV_PHI2, 0), /* @__PURE__ */ new Vector32(-PHI2, INV_PHI2, 0)]; + var PMREMGenerator2 = class { + constructor(renderer) { + this._renderer = renderer; + this._pingPongRenderTarget = null; + this._lodMax = 0; + this._cubeSize = 0; + this._lodPlanes = []; + this._sizeLods = []; + this._sigmas = []; + this._blurMaterial = null; + this._cubemapMaterial = null; + this._equirectMaterial = null; + this._compileMaterial(this._blurMaterial); + } + fromScene(scene, sigma = 0, near = 0.1, far = 100) { + _oldTarget2 = this._renderer.getRenderTarget(); + this._setSize(256); + const cubeUVRenderTarget = this._allocateTargets(); + cubeUVRenderTarget.depthBuffer = true; + this._sceneToCubeUV(scene, near, far, cubeUVRenderTarget); + if (sigma > 0) { + this._blur(cubeUVRenderTarget, 0, 0, sigma); + } + this._applyPMREM(cubeUVRenderTarget); + this._cleanup(cubeUVRenderTarget); + return cubeUVRenderTarget; + } + fromEquirectangular(equirectangular, renderTarget = null) { + return this._fromTexture(equirectangular, renderTarget); + } + fromCubemap(cubemap, renderTarget = null) { + return this._fromTexture(cubemap, renderTarget); + } + compileCubemapShader() { + if (this._cubemapMaterial === null) { + this._cubemapMaterial = _getCubemapMaterial2(); + this._compileMaterial(this._cubemapMaterial); + } + } + compileEquirectangularShader() { + if (this._equirectMaterial === null) { + this._equirectMaterial = _getEquirectMaterial2(); + this._compileMaterial(this._equirectMaterial); + } + } + dispose() { + this._dispose(); + if (this._cubemapMaterial !== null) + this._cubemapMaterial.dispose(); + if (this._equirectMaterial !== null) + this._equirectMaterial.dispose(); + } + _setSize(cubeSize) { + this._lodMax = Math.floor(Math.log2(cubeSize)); + this._cubeSize = Math.pow(2, this._lodMax); + } + _dispose() { + if (this._blurMaterial !== null) + this._blurMaterial.dispose(); + if (this._pingPongRenderTarget !== null) + this._pingPongRenderTarget.dispose(); + for (let i = 0; i < this._lodPlanes.length; i++) { + this._lodPlanes[i].dispose(); + } + } + _cleanup(outputTarget) { + this._renderer.setRenderTarget(_oldTarget2); + outputTarget.scissorTest = false; + _setViewport2(outputTarget, 0, 0, outputTarget.width, outputTarget.height); + } + _fromTexture(texture, renderTarget) { + if (texture.mapping === CubeReflectionMapping2 || texture.mapping === CubeRefractionMapping2) { + this._setSize(texture.image.length === 0 ? 16 : texture.image[0].width || texture.image[0].image.width); + } else { + this._setSize(texture.image.width / 4); + } + _oldTarget2 = this._renderer.getRenderTarget(); + const cubeUVRenderTarget = renderTarget || this._allocateTargets(); + this._textureToCubeUV(texture, cubeUVRenderTarget); + this._applyPMREM(cubeUVRenderTarget); + this._cleanup(cubeUVRenderTarget); + return cubeUVRenderTarget; + } + _allocateTargets() { + const width = 3 * Math.max(this._cubeSize, 16 * 7); + const height = 4 * this._cubeSize; + const params = { + magFilter: LinearFilter2, + minFilter: LinearFilter2, + generateMipmaps: false, + type: HalfFloatType2, + format: RGBAFormat2, + encoding: LinearEncoding2, + depthBuffer: false + }; + const cubeUVRenderTarget = _createRenderTarget2(width, height, params); + if (this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width) { + if (this._pingPongRenderTarget !== null) { + this._dispose(); + } + this._pingPongRenderTarget = _createRenderTarget2(width, height, params); + const { + _lodMax + } = this; + ({ + sizeLods: this._sizeLods, + lodPlanes: this._lodPlanes, + sigmas: this._sigmas + } = _createPlanes2(_lodMax)); + this._blurMaterial = _getBlurShader2(_lodMax, width, height); + } + return cubeUVRenderTarget; + } + _compileMaterial(material) { + const tmpMesh = new Mesh2(this._lodPlanes[0], material); + this._renderer.compile(tmpMesh, _flatCamera2); + } + _sceneToCubeUV(scene, near, far, cubeUVRenderTarget) { + const fov3 = 90; + const aspect3 = 1; + const cubeCamera = new PerspectiveCamera2(fov3, aspect3, near, far); + const upSign = [1, -1, 1, 1, 1, 1]; + const forwardSign = [1, 1, 1, -1, -1, -1]; + const renderer = this._renderer; + const originalAutoClear = renderer.autoClear; + const toneMapping = renderer.toneMapping; + renderer.getClearColor(_clearColor2); + renderer.toneMapping = NoToneMapping2; + renderer.autoClear = false; + const backgroundMaterial = new MeshBasicMaterial2({ + name: "PMREM.Background", + side: BackSide2, + depthWrite: false, + depthTest: false + }); + const backgroundBox = new Mesh2(new BoxGeometry2(), backgroundMaterial); + let useSolidColor = false; + const background = scene.background; + if (background) { + if (background.isColor) { + backgroundMaterial.color.copy(background); + scene.background = null; + useSolidColor = true; + } + } else { + backgroundMaterial.color.copy(_clearColor2); + useSolidColor = true; + } + for (let i = 0; i < 6; i++) { + const col = i % 3; + if (col === 0) { + cubeCamera.up.set(0, upSign[i], 0); + cubeCamera.lookAt(forwardSign[i], 0, 0); + } else if (col === 1) { + cubeCamera.up.set(0, 0, upSign[i]); + cubeCamera.lookAt(0, forwardSign[i], 0); + } else { + cubeCamera.up.set(0, upSign[i], 0); + cubeCamera.lookAt(0, 0, forwardSign[i]); + } + const size = this._cubeSize; + _setViewport2(cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size); + renderer.setRenderTarget(cubeUVRenderTarget); + if (useSolidColor) { + renderer.render(backgroundBox, cubeCamera); + } + renderer.render(scene, cubeCamera); + } + backgroundBox.geometry.dispose(); + backgroundBox.material.dispose(); + renderer.toneMapping = toneMapping; + renderer.autoClear = originalAutoClear; + scene.background = background; + } + _textureToCubeUV(texture, cubeUVRenderTarget) { + const renderer = this._renderer; + const isCubeTexture = texture.mapping === CubeReflectionMapping2 || texture.mapping === CubeRefractionMapping2; + if (isCubeTexture) { + if (this._cubemapMaterial === null) { + this._cubemapMaterial = _getCubemapMaterial2(); + } + this._cubemapMaterial.uniforms.flipEnvMap.value = texture.isRenderTargetTexture === false ? -1 : 1; + } else { + if (this._equirectMaterial === null) { + this._equirectMaterial = _getEquirectMaterial2(); + } + } + const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; + const mesh = new Mesh2(this._lodPlanes[0], material); + const uniforms = material.uniforms; + uniforms["envMap"].value = texture; + const size = this._cubeSize; + _setViewport2(cubeUVRenderTarget, 0, 0, 3 * size, 2 * size); + renderer.setRenderTarget(cubeUVRenderTarget); + renderer.render(mesh, _flatCamera2); + } + _applyPMREM(cubeUVRenderTarget) { + const renderer = this._renderer; + const autoClear = renderer.autoClear; + renderer.autoClear = false; + for (let i = 1; i < this._lodPlanes.length; i++) { + const sigma = Math.sqrt(this._sigmas[i] * this._sigmas[i] - this._sigmas[i - 1] * this._sigmas[i - 1]); + const poleAxis = _axisDirections2[(i - 1) % _axisDirections2.length]; + this._blur(cubeUVRenderTarget, i - 1, i, sigma, poleAxis); + } + renderer.autoClear = autoClear; + } + _blur(cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis) { + const pingPongRenderTarget = this._pingPongRenderTarget; + this._halfBlur(cubeUVRenderTarget, pingPongRenderTarget, lodIn, lodOut, sigma, "latitudinal", poleAxis); + this._halfBlur(pingPongRenderTarget, cubeUVRenderTarget, lodOut, lodOut, sigma, "longitudinal", poleAxis); + } + _halfBlur(targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis) { + const renderer = this._renderer; + const blurMaterial = this._blurMaterial; + if (direction !== "latitudinal" && direction !== "longitudinal") { + console.error("blur direction must be either latitudinal or longitudinal!"); + } + const STANDARD_DEVIATIONS = 3; + const blurMesh = new Mesh2(this._lodPlanes[lodOut], blurMaterial); + const blurUniforms = blurMaterial.uniforms; + const pixels = this._sizeLods[lodIn] - 1; + const radiansPerPixel = isFinite(sigmaRadians) ? Math.PI / (2 * pixels) : 2 * Math.PI / (2 * MAX_SAMPLES2 - 1); + const sigmaPixels = sigmaRadians / radiansPerPixel; + const samples = isFinite(sigmaRadians) ? 1 + Math.floor(STANDARD_DEVIATIONS * sigmaPixels) : MAX_SAMPLES2; + if (samples > MAX_SAMPLES2) { + console.warn(`sigmaRadians, ${sigmaRadians}, is too large and will clip, as it requested ${samples} samples when the maximum is set to ${MAX_SAMPLES2}`); + } + const weights = []; + let sum = 0; + for (let i = 0; i < MAX_SAMPLES2; ++i) { + const x3 = i / sigmaPixels; + const weight = Math.exp(-x3 * x3 / 2); + weights.push(weight); + if (i === 0) { + sum += weight; + } else if (i < samples) { + sum += 2 * weight; + } + } + for (let i = 0; i < weights.length; i++) { + weights[i] = weights[i] / sum; + } + blurUniforms["envMap"].value = targetIn.texture; + blurUniforms["samples"].value = samples; + blurUniforms["weights"].value = weights; + blurUniforms["latitudinal"].value = direction === "latitudinal"; + if (poleAxis) { + blurUniforms["poleAxis"].value = poleAxis; + } + const { + _lodMax + } = this; + blurUniforms["dTheta"].value = radiansPerPixel; + blurUniforms["mipInt"].value = _lodMax - lodIn; + const outputSize = this._sizeLods[lodOut]; + const x2 = 3 * outputSize * (lodOut > _lodMax - LOD_MIN2 ? lodOut - _lodMax + LOD_MIN2 : 0); + const y2 = 4 * (this._cubeSize - outputSize); + _setViewport2(targetOut, x2, y2, 3 * outputSize, 2 * outputSize); + renderer.setRenderTarget(targetOut); + renderer.render(blurMesh, _flatCamera2); + } + }; + function _createPlanes2(lodMax) { + const lodPlanes = []; + const sizeLods = []; + const sigmas = []; + let lod = lodMax; + const totalLods = lodMax - LOD_MIN2 + 1 + EXTRA_LOD_SIGMA2.length; + for (let i = 0; i < totalLods; i++) { + const sizeLod = Math.pow(2, lod); + sizeLods.push(sizeLod); + let sigma = 1 / sizeLod; + if (i > lodMax - LOD_MIN2) { + sigma = EXTRA_LOD_SIGMA2[i - lodMax + LOD_MIN2 - 1]; + } else if (i === 0) { + sigma = 0; + } + sigmas.push(sigma); + const texelSize = 1 / (sizeLod - 2); + const min2 = -texelSize; + const max2 = 1 + texelSize; + const uv1 = [min2, min2, max2, min2, max2, max2, min2, min2, max2, max2, min2, max2]; + const cubeFaces = 6; + const vertices = 6; + const positionSize = 3; + const uvSize = 2; + const faceIndexSize = 1; + const position = new Float32Array(positionSize * vertices * cubeFaces); + const uv = new Float32Array(uvSize * vertices * cubeFaces); + const faceIndex = new Float32Array(faceIndexSize * vertices * cubeFaces); + for (let face = 0; face < cubeFaces; face++) { + const x2 = face % 3 * 2 / 3 - 1; + const y2 = face > 2 ? 0 : -1; + const coordinates = [x2, y2, 0, x2 + 2 / 3, y2, 0, x2 + 2 / 3, y2 + 1, 0, x2, y2, 0, x2 + 2 / 3, y2 + 1, 0, x2, y2 + 1, 0]; + position.set(coordinates, positionSize * vertices * face); + uv.set(uv1, uvSize * vertices * face); + const fill = [face, face, face, face, face, face]; + faceIndex.set(fill, faceIndexSize * vertices * face); + } + const planes = new BufferGeometry2(); + planes.setAttribute("position", new BufferAttribute2(position, positionSize)); + planes.setAttribute("uv", new BufferAttribute2(uv, uvSize)); + planes.setAttribute("faceIndex", new BufferAttribute2(faceIndex, faceIndexSize)); + lodPlanes.push(planes); + if (lod > LOD_MIN2) { + lod--; + } + } + return { + lodPlanes, + sizeLods, + sigmas + }; + } + function _createRenderTarget2(width, height, params) { + const cubeUVRenderTarget = new WebGLRenderTarget2(width, height, params); + cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping2; + cubeUVRenderTarget.texture.name = "PMREM.cubeUv"; + cubeUVRenderTarget.scissorTest = true; + return cubeUVRenderTarget; + } + function _setViewport2(target, x2, y2, width, height) { + target.viewport.set(x2, y2, width, height); + target.scissor.set(x2, y2, width, height); + } + function _getBlurShader2(lodMax, width, height) { + const weights = new Float32Array(MAX_SAMPLES2); + const poleAxis = new Vector32(0, 1, 0); + const shaderMaterial = new ShaderMaterial2({ + name: "SphericalGaussianBlur", + defines: { + "n": MAX_SAMPLES2, + "CUBEUV_TEXEL_WIDTH": 1 / width, + "CUBEUV_TEXEL_HEIGHT": 1 / height, + "CUBEUV_MAX_MIP": `${lodMax}.0` + }, + uniforms: { + "envMap": { + value: null + }, + "samples": { + value: 1 + }, + "weights": { + value: weights + }, + "latitudinal": { + value: false + }, + "dTheta": { + value: 0 + }, + "mipInt": { + value: 0 + }, + "poleAxis": { + value: poleAxis + } + }, + vertexShader: _getCommonVertexShader2(), + fragmentShader: ` + + precision mediump float; + precision mediump int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + uniform int samples; + uniform float weights[ n ]; + uniform bool latitudinal; + uniform float dTheta; + uniform float mipInt; + uniform vec3 poleAxis; + + #define ENVMAP_TYPE_CUBE_UV + #include + + vec3 getSample( float theta, vec3 axis ) { + + float cosTheta = cos( theta ); + // Rodrigues' axis-angle rotation + vec3 sampleDirection = vOutputDirection * cosTheta + + cross( axis, vOutputDirection ) * sin( theta ) + + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta ); + + return bilinearCubeUV( envMap, sampleDirection, mipInt ); + + } + + void main() { + + vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); + + if ( all( equal( axis, vec3( 0.0 ) ) ) ) { + + axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); + + } + + axis = normalize( axis ); + + gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); + + for ( int i = 1; i < n; i++ ) { + + if ( i >= samples ) { + + break; + + } + + float theta = dTheta * float( i ); + gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); + gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); + + } + + } + `, + blending: NoBlending2, + depthTest: false, + depthWrite: false + }); + return shaderMaterial; + } + function _getEquirectMaterial2() { + return new ShaderMaterial2({ + name: "EquirectangularToCubeUV", + uniforms: { + "envMap": { + value: null + } + }, + vertexShader: _getCommonVertexShader2(), + fragmentShader: ` + + precision mediump float; + precision mediump int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + + #include + + void main() { + + vec3 outputDirection = normalize( vOutputDirection ); + vec2 uv = equirectUv( outputDirection ); + + gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); + + } + `, + blending: NoBlending2, + depthTest: false, + depthWrite: false + }); + } + function _getCubemapMaterial2() { + return new ShaderMaterial2({ + name: "CubemapToCubeUV", + uniforms: { + "envMap": { + value: null + }, + "flipEnvMap": { + value: -1 + } + }, + vertexShader: _getCommonVertexShader2(), + fragmentShader: ` + + precision mediump float; + precision mediump int; + + uniform float flipEnvMap; + + varying vec3 vOutputDirection; + + uniform samplerCube envMap; + + void main() { + + gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); + + } + `, + blending: NoBlending2, + depthTest: false, + depthWrite: false + }); + } + function _getCommonVertexShader2() { + return ` + + precision mediump float; + precision mediump int; + + attribute float faceIndex; + + varying vec3 vOutputDirection; + + // RH coordinate system; PMREM face-indexing convention + vec3 getDirection( vec2 uv, float face ) { + + uv = 2.0 * uv - 1.0; + + vec3 direction = vec3( uv, 1.0 ); + + if ( face == 0.0 ) { + + direction = direction.zyx; // ( 1, v, u ) pos x + + } else if ( face == 1.0 ) { + + direction = direction.xzy; + direction.xz *= -1.0; // ( -u, 1, -v ) pos y + + } else if ( face == 2.0 ) { + + direction.x *= -1.0; // ( -u, v, 1 ) pos z + + } else if ( face == 3.0 ) { + + direction = direction.zyx; + direction.xz *= -1.0; // ( -1, v, -u ) neg x + + } else if ( face == 4.0 ) { + + direction = direction.xzy; + direction.xy *= -1.0; // ( -u, -1, v ) neg y + + } else if ( face == 5.0 ) { + + direction.z *= -1.0; // ( u, v, -1 ) neg z + + } + + return direction; + + } + + void main() { + + vOutputDirection = getDirection( uv, faceIndex ); + gl_Position = vec4( position, 1.0 ); + + } + `; + } + function WebGLCubeUVMaps2(renderer) { + let cubeUVmaps = /* @__PURE__ */ new WeakMap(); + let pmremGenerator = null; + function get3(texture) { + if (texture && texture.isTexture) { + const mapping = texture.mapping; + const isEquirectMap = mapping === EquirectangularReflectionMapping2 || mapping === EquirectangularRefractionMapping2; + const isCubeMap = mapping === CubeReflectionMapping2 || mapping === CubeRefractionMapping2; + if (isEquirectMap || isCubeMap) { + if (texture.isRenderTargetTexture && texture.needsPMREMUpdate === true) { + texture.needsPMREMUpdate = false; + let renderTarget = cubeUVmaps.get(texture); + if (pmremGenerator === null) + pmremGenerator = new PMREMGenerator2(renderer); + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture, renderTarget) : pmremGenerator.fromCubemap(texture, renderTarget); + cubeUVmaps.set(texture, renderTarget); + return renderTarget.texture; + } else { + if (cubeUVmaps.has(texture)) { + return cubeUVmaps.get(texture).texture; + } else { + const image = texture.image; + if (isEquirectMap && image && image.height > 0 || isCubeMap && image && isCubeTextureComplete(image)) { + if (pmremGenerator === null) + pmremGenerator = new PMREMGenerator2(renderer); + const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture) : pmremGenerator.fromCubemap(texture); + cubeUVmaps.set(texture, renderTarget); + texture.addEventListener("dispose", onTextureDispose); + return renderTarget.texture; + } else { + return null; + } + } + } + } + } + return texture; + } + function isCubeTextureComplete(image) { + let count = 0; + const length = 6; + for (let i = 0; i < length; i++) { + if (image[i] !== void 0) + count++; + } + return count === length; + } + function onTextureDispose(event) { + const texture = event.target; + texture.removeEventListener("dispose", onTextureDispose); + const cubemapUV = cubeUVmaps.get(texture); + if (cubemapUV !== void 0) { + cubeUVmaps.delete(texture); + cubemapUV.dispose(); + } + } + function dispose() { + cubeUVmaps = /* @__PURE__ */ new WeakMap(); + if (pmremGenerator !== null) { + pmremGenerator.dispose(); + pmremGenerator = null; + } + } + return { + get: get3, + dispose + }; + } + function WebGLExtensions2(gl) { + const extensions = {}; + function getExtension(name) { + if (extensions[name] !== void 0) { + return extensions[name]; + } + let extension; + switch (name) { + case "WEBGL_depth_texture": + extension = gl.getExtension("WEBGL_depth_texture") || gl.getExtension("MOZ_WEBGL_depth_texture") || gl.getExtension("WEBKIT_WEBGL_depth_texture"); + break; + case "EXT_texture_filter_anisotropic": + extension = gl.getExtension("EXT_texture_filter_anisotropic") || gl.getExtension("MOZ_EXT_texture_filter_anisotropic") || gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic"); + break; + case "WEBGL_compressed_texture_s3tc": + extension = gl.getExtension("WEBGL_compressed_texture_s3tc") || gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc"); + break; + case "WEBGL_compressed_texture_pvrtc": + extension = gl.getExtension("WEBGL_compressed_texture_pvrtc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc"); + break; + default: + extension = gl.getExtension(name); + } + extensions[name] = extension; + return extension; + } + return { + has: function(name) { + return getExtension(name) !== null; + }, + init: function(capabilities) { + if (capabilities.isWebGL2) { + getExtension("EXT_color_buffer_float"); + } else { + getExtension("WEBGL_depth_texture"); + getExtension("OES_texture_float"); + getExtension("OES_texture_half_float"); + getExtension("OES_texture_half_float_linear"); + getExtension("OES_standard_derivatives"); + getExtension("OES_element_index_uint"); + getExtension("OES_vertex_array_object"); + getExtension("ANGLE_instanced_arrays"); + } + getExtension("OES_texture_float_linear"); + getExtension("EXT_color_buffer_half_float"); + getExtension("WEBGL_multisampled_render_to_texture"); + }, + get: function(name) { + const extension = getExtension(name); + if (extension === null) { + console.warn("THREE.WebGLRenderer: " + name + " extension not supported."); + } + return extension; + } + }; + } + function WebGLGeometries2(gl, attributes, info, bindingStates) { + const geometries = {}; + const wireframeAttributes = /* @__PURE__ */ new WeakMap(); + function onGeometryDispose(event) { + const geometry = event.target; + if (geometry.index !== null) { + attributes.remove(geometry.index); + } + for (const name in geometry.attributes) { + attributes.remove(geometry.attributes[name]); + } + geometry.removeEventListener("dispose", onGeometryDispose); + delete geometries[geometry.id]; + const attribute = wireframeAttributes.get(geometry); + if (attribute) { + attributes.remove(attribute); + wireframeAttributes.delete(geometry); + } + bindingStates.releaseStatesOfGeometry(geometry); + if (geometry.isInstancedBufferGeometry === true) { + delete geometry._maxInstanceCount; + } + info.memory.geometries--; + } + function get3(object, geometry) { + if (geometries[geometry.id] === true) + return geometry; + geometry.addEventListener("dispose", onGeometryDispose); + geometries[geometry.id] = true; + info.memory.geometries++; + return geometry; + } + function update(geometry) { + const geometryAttributes = geometry.attributes; + for (const name in geometryAttributes) { + attributes.update(geometryAttributes[name], gl.ARRAY_BUFFER); + } + const morphAttributes = geometry.morphAttributes; + for (const name in morphAttributes) { + const array2 = morphAttributes[name]; + for (let i = 0, l = array2.length; i < l; i++) { + attributes.update(array2[i], gl.ARRAY_BUFFER); + } + } + } + function updateWireframeAttribute(geometry) { + const indices = []; + const geometryIndex = geometry.index; + const geometryPosition = geometry.attributes.position; + let version = 0; + if (geometryIndex !== null) { + const array2 = geometryIndex.array; + version = geometryIndex.version; + for (let i = 0, l = array2.length; i < l; i += 3) { + const a2 = array2[i + 0]; + const b = array2[i + 1]; + const c2 = array2[i + 2]; + indices.push(a2, b, b, c2, c2, a2); + } + } else { + const array2 = geometryPosition.array; + version = geometryPosition.version; + for (let i = 0, l = array2.length / 3 - 1; i < l; i += 3) { + const a2 = i + 0; + const b = i + 1; + const c2 = i + 2; + indices.push(a2, b, b, c2, c2, a2); + } + } + const attribute = new (arrayNeedsUint322(indices) ? Uint32BufferAttribute2 : Uint16BufferAttribute2)(indices, 1); + attribute.version = version; + const previousAttribute = wireframeAttributes.get(geometry); + if (previousAttribute) + attributes.remove(previousAttribute); + wireframeAttributes.set(geometry, attribute); + } + function getWireframeAttribute(geometry) { + const currentAttribute = wireframeAttributes.get(geometry); + if (currentAttribute) { + const geometryIndex = geometry.index; + if (geometryIndex !== null) { + if (currentAttribute.version < geometryIndex.version) { + updateWireframeAttribute(geometry); + } + } + } else { + updateWireframeAttribute(geometry); + } + return wireframeAttributes.get(geometry); + } + return { + get: get3, + update, + getWireframeAttribute + }; + } + function WebGLIndexedBufferRenderer2(gl, extensions, info, capabilities) { + const isWebGL2 = capabilities.isWebGL2; + let mode; + function setMode(value) { + mode = value; + } + let type2, bytesPerElement; + function setIndex(value) { + type2 = value.type; + bytesPerElement = value.bytesPerElement; + } + function render(start2, count) { + gl.drawElements(mode, count, type2, start2 * bytesPerElement); + info.update(count, mode, 1); + } + function renderInstances(start2, count, primcount) { + if (primcount === 0) + return; + let extension, methodName; + if (isWebGL2) { + extension = gl; + methodName = "drawElementsInstanced"; + } else { + extension = extensions.get("ANGLE_instanced_arrays"); + methodName = "drawElementsInstancedANGLE"; + if (extension === null) { + console.error("THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays."); + return; + } + } + extension[methodName](mode, count, type2, start2 * bytesPerElement, primcount); + info.update(count, mode, primcount); + } + this.setMode = setMode; + this.setIndex = setIndex; + this.render = render; + this.renderInstances = renderInstances; + } + function WebGLInfo2(gl) { + const memory = { + geometries: 0, + textures: 0 + }; + const render = { + frame: 0, + calls: 0, + triangles: 0, + points: 0, + lines: 0 + }; + function update(count, mode, instanceCount) { + render.calls++; + switch (mode) { + case gl.TRIANGLES: + render.triangles += instanceCount * (count / 3); + break; + case gl.LINES: + render.lines += instanceCount * (count / 2); + break; + case gl.LINE_STRIP: + render.lines += instanceCount * (count - 1); + break; + case gl.LINE_LOOP: + render.lines += instanceCount * count; + break; + case gl.POINTS: + render.points += instanceCount * count; + break; + default: + console.error("THREE.WebGLInfo: Unknown draw mode:", mode); + break; + } + } + function reset() { + render.frame++; + render.calls = 0; + render.triangles = 0; + render.points = 0; + render.lines = 0; + } + return { + memory, + render, + programs: null, + autoReset: true, + reset, + update + }; + } + function numericalSort2(a2, b) { + return a2[0] - b[0]; + } + function absNumericalSort2(a2, b) { + return Math.abs(b[1]) - Math.abs(a2[1]); + } + function denormalize2(morph, attribute) { + let denominator = 1; + const array2 = attribute.isInterleavedBufferAttribute ? attribute.data.array : attribute.array; + if (array2 instanceof Int8Array) + denominator = 127; + else if (array2 instanceof Uint8Array) + denominator = 255; + else if (array2 instanceof Uint16Array) + denominator = 65535; + else if (array2 instanceof Int16Array) + denominator = 32767; + else if (array2 instanceof Int32Array) + denominator = 2147483647; + else + console.error("THREE.WebGLMorphtargets: Unsupported morph attribute data type: ", array2); + morph.divideScalar(denominator); + } + function WebGLMorphtargets2(gl, capabilities, textures) { + const influencesList = {}; + const morphInfluences = new Float32Array(8); + const morphTextures = /* @__PURE__ */ new WeakMap(); + const morph = new Vector42(); + const workInfluences = []; + for (let i = 0; i < 8; i++) { + workInfluences[i] = [i, 0]; + } + function update(object, geometry, material, program) { + const objectInfluences = object.morphTargetInfluences; + if (capabilities.isWebGL2 === true) { + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = morphAttribute !== void 0 ? morphAttribute.length : 0; + let entry = morphTextures.get(geometry); + if (entry === void 0 || entry.count !== morphTargetsCount) { + let disposeTexture = function() { + texture.dispose(); + morphTextures.delete(geometry); + geometry.removeEventListener("dispose", disposeTexture); + }; + if (entry !== void 0) + entry.texture.dispose(); + const hasMorphPosition = geometry.morphAttributes.position !== void 0; + const hasMorphNormals = geometry.morphAttributes.normal !== void 0; + const hasMorphColors = geometry.morphAttributes.color !== void 0; + const morphTargets = geometry.morphAttributes.position || []; + const morphNormals = geometry.morphAttributes.normal || []; + const morphColors = geometry.morphAttributes.color || []; + let vertexDataCount = 0; + if (hasMorphPosition === true) + vertexDataCount = 1; + if (hasMorphNormals === true) + vertexDataCount = 2; + if (hasMorphColors === true) + vertexDataCount = 3; + let width = geometry.attributes.position.count * vertexDataCount; + let height = 1; + if (width > capabilities.maxTextureSize) { + height = Math.ceil(width / capabilities.maxTextureSize); + width = capabilities.maxTextureSize; + } + const buffer = new Float32Array(width * height * 4 * morphTargetsCount); + const texture = new DataArrayTexture2(buffer, width, height, morphTargetsCount); + texture.type = FloatType2; + texture.needsUpdate = true; + const vertexDataStride = vertexDataCount * 4; + for (let i = 0; i < morphTargetsCount; i++) { + const morphTarget = morphTargets[i]; + const morphNormal = morphNormals[i]; + const morphColor = morphColors[i]; + const offset = width * height * 4 * i; + for (let j = 0; j < morphTarget.count; j++) { + const stride = j * vertexDataStride; + if (hasMorphPosition === true) { + morph.fromBufferAttribute(morphTarget, j); + if (morphTarget.normalized === true) + denormalize2(morph, morphTarget); + buffer[offset + stride + 0] = morph.x; + buffer[offset + stride + 1] = morph.y; + buffer[offset + stride + 2] = morph.z; + buffer[offset + stride + 3] = 0; + } + if (hasMorphNormals === true) { + morph.fromBufferAttribute(morphNormal, j); + if (morphNormal.normalized === true) + denormalize2(morph, morphNormal); + buffer[offset + stride + 4] = morph.x; + buffer[offset + stride + 5] = morph.y; + buffer[offset + stride + 6] = morph.z; + buffer[offset + stride + 7] = 0; + } + if (hasMorphColors === true) { + morph.fromBufferAttribute(morphColor, j); + if (morphColor.normalized === true) + denormalize2(morph, morphColor); + buffer[offset + stride + 8] = morph.x; + buffer[offset + stride + 9] = morph.y; + buffer[offset + stride + 10] = morph.z; + buffer[offset + stride + 11] = morphColor.itemSize === 4 ? morph.w : 1; + } + } + } + entry = { + count: morphTargetsCount, + texture, + size: new Vector22(width, height) + }; + morphTextures.set(geometry, entry); + geometry.addEventListener("dispose", disposeTexture); + } + let morphInfluencesSum = 0; + for (let i = 0; i < objectInfluences.length; i++) { + morphInfluencesSum += objectInfluences[i]; + } + const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; + program.getUniforms().setValue(gl, "morphTargetBaseInfluence", morphBaseInfluence); + program.getUniforms().setValue(gl, "morphTargetInfluences", objectInfluences); + program.getUniforms().setValue(gl, "morphTargetsTexture", entry.texture, textures); + program.getUniforms().setValue(gl, "morphTargetsTextureSize", entry.size); + } else { + const length = objectInfluences === void 0 ? 0 : objectInfluences.length; + let influences = influencesList[geometry.id]; + if (influences === void 0 || influences.length !== length) { + influences = []; + for (let i = 0; i < length; i++) { + influences[i] = [i, 0]; + } + influencesList[geometry.id] = influences; + } + for (let i = 0; i < length; i++) { + const influence = influences[i]; + influence[0] = i; + influence[1] = objectInfluences[i]; + } + influences.sort(absNumericalSort2); + for (let i = 0; i < 8; i++) { + if (i < length && influences[i][1]) { + workInfluences[i][0] = influences[i][0]; + workInfluences[i][1] = influences[i][1]; + } else { + workInfluences[i][0] = Number.MAX_SAFE_INTEGER; + workInfluences[i][1] = 0; + } + } + workInfluences.sort(numericalSort2); + const morphTargets = geometry.morphAttributes.position; + const morphNormals = geometry.morphAttributes.normal; + let morphInfluencesSum = 0; + for (let i = 0; i < 8; i++) { + const influence = workInfluences[i]; + const index2 = influence[0]; + const value = influence[1]; + if (index2 !== Number.MAX_SAFE_INTEGER && value) { + if (morphTargets && geometry.getAttribute("morphTarget" + i) !== morphTargets[index2]) { + geometry.setAttribute("morphTarget" + i, morphTargets[index2]); + } + if (morphNormals && geometry.getAttribute("morphNormal" + i) !== morphNormals[index2]) { + geometry.setAttribute("morphNormal" + i, morphNormals[index2]); + } + morphInfluences[i] = value; + morphInfluencesSum += value; + } else { + if (morphTargets && geometry.hasAttribute("morphTarget" + i) === true) { + geometry.deleteAttribute("morphTarget" + i); + } + if (morphNormals && geometry.hasAttribute("morphNormal" + i) === true) { + geometry.deleteAttribute("morphNormal" + i); + } + morphInfluences[i] = 0; + } + } + const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; + program.getUniforms().setValue(gl, "morphTargetBaseInfluence", morphBaseInfluence); + program.getUniforms().setValue(gl, "morphTargetInfluences", morphInfluences); + } + } + return { + update + }; + } + function WebGLObjects2(gl, geometries, attributes, info) { + let updateMap = /* @__PURE__ */ new WeakMap(); + function update(object) { + const frame2 = info.render.frame; + const geometry = object.geometry; + const buffergeometry = geometries.get(object, geometry); + if (updateMap.get(buffergeometry) !== frame2) { + geometries.update(buffergeometry); + updateMap.set(buffergeometry, frame2); + } + if (object.isInstancedMesh) { + if (object.hasEventListener("dispose", onInstancedMeshDispose) === false) { + object.addEventListener("dispose", onInstancedMeshDispose); + } + attributes.update(object.instanceMatrix, gl.ARRAY_BUFFER); + if (object.instanceColor !== null) { + attributes.update(object.instanceColor, gl.ARRAY_BUFFER); + } + } + return buffergeometry; + } + function dispose() { + updateMap = /* @__PURE__ */ new WeakMap(); + } + function onInstancedMeshDispose(event) { + const instancedMesh = event.target; + instancedMesh.removeEventListener("dispose", onInstancedMeshDispose); + attributes.remove(instancedMesh.instanceMatrix); + if (instancedMesh.instanceColor !== null) + attributes.remove(instancedMesh.instanceColor); + } + return { + update, + dispose + }; + } + var emptyTexture2 = /* @__PURE__ */ new Texture2(); + var emptyArrayTexture2 = /* @__PURE__ */ new DataArrayTexture2(); + var empty3dTexture2 = /* @__PURE__ */ new Data3DTexture2(); + var emptyCubeTexture2 = /* @__PURE__ */ new CubeTexture2(); + var arrayCacheF322 = []; + var arrayCacheI322 = []; + var mat4array2 = new Float32Array(16); + var mat3array2 = new Float32Array(9); + var mat2array2 = new Float32Array(4); + function flatten2(array2, nBlocks, blockSize) { + const firstElem = array2[0]; + if (firstElem <= 0 || firstElem > 0) + return array2; + const n = nBlocks * blockSize; + let r = arrayCacheF322[n]; + if (r === void 0) { + r = new Float32Array(n); + arrayCacheF322[n] = r; + } + if (nBlocks !== 0) { + firstElem.toArray(r, 0); + for (let i = 1, offset = 0; i !== nBlocks; ++i) { + offset += blockSize; + array2[i].toArray(r, offset); + } + } + return r; + } + function arraysEqual2(a2, b) { + if (a2.length !== b.length) + return false; + for (let i = 0, l = a2.length; i < l; i++) { + if (a2[i] !== b[i]) + return false; + } + return true; + } + function copyArray2(a2, b) { + for (let i = 0, l = b.length; i < l; i++) { + a2[i] = b[i]; + } + } + function allocTexUnits2(textures, n) { + let r = arrayCacheI322[n]; + if (r === void 0) { + r = new Int32Array(n); + arrayCacheI322[n] = r; + } + for (let i = 0; i !== n; ++i) { + r[i] = textures.allocateTextureUnit(); + } + return r; + } + function setValueV1f2(gl, v) { + const cache2 = this.cache; + if (cache2[0] === v) + return; + gl.uniform1f(this.addr, v); + cache2[0] = v; + } + function setValueV2f2(gl, v) { + const cache2 = this.cache; + if (v.x !== void 0) { + if (cache2[0] !== v.x || cache2[1] !== v.y) { + gl.uniform2f(this.addr, v.x, v.y); + cache2[0] = v.x; + cache2[1] = v.y; + } + } else { + if (arraysEqual2(cache2, v)) + return; + gl.uniform2fv(this.addr, v); + copyArray2(cache2, v); + } + } + function setValueV3f2(gl, v) { + const cache2 = this.cache; + if (v.x !== void 0) { + if (cache2[0] !== v.x || cache2[1] !== v.y || cache2[2] !== v.z) { + gl.uniform3f(this.addr, v.x, v.y, v.z); + cache2[0] = v.x; + cache2[1] = v.y; + cache2[2] = v.z; + } + } else if (v.r !== void 0) { + if (cache2[0] !== v.r || cache2[1] !== v.g || cache2[2] !== v.b) { + gl.uniform3f(this.addr, v.r, v.g, v.b); + cache2[0] = v.r; + cache2[1] = v.g; + cache2[2] = v.b; + } + } else { + if (arraysEqual2(cache2, v)) + return; + gl.uniform3fv(this.addr, v); + copyArray2(cache2, v); + } + } + function setValueV4f2(gl, v) { + const cache2 = this.cache; + if (v.x !== void 0) { + if (cache2[0] !== v.x || cache2[1] !== v.y || cache2[2] !== v.z || cache2[3] !== v.w) { + gl.uniform4f(this.addr, v.x, v.y, v.z, v.w); + cache2[0] = v.x; + cache2[1] = v.y; + cache2[2] = v.z; + cache2[3] = v.w; + } + } else { + if (arraysEqual2(cache2, v)) + return; + gl.uniform4fv(this.addr, v); + copyArray2(cache2, v); + } + } + function setValueM22(gl, v) { + const cache2 = this.cache; + const elements = v.elements; + if (elements === void 0) { + if (arraysEqual2(cache2, v)) + return; + gl.uniformMatrix2fv(this.addr, false, v); + copyArray2(cache2, v); + } else { + if (arraysEqual2(cache2, elements)) + return; + mat2array2.set(elements); + gl.uniformMatrix2fv(this.addr, false, mat2array2); + copyArray2(cache2, elements); + } + } + function setValueM32(gl, v) { + const cache2 = this.cache; + const elements = v.elements; + if (elements === void 0) { + if (arraysEqual2(cache2, v)) + return; + gl.uniformMatrix3fv(this.addr, false, v); + copyArray2(cache2, v); + } else { + if (arraysEqual2(cache2, elements)) + return; + mat3array2.set(elements); + gl.uniformMatrix3fv(this.addr, false, mat3array2); + copyArray2(cache2, elements); + } + } + function setValueM42(gl, v) { + const cache2 = this.cache; + const elements = v.elements; + if (elements === void 0) { + if (arraysEqual2(cache2, v)) + return; + gl.uniformMatrix4fv(this.addr, false, v); + copyArray2(cache2, v); + } else { + if (arraysEqual2(cache2, elements)) + return; + mat4array2.set(elements); + gl.uniformMatrix4fv(this.addr, false, mat4array2); + copyArray2(cache2, elements); + } + } + function setValueV1i2(gl, v) { + const cache2 = this.cache; + if (cache2[0] === v) + return; + gl.uniform1i(this.addr, v); + cache2[0] = v; + } + function setValueV2i2(gl, v) { + const cache2 = this.cache; + if (arraysEqual2(cache2, v)) + return; + gl.uniform2iv(this.addr, v); + copyArray2(cache2, v); + } + function setValueV3i2(gl, v) { + const cache2 = this.cache; + if (arraysEqual2(cache2, v)) + return; + gl.uniform3iv(this.addr, v); + copyArray2(cache2, v); + } + function setValueV4i2(gl, v) { + const cache2 = this.cache; + if (arraysEqual2(cache2, v)) + return; + gl.uniform4iv(this.addr, v); + copyArray2(cache2, v); + } + function setValueV1ui2(gl, v) { + const cache2 = this.cache; + if (cache2[0] === v) + return; + gl.uniform1ui(this.addr, v); + cache2[0] = v; + } + function setValueV2ui2(gl, v) { + const cache2 = this.cache; + if (arraysEqual2(cache2, v)) + return; + gl.uniform2uiv(this.addr, v); + copyArray2(cache2, v); + } + function setValueV3ui2(gl, v) { + const cache2 = this.cache; + if (arraysEqual2(cache2, v)) + return; + gl.uniform3uiv(this.addr, v); + copyArray2(cache2, v); + } + function setValueV4ui2(gl, v) { + const cache2 = this.cache; + if (arraysEqual2(cache2, v)) + return; + gl.uniform4uiv(this.addr, v); + copyArray2(cache2, v); + } + function setValueT12(gl, v, textures) { + const cache2 = this.cache; + const unit2 = textures.allocateTextureUnit(); + if (cache2[0] !== unit2) { + gl.uniform1i(this.addr, unit2); + cache2[0] = unit2; + } + textures.setTexture2D(v || emptyTexture2, unit2); + } + function setValueT3D12(gl, v, textures) { + const cache2 = this.cache; + const unit2 = textures.allocateTextureUnit(); + if (cache2[0] !== unit2) { + gl.uniform1i(this.addr, unit2); + cache2[0] = unit2; + } + textures.setTexture3D(v || empty3dTexture2, unit2); + } + function setValueT62(gl, v, textures) { + const cache2 = this.cache; + const unit2 = textures.allocateTextureUnit(); + if (cache2[0] !== unit2) { + gl.uniform1i(this.addr, unit2); + cache2[0] = unit2; + } + textures.setTextureCube(v || emptyCubeTexture2, unit2); + } + function setValueT2DArray12(gl, v, textures) { + const cache2 = this.cache; + const unit2 = textures.allocateTextureUnit(); + if (cache2[0] !== unit2) { + gl.uniform1i(this.addr, unit2); + cache2[0] = unit2; + } + textures.setTexture2DArray(v || emptyArrayTexture2, unit2); + } + function getSingularSetter2(type2) { + switch (type2) { + case 5126: + return setValueV1f2; + case 35664: + return setValueV2f2; + case 35665: + return setValueV3f2; + case 35666: + return setValueV4f2; + case 35674: + return setValueM22; + case 35675: + return setValueM32; + case 35676: + return setValueM42; + case 5124: + case 35670: + return setValueV1i2; + case 35667: + case 35671: + return setValueV2i2; + case 35668: + case 35672: + return setValueV3i2; + case 35669: + case 35673: + return setValueV4i2; + case 5125: + return setValueV1ui2; + case 36294: + return setValueV2ui2; + case 36295: + return setValueV3ui2; + case 36296: + return setValueV4ui2; + case 35678: + case 36198: + case 36298: + case 36306: + case 35682: + return setValueT12; + case 35679: + case 36299: + case 36307: + return setValueT3D12; + case 35680: + case 36300: + case 36308: + case 36293: + return setValueT62; + case 36289: + case 36303: + case 36311: + case 36292: + return setValueT2DArray12; + } + } + function setValueV1fArray2(gl, v) { + gl.uniform1fv(this.addr, v); + } + function setValueV2fArray2(gl, v) { + const data = flatten2(v, this.size, 2); + gl.uniform2fv(this.addr, data); + } + function setValueV3fArray2(gl, v) { + const data = flatten2(v, this.size, 3); + gl.uniform3fv(this.addr, data); + } + function setValueV4fArray2(gl, v) { + const data = flatten2(v, this.size, 4); + gl.uniform4fv(this.addr, data); + } + function setValueM2Array2(gl, v) { + const data = flatten2(v, this.size, 4); + gl.uniformMatrix2fv(this.addr, false, data); + } + function setValueM3Array2(gl, v) { + const data = flatten2(v, this.size, 9); + gl.uniformMatrix3fv(this.addr, false, data); + } + function setValueM4Array2(gl, v) { + const data = flatten2(v, this.size, 16); + gl.uniformMatrix4fv(this.addr, false, data); + } + function setValueV1iArray2(gl, v) { + gl.uniform1iv(this.addr, v); + } + function setValueV2iArray2(gl, v) { + gl.uniform2iv(this.addr, v); + } + function setValueV3iArray2(gl, v) { + gl.uniform3iv(this.addr, v); + } + function setValueV4iArray2(gl, v) { + gl.uniform4iv(this.addr, v); + } + function setValueV1uiArray2(gl, v) { + gl.uniform1uiv(this.addr, v); + } + function setValueV2uiArray2(gl, v) { + gl.uniform2uiv(this.addr, v); + } + function setValueV3uiArray2(gl, v) { + gl.uniform3uiv(this.addr, v); + } + function setValueV4uiArray2(gl, v) { + gl.uniform4uiv(this.addr, v); + } + function setValueT1Array2(gl, v, textures) { + const n = v.length; + const units = allocTexUnits2(textures, n); + gl.uniform1iv(this.addr, units); + for (let i = 0; i !== n; ++i) { + textures.setTexture2D(v[i] || emptyTexture2, units[i]); + } + } + function setValueT3DArray2(gl, v, textures) { + const n = v.length; + const units = allocTexUnits2(textures, n); + gl.uniform1iv(this.addr, units); + for (let i = 0; i !== n; ++i) { + textures.setTexture3D(v[i] || empty3dTexture2, units[i]); + } + } + function setValueT6Array2(gl, v, textures) { + const n = v.length; + const units = allocTexUnits2(textures, n); + gl.uniform1iv(this.addr, units); + for (let i = 0; i !== n; ++i) { + textures.setTextureCube(v[i] || emptyCubeTexture2, units[i]); + } + } + function setValueT2DArrayArray2(gl, v, textures) { + const n = v.length; + const units = allocTexUnits2(textures, n); + gl.uniform1iv(this.addr, units); + for (let i = 0; i !== n; ++i) { + textures.setTexture2DArray(v[i] || emptyArrayTexture2, units[i]); + } + } + function getPureArraySetter2(type2) { + switch (type2) { + case 5126: + return setValueV1fArray2; + case 35664: + return setValueV2fArray2; + case 35665: + return setValueV3fArray2; + case 35666: + return setValueV4fArray2; + case 35674: + return setValueM2Array2; + case 35675: + return setValueM3Array2; + case 35676: + return setValueM4Array2; + case 5124: + case 35670: + return setValueV1iArray2; + case 35667: + case 35671: + return setValueV2iArray2; + case 35668: + case 35672: + return setValueV3iArray2; + case 35669: + case 35673: + return setValueV4iArray2; + case 5125: + return setValueV1uiArray2; + case 36294: + return setValueV2uiArray2; + case 36295: + return setValueV3uiArray2; + case 36296: + return setValueV4uiArray2; + case 35678: + case 36198: + case 36298: + case 36306: + case 35682: + return setValueT1Array2; + case 35679: + case 36299: + case 36307: + return setValueT3DArray2; + case 35680: + case 36300: + case 36308: + case 36293: + return setValueT6Array2; + case 36289: + case 36303: + case 36311: + case 36292: + return setValueT2DArrayArray2; + } + } + var SingleUniform2 = class { + constructor(id3, activeInfo, addr) { + this.id = id3; + this.addr = addr; + this.cache = []; + this.setValue = getSingularSetter2(activeInfo.type); + } + }; + var PureArrayUniform2 = class { + constructor(id3, activeInfo, addr) { + this.id = id3; + this.addr = addr; + this.cache = []; + this.size = activeInfo.size; + this.setValue = getPureArraySetter2(activeInfo.type); + } + }; + var StructuredUniform2 = class { + constructor(id3) { + this.id = id3; + this.seq = []; + this.map = {}; + } + setValue(gl, value, textures) { + const seq = this.seq; + for (let i = 0, n = seq.length; i !== n; ++i) { + const u = seq[i]; + u.setValue(gl, value[u.id], textures); + } + } + }; + var RePathPart2 = /(\w+)(\])?(\[|\.)?/g; + function addUniform2(container, uniformObject) { + container.seq.push(uniformObject); + container.map[uniformObject.id] = uniformObject; + } + function parseUniform2(activeInfo, addr, container) { + const path = activeInfo.name, pathLength = path.length; + RePathPart2.lastIndex = 0; + while (true) { + const match = RePathPart2.exec(path), matchEnd = RePathPart2.lastIndex; + let id3 = match[1]; + const idIsIndex = match[2] === "]", subscript = match[3]; + if (idIsIndex) + id3 = id3 | 0; + if (subscript === void 0 || subscript === "[" && matchEnd + 2 === pathLength) { + addUniform2(container, subscript === void 0 ? new SingleUniform2(id3, activeInfo, addr) : new PureArrayUniform2(id3, activeInfo, addr)); + break; + } else { + const map2 = container.map; + let next = map2[id3]; + if (next === void 0) { + next = new StructuredUniform2(id3); + addUniform2(container, next); + } + container = next; + } + } + } + var WebGLUniforms2 = class { + constructor(gl, program) { + this.seq = []; + this.map = {}; + const n = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); + for (let i = 0; i < n; ++i) { + const info = gl.getActiveUniform(program, i), addr = gl.getUniformLocation(program, info.name); + parseUniform2(info, addr, this); + } + } + setValue(gl, name, value, textures) { + const u = this.map[name]; + if (u !== void 0) + u.setValue(gl, value, textures); + } + setOptional(gl, object, name) { + const v = object[name]; + if (v !== void 0) + this.setValue(gl, name, v); + } + static upload(gl, seq, values, textures) { + for (let i = 0, n = seq.length; i !== n; ++i) { + const u = seq[i], v = values[u.id]; + if (v.needsUpdate !== false) { + u.setValue(gl, v.value, textures); + } + } + } + static seqWithValue(seq, values) { + const r = []; + for (let i = 0, n = seq.length; i !== n; ++i) { + const u = seq[i]; + if (u.id in values) + r.push(u); + } + return r; + } + }; + function WebGLShader2(gl, type2, string) { + const shader = gl.createShader(type2); + gl.shaderSource(shader, string); + gl.compileShader(shader); + return shader; + } + var programIdCount2 = 0; + function handleSource2(string, errorLine) { + const lines = string.split("\n"); + const lines2 = []; + const from = Math.max(errorLine - 6, 0); + const to = Math.min(errorLine + 6, lines.length); + for (let i = from; i < to; i++) { + const line = i + 1; + lines2.push(`${line === errorLine ? ">" : " "} ${line}: ${lines[i]}`); + } + return lines2.join("\n"); + } + function getEncodingComponents2(encoding) { + switch (encoding) { + case LinearEncoding2: + return ["Linear", "( value )"]; + case sRGBEncoding2: + return ["sRGB", "( value )"]; + default: + console.warn("THREE.WebGLProgram: Unsupported encoding:", encoding); + return ["Linear", "( value )"]; + } + } + function getShaderErrors2(gl, shader, type2) { + const status = gl.getShaderParameter(shader, gl.COMPILE_STATUS); + const errors = gl.getShaderInfoLog(shader).trim(); + if (status && errors === "") + return ""; + const errorMatches = /ERROR: 0:(\d+)/.exec(errors); + if (errorMatches) { + const errorLine = parseInt(errorMatches[1]); + return type2.toUpperCase() + "\n\n" + errors + "\n\n" + handleSource2(gl.getShaderSource(shader), errorLine); + } else { + return errors; + } + } + function getTexelEncodingFunction2(functionName, encoding) { + const components = getEncodingComponents2(encoding); + return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[0] + components[1] + "; }"; + } + function getToneMappingFunction2(functionName, toneMapping) { + let toneMappingName; + switch (toneMapping) { + case LinearToneMapping2: + toneMappingName = "Linear"; + break; + case ReinhardToneMapping2: + toneMappingName = "Reinhard"; + break; + case CineonToneMapping2: + toneMappingName = "OptimizedCineon"; + break; + case ACESFilmicToneMapping2: + toneMappingName = "ACESFilmic"; + break; + case CustomToneMapping2: + toneMappingName = "Custom"; + break; + default: + console.warn("THREE.WebGLProgram: Unsupported toneMapping:", toneMapping); + toneMappingName = "Linear"; + } + return "vec3 " + functionName + "( vec3 color ) { return " + toneMappingName + "ToneMapping( color ); }"; + } + function generateExtensions2(parameters) { + const chunks = [parameters.extensionDerivatives || !!parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === "physical" ? "#extension GL_OES_standard_derivatives : enable" : "", (parameters.extensionFragDepth || parameters.logarithmicDepthBuffer) && parameters.rendererExtensionFragDepth ? "#extension GL_EXT_frag_depth : enable" : "", parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ? "#extension GL_EXT_draw_buffers : require" : "", (parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission) && parameters.rendererExtensionShaderTextureLod ? "#extension GL_EXT_shader_texture_lod : enable" : ""]; + return chunks.filter(filterEmptyLine2).join("\n"); + } + function generateDefines2(defines) { + const chunks = []; + for (const name in defines) { + const value = defines[name]; + if (value === false) + continue; + chunks.push("#define " + name + " " + value); + } + return chunks.join("\n"); + } + function fetchAttributeLocations2(gl, program) { + const attributes = {}; + const n = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); + for (let i = 0; i < n; i++) { + const info = gl.getActiveAttrib(program, i); + const name = info.name; + let locationSize = 1; + if (info.type === gl.FLOAT_MAT2) + locationSize = 2; + if (info.type === gl.FLOAT_MAT3) + locationSize = 3; + if (info.type === gl.FLOAT_MAT4) + locationSize = 4; + attributes[name] = { + type: info.type, + location: gl.getAttribLocation(program, name), + locationSize + }; + } + return attributes; + } + function filterEmptyLine2(string) { + return string !== ""; + } + function replaceLightNums2(string, parameters) { + return string.replace(/NUM_DIR_LIGHTS/g, parameters.numDirLights).replace(/NUM_SPOT_LIGHTS/g, parameters.numSpotLights).replace(/NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g, parameters.numPointLights).replace(/NUM_HEMI_LIGHTS/g, parameters.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows); + } + function replaceClippingPlaneNums2(string, parameters) { + return string.replace(/NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g, parameters.numClippingPlanes - parameters.numClipIntersection); + } + var includePattern2 = /^[ \t]*#include +<([\w\d./]+)>/gm; + function resolveIncludes2(string) { + return string.replace(includePattern2, includeReplacer2); + } + function includeReplacer2(match, include) { + const string = ShaderChunk2[include]; + if (string === void 0) { + throw new Error("Can not resolve #include <" + include + ">"); + } + return resolveIncludes2(string); + } + var deprecatedUnrollLoopPattern2 = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g; + var unrollLoopPattern2 = /#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g; + function unrollLoops2(string) { + return string.replace(unrollLoopPattern2, loopReplacer2).replace(deprecatedUnrollLoopPattern2, deprecatedLoopReplacer2); + } + function deprecatedLoopReplacer2(match, start2, end, snippet) { + console.warn("WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead."); + return loopReplacer2(match, start2, end, snippet); + } + function loopReplacer2(match, start2, end, snippet) { + let string = ""; + for (let i = parseInt(start2); i < parseInt(end); i++) { + string += snippet.replace(/\[\s*i\s*\]/g, "[ " + i + " ]").replace(/UNROLLED_LOOP_INDEX/g, i); + } + return string; + } + function generatePrecision2(parameters) { + let precisionstring = "precision " + parameters.precision + " float;\nprecision " + parameters.precision + " int;"; + if (parameters.precision === "highp") { + precisionstring += "\n#define HIGH_PRECISION"; + } else if (parameters.precision === "mediump") { + precisionstring += "\n#define MEDIUM_PRECISION"; + } else if (parameters.precision === "lowp") { + precisionstring += "\n#define LOW_PRECISION"; + } + return precisionstring; + } + function generateShadowMapTypeDefine2(parameters) { + let shadowMapTypeDefine = "SHADOWMAP_TYPE_BASIC"; + if (parameters.shadowMapType === PCFShadowMap2) { + shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF"; + } else if (parameters.shadowMapType === PCFSoftShadowMap2) { + shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF_SOFT"; + } else if (parameters.shadowMapType === VSMShadowMap2) { + shadowMapTypeDefine = "SHADOWMAP_TYPE_VSM"; + } + return shadowMapTypeDefine; + } + function generateEnvMapTypeDefine2(parameters) { + let envMapTypeDefine = "ENVMAP_TYPE_CUBE"; + if (parameters.envMap) { + switch (parameters.envMapMode) { + case CubeReflectionMapping2: + case CubeRefractionMapping2: + envMapTypeDefine = "ENVMAP_TYPE_CUBE"; + break; + case CubeUVReflectionMapping2: + envMapTypeDefine = "ENVMAP_TYPE_CUBE_UV"; + break; + } + } + return envMapTypeDefine; + } + function generateEnvMapModeDefine2(parameters) { + let envMapModeDefine = "ENVMAP_MODE_REFLECTION"; + if (parameters.envMap) { + switch (parameters.envMapMode) { + case CubeRefractionMapping2: + envMapModeDefine = "ENVMAP_MODE_REFRACTION"; + break; + } + } + return envMapModeDefine; + } + function generateEnvMapBlendingDefine2(parameters) { + let envMapBlendingDefine = "ENVMAP_BLENDING_NONE"; + if (parameters.envMap) { + switch (parameters.combine) { + case MultiplyOperation2: + envMapBlendingDefine = "ENVMAP_BLENDING_MULTIPLY"; + break; + case MixOperation2: + envMapBlendingDefine = "ENVMAP_BLENDING_MIX"; + break; + case AddOperation2: + envMapBlendingDefine = "ENVMAP_BLENDING_ADD"; + break; + } + } + return envMapBlendingDefine; + } + function generateCubeUVSize2(parameters) { + const imageHeight = parameters.envMapCubeUVHeight; + if (imageHeight === null) + return null; + const maxMip = Math.log2(imageHeight) - 2; + const texelHeight = 1 / imageHeight; + const texelWidth = 1 / (3 * Math.max(Math.pow(2, maxMip), 7 * 16)); + return { + texelWidth, + texelHeight, + maxMip + }; + } + function WebGLProgram2(renderer, cacheKey, parameters, bindingStates) { + const gl = renderer.getContext(); + const defines = parameters.defines; + let vertexShader = parameters.vertexShader; + let fragmentShader = parameters.fragmentShader; + const shadowMapTypeDefine = generateShadowMapTypeDefine2(parameters); + const envMapTypeDefine = generateEnvMapTypeDefine2(parameters); + const envMapModeDefine = generateEnvMapModeDefine2(parameters); + const envMapBlendingDefine = generateEnvMapBlendingDefine2(parameters); + const envMapCubeUVSize = generateCubeUVSize2(parameters); + const customExtensions = parameters.isWebGL2 ? "" : generateExtensions2(parameters); + const customDefines = generateDefines2(defines); + const program = gl.createProgram(); + let prefixVertex, prefixFragment; + let versionString = parameters.glslVersion ? "#version " + parameters.glslVersion + "\n" : ""; + if (parameters.isRawShaderMaterial) { + prefixVertex = [customDefines].filter(filterEmptyLine2).join("\n"); + if (prefixVertex.length > 0) { + prefixVertex += "\n"; + } + prefixFragment = [customExtensions, customDefines].filter(filterEmptyLine2).join("\n"); + if (prefixFragment.length > 0) { + prefixFragment += "\n"; + } + } else { + prefixVertex = [generatePrecision2(parameters), "#define SHADER_NAME " + parameters.shaderName, customDefines, parameters.instancing ? "#define USE_INSTANCING" : "", parameters.instancingColor ? "#define USE_INSTANCING_COLOR" : "", parameters.supportsVertexTextures ? "#define VERTEX_TEXTURES" : "", parameters.useFog && parameters.fog ? "#define USE_FOG" : "", parameters.useFog && parameters.fogExp2 ? "#define FOG_EXP2" : "", parameters.map ? "#define USE_MAP" : "", parameters.envMap ? "#define USE_ENVMAP" : "", parameters.envMap ? "#define " + envMapModeDefine : "", parameters.lightMap ? "#define USE_LIGHTMAP" : "", parameters.aoMap ? "#define USE_AOMAP" : "", parameters.emissiveMap ? "#define USE_EMISSIVEMAP" : "", parameters.bumpMap ? "#define USE_BUMPMAP" : "", parameters.normalMap ? "#define USE_NORMALMAP" : "", parameters.normalMap && parameters.objectSpaceNormalMap ? "#define OBJECTSPACE_NORMALMAP" : "", parameters.normalMap && parameters.tangentSpaceNormalMap ? "#define TANGENTSPACE_NORMALMAP" : "", parameters.clearcoatMap ? "#define USE_CLEARCOATMAP" : "", parameters.clearcoatRoughnessMap ? "#define USE_CLEARCOAT_ROUGHNESSMAP" : "", parameters.clearcoatNormalMap ? "#define USE_CLEARCOAT_NORMALMAP" : "", parameters.iridescenceMap ? "#define USE_IRIDESCENCEMAP" : "", parameters.iridescenceThicknessMap ? "#define USE_IRIDESCENCE_THICKNESSMAP" : "", parameters.displacementMap && parameters.supportsVertexTextures ? "#define USE_DISPLACEMENTMAP" : "", parameters.specularMap ? "#define USE_SPECULARMAP" : "", parameters.specularIntensityMap ? "#define USE_SPECULARINTENSITYMAP" : "", parameters.specularColorMap ? "#define USE_SPECULARCOLORMAP" : "", parameters.roughnessMap ? "#define USE_ROUGHNESSMAP" : "", parameters.metalnessMap ? "#define USE_METALNESSMAP" : "", parameters.alphaMap ? "#define USE_ALPHAMAP" : "", parameters.transmission ? "#define USE_TRANSMISSION" : "", parameters.transmissionMap ? "#define USE_TRANSMISSIONMAP" : "", parameters.thicknessMap ? "#define USE_THICKNESSMAP" : "", parameters.sheenColorMap ? "#define USE_SHEENCOLORMAP" : "", parameters.sheenRoughnessMap ? "#define USE_SHEENROUGHNESSMAP" : "", parameters.vertexTangents ? "#define USE_TANGENT" : "", parameters.vertexColors ? "#define USE_COLOR" : "", parameters.vertexAlphas ? "#define USE_COLOR_ALPHA" : "", parameters.vertexUvs ? "#define USE_UV" : "", parameters.uvsVertexOnly ? "#define UVS_VERTEX_ONLY" : "", parameters.flatShading ? "#define FLAT_SHADED" : "", parameters.skinning ? "#define USE_SKINNING" : "", parameters.morphTargets ? "#define USE_MORPHTARGETS" : "", parameters.morphNormals && parameters.flatShading === false ? "#define USE_MORPHNORMALS" : "", parameters.morphColors && parameters.isWebGL2 ? "#define USE_MORPHCOLORS" : "", parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? "#define MORPHTARGETS_TEXTURE" : "", parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? "#define MORPHTARGETS_TEXTURE_STRIDE " + parameters.morphTextureStride : "", parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? "#define MORPHTARGETS_COUNT " + parameters.morphTargetsCount : "", parameters.doubleSided ? "#define DOUBLE_SIDED" : "", parameters.flipSided ? "#define FLIP_SIDED" : "", parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "", parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "", parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "", parameters.logarithmicDepthBuffer ? "#define USE_LOGDEPTHBUF" : "", parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? "#define USE_LOGDEPTHBUF_EXT" : "", "uniform mat4 modelMatrix;", "uniform mat4 modelViewMatrix;", "uniform mat4 projectionMatrix;", "uniform mat4 viewMatrix;", "uniform mat3 normalMatrix;", "uniform vec3 cameraPosition;", "uniform bool isOrthographic;", "#ifdef USE_INSTANCING", " attribute mat4 instanceMatrix;", "#endif", "#ifdef USE_INSTANCING_COLOR", " attribute vec3 instanceColor;", "#endif", "attribute vec3 position;", "attribute vec3 normal;", "attribute vec2 uv;", "#ifdef USE_TANGENT", " attribute vec4 tangent;", "#endif", "#if defined( USE_COLOR_ALPHA )", " attribute vec4 color;", "#elif defined( USE_COLOR )", " attribute vec3 color;", "#endif", "#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )", " attribute vec3 morphTarget0;", " attribute vec3 morphTarget1;", " attribute vec3 morphTarget2;", " attribute vec3 morphTarget3;", " #ifdef USE_MORPHNORMALS", " attribute vec3 morphNormal0;", " attribute vec3 morphNormal1;", " attribute vec3 morphNormal2;", " attribute vec3 morphNormal3;", " #else", " attribute vec3 morphTarget4;", " attribute vec3 morphTarget5;", " attribute vec3 morphTarget6;", " attribute vec3 morphTarget7;", " #endif", "#endif", "#ifdef USE_SKINNING", " attribute vec4 skinIndex;", " attribute vec4 skinWeight;", "#endif", "\n"].filter(filterEmptyLine2).join("\n"); + prefixFragment = [ + customExtensions, + generatePrecision2(parameters), + "#define SHADER_NAME " + parameters.shaderName, + customDefines, + parameters.useFog && parameters.fog ? "#define USE_FOG" : "", + parameters.useFog && parameters.fogExp2 ? "#define FOG_EXP2" : "", + parameters.map ? "#define USE_MAP" : "", + parameters.matcap ? "#define USE_MATCAP" : "", + parameters.envMap ? "#define USE_ENVMAP" : "", + parameters.envMap ? "#define " + envMapTypeDefine : "", + parameters.envMap ? "#define " + envMapModeDefine : "", + parameters.envMap ? "#define " + envMapBlendingDefine : "", + envMapCubeUVSize ? "#define CUBEUV_TEXEL_WIDTH " + envMapCubeUVSize.texelWidth : "", + envMapCubeUVSize ? "#define CUBEUV_TEXEL_HEIGHT " + envMapCubeUVSize.texelHeight : "", + envMapCubeUVSize ? "#define CUBEUV_MAX_MIP " + envMapCubeUVSize.maxMip + ".0" : "", + parameters.lightMap ? "#define USE_LIGHTMAP" : "", + parameters.aoMap ? "#define USE_AOMAP" : "", + parameters.emissiveMap ? "#define USE_EMISSIVEMAP" : "", + parameters.bumpMap ? "#define USE_BUMPMAP" : "", + parameters.normalMap ? "#define USE_NORMALMAP" : "", + parameters.normalMap && parameters.objectSpaceNormalMap ? "#define OBJECTSPACE_NORMALMAP" : "", + parameters.normalMap && parameters.tangentSpaceNormalMap ? "#define TANGENTSPACE_NORMALMAP" : "", + parameters.clearcoat ? "#define USE_CLEARCOAT" : "", + parameters.clearcoatMap ? "#define USE_CLEARCOATMAP" : "", + parameters.clearcoatRoughnessMap ? "#define USE_CLEARCOAT_ROUGHNESSMAP" : "", + parameters.clearcoatNormalMap ? "#define USE_CLEARCOAT_NORMALMAP" : "", + parameters.iridescence ? "#define USE_IRIDESCENCE" : "", + parameters.iridescenceMap ? "#define USE_IRIDESCENCEMAP" : "", + parameters.iridescenceThicknessMap ? "#define USE_IRIDESCENCE_THICKNESSMAP" : "", + parameters.specularMap ? "#define USE_SPECULARMAP" : "", + parameters.specularIntensityMap ? "#define USE_SPECULARINTENSITYMAP" : "", + parameters.specularColorMap ? "#define USE_SPECULARCOLORMAP" : "", + parameters.roughnessMap ? "#define USE_ROUGHNESSMAP" : "", + parameters.metalnessMap ? "#define USE_METALNESSMAP" : "", + parameters.alphaMap ? "#define USE_ALPHAMAP" : "", + parameters.alphaTest ? "#define USE_ALPHATEST" : "", + parameters.sheen ? "#define USE_SHEEN" : "", + parameters.sheenColorMap ? "#define USE_SHEENCOLORMAP" : "", + parameters.sheenRoughnessMap ? "#define USE_SHEENROUGHNESSMAP" : "", + parameters.transmission ? "#define USE_TRANSMISSION" : "", + parameters.transmissionMap ? "#define USE_TRANSMISSIONMAP" : "", + parameters.thicknessMap ? "#define USE_THICKNESSMAP" : "", + parameters.decodeVideoTexture ? "#define DECODE_VIDEO_TEXTURE" : "", + parameters.vertexTangents ? "#define USE_TANGENT" : "", + parameters.vertexColors || parameters.instancingColor ? "#define USE_COLOR" : "", + parameters.vertexAlphas ? "#define USE_COLOR_ALPHA" : "", + parameters.vertexUvs ? "#define USE_UV" : "", + parameters.uvsVertexOnly ? "#define UVS_VERTEX_ONLY" : "", + parameters.gradientMap ? "#define USE_GRADIENTMAP" : "", + parameters.flatShading ? "#define FLAT_SHADED" : "", + parameters.doubleSided ? "#define DOUBLE_SIDED" : "", + parameters.flipSided ? "#define FLIP_SIDED" : "", + parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "", + parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "", + parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : "", + parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : "", + parameters.logarithmicDepthBuffer ? "#define USE_LOGDEPTHBUF" : "", + parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? "#define USE_LOGDEPTHBUF_EXT" : "", + "uniform mat4 viewMatrix;", + "uniform vec3 cameraPosition;", + "uniform bool isOrthographic;", + parameters.toneMapping !== NoToneMapping2 ? "#define TONE_MAPPING" : "", + parameters.toneMapping !== NoToneMapping2 ? ShaderChunk2["tonemapping_pars_fragment"] : "", + parameters.toneMapping !== NoToneMapping2 ? getToneMappingFunction2("toneMapping", parameters.toneMapping) : "", + parameters.dithering ? "#define DITHERING" : "", + parameters.opaque ? "#define OPAQUE" : "", + ShaderChunk2["encodings_pars_fragment"], + getTexelEncodingFunction2("linearToOutputTexel", parameters.outputEncoding), + parameters.useDepthPacking ? "#define DEPTH_PACKING " + parameters.depthPacking : "", + "\n" + ].filter(filterEmptyLine2).join("\n"); + } + vertexShader = resolveIncludes2(vertexShader); + vertexShader = replaceLightNums2(vertexShader, parameters); + vertexShader = replaceClippingPlaneNums2(vertexShader, parameters); + fragmentShader = resolveIncludes2(fragmentShader); + fragmentShader = replaceLightNums2(fragmentShader, parameters); + fragmentShader = replaceClippingPlaneNums2(fragmentShader, parameters); + vertexShader = unrollLoops2(vertexShader); + fragmentShader = unrollLoops2(fragmentShader); + if (parameters.isWebGL2 && parameters.isRawShaderMaterial !== true) { + versionString = "#version 300 es\n"; + prefixVertex = ["precision mediump sampler2DArray;", "#define attribute in", "#define varying out", "#define texture2D texture"].join("\n") + "\n" + prefixVertex; + prefixFragment = ["#define varying in", parameters.glslVersion === GLSL32 ? "" : "layout(location = 0) out highp vec4 pc_fragColor;", parameters.glslVersion === GLSL32 ? "" : "#define gl_FragColor pc_fragColor", "#define gl_FragDepthEXT gl_FragDepth", "#define texture2D texture", "#define textureCube texture", "#define texture2DProj textureProj", "#define texture2DLodEXT textureLod", "#define texture2DProjLodEXT textureProjLod", "#define textureCubeLodEXT textureLod", "#define texture2DGradEXT textureGrad", "#define texture2DProjGradEXT textureProjGrad", "#define textureCubeGradEXT textureGrad"].join("\n") + "\n" + prefixFragment; + } + const vertexGlsl = versionString + prefixVertex + vertexShader; + const fragmentGlsl = versionString + prefixFragment + fragmentShader; + const glVertexShader = WebGLShader2(gl, gl.VERTEX_SHADER, vertexGlsl); + const glFragmentShader = WebGLShader2(gl, gl.FRAGMENT_SHADER, fragmentGlsl); + gl.attachShader(program, glVertexShader); + gl.attachShader(program, glFragmentShader); + if (parameters.index0AttributeName !== void 0) { + gl.bindAttribLocation(program, 0, parameters.index0AttributeName); + } else if (parameters.morphTargets === true) { + gl.bindAttribLocation(program, 0, "position"); + } + gl.linkProgram(program); + if (renderer.debug.checkShaderErrors) { + const programLog = gl.getProgramInfoLog(program).trim(); + const vertexLog = gl.getShaderInfoLog(glVertexShader).trim(); + const fragmentLog = gl.getShaderInfoLog(glFragmentShader).trim(); + let runnable = true; + let haveDiagnostics = true; + if (gl.getProgramParameter(program, gl.LINK_STATUS) === false) { + runnable = false; + const vertexErrors = getShaderErrors2(gl, glVertexShader, "vertex"); + const fragmentErrors = getShaderErrors2(gl, glFragmentShader, "fragment"); + console.error("THREE.WebGLProgram: Shader Error " + gl.getError() + " - VALIDATE_STATUS " + gl.getProgramParameter(program, gl.VALIDATE_STATUS) + "\n\nProgram Info Log: " + programLog + "\n" + vertexErrors + "\n" + fragmentErrors); + } else if (programLog !== "") { + console.warn("THREE.WebGLProgram: Program Info Log:", programLog); + } else if (vertexLog === "" || fragmentLog === "") { + haveDiagnostics = false; + } + if (haveDiagnostics) { + this.diagnostics = { + runnable, + programLog, + vertexShader: { + log: vertexLog, + prefix: prefixVertex + }, + fragmentShader: { + log: fragmentLog, + prefix: prefixFragment + } + }; + } + } + gl.deleteShader(glVertexShader); + gl.deleteShader(glFragmentShader); + let cachedUniforms; + this.getUniforms = function() { + if (cachedUniforms === void 0) { + cachedUniforms = new WebGLUniforms2(gl, program); + } + return cachedUniforms; + }; + let cachedAttributes; + this.getAttributes = function() { + if (cachedAttributes === void 0) { + cachedAttributes = fetchAttributeLocations2(gl, program); + } + return cachedAttributes; + }; + this.destroy = function() { + bindingStates.releaseStatesOfProgram(this); + gl.deleteProgram(program); + this.program = void 0; + }; + this.name = parameters.shaderName; + this.id = programIdCount2++; + this.cacheKey = cacheKey; + this.usedTimes = 1; + this.program = program; + this.vertexShader = glVertexShader; + this.fragmentShader = glFragmentShader; + return this; + } + var _id2 = 0; + var WebGLShaderCache2 = class { + constructor() { + this.shaderCache = /* @__PURE__ */ new Map(); + this.materialCache = /* @__PURE__ */ new Map(); + } + update(material) { + const vertexShader = material.vertexShader; + const fragmentShader = material.fragmentShader; + const vertexShaderStage = this._getShaderStage(vertexShader); + const fragmentShaderStage = this._getShaderStage(fragmentShader); + const materialShaders = this._getShaderCacheForMaterial(material); + if (materialShaders.has(vertexShaderStage) === false) { + materialShaders.add(vertexShaderStage); + vertexShaderStage.usedTimes++; + } + if (materialShaders.has(fragmentShaderStage) === false) { + materialShaders.add(fragmentShaderStage); + fragmentShaderStage.usedTimes++; + } + return this; + } + remove(material) { + const materialShaders = this.materialCache.get(material); + for (const shaderStage of materialShaders) { + shaderStage.usedTimes--; + if (shaderStage.usedTimes === 0) + this.shaderCache.delete(shaderStage.code); + } + this.materialCache.delete(material); + return this; + } + getVertexShaderID(material) { + return this._getShaderStage(material.vertexShader).id; + } + getFragmentShaderID(material) { + return this._getShaderStage(material.fragmentShader).id; + } + dispose() { + this.shaderCache.clear(); + this.materialCache.clear(); + } + _getShaderCacheForMaterial(material) { + const cache2 = this.materialCache; + if (cache2.has(material) === false) { + cache2.set(material, /* @__PURE__ */ new Set()); + } + return cache2.get(material); + } + _getShaderStage(code) { + const cache2 = this.shaderCache; + if (cache2.has(code) === false) { + const stage = new WebGLShaderStage2(code); + cache2.set(code, stage); + } + return cache2.get(code); + } + }; + var WebGLShaderStage2 = class { + constructor(code) { + this.id = _id2++; + this.code = code; + this.usedTimes = 0; + } + }; + function WebGLPrograms2(renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping) { + const _programLayers = new Layers2(); + const _customShaders = new WebGLShaderCache2(); + const programs = []; + const isWebGL2 = capabilities.isWebGL2; + const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; + const vertexTextures = capabilities.vertexTextures; + let precision = capabilities.precision; + const shaderIDs = { + MeshDepthMaterial: "depth", + MeshDistanceMaterial: "distanceRGBA", + MeshNormalMaterial: "normal", + MeshBasicMaterial: "basic", + MeshLambertMaterial: "lambert", + MeshPhongMaterial: "phong", + MeshToonMaterial: "toon", + MeshStandardMaterial: "physical", + MeshPhysicalMaterial: "physical", + MeshMatcapMaterial: "matcap", + LineBasicMaterial: "basic", + LineDashedMaterial: "dashed", + PointsMaterial: "points", + ShadowMaterial: "shadow", + SpriteMaterial: "sprite" + }; + function getParameters(material, lights, shadows, scene, object) { + const fog = scene.fog; + const geometry = object.geometry; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment); + const envMapCubeUVHeight = !!envMap && envMap.mapping === CubeUVReflectionMapping2 ? envMap.image.height : null; + const shaderID = shaderIDs[material.type]; + if (material.precision !== null) { + precision = capabilities.getMaxPrecision(material.precision); + if (precision !== material.precision) { + console.warn("THREE.WebGLProgram.getParameters:", material.precision, "not supported, using", precision, "instead."); + } + } + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = morphAttribute !== void 0 ? morphAttribute.length : 0; + let morphTextureStride = 0; + if (geometry.morphAttributes.position !== void 0) + morphTextureStride = 1; + if (geometry.morphAttributes.normal !== void 0) + morphTextureStride = 2; + if (geometry.morphAttributes.color !== void 0) + morphTextureStride = 3; + let vertexShader, fragmentShader; + let customVertexShaderID, customFragmentShaderID; + if (shaderID) { + const shader = ShaderLib2[shaderID]; + vertexShader = shader.vertexShader; + fragmentShader = shader.fragmentShader; + } else { + vertexShader = material.vertexShader; + fragmentShader = material.fragmentShader; + _customShaders.update(material); + customVertexShaderID = _customShaders.getVertexShaderID(material); + customFragmentShaderID = _customShaders.getFragmentShaderID(material); + } + const currentRenderTarget = renderer.getRenderTarget(); + const useAlphaTest = material.alphaTest > 0; + const useClearcoat = material.clearcoat > 0; + const useIridescence = material.iridescence > 0; + const parameters = { + isWebGL2, + shaderID, + shaderName: material.type, + vertexShader, + fragmentShader, + defines: material.defines, + customVertexShaderID, + customFragmentShaderID, + isRawShaderMaterial: material.isRawShaderMaterial === true, + glslVersion: material.glslVersion, + precision, + instancing: object.isInstancedMesh === true, + instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, + supportsVertexTextures: vertexTextures, + outputEncoding: currentRenderTarget === null ? renderer.outputEncoding : currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding2, + map: !!material.map, + matcap: !!material.matcap, + envMap: !!envMap, + envMapMode: envMap && envMap.mapping, + envMapCubeUVHeight, + lightMap: !!material.lightMap, + aoMap: !!material.aoMap, + emissiveMap: !!material.emissiveMap, + bumpMap: !!material.bumpMap, + normalMap: !!material.normalMap, + objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap2, + tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap2, + decodeVideoTexture: !!material.map && material.map.isVideoTexture === true && material.map.encoding === sRGBEncoding2, + clearcoat: useClearcoat, + clearcoatMap: useClearcoat && !!material.clearcoatMap, + clearcoatRoughnessMap: useClearcoat && !!material.clearcoatRoughnessMap, + clearcoatNormalMap: useClearcoat && !!material.clearcoatNormalMap, + iridescence: useIridescence, + iridescenceMap: useIridescence && !!material.iridescenceMap, + iridescenceThicknessMap: useIridescence && !!material.iridescenceThicknessMap, + displacementMap: !!material.displacementMap, + roughnessMap: !!material.roughnessMap, + metalnessMap: !!material.metalnessMap, + specularMap: !!material.specularMap, + specularIntensityMap: !!material.specularIntensityMap, + specularColorMap: !!material.specularColorMap, + opaque: material.transparent === false && material.blending === NormalBlending2, + alphaMap: !!material.alphaMap, + alphaTest: useAlphaTest, + gradientMap: !!material.gradientMap, + sheen: material.sheen > 0, + sheenColorMap: !!material.sheenColorMap, + sheenRoughnessMap: !!material.sheenRoughnessMap, + transmission: material.transmission > 0, + transmissionMap: !!material.transmissionMap, + thicknessMap: !!material.thicknessMap, + combine: material.combine, + vertexTangents: !!material.normalMap && !!geometry.attributes.tangent, + vertexColors: material.vertexColors, + vertexAlphas: material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4, + vertexUvs: !!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatMap || !!material.clearcoatRoughnessMap || !!material.clearcoatNormalMap || !!material.iridescenceMap || !!material.iridescenceThicknessMap || !!material.displacementMap || !!material.transmissionMap || !!material.thicknessMap || !!material.specularIntensityMap || !!material.specularColorMap || !!material.sheenColorMap || !!material.sheenRoughnessMap, + uvsVertexOnly: !(!!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatNormalMap || !!material.iridescenceMap || !!material.iridescenceThicknessMap || material.transmission > 0 || !!material.transmissionMap || !!material.thicknessMap || !!material.specularIntensityMap || !!material.specularColorMap || material.sheen > 0 || !!material.sheenColorMap || !!material.sheenRoughnessMap) && !!material.displacementMap, + fog: !!fog, + useFog: material.fog === true, + fogExp2: fog && fog.isFogExp2, + flatShading: !!material.flatShading, + sizeAttenuation: material.sizeAttenuation, + logarithmicDepthBuffer, + skinning: object.isSkinnedMesh === true, + morphTargets: geometry.morphAttributes.position !== void 0, + morphNormals: geometry.morphAttributes.normal !== void 0, + morphColors: geometry.morphAttributes.color !== void 0, + morphTargetsCount, + morphTextureStride, + numDirLights: lights.directional.length, + numPointLights: lights.point.length, + numSpotLights: lights.spot.length, + numRectAreaLights: lights.rectArea.length, + numHemiLights: lights.hemi.length, + numDirLightShadows: lights.directionalShadowMap.length, + numPointLightShadows: lights.pointShadowMap.length, + numSpotLightShadows: lights.spotShadowMap.length, + numClippingPlanes: clipping.numPlanes, + numClipIntersection: clipping.numIntersection, + dithering: material.dithering, + shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, + shadowMapType: renderer.shadowMap.type, + toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping2, + physicallyCorrectLights: renderer.physicallyCorrectLights, + premultipliedAlpha: material.premultipliedAlpha, + doubleSided: material.side === DoubleSide2, + flipSided: material.side === BackSide2, + useDepthPacking: !!material.depthPacking, + depthPacking: material.depthPacking || 0, + index0AttributeName: material.index0AttributeName, + extensionDerivatives: material.extensions && material.extensions.derivatives, + extensionFragDepth: material.extensions && material.extensions.fragDepth, + extensionDrawBuffers: material.extensions && material.extensions.drawBuffers, + extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD, + rendererExtensionFragDepth: isWebGL2 || extensions.has("EXT_frag_depth"), + rendererExtensionDrawBuffers: isWebGL2 || extensions.has("WEBGL_draw_buffers"), + rendererExtensionShaderTextureLod: isWebGL2 || extensions.has("EXT_shader_texture_lod"), + customProgramCacheKey: material.customProgramCacheKey() + }; + return parameters; + } + function getProgramCacheKey(parameters) { + const array2 = []; + if (parameters.shaderID) { + array2.push(parameters.shaderID); + } else { + array2.push(parameters.customVertexShaderID); + array2.push(parameters.customFragmentShaderID); + } + if (parameters.defines !== void 0) { + for (const name in parameters.defines) { + array2.push(name); + array2.push(parameters.defines[name]); + } + } + if (parameters.isRawShaderMaterial === false) { + getProgramCacheKeyParameters(array2, parameters); + getProgramCacheKeyBooleans(array2, parameters); + array2.push(renderer.outputEncoding); + } + array2.push(parameters.customProgramCacheKey); + return array2.join(); + } + function getProgramCacheKeyParameters(array2, parameters) { + array2.push(parameters.precision); + array2.push(parameters.outputEncoding); + array2.push(parameters.envMapMode); + array2.push(parameters.envMapCubeUVHeight); + array2.push(parameters.combine); + array2.push(parameters.vertexUvs); + array2.push(parameters.fogExp2); + array2.push(parameters.sizeAttenuation); + array2.push(parameters.morphTargetsCount); + array2.push(parameters.morphAttributeCount); + array2.push(parameters.numDirLights); + array2.push(parameters.numPointLights); + array2.push(parameters.numSpotLights); + array2.push(parameters.numHemiLights); + array2.push(parameters.numRectAreaLights); + array2.push(parameters.numDirLightShadows); + array2.push(parameters.numPointLightShadows); + array2.push(parameters.numSpotLightShadows); + array2.push(parameters.shadowMapType); + array2.push(parameters.toneMapping); + array2.push(parameters.numClippingPlanes); + array2.push(parameters.numClipIntersection); + array2.push(parameters.depthPacking); + } + function getProgramCacheKeyBooleans(array2, parameters) { + _programLayers.disableAll(); + if (parameters.isWebGL2) + _programLayers.enable(0); + if (parameters.supportsVertexTextures) + _programLayers.enable(1); + if (parameters.instancing) + _programLayers.enable(2); + if (parameters.instancingColor) + _programLayers.enable(3); + if (parameters.map) + _programLayers.enable(4); + if (parameters.matcap) + _programLayers.enable(5); + if (parameters.envMap) + _programLayers.enable(6); + if (parameters.lightMap) + _programLayers.enable(7); + if (parameters.aoMap) + _programLayers.enable(8); + if (parameters.emissiveMap) + _programLayers.enable(9); + if (parameters.bumpMap) + _programLayers.enable(10); + if (parameters.normalMap) + _programLayers.enable(11); + if (parameters.objectSpaceNormalMap) + _programLayers.enable(12); + if (parameters.tangentSpaceNormalMap) + _programLayers.enable(13); + if (parameters.clearcoat) + _programLayers.enable(14); + if (parameters.clearcoatMap) + _programLayers.enable(15); + if (parameters.clearcoatRoughnessMap) + _programLayers.enable(16); + if (parameters.clearcoatNormalMap) + _programLayers.enable(17); + if (parameters.iridescence) + _programLayers.enable(18); + if (parameters.iridescenceMap) + _programLayers.enable(19); + if (parameters.iridescenceThicknessMap) + _programLayers.enable(20); + if (parameters.displacementMap) + _programLayers.enable(21); + if (parameters.specularMap) + _programLayers.enable(22); + if (parameters.roughnessMap) + _programLayers.enable(23); + if (parameters.metalnessMap) + _programLayers.enable(24); + if (parameters.gradientMap) + _programLayers.enable(25); + if (parameters.alphaMap) + _programLayers.enable(26); + if (parameters.alphaTest) + _programLayers.enable(27); + if (parameters.vertexColors) + _programLayers.enable(28); + if (parameters.vertexAlphas) + _programLayers.enable(29); + if (parameters.vertexUvs) + _programLayers.enable(30); + if (parameters.vertexTangents) + _programLayers.enable(31); + if (parameters.uvsVertexOnly) + _programLayers.enable(32); + if (parameters.fog) + _programLayers.enable(33); + array2.push(_programLayers.mask); + _programLayers.disableAll(); + if (parameters.useFog) + _programLayers.enable(0); + if (parameters.flatShading) + _programLayers.enable(1); + if (parameters.logarithmicDepthBuffer) + _programLayers.enable(2); + if (parameters.skinning) + _programLayers.enable(3); + if (parameters.morphTargets) + _programLayers.enable(4); + if (parameters.morphNormals) + _programLayers.enable(5); + if (parameters.morphColors) + _programLayers.enable(6); + if (parameters.premultipliedAlpha) + _programLayers.enable(7); + if (parameters.shadowMapEnabled) + _programLayers.enable(8); + if (parameters.physicallyCorrectLights) + _programLayers.enable(9); + if (parameters.doubleSided) + _programLayers.enable(10); + if (parameters.flipSided) + _programLayers.enable(11); + if (parameters.useDepthPacking) + _programLayers.enable(12); + if (parameters.dithering) + _programLayers.enable(13); + if (parameters.specularIntensityMap) + _programLayers.enable(14); + if (parameters.specularColorMap) + _programLayers.enable(15); + if (parameters.transmission) + _programLayers.enable(16); + if (parameters.transmissionMap) + _programLayers.enable(17); + if (parameters.thicknessMap) + _programLayers.enable(18); + if (parameters.sheen) + _programLayers.enable(19); + if (parameters.sheenColorMap) + _programLayers.enable(20); + if (parameters.sheenRoughnessMap) + _programLayers.enable(21); + if (parameters.decodeVideoTexture) + _programLayers.enable(22); + if (parameters.opaque) + _programLayers.enable(23); + array2.push(_programLayers.mask); + } + function getUniforms(material) { + const shaderID = shaderIDs[material.type]; + let uniforms; + if (shaderID) { + const shader = ShaderLib2[shaderID]; + uniforms = UniformsUtils2.clone(shader.uniforms); + } else { + uniforms = material.uniforms; + } + return uniforms; + } + function acquireProgram(parameters, cacheKey) { + let program; + for (let p = 0, pl = programs.length; p < pl; p++) { + const preexistingProgram = programs[p]; + if (preexistingProgram.cacheKey === cacheKey) { + program = preexistingProgram; + ++program.usedTimes; + break; + } + } + if (program === void 0) { + program = new WebGLProgram2(renderer, cacheKey, parameters, bindingStates); + programs.push(program); + } + return program; + } + function releaseProgram(program) { + if (--program.usedTimes === 0) { + const i = programs.indexOf(program); + programs[i] = programs[programs.length - 1]; + programs.pop(); + program.destroy(); + } + } + function releaseShaderCache(material) { + _customShaders.remove(material); + } + function dispose() { + _customShaders.dispose(); + } + return { + getParameters, + getProgramCacheKey, + getUniforms, + acquireProgram, + releaseProgram, + releaseShaderCache, + programs, + dispose + }; + } + function WebGLProperties2() { + let properties = /* @__PURE__ */ new WeakMap(); + function get3(object) { + let map2 = properties.get(object); + if (map2 === void 0) { + map2 = {}; + properties.set(object, map2); + } + return map2; + } + function remove2(object) { + properties.delete(object); + } + function update(object, key, value) { + properties.get(object)[key] = value; + } + function dispose() { + properties = /* @__PURE__ */ new WeakMap(); + } + return { + get: get3, + remove: remove2, + update, + dispose + }; + } + function painterSortStable2(a2, b) { + if (a2.groupOrder !== b.groupOrder) { + return a2.groupOrder - b.groupOrder; + } else if (a2.renderOrder !== b.renderOrder) { + return a2.renderOrder - b.renderOrder; + } else if (a2.material.id !== b.material.id) { + return a2.material.id - b.material.id; + } else if (a2.z !== b.z) { + return a2.z - b.z; + } else { + return a2.id - b.id; + } + } + function reversePainterSortStable2(a2, b) { + if (a2.groupOrder !== b.groupOrder) { + return a2.groupOrder - b.groupOrder; + } else if (a2.renderOrder !== b.renderOrder) { + return a2.renderOrder - b.renderOrder; + } else if (a2.z !== b.z) { + return b.z - a2.z; + } else { + return a2.id - b.id; + } + } + function WebGLRenderList2() { + const renderItems = []; + let renderItemsIndex = 0; + const opaque = []; + const transmissive = []; + const transparent = []; + function init2() { + renderItemsIndex = 0; + opaque.length = 0; + transmissive.length = 0; + transparent.length = 0; + } + function getNextRenderItem(object, geometry, material, groupOrder, z, group) { + let renderItem = renderItems[renderItemsIndex]; + if (renderItem === void 0) { + renderItem = { + id: object.id, + object, + geometry, + material, + groupOrder, + renderOrder: object.renderOrder, + z, + group + }; + renderItems[renderItemsIndex] = renderItem; + } else { + renderItem.id = object.id; + renderItem.object = object; + renderItem.geometry = geometry; + renderItem.material = material; + renderItem.groupOrder = groupOrder; + renderItem.renderOrder = object.renderOrder; + renderItem.z = z; + renderItem.group = group; + } + renderItemsIndex++; + return renderItem; + } + function push(object, geometry, material, groupOrder, z, group) { + const renderItem = getNextRenderItem(object, geometry, material, groupOrder, z, group); + if (material.transmission > 0) { + transmissive.push(renderItem); + } else if (material.transparent === true) { + transparent.push(renderItem); + } else { + opaque.push(renderItem); + } + } + function unshift(object, geometry, material, groupOrder, z, group) { + const renderItem = getNextRenderItem(object, geometry, material, groupOrder, z, group); + if (material.transmission > 0) { + transmissive.unshift(renderItem); + } else if (material.transparent === true) { + transparent.unshift(renderItem); + } else { + opaque.unshift(renderItem); + } + } + function sort(customOpaqueSort, customTransparentSort) { + if (opaque.length > 1) + opaque.sort(customOpaqueSort || painterSortStable2); + if (transmissive.length > 1) + transmissive.sort(customTransparentSort || reversePainterSortStable2); + if (transparent.length > 1) + transparent.sort(customTransparentSort || reversePainterSortStable2); + } + function finish() { + for (let i = renderItemsIndex, il = renderItems.length; i < il; i++) { + const renderItem = renderItems[i]; + if (renderItem.id === null) + break; + renderItem.id = null; + renderItem.object = null; + renderItem.geometry = null; + renderItem.material = null; + renderItem.group = null; + } + } + return { + opaque, + transmissive, + transparent, + init: init2, + push, + unshift, + finish, + sort + }; + } + function WebGLRenderLists2() { + let lists = /* @__PURE__ */ new WeakMap(); + function get3(scene, renderCallDepth) { + let list; + if (lists.has(scene) === false) { + list = new WebGLRenderList2(); + lists.set(scene, [list]); + } else { + if (renderCallDepth >= lists.get(scene).length) { + list = new WebGLRenderList2(); + lists.get(scene).push(list); + } else { + list = lists.get(scene)[renderCallDepth]; + } + } + return list; + } + function dispose() { + lists = /* @__PURE__ */ new WeakMap(); + } + return { + get: get3, + dispose + }; + } + function UniformsCache2() { + const lights = {}; + return { + get: function(light) { + if (lights[light.id] !== void 0) { + return lights[light.id]; + } + let uniforms; + switch (light.type) { + case "DirectionalLight": + uniforms = { + direction: new Vector32(), + color: new Color3() + }; + break; + case "SpotLight": + uniforms = { + position: new Vector32(), + direction: new Vector32(), + color: new Color3(), + distance: 0, + coneCos: 0, + penumbraCos: 0, + decay: 0 + }; + break; + case "PointLight": + uniforms = { + position: new Vector32(), + color: new Color3(), + distance: 0, + decay: 0 + }; + break; + case "HemisphereLight": + uniforms = { + direction: new Vector32(), + skyColor: new Color3(), + groundColor: new Color3() + }; + break; + case "RectAreaLight": + uniforms = { + color: new Color3(), + position: new Vector32(), + halfWidth: new Vector32(), + halfHeight: new Vector32() + }; + break; + } + lights[light.id] = uniforms; + return uniforms; + } + }; + } + function ShadowUniformsCache2() { + const lights = {}; + return { + get: function(light) { + if (lights[light.id] !== void 0) { + return lights[light.id]; + } + let uniforms; + switch (light.type) { + case "DirectionalLight": + uniforms = { + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector22() + }; + break; + case "SpotLight": + uniforms = { + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector22() + }; + break; + case "PointLight": + uniforms = { + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector22(), + shadowCameraNear: 1, + shadowCameraFar: 1e3 + }; + break; + } + lights[light.id] = uniforms; + return uniforms; + } + }; + } + var nextVersion2 = 0; + function shadowCastingLightsFirst2(lightA, lightB) { + return (lightB.castShadow ? 1 : 0) - (lightA.castShadow ? 1 : 0); + } + function WebGLLights2(extensions, capabilities) { + const cache2 = new UniformsCache2(); + const shadowCache = ShadowUniformsCache2(); + const state = { + version: 0, + hash: { + directionalLength: -1, + pointLength: -1, + spotLength: -1, + rectAreaLength: -1, + hemiLength: -1, + numDirectionalShadows: -1, + numPointShadows: -1, + numSpotShadows: -1 + }, + ambient: [0, 0, 0], + probe: [], + directional: [], + directionalShadow: [], + directionalShadowMap: [], + directionalShadowMatrix: [], + spot: [], + spotShadow: [], + spotShadowMap: [], + spotShadowMatrix: [], + rectArea: [], + rectAreaLTC1: null, + rectAreaLTC2: null, + point: [], + pointShadow: [], + pointShadowMap: [], + pointShadowMatrix: [], + hemi: [] + }; + for (let i = 0; i < 9; i++) + state.probe.push(new Vector32()); + const vector3 = new Vector32(); + const matrix4 = new Matrix42(); + const matrix42 = new Matrix42(); + function setup(lights, physicallyCorrectLights) { + let r = 0, g = 0, b = 0; + for (let i = 0; i < 9; i++) + state.probe[i].set(0, 0, 0); + let directionalLength = 0; + let pointLength = 0; + let spotLength = 0; + let rectAreaLength = 0; + let hemiLength = 0; + let numDirectionalShadows = 0; + let numPointShadows = 0; + let numSpotShadows = 0; + lights.sort(shadowCastingLightsFirst2); + const scaleFactor = physicallyCorrectLights !== true ? Math.PI : 1; + for (let i = 0, l = lights.length; i < l; i++) { + const light = lights[i]; + const color2 = light.color; + const intensity = light.intensity; + const distance = light.distance; + const shadowMap = light.shadow && light.shadow.map ? light.shadow.map.texture : null; + if (light.isAmbientLight) { + r += color2.r * intensity * scaleFactor; + g += color2.g * intensity * scaleFactor; + b += color2.b * intensity * scaleFactor; + } else if (light.isLightProbe) { + for (let j = 0; j < 9; j++) { + state.probe[j].addScaledVector(light.sh.coefficients[j], intensity); + } + } else if (light.isDirectionalLight) { + const uniforms = cache2.get(light); + uniforms.color.copy(light.color).multiplyScalar(light.intensity * scaleFactor); + if (light.castShadow) { + const shadow = light.shadow; + const shadowUniforms = shadowCache.get(light); + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; + state.directionalShadow[directionalLength] = shadowUniforms; + state.directionalShadowMap[directionalLength] = shadowMap; + state.directionalShadowMatrix[directionalLength] = light.shadow.matrix; + numDirectionalShadows++; + } + state.directional[directionalLength] = uniforms; + directionalLength++; + } else if (light.isSpotLight) { + const uniforms = cache2.get(light); + uniforms.position.setFromMatrixPosition(light.matrixWorld); + uniforms.color.copy(color2).multiplyScalar(intensity * scaleFactor); + uniforms.distance = distance; + uniforms.coneCos = Math.cos(light.angle); + uniforms.penumbraCos = Math.cos(light.angle * (1 - light.penumbra)); + uniforms.decay = light.decay; + if (light.castShadow) { + const shadow = light.shadow; + const shadowUniforms = shadowCache.get(light); + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; + state.spotShadow[spotLength] = shadowUniforms; + state.spotShadowMap[spotLength] = shadowMap; + state.spotShadowMatrix[spotLength] = light.shadow.matrix; + numSpotShadows++; + } + state.spot[spotLength] = uniforms; + spotLength++; + } else if (light.isRectAreaLight) { + const uniforms = cache2.get(light); + uniforms.color.copy(color2).multiplyScalar(intensity); + uniforms.halfWidth.set(light.width * 0.5, 0, 0); + uniforms.halfHeight.set(0, light.height * 0.5, 0); + state.rectArea[rectAreaLength] = uniforms; + rectAreaLength++; + } else if (light.isPointLight) { + const uniforms = cache2.get(light); + uniforms.color.copy(light.color).multiplyScalar(light.intensity * scaleFactor); + uniforms.distance = light.distance; + uniforms.decay = light.decay; + if (light.castShadow) { + const shadow = light.shadow; + const shadowUniforms = shadowCache.get(light); + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; + shadowUniforms.shadowCameraNear = shadow.camera.near; + shadowUniforms.shadowCameraFar = shadow.camera.far; + state.pointShadow[pointLength] = shadowUniforms; + state.pointShadowMap[pointLength] = shadowMap; + state.pointShadowMatrix[pointLength] = light.shadow.matrix; + numPointShadows++; + } + state.point[pointLength] = uniforms; + pointLength++; + } else if (light.isHemisphereLight) { + const uniforms = cache2.get(light); + uniforms.skyColor.copy(light.color).multiplyScalar(intensity * scaleFactor); + uniforms.groundColor.copy(light.groundColor).multiplyScalar(intensity * scaleFactor); + state.hemi[hemiLength] = uniforms; + hemiLength++; + } + } + if (rectAreaLength > 0) { + if (capabilities.isWebGL2) { + state.rectAreaLTC1 = UniformsLib2.LTC_FLOAT_1; + state.rectAreaLTC2 = UniformsLib2.LTC_FLOAT_2; + } else { + if (extensions.has("OES_texture_float_linear") === true) { + state.rectAreaLTC1 = UniformsLib2.LTC_FLOAT_1; + state.rectAreaLTC2 = UniformsLib2.LTC_FLOAT_2; + } else if (extensions.has("OES_texture_half_float_linear") === true) { + state.rectAreaLTC1 = UniformsLib2.LTC_HALF_1; + state.rectAreaLTC2 = UniformsLib2.LTC_HALF_2; + } else { + console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions."); + } + } + } + state.ambient[0] = r; + state.ambient[1] = g; + state.ambient[2] = b; + const hash = state.hash; + if (hash.directionalLength !== directionalLength || hash.pointLength !== pointLength || hash.spotLength !== spotLength || hash.rectAreaLength !== rectAreaLength || hash.hemiLength !== hemiLength || hash.numDirectionalShadows !== numDirectionalShadows || hash.numPointShadows !== numPointShadows || hash.numSpotShadows !== numSpotShadows) { + state.directional.length = directionalLength; + state.spot.length = spotLength; + state.rectArea.length = rectAreaLength; + state.point.length = pointLength; + state.hemi.length = hemiLength; + state.directionalShadow.length = numDirectionalShadows; + state.directionalShadowMap.length = numDirectionalShadows; + state.pointShadow.length = numPointShadows; + state.pointShadowMap.length = numPointShadows; + state.spotShadow.length = numSpotShadows; + state.spotShadowMap.length = numSpotShadows; + state.directionalShadowMatrix.length = numDirectionalShadows; + state.pointShadowMatrix.length = numPointShadows; + state.spotShadowMatrix.length = numSpotShadows; + hash.directionalLength = directionalLength; + hash.pointLength = pointLength; + hash.spotLength = spotLength; + hash.rectAreaLength = rectAreaLength; + hash.hemiLength = hemiLength; + hash.numDirectionalShadows = numDirectionalShadows; + hash.numPointShadows = numPointShadows; + hash.numSpotShadows = numSpotShadows; + state.version = nextVersion2++; + } + } + function setupView(lights, camera) { + let directionalLength = 0; + let pointLength = 0; + let spotLength = 0; + let rectAreaLength = 0; + let hemiLength = 0; + const viewMatrix = camera.matrixWorldInverse; + for (let i = 0, l = lights.length; i < l; i++) { + const light = lights[i]; + if (light.isDirectionalLight) { + const uniforms = state.directional[directionalLength]; + uniforms.direction.setFromMatrixPosition(light.matrixWorld); + vector3.setFromMatrixPosition(light.target.matrixWorld); + uniforms.direction.sub(vector3); + uniforms.direction.transformDirection(viewMatrix); + directionalLength++; + } else if (light.isSpotLight) { + const uniforms = state.spot[spotLength]; + uniforms.position.setFromMatrixPosition(light.matrixWorld); + uniforms.position.applyMatrix4(viewMatrix); + uniforms.direction.setFromMatrixPosition(light.matrixWorld); + vector3.setFromMatrixPosition(light.target.matrixWorld); + uniforms.direction.sub(vector3); + uniforms.direction.transformDirection(viewMatrix); + spotLength++; + } else if (light.isRectAreaLight) { + const uniforms = state.rectArea[rectAreaLength]; + uniforms.position.setFromMatrixPosition(light.matrixWorld); + uniforms.position.applyMatrix4(viewMatrix); + matrix42.identity(); + matrix4.copy(light.matrixWorld); + matrix4.premultiply(viewMatrix); + matrix42.extractRotation(matrix4); + uniforms.halfWidth.set(light.width * 0.5, 0, 0); + uniforms.halfHeight.set(0, light.height * 0.5, 0); + uniforms.halfWidth.applyMatrix4(matrix42); + uniforms.halfHeight.applyMatrix4(matrix42); + rectAreaLength++; + } else if (light.isPointLight) { + const uniforms = state.point[pointLength]; + uniforms.position.setFromMatrixPosition(light.matrixWorld); + uniforms.position.applyMatrix4(viewMatrix); + pointLength++; + } else if (light.isHemisphereLight) { + const uniforms = state.hemi[hemiLength]; + uniforms.direction.setFromMatrixPosition(light.matrixWorld); + uniforms.direction.transformDirection(viewMatrix); + hemiLength++; + } + } + } + return { + setup, + setupView, + state + }; + } + function WebGLRenderState2(extensions, capabilities) { + const lights = new WebGLLights2(extensions, capabilities); + const lightsArray = []; + const shadowsArray = []; + function init2() { + lightsArray.length = 0; + shadowsArray.length = 0; + } + function pushLight(light) { + lightsArray.push(light); + } + function pushShadow(shadowLight) { + shadowsArray.push(shadowLight); + } + function setupLights(physicallyCorrectLights) { + lights.setup(lightsArray, physicallyCorrectLights); + } + function setupLightsView(camera) { + lights.setupView(lightsArray, camera); + } + const state = { + lightsArray, + shadowsArray, + lights + }; + return { + init: init2, + state, + setupLights, + setupLightsView, + pushLight, + pushShadow + }; + } + function WebGLRenderStates2(extensions, capabilities) { + let renderStates = /* @__PURE__ */ new WeakMap(); + function get3(scene, renderCallDepth = 0) { + let renderState; + if (renderStates.has(scene) === false) { + renderState = new WebGLRenderState2(extensions, capabilities); + renderStates.set(scene, [renderState]); + } else { + if (renderCallDepth >= renderStates.get(scene).length) { + renderState = new WebGLRenderState2(extensions, capabilities); + renderStates.get(scene).push(renderState); + } else { + renderState = renderStates.get(scene)[renderCallDepth]; + } + } + return renderState; + } + function dispose() { + renderStates = /* @__PURE__ */ new WeakMap(); + } + return { + get: get3, + dispose + }; + } + var MeshDepthMaterial2 = class extends Material2 { + constructor(parameters) { + super(); + this.isMeshDepthMaterial = true; + this.type = "MeshDepthMaterial"; + this.depthPacking = BasicDepthPacking2; + this.map = null; + this.alphaMap = null; + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.depthPacking = source.depthPacking; + this.map = source.map; + this.alphaMap = source.alphaMap; + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + return this; + } + }; + var MeshDistanceMaterial2 = class extends Material2 { + constructor(parameters) { + super(); + this.isMeshDistanceMaterial = true; + this.type = "MeshDistanceMaterial"; + this.referencePosition = new Vector32(); + this.nearDistance = 1; + this.farDistance = 1e3; + this.map = null; + this.alphaMap = null; + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.referencePosition.copy(source.referencePosition); + this.nearDistance = source.nearDistance; + this.farDistance = source.farDistance; + this.map = source.map; + this.alphaMap = source.alphaMap; + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + return this; + } + }; + var vertex2 = "void main() {\n gl_Position = vec4( position, 1.0 );\n}"; + var fragment2 = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n const float samples = float( VSM_SAMPLES );\n float mean = 0.0;\n float squared_mean = 0.0;\n float uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n float uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n for ( float i = 0.0; i < samples; i ++ ) {\n float uvOffset = uvStart + i * uvStride;\n #ifdef HORIZONTAL_PASS\n vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n mean += distribution.x;\n squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n #else\n float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n mean += depth;\n squared_mean += depth * depth;\n #endif\n }\n mean = mean / samples;\n squared_mean = squared_mean / samples;\n float std_dev = sqrt( squared_mean - mean * mean );\n gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"; + function WebGLShadowMap2(_renderer, _objects, _capabilities) { + let _frustum = new Frustum2(); + const _shadowMapSize = new Vector22(), _viewportSize = new Vector22(), _viewport = new Vector42(), _depthMaterial = new MeshDepthMaterial2({ + depthPacking: RGBADepthPacking2 + }), _distanceMaterial = new MeshDistanceMaterial2(), _materialCache = {}, _maxTextureSize = _capabilities.maxTextureSize; + const shadowSide = { + 0: BackSide2, + 1: FrontSide2, + 2: DoubleSide2 + }; + const shadowMaterialVertical = new ShaderMaterial2({ + defines: { + VSM_SAMPLES: 8 + }, + uniforms: { + shadow_pass: { + value: null + }, + resolution: { + value: new Vector22() + }, + radius: { + value: 4 + } + }, + vertexShader: vertex2, + fragmentShader: fragment2 + }); + const shadowMaterialHorizontal = shadowMaterialVertical.clone(); + shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1; + const fullScreenTri = new BufferGeometry2(); + fullScreenTri.setAttribute("position", new BufferAttribute2(new Float32Array([-1, -1, 0.5, 3, -1, 0.5, -1, 3, 0.5]), 3)); + const fullScreenMesh = new Mesh2(fullScreenTri, shadowMaterialVertical); + const scope = this; + this.enabled = false; + this.autoUpdate = true; + this.needsUpdate = false; + this.type = PCFShadowMap2; + this.render = function(lights, scene, camera) { + if (scope.enabled === false) + return; + if (scope.autoUpdate === false && scope.needsUpdate === false) + return; + if (lights.length === 0) + return; + const currentRenderTarget = _renderer.getRenderTarget(); + const activeCubeFace = _renderer.getActiveCubeFace(); + const activeMipmapLevel = _renderer.getActiveMipmapLevel(); + const _state = _renderer.state; + _state.setBlending(NoBlending2); + _state.buffers.color.setClear(1, 1, 1, 1); + _state.buffers.depth.setTest(true); + _state.setScissorTest(false); + for (let i = 0, il = lights.length; i < il; i++) { + const light = lights[i]; + const shadow = light.shadow; + if (shadow === void 0) { + console.warn("THREE.WebGLShadowMap:", light, "has no shadow."); + continue; + } + if (shadow.autoUpdate === false && shadow.needsUpdate === false) + continue; + _shadowMapSize.copy(shadow.mapSize); + const shadowFrameExtents = shadow.getFrameExtents(); + _shadowMapSize.multiply(shadowFrameExtents); + _viewportSize.copy(shadow.mapSize); + if (_shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize) { + if (_shadowMapSize.x > _maxTextureSize) { + _viewportSize.x = Math.floor(_maxTextureSize / shadowFrameExtents.x); + _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x; + shadow.mapSize.x = _viewportSize.x; + } + if (_shadowMapSize.y > _maxTextureSize) { + _viewportSize.y = Math.floor(_maxTextureSize / shadowFrameExtents.y); + _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y; + shadow.mapSize.y = _viewportSize.y; + } + } + if (shadow.map === null) { + const pars = this.type !== VSMShadowMap2 ? { + minFilter: NearestFilter2, + magFilter: NearestFilter2 + } : {}; + shadow.map = new WebGLRenderTarget2(_shadowMapSize.x, _shadowMapSize.y, pars); + shadow.map.texture.name = light.name + ".shadowMap"; + shadow.camera.updateProjectionMatrix(); + } + _renderer.setRenderTarget(shadow.map); + _renderer.clear(); + const viewportCount = shadow.getViewportCount(); + for (let vp = 0; vp < viewportCount; vp++) { + const viewport = shadow.getViewport(vp); + _viewport.set(_viewportSize.x * viewport.x, _viewportSize.y * viewport.y, _viewportSize.x * viewport.z, _viewportSize.y * viewport.w); + _state.viewport(_viewport); + shadow.updateMatrices(light, vp); + _frustum = shadow.getFrustum(); + renderObject(scene, camera, shadow.camera, light, this.type); + } + if (shadow.isPointLightShadow !== true && this.type === VSMShadowMap2) { + VSMPass(shadow, camera); + } + shadow.needsUpdate = false; + } + scope.needsUpdate = false; + _renderer.setRenderTarget(currentRenderTarget, activeCubeFace, activeMipmapLevel); + }; + function VSMPass(shadow, camera) { + const geometry = _objects.update(fullScreenMesh); + if (shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples) { + shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples; + shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples; + shadowMaterialVertical.needsUpdate = true; + shadowMaterialHorizontal.needsUpdate = true; + } + if (shadow.mapPass === null) { + shadow.mapPass = new WebGLRenderTarget2(_shadowMapSize.x, _shadowMapSize.y); + } + shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture; + shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize; + shadowMaterialVertical.uniforms.radius.value = shadow.radius; + _renderer.setRenderTarget(shadow.mapPass); + _renderer.clear(); + _renderer.renderBufferDirect(camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null); + shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture; + shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize; + shadowMaterialHorizontal.uniforms.radius.value = shadow.radius; + _renderer.setRenderTarget(shadow.map); + _renderer.clear(); + _renderer.renderBufferDirect(camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null); + } + function getDepthMaterial(object, material, light, shadowCameraNear, shadowCameraFar, type2) { + let result = null; + const customMaterial = light.isPointLight === true ? object.customDistanceMaterial : object.customDepthMaterial; + if (customMaterial !== void 0) { + result = customMaterial; + } else { + result = light.isPointLight === true ? _distanceMaterial : _depthMaterial; + } + if (_renderer.localClippingEnabled && material.clipShadows === true && Array.isArray(material.clippingPlanes) && material.clippingPlanes.length !== 0 || material.displacementMap && material.displacementScale !== 0 || material.alphaMap && material.alphaTest > 0) { + const keyA = result.uuid, keyB = material.uuid; + let materialsForVariant = _materialCache[keyA]; + if (materialsForVariant === void 0) { + materialsForVariant = {}; + _materialCache[keyA] = materialsForVariant; + } + let cachedMaterial = materialsForVariant[keyB]; + if (cachedMaterial === void 0) { + cachedMaterial = result.clone(); + materialsForVariant[keyB] = cachedMaterial; + } + result = cachedMaterial; + } + result.visible = material.visible; + result.wireframe = material.wireframe; + if (type2 === VSMShadowMap2) { + result.side = material.shadowSide !== null ? material.shadowSide : material.side; + } else { + result.side = material.shadowSide !== null ? material.shadowSide : shadowSide[material.side]; + } + result.alphaMap = material.alphaMap; + result.alphaTest = material.alphaTest; + result.clipShadows = material.clipShadows; + result.clippingPlanes = material.clippingPlanes; + result.clipIntersection = material.clipIntersection; + result.displacementMap = material.displacementMap; + result.displacementScale = material.displacementScale; + result.displacementBias = material.displacementBias; + result.wireframeLinewidth = material.wireframeLinewidth; + result.linewidth = material.linewidth; + if (light.isPointLight === true && result.isMeshDistanceMaterial === true) { + result.referencePosition.setFromMatrixPosition(light.matrixWorld); + result.nearDistance = shadowCameraNear; + result.farDistance = shadowCameraFar; + } + return result; + } + function renderObject(object, camera, shadowCamera, light, type2) { + if (object.visible === false) + return; + const visible = object.layers.test(camera.layers); + if (visible && (object.isMesh || object.isLine || object.isPoints)) { + if ((object.castShadow || object.receiveShadow && type2 === VSMShadowMap2) && (!object.frustumCulled || _frustum.intersectsObject(object))) { + object.modelViewMatrix.multiplyMatrices(shadowCamera.matrixWorldInverse, object.matrixWorld); + const geometry = _objects.update(object); + const material = object.material; + if (Array.isArray(material)) { + const groups = geometry.groups; + for (let k = 0, kl = groups.length; k < kl; k++) { + const group = groups[k]; + const groupMaterial = material[group.materialIndex]; + if (groupMaterial && groupMaterial.visible) { + const depthMaterial = getDepthMaterial(object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type2); + _renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, group); + } + } + } else if (material.visible) { + const depthMaterial = getDepthMaterial(object, material, light, shadowCamera.near, shadowCamera.far, type2); + _renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, null); + } + } + } + const children2 = object.children; + for (let i = 0, l = children2.length; i < l; i++) { + renderObject(children2[i], camera, shadowCamera, light, type2); + } + } + } + function WebGLState2(gl, extensions, capabilities) { + const isWebGL2 = capabilities.isWebGL2; + function ColorBuffer() { + let locked = false; + const color2 = new Vector42(); + let currentColorMask = null; + const currentColorClear = new Vector42(0, 0, 0, 0); + return { + setMask: function(colorMask) { + if (currentColorMask !== colorMask && !locked) { + gl.colorMask(colorMask, colorMask, colorMask, colorMask); + currentColorMask = colorMask; + } + }, + setLocked: function(lock) { + locked = lock; + }, + setClear: function(r, g, b, a2, premultipliedAlpha) { + if (premultipliedAlpha === true) { + r *= a2; + g *= a2; + b *= a2; + } + color2.set(r, g, b, a2); + if (currentColorClear.equals(color2) === false) { + gl.clearColor(r, g, b, a2); + currentColorClear.copy(color2); + } + }, + reset: function() { + locked = false; + currentColorMask = null; + currentColorClear.set(-1, 0, 0, 0); + } + }; + } + function DepthBuffer() { + let locked = false; + let currentDepthMask = null; + let currentDepthFunc = null; + let currentDepthClear = null; + return { + setTest: function(depthTest) { + if (depthTest) { + enable(gl.DEPTH_TEST); + } else { + disable(gl.DEPTH_TEST); + } + }, + setMask: function(depthMask) { + if (currentDepthMask !== depthMask && !locked) { + gl.depthMask(depthMask); + currentDepthMask = depthMask; + } + }, + setFunc: function(depthFunc) { + if (currentDepthFunc !== depthFunc) { + if (depthFunc) { + switch (depthFunc) { + case NeverDepth2: + gl.depthFunc(gl.NEVER); + break; + case AlwaysDepth2: + gl.depthFunc(gl.ALWAYS); + break; + case LessDepth2: + gl.depthFunc(gl.LESS); + break; + case LessEqualDepth2: + gl.depthFunc(gl.LEQUAL); + break; + case EqualDepth2: + gl.depthFunc(gl.EQUAL); + break; + case GreaterEqualDepth2: + gl.depthFunc(gl.GEQUAL); + break; + case GreaterDepth2: + gl.depthFunc(gl.GREATER); + break; + case NotEqualDepth2: + gl.depthFunc(gl.NOTEQUAL); + break; + default: + gl.depthFunc(gl.LEQUAL); + } + } else { + gl.depthFunc(gl.LEQUAL); + } + currentDepthFunc = depthFunc; + } + }, + setLocked: function(lock) { + locked = lock; + }, + setClear: function(depth) { + if (currentDepthClear !== depth) { + gl.clearDepth(depth); + currentDepthClear = depth; + } + }, + reset: function() { + locked = false; + currentDepthMask = null; + currentDepthFunc = null; + currentDepthClear = null; + } + }; + } + function StencilBuffer() { + let locked = false; + let currentStencilMask = null; + let currentStencilFunc = null; + let currentStencilRef = null; + let currentStencilFuncMask = null; + let currentStencilFail = null; + let currentStencilZFail = null; + let currentStencilZPass = null; + let currentStencilClear = null; + return { + setTest: function(stencilTest) { + if (!locked) { + if (stencilTest) { + enable(gl.STENCIL_TEST); + } else { + disable(gl.STENCIL_TEST); + } + } + }, + setMask: function(stencilMask) { + if (currentStencilMask !== stencilMask && !locked) { + gl.stencilMask(stencilMask); + currentStencilMask = stencilMask; + } + }, + setFunc: function(stencilFunc, stencilRef, stencilMask) { + if (currentStencilFunc !== stencilFunc || currentStencilRef !== stencilRef || currentStencilFuncMask !== stencilMask) { + gl.stencilFunc(stencilFunc, stencilRef, stencilMask); + currentStencilFunc = stencilFunc; + currentStencilRef = stencilRef; + currentStencilFuncMask = stencilMask; + } + }, + setOp: function(stencilFail, stencilZFail, stencilZPass) { + if (currentStencilFail !== stencilFail || currentStencilZFail !== stencilZFail || currentStencilZPass !== stencilZPass) { + gl.stencilOp(stencilFail, stencilZFail, stencilZPass); + currentStencilFail = stencilFail; + currentStencilZFail = stencilZFail; + currentStencilZPass = stencilZPass; + } + }, + setLocked: function(lock) { + locked = lock; + }, + setClear: function(stencil) { + if (currentStencilClear !== stencil) { + gl.clearStencil(stencil); + currentStencilClear = stencil; + } + }, + reset: function() { + locked = false; + currentStencilMask = null; + currentStencilFunc = null; + currentStencilRef = null; + currentStencilFuncMask = null; + currentStencilFail = null; + currentStencilZFail = null; + currentStencilZPass = null; + currentStencilClear = null; + } + }; + } + const colorBuffer = new ColorBuffer(); + const depthBuffer = new DepthBuffer(); + const stencilBuffer = new StencilBuffer(); + const uboBindings = /* @__PURE__ */ new WeakMap(); + const uboProgamMap = /* @__PURE__ */ new WeakMap(); + let enabledCapabilities = {}; + let currentBoundFramebuffers = {}; + let currentDrawbuffers = /* @__PURE__ */ new WeakMap(); + let defaultDrawbuffers = []; + let currentProgram = null; + let currentBlendingEnabled = false; + let currentBlending = null; + let currentBlendEquation = null; + let currentBlendSrc = null; + let currentBlendDst = null; + let currentBlendEquationAlpha = null; + let currentBlendSrcAlpha = null; + let currentBlendDstAlpha = null; + let currentPremultipledAlpha = false; + let currentFlipSided = null; + let currentCullFace = null; + let currentLineWidth = null; + let currentPolygonOffsetFactor = null; + let currentPolygonOffsetUnits = null; + const maxTextures = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS); + let lineWidthAvailable = false; + let version = 0; + const glVersion = gl.getParameter(gl.VERSION); + if (glVersion.indexOf("WebGL") !== -1) { + version = parseFloat(/^WebGL (\d)/.exec(glVersion)[1]); + lineWidthAvailable = version >= 1; + } else if (glVersion.indexOf("OpenGL ES") !== -1) { + version = parseFloat(/^OpenGL ES (\d)/.exec(glVersion)[1]); + lineWidthAvailable = version >= 2; + } + let currentTextureSlot = null; + let currentBoundTextures = {}; + const scissorParam = gl.getParameter(gl.SCISSOR_BOX); + const viewportParam = gl.getParameter(gl.VIEWPORT); + const currentScissor = new Vector42().fromArray(scissorParam); + const currentViewport = new Vector42().fromArray(viewportParam); + function createTexture(type2, target, count) { + const data = new Uint8Array(4); + const texture = gl.createTexture(); + gl.bindTexture(type2, texture); + gl.texParameteri(type2, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(type2, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + for (let i = 0; i < count; i++) { + gl.texImage2D(target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); + } + return texture; + } + const emptyTextures = {}; + emptyTextures[gl.TEXTURE_2D] = createTexture(gl.TEXTURE_2D, gl.TEXTURE_2D, 1); + emptyTextures[gl.TEXTURE_CUBE_MAP] = createTexture(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6); + colorBuffer.setClear(0, 0, 0, 1); + depthBuffer.setClear(1); + stencilBuffer.setClear(0); + enable(gl.DEPTH_TEST); + depthBuffer.setFunc(LessEqualDepth2); + setFlipSided(false); + setCullFace(CullFaceBack2); + enable(gl.CULL_FACE); + setBlending(NoBlending2); + function enable(id3) { + if (enabledCapabilities[id3] !== true) { + gl.enable(id3); + enabledCapabilities[id3] = true; + } + } + function disable(id3) { + if (enabledCapabilities[id3] !== false) { + gl.disable(id3); + enabledCapabilities[id3] = false; + } + } + function bindFramebuffer(target, framebuffer) { + if (currentBoundFramebuffers[target] !== framebuffer) { + gl.bindFramebuffer(target, framebuffer); + currentBoundFramebuffers[target] = framebuffer; + if (isWebGL2) { + if (target === gl.DRAW_FRAMEBUFFER) { + currentBoundFramebuffers[gl.FRAMEBUFFER] = framebuffer; + } + if (target === gl.FRAMEBUFFER) { + currentBoundFramebuffers[gl.DRAW_FRAMEBUFFER] = framebuffer; + } + } + return true; + } + return false; + } + function drawBuffers(renderTarget, framebuffer) { + let drawBuffers2 = defaultDrawbuffers; + let needsUpdate = false; + if (renderTarget) { + drawBuffers2 = currentDrawbuffers.get(framebuffer); + if (drawBuffers2 === void 0) { + drawBuffers2 = []; + currentDrawbuffers.set(framebuffer, drawBuffers2); + } + if (renderTarget.isWebGLMultipleRenderTargets) { + const textures = renderTarget.texture; + if (drawBuffers2.length !== textures.length || drawBuffers2[0] !== gl.COLOR_ATTACHMENT0) { + for (let i = 0, il = textures.length; i < il; i++) { + drawBuffers2[i] = gl.COLOR_ATTACHMENT0 + i; + } + drawBuffers2.length = textures.length; + needsUpdate = true; + } + } else { + if (drawBuffers2[0] !== gl.COLOR_ATTACHMENT0) { + drawBuffers2[0] = gl.COLOR_ATTACHMENT0; + needsUpdate = true; + } + } + } else { + if (drawBuffers2[0] !== gl.BACK) { + drawBuffers2[0] = gl.BACK; + needsUpdate = true; + } + } + if (needsUpdate) { + if (capabilities.isWebGL2) { + gl.drawBuffers(drawBuffers2); + } else { + extensions.get("WEBGL_draw_buffers").drawBuffersWEBGL(drawBuffers2); + } + } + } + function useProgram(program) { + if (currentProgram !== program) { + gl.useProgram(program); + currentProgram = program; + return true; + } + return false; + } + const equationToGL = { + [AddEquation2]: gl.FUNC_ADD, + [SubtractEquation2]: gl.FUNC_SUBTRACT, + [ReverseSubtractEquation2]: gl.FUNC_REVERSE_SUBTRACT + }; + if (isWebGL2) { + equationToGL[MinEquation2] = gl.MIN; + equationToGL[MaxEquation2] = gl.MAX; + } else { + const extension = extensions.get("EXT_blend_minmax"); + if (extension !== null) { + equationToGL[MinEquation2] = extension.MIN_EXT; + equationToGL[MaxEquation2] = extension.MAX_EXT; + } + } + const factorToGL = { + [ZeroFactor2]: gl.ZERO, + [OneFactor2]: gl.ONE, + [SrcColorFactor2]: gl.SRC_COLOR, + [SrcAlphaFactor2]: gl.SRC_ALPHA, + [SrcAlphaSaturateFactor2]: gl.SRC_ALPHA_SATURATE, + [DstColorFactor2]: gl.DST_COLOR, + [DstAlphaFactor2]: gl.DST_ALPHA, + [OneMinusSrcColorFactor2]: gl.ONE_MINUS_SRC_COLOR, + [OneMinusSrcAlphaFactor2]: gl.ONE_MINUS_SRC_ALPHA, + [OneMinusDstColorFactor2]: gl.ONE_MINUS_DST_COLOR, + [OneMinusDstAlphaFactor2]: gl.ONE_MINUS_DST_ALPHA + }; + function setBlending(blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha) { + if (blending === NoBlending2) { + if (currentBlendingEnabled === true) { + disable(gl.BLEND); + currentBlendingEnabled = false; + } + return; + } + if (currentBlendingEnabled === false) { + enable(gl.BLEND); + currentBlendingEnabled = true; + } + if (blending !== CustomBlending2) { + if (blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha) { + if (currentBlendEquation !== AddEquation2 || currentBlendEquationAlpha !== AddEquation2) { + gl.blendEquation(gl.FUNC_ADD); + currentBlendEquation = AddEquation2; + currentBlendEquationAlpha = AddEquation2; + } + if (premultipliedAlpha) { + switch (blending) { + case NormalBlending2: + gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + break; + case AdditiveBlending2: + gl.blendFunc(gl.ONE, gl.ONE); + break; + case SubtractiveBlending2: + gl.blendFuncSeparate(gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE); + break; + case MultiplyBlending2: + gl.blendFuncSeparate(gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA); + break; + default: + console.error("THREE.WebGLState: Invalid blending: ", blending); + break; + } + } else { + switch (blending) { + case NormalBlending2: + gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + break; + case AdditiveBlending2: + gl.blendFunc(gl.SRC_ALPHA, gl.ONE); + break; + case SubtractiveBlending2: + gl.blendFuncSeparate(gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE); + break; + case MultiplyBlending2: + gl.blendFunc(gl.ZERO, gl.SRC_COLOR); + break; + default: + console.error("THREE.WebGLState: Invalid blending: ", blending); + break; + } + } + currentBlendSrc = null; + currentBlendDst = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + currentBlending = blending; + currentPremultipledAlpha = premultipliedAlpha; + } + return; + } + blendEquationAlpha = blendEquationAlpha || blendEquation; + blendSrcAlpha = blendSrcAlpha || blendSrc; + blendDstAlpha = blendDstAlpha || blendDst; + if (blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha) { + gl.blendEquationSeparate(equationToGL[blendEquation], equationToGL[blendEquationAlpha]); + currentBlendEquation = blendEquation; + currentBlendEquationAlpha = blendEquationAlpha; + } + if (blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha) { + gl.blendFuncSeparate(factorToGL[blendSrc], factorToGL[blendDst], factorToGL[blendSrcAlpha], factorToGL[blendDstAlpha]); + currentBlendSrc = blendSrc; + currentBlendDst = blendDst; + currentBlendSrcAlpha = blendSrcAlpha; + currentBlendDstAlpha = blendDstAlpha; + } + currentBlending = blending; + currentPremultipledAlpha = null; + } + function setMaterial(material, frontFaceCW) { + material.side === DoubleSide2 ? disable(gl.CULL_FACE) : enable(gl.CULL_FACE); + let flipSided = material.side === BackSide2; + if (frontFaceCW) + flipSided = !flipSided; + setFlipSided(flipSided); + material.blending === NormalBlending2 && material.transparent === false ? setBlending(NoBlending2) : setBlending(material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha); + depthBuffer.setFunc(material.depthFunc); + depthBuffer.setTest(material.depthTest); + depthBuffer.setMask(material.depthWrite); + colorBuffer.setMask(material.colorWrite); + const stencilWrite = material.stencilWrite; + stencilBuffer.setTest(stencilWrite); + if (stencilWrite) { + stencilBuffer.setMask(material.stencilWriteMask); + stencilBuffer.setFunc(material.stencilFunc, material.stencilRef, material.stencilFuncMask); + stencilBuffer.setOp(material.stencilFail, material.stencilZFail, material.stencilZPass); + } + setPolygonOffset(material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits); + material.alphaToCoverage === true ? enable(gl.SAMPLE_ALPHA_TO_COVERAGE) : disable(gl.SAMPLE_ALPHA_TO_COVERAGE); + } + function setFlipSided(flipSided) { + if (currentFlipSided !== flipSided) { + if (flipSided) { + gl.frontFace(gl.CW); + } else { + gl.frontFace(gl.CCW); + } + currentFlipSided = flipSided; + } + } + function setCullFace(cullFace) { + if (cullFace !== CullFaceNone2) { + enable(gl.CULL_FACE); + if (cullFace !== currentCullFace) { + if (cullFace === CullFaceBack2) { + gl.cullFace(gl.BACK); + } else if (cullFace === CullFaceFront2) { + gl.cullFace(gl.FRONT); + } else { + gl.cullFace(gl.FRONT_AND_BACK); + } + } + } else { + disable(gl.CULL_FACE); + } + currentCullFace = cullFace; + } + function setLineWidth(width) { + if (width !== currentLineWidth) { + if (lineWidthAvailable) + gl.lineWidth(width); + currentLineWidth = width; + } + } + function setPolygonOffset(polygonOffset, factor, units) { + if (polygonOffset) { + enable(gl.POLYGON_OFFSET_FILL); + if (currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units) { + gl.polygonOffset(factor, units); + currentPolygonOffsetFactor = factor; + currentPolygonOffsetUnits = units; + } + } else { + disable(gl.POLYGON_OFFSET_FILL); + } + } + function setScissorTest(scissorTest) { + if (scissorTest) { + enable(gl.SCISSOR_TEST); + } else { + disable(gl.SCISSOR_TEST); + } + } + function activeTexture(webglSlot) { + if (webglSlot === void 0) + webglSlot = gl.TEXTURE0 + maxTextures - 1; + if (currentTextureSlot !== webglSlot) { + gl.activeTexture(webglSlot); + currentTextureSlot = webglSlot; + } + } + function bindTexture(webglType, webglTexture) { + if (currentTextureSlot === null) { + activeTexture(); + } + let boundTexture = currentBoundTextures[currentTextureSlot]; + if (boundTexture === void 0) { + boundTexture = { + type: void 0, + texture: void 0 + }; + currentBoundTextures[currentTextureSlot] = boundTexture; + } + if (boundTexture.type !== webglType || boundTexture.texture !== webglTexture) { + gl.bindTexture(webglType, webglTexture || emptyTextures[webglType]); + boundTexture.type = webglType; + boundTexture.texture = webglTexture; + } + } + function unbindTexture() { + const boundTexture = currentBoundTextures[currentTextureSlot]; + if (boundTexture !== void 0 && boundTexture.type !== void 0) { + gl.bindTexture(boundTexture.type, null); + boundTexture.type = void 0; + boundTexture.texture = void 0; + } + } + function compressedTexImage2D() { + try { + gl.compressedTexImage2D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texSubImage2D() { + try { + gl.texSubImage2D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texSubImage3D() { + try { + gl.texSubImage3D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function compressedTexSubImage2D() { + try { + gl.compressedTexSubImage2D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texStorage2D() { + try { + gl.texStorage2D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texStorage3D() { + try { + gl.texStorage3D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texImage2D() { + try { + gl.texImage2D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texImage3D() { + try { + gl.texImage3D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function scissor(scissor2) { + if (currentScissor.equals(scissor2) === false) { + gl.scissor(scissor2.x, scissor2.y, scissor2.z, scissor2.w); + currentScissor.copy(scissor2); + } + } + function viewport(viewport2) { + if (currentViewport.equals(viewport2) === false) { + gl.viewport(viewport2.x, viewport2.y, viewport2.z, viewport2.w); + currentViewport.copy(viewport2); + } + } + function updateUBOMapping(uniformsGroup, program) { + let mapping = uboProgamMap.get(program); + if (mapping === void 0) { + mapping = /* @__PURE__ */ new WeakMap(); + uboProgamMap.set(program, mapping); + } + let blockIndex = mapping.get(uniformsGroup); + if (blockIndex === void 0) { + blockIndex = gl.getUniformBlockIndex(program, uniformsGroup.name); + mapping.set(uniformsGroup, blockIndex); + } + } + function uniformBlockBinding(uniformsGroup, program) { + const mapping = uboProgamMap.get(program); + const blockIndex = mapping.get(uniformsGroup); + if (uboBindings.get(uniformsGroup) !== blockIndex) { + gl.uniformBlockBinding(program, blockIndex, uniformsGroup.__bindingPointIndex); + uboBindings.set(uniformsGroup, blockIndex); + } + } + function reset() { + gl.disable(gl.BLEND); + gl.disable(gl.CULL_FACE); + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.POLYGON_OFFSET_FILL); + gl.disable(gl.SCISSOR_TEST); + gl.disable(gl.STENCIL_TEST); + gl.disable(gl.SAMPLE_ALPHA_TO_COVERAGE); + gl.blendEquation(gl.FUNC_ADD); + gl.blendFunc(gl.ONE, gl.ZERO); + gl.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ONE, gl.ZERO); + gl.colorMask(true, true, true, true); + gl.clearColor(0, 0, 0, 0); + gl.depthMask(true); + gl.depthFunc(gl.LESS); + gl.clearDepth(1); + gl.stencilMask(4294967295); + gl.stencilFunc(gl.ALWAYS, 0, 4294967295); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + gl.clearStencil(0); + gl.cullFace(gl.BACK); + gl.frontFace(gl.CCW); + gl.polygonOffset(0, 0); + gl.activeTexture(gl.TEXTURE0); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + if (isWebGL2 === true) { + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); + } + gl.useProgram(null); + gl.lineWidth(1); + gl.scissor(0, 0, gl.canvas.width, gl.canvas.height); + gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); + enabledCapabilities = {}; + currentTextureSlot = null; + currentBoundTextures = {}; + currentBoundFramebuffers = {}; + currentDrawbuffers = /* @__PURE__ */ new WeakMap(); + defaultDrawbuffers = []; + currentProgram = null; + currentBlendingEnabled = false; + currentBlending = null; + currentBlendEquation = null; + currentBlendSrc = null; + currentBlendDst = null; + currentBlendEquationAlpha = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + currentPremultipledAlpha = false; + currentFlipSided = null; + currentCullFace = null; + currentLineWidth = null; + currentPolygonOffsetFactor = null; + currentPolygonOffsetUnits = null; + currentScissor.set(0, 0, gl.canvas.width, gl.canvas.height); + currentViewport.set(0, 0, gl.canvas.width, gl.canvas.height); + colorBuffer.reset(); + depthBuffer.reset(); + stencilBuffer.reset(); + } + return { + buffers: { + color: colorBuffer, + depth: depthBuffer, + stencil: stencilBuffer + }, + enable, + disable, + bindFramebuffer, + drawBuffers, + useProgram, + setBlending, + setMaterial, + setFlipSided, + setCullFace, + setLineWidth, + setPolygonOffset, + setScissorTest, + activeTexture, + bindTexture, + unbindTexture, + compressedTexImage2D, + texImage2D, + texImage3D, + updateUBOMapping, + uniformBlockBinding, + texStorage2D, + texStorage3D, + texSubImage2D, + texSubImage3D, + compressedTexSubImage2D, + scissor, + viewport, + reset + }; + } + function WebGLTextures2(_gl, extensions, state, properties, capabilities, utils, info) { + const isWebGL2 = capabilities.isWebGL2; + const maxTextures = capabilities.maxTextures; + const maxCubemapSize = capabilities.maxCubemapSize; + const maxTextureSize = capabilities.maxTextureSize; + const maxSamples = capabilities.maxSamples; + const multisampledRTTExt = extensions.has("WEBGL_multisampled_render_to_texture") ? extensions.get("WEBGL_multisampled_render_to_texture") : null; + const supportsInvalidateFramebuffer = /OculusBrowser/g.test(navigator.userAgent); + const _videoTextures = /* @__PURE__ */ new WeakMap(); + let _canvas3; + const _sources = /* @__PURE__ */ new WeakMap(); + let useOffscreenCanvas = false; + try { + useOffscreenCanvas = typeof OffscreenCanvas !== "undefined" && new OffscreenCanvas(1, 1).getContext("2d") !== null; + } catch (err) { + } + function createCanvas(width, height) { + return useOffscreenCanvas ? new OffscreenCanvas(width, height) : createElementNS2("canvas"); + } + function resizeImage(image, needsPowerOfTwo, needsNewCanvas, maxSize) { + let scale = 1; + if (image.width > maxSize || image.height > maxSize) { + scale = maxSize / Math.max(image.width, image.height); + } + if (scale < 1 || needsPowerOfTwo === true) { + if (typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && image instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) { + const floor = needsPowerOfTwo ? floorPowerOfTwo2 : Math.floor; + const width = floor(scale * image.width); + const height = floor(scale * image.height); + if (_canvas3 === void 0) + _canvas3 = createCanvas(width, height); + const canvas = needsNewCanvas ? createCanvas(width, height) : _canvas3; + canvas.width = width; + canvas.height = height; + const context = canvas.getContext("2d"); + context.drawImage(image, 0, 0, width, height); + console.warn("THREE.WebGLRenderer: Texture has been resized from (" + image.width + "x" + image.height + ") to (" + width + "x" + height + ")."); + return canvas; + } else { + if ("data" in image) { + console.warn("THREE.WebGLRenderer: Image in DataTexture is too big (" + image.width + "x" + image.height + ")."); + } + return image; + } + } + return image; + } + function isPowerOfTwo$1(image) { + return isPowerOfTwo2(image.width) && isPowerOfTwo2(image.height); + } + function textureNeedsPowerOfTwo(texture) { + if (isWebGL2) + return false; + return texture.wrapS !== ClampToEdgeWrapping2 || texture.wrapT !== ClampToEdgeWrapping2 || texture.minFilter !== NearestFilter2 && texture.minFilter !== LinearFilter2; + } + function textureNeedsGenerateMipmaps(texture, supportsMips) { + return texture.generateMipmaps && supportsMips && texture.minFilter !== NearestFilter2 && texture.minFilter !== LinearFilter2; + } + function generateMipmap(target) { + _gl.generateMipmap(target); + } + function getInternalFormat(internalFormatName, glFormat, glType, encoding, isVideoTexture = false) { + if (isWebGL2 === false) + return glFormat; + if (internalFormatName !== null) { + if (_gl[internalFormatName] !== void 0) + return _gl[internalFormatName]; + console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '" + internalFormatName + "'"); + } + let internalFormat = glFormat; + if (glFormat === _gl.RED) { + if (glType === _gl.FLOAT) + internalFormat = _gl.R32F; + if (glType === _gl.HALF_FLOAT) + internalFormat = _gl.R16F; + if (glType === _gl.UNSIGNED_BYTE) + internalFormat = _gl.R8; + } + if (glFormat === _gl.RG) { + if (glType === _gl.FLOAT) + internalFormat = _gl.RG32F; + if (glType === _gl.HALF_FLOAT) + internalFormat = _gl.RG16F; + if (glType === _gl.UNSIGNED_BYTE) + internalFormat = _gl.RG8; + } + if (glFormat === _gl.RGBA) { + if (glType === _gl.FLOAT) + internalFormat = _gl.RGBA32F; + if (glType === _gl.HALF_FLOAT) + internalFormat = _gl.RGBA16F; + if (glType === _gl.UNSIGNED_BYTE) + internalFormat = encoding === sRGBEncoding2 && isVideoTexture === false ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; + if (glType === _gl.UNSIGNED_SHORT_4_4_4_4) + internalFormat = _gl.RGBA4; + if (glType === _gl.UNSIGNED_SHORT_5_5_5_1) + internalFormat = _gl.RGB5_A1; + } + if (internalFormat === _gl.R16F || internalFormat === _gl.R32F || internalFormat === _gl.RG16F || internalFormat === _gl.RG32F || internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F) { + extensions.get("EXT_color_buffer_float"); + } + return internalFormat; + } + function getMipLevels(texture, image, supportsMips) { + if (textureNeedsGenerateMipmaps(texture, supportsMips) === true || texture.isFramebufferTexture && texture.minFilter !== NearestFilter2 && texture.minFilter !== LinearFilter2) { + return Math.log2(Math.max(image.width, image.height)) + 1; + } else if (texture.mipmaps !== void 0 && texture.mipmaps.length > 0) { + return texture.mipmaps.length; + } else if (texture.isCompressedTexture && Array.isArray(texture.image)) { + return image.mipmaps.length; + } else { + return 1; + } + } + function filterFallback(f) { + if (f === NearestFilter2 || f === NearestMipmapNearestFilter2 || f === NearestMipmapLinearFilter2) { + return _gl.NEAREST; + } + return _gl.LINEAR; + } + function onTextureDispose(event) { + const texture = event.target; + texture.removeEventListener("dispose", onTextureDispose); + deallocateTexture(texture); + if (texture.isVideoTexture) { + _videoTextures.delete(texture); + } + } + function onRenderTargetDispose(event) { + const renderTarget = event.target; + renderTarget.removeEventListener("dispose", onRenderTargetDispose); + deallocateRenderTarget(renderTarget); + } + function deallocateTexture(texture) { + const textureProperties = properties.get(texture); + if (textureProperties.__webglInit === void 0) + return; + const source = texture.source; + const webglTextures = _sources.get(source); + if (webglTextures) { + const webglTexture = webglTextures[textureProperties.__cacheKey]; + webglTexture.usedTimes--; + if (webglTexture.usedTimes === 0) { + deleteTexture(texture); + } + if (Object.keys(webglTextures).length === 0) { + _sources.delete(source); + } + } + properties.remove(texture); + } + function deleteTexture(texture) { + const textureProperties = properties.get(texture); + _gl.deleteTexture(textureProperties.__webglTexture); + const source = texture.source; + const webglTextures = _sources.get(source); + delete webglTextures[textureProperties.__cacheKey]; + info.memory.textures--; + } + function deallocateRenderTarget(renderTarget) { + const texture = renderTarget.texture; + const renderTargetProperties = properties.get(renderTarget); + const textureProperties = properties.get(texture); + if (textureProperties.__webglTexture !== void 0) { + _gl.deleteTexture(textureProperties.__webglTexture); + info.memory.textures--; + } + if (renderTarget.depthTexture) { + renderTarget.depthTexture.dispose(); + } + if (renderTarget.isWebGLCubeRenderTarget) { + for (let i = 0; i < 6; i++) { + _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer[i]); + if (renderTargetProperties.__webglDepthbuffer) + _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer[i]); + } + } else { + _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer); + if (renderTargetProperties.__webglDepthbuffer) + _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer); + if (renderTargetProperties.__webglMultisampledFramebuffer) + _gl.deleteFramebuffer(renderTargetProperties.__webglMultisampledFramebuffer); + if (renderTargetProperties.__webglColorRenderbuffer) { + for (let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i++) { + if (renderTargetProperties.__webglColorRenderbuffer[i]) + _gl.deleteRenderbuffer(renderTargetProperties.__webglColorRenderbuffer[i]); + } + } + if (renderTargetProperties.__webglDepthRenderbuffer) + _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthRenderbuffer); + } + if (renderTarget.isWebGLMultipleRenderTargets) { + for (let i = 0, il = texture.length; i < il; i++) { + const attachmentProperties = properties.get(texture[i]); + if (attachmentProperties.__webglTexture) { + _gl.deleteTexture(attachmentProperties.__webglTexture); + info.memory.textures--; + } + properties.remove(texture[i]); + } + } + properties.remove(texture); + properties.remove(renderTarget); + } + let textureUnits = 0; + function resetTextureUnits() { + textureUnits = 0; + } + function allocateTextureUnit() { + const textureUnit = textureUnits; + if (textureUnit >= maxTextures) { + console.warn("THREE.WebGLTextures: Trying to use " + textureUnit + " texture units while this GPU supports only " + maxTextures); + } + textureUnits += 1; + return textureUnit; + } + function getTextureCacheKey(texture) { + const array2 = []; + array2.push(texture.wrapS); + array2.push(texture.wrapT); + array2.push(texture.magFilter); + array2.push(texture.minFilter); + array2.push(texture.anisotropy); + array2.push(texture.internalFormat); + array2.push(texture.format); + array2.push(texture.type); + array2.push(texture.generateMipmaps); + array2.push(texture.premultiplyAlpha); + array2.push(texture.flipY); + array2.push(texture.unpackAlignment); + array2.push(texture.encoding); + return array2.join(); + } + function setTexture2D(texture, slot) { + const textureProperties = properties.get(texture); + if (texture.isVideoTexture) + updateVideoTexture(texture); + if (texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version) { + const image = texture.image; + if (image === null) { + console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found."); + } else if (image.complete === false) { + console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete"); + } else { + uploadTexture(textureProperties, texture, slot); + return; + } + } + state.activeTexture(_gl.TEXTURE0 + slot); + state.bindTexture(_gl.TEXTURE_2D, textureProperties.__webglTexture); + } + function setTexture2DArray(texture, slot) { + const textureProperties = properties.get(texture); + if (texture.version > 0 && textureProperties.__version !== texture.version) { + uploadTexture(textureProperties, texture, slot); + return; + } + state.activeTexture(_gl.TEXTURE0 + slot); + state.bindTexture(_gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture); + } + function setTexture3D(texture, slot) { + const textureProperties = properties.get(texture); + if (texture.version > 0 && textureProperties.__version !== texture.version) { + uploadTexture(textureProperties, texture, slot); + return; + } + state.activeTexture(_gl.TEXTURE0 + slot); + state.bindTexture(_gl.TEXTURE_3D, textureProperties.__webglTexture); + } + function setTextureCube(texture, slot) { + const textureProperties = properties.get(texture); + if (texture.version > 0 && textureProperties.__version !== texture.version) { + uploadCubeTexture(textureProperties, texture, slot); + return; + } + state.activeTexture(_gl.TEXTURE0 + slot); + state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture); + } + const wrappingToGL = { + [RepeatWrapping2]: _gl.REPEAT, + [ClampToEdgeWrapping2]: _gl.CLAMP_TO_EDGE, + [MirroredRepeatWrapping2]: _gl.MIRRORED_REPEAT + }; + const filterToGL = { + [NearestFilter2]: _gl.NEAREST, + [NearestMipmapNearestFilter2]: _gl.NEAREST_MIPMAP_NEAREST, + [NearestMipmapLinearFilter2]: _gl.NEAREST_MIPMAP_LINEAR, + [LinearFilter2]: _gl.LINEAR, + [LinearMipmapNearestFilter2]: _gl.LINEAR_MIPMAP_NEAREST, + [LinearMipmapLinearFilter2]: _gl.LINEAR_MIPMAP_LINEAR + }; + function setTextureParameters(textureType, texture, supportsMips) { + if (supportsMips) { + _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[texture.wrapS]); + _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[texture.wrapT]); + if (textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY) { + _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[texture.wrapR]); + } + _gl.texParameteri(textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[texture.magFilter]); + _gl.texParameteri(textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[texture.minFilter]); + } else { + _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE); + _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE); + if (textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY) { + _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_R, _gl.CLAMP_TO_EDGE); + } + if (texture.wrapS !== ClampToEdgeWrapping2 || texture.wrapT !== ClampToEdgeWrapping2) { + console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."); + } + _gl.texParameteri(textureType, _gl.TEXTURE_MAG_FILTER, filterFallback(texture.magFilter)); + _gl.texParameteri(textureType, _gl.TEXTURE_MIN_FILTER, filterFallback(texture.minFilter)); + if (texture.minFilter !== NearestFilter2 && texture.minFilter !== LinearFilter2) { + console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter."); + } + } + if (extensions.has("EXT_texture_filter_anisotropic") === true) { + const extension = extensions.get("EXT_texture_filter_anisotropic"); + if (texture.type === FloatType2 && extensions.has("OES_texture_float_linear") === false) + return; + if (isWebGL2 === false && texture.type === HalfFloatType2 && extensions.has("OES_texture_half_float_linear") === false) + return; + if (texture.anisotropy > 1 || properties.get(texture).__currentAnisotropy) { + _gl.texParameterf(textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(texture.anisotropy, capabilities.getMaxAnisotropy())); + properties.get(texture).__currentAnisotropy = texture.anisotropy; + } + } + } + function initTexture(textureProperties, texture) { + let forceUpload = false; + if (textureProperties.__webglInit === void 0) { + textureProperties.__webglInit = true; + texture.addEventListener("dispose", onTextureDispose); + } + const source = texture.source; + let webglTextures = _sources.get(source); + if (webglTextures === void 0) { + webglTextures = {}; + _sources.set(source, webglTextures); + } + const textureCacheKey = getTextureCacheKey(texture); + if (textureCacheKey !== textureProperties.__cacheKey) { + if (webglTextures[textureCacheKey] === void 0) { + webglTextures[textureCacheKey] = { + texture: _gl.createTexture(), + usedTimes: 0 + }; + info.memory.textures++; + forceUpload = true; + } + webglTextures[textureCacheKey].usedTimes++; + const webglTexture = webglTextures[textureProperties.__cacheKey]; + if (webglTexture !== void 0) { + webglTextures[textureProperties.__cacheKey].usedTimes--; + if (webglTexture.usedTimes === 0) { + deleteTexture(texture); + } + } + textureProperties.__cacheKey = textureCacheKey; + textureProperties.__webglTexture = webglTextures[textureCacheKey].texture; + } + return forceUpload; + } + function uploadTexture(textureProperties, texture, slot) { + let textureType = _gl.TEXTURE_2D; + if (texture.isDataArrayTexture) + textureType = _gl.TEXTURE_2D_ARRAY; + if (texture.isData3DTexture) + textureType = _gl.TEXTURE_3D; + const forceUpload = initTexture(textureProperties, texture); + const source = texture.source; + state.activeTexture(_gl.TEXTURE0 + slot); + state.bindTexture(textureType, textureProperties.__webglTexture); + if (source.version !== source.__currentVersion || forceUpload === true) { + _gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, texture.flipY); + _gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha); + _gl.pixelStorei(_gl.UNPACK_ALIGNMENT, texture.unpackAlignment); + _gl.pixelStorei(_gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE); + const needsPowerOfTwo = textureNeedsPowerOfTwo(texture) && isPowerOfTwo$1(texture.image) === false; + let image = resizeImage(texture.image, needsPowerOfTwo, false, maxTextureSize); + image = verifyColorSpace(texture, image); + const supportsMips = isPowerOfTwo$1(image) || isWebGL2, glFormat = utils.convert(texture.format, texture.encoding); + let glType = utils.convert(texture.type), glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture); + setTextureParameters(textureType, texture, supportsMips); + let mipmap; + const mipmaps = texture.mipmaps; + const useTexStorage = isWebGL2 && texture.isVideoTexture !== true; + const allocateMemory = source.__currentVersion === void 0 || forceUpload === true; + const levels = getMipLevels(texture, image, supportsMips); + if (texture.isDepthTexture) { + glInternalFormat = _gl.DEPTH_COMPONENT; + if (isWebGL2) { + if (texture.type === FloatType2) { + glInternalFormat = _gl.DEPTH_COMPONENT32F; + } else if (texture.type === UnsignedIntType2) { + glInternalFormat = _gl.DEPTH_COMPONENT24; + } else if (texture.type === UnsignedInt248Type2) { + glInternalFormat = _gl.DEPTH24_STENCIL8; + } else { + glInternalFormat = _gl.DEPTH_COMPONENT16; + } + } else { + if (texture.type === FloatType2) { + console.error("WebGLRenderer: Floating point depth texture requires WebGL2."); + } + } + if (texture.format === DepthFormat2 && glInternalFormat === _gl.DEPTH_COMPONENT) { + if (texture.type !== UnsignedShortType2 && texture.type !== UnsignedIntType2) { + console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."); + texture.type = UnsignedIntType2; + glType = utils.convert(texture.type); + } + } + if (texture.format === DepthStencilFormat2 && glInternalFormat === _gl.DEPTH_COMPONENT) { + glInternalFormat = _gl.DEPTH_STENCIL; + if (texture.type !== UnsignedInt248Type2) { + console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."); + texture.type = UnsignedInt248Type2; + glType = utils.convert(texture.type); + } + } + if (allocateMemory) { + if (useTexStorage) { + state.texStorage2D(_gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height); + } else { + state.texImage2D(_gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null); + } + } + } else if (texture.isDataTexture) { + if (mipmaps.length > 0 && supportsMips) { + if (useTexStorage && allocateMemory) { + state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height); + } + for (let i = 0, il = mipmaps.length; i < il; i++) { + mipmap = mipmaps[i]; + if (useTexStorage) { + state.texSubImage2D(_gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data); + } else { + state.texImage2D(_gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data); + } + } + texture.generateMipmaps = false; + } else { + if (useTexStorage) { + if (allocateMemory) { + state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height); + } + state.texSubImage2D(_gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data); + } else { + state.texImage2D(_gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data); + } + } + } else if (texture.isCompressedTexture) { + if (useTexStorage && allocateMemory) { + state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height); + } + for (let i = 0, il = mipmaps.length; i < il; i++) { + mipmap = mipmaps[i]; + if (texture.format !== RGBAFormat2) { + if (glFormat !== null) { + if (useTexStorage) { + state.compressedTexSubImage2D(_gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data); + } else { + state.compressedTexImage2D(_gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data); + } + } else { + console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"); + } + } else { + if (useTexStorage) { + state.texSubImage2D(_gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data); + } else { + state.texImage2D(_gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data); + } + } + } + } else if (texture.isDataArrayTexture) { + if (useTexStorage) { + if (allocateMemory) { + state.texStorage3D(_gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth); + } + state.texSubImage3D(_gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data); + } else { + state.texImage3D(_gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data); + } + } else if (texture.isData3DTexture) { + if (useTexStorage) { + if (allocateMemory) { + state.texStorage3D(_gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth); + } + state.texSubImage3D(_gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data); + } else { + state.texImage3D(_gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data); + } + } else if (texture.isFramebufferTexture) { + if (allocateMemory) { + if (useTexStorage) { + state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height); + } else { + let width = image.width, height = image.height; + for (let i = 0; i < levels; i++) { + state.texImage2D(_gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null); + width >>= 1; + height >>= 1; + } + } + } + } else { + if (mipmaps.length > 0 && supportsMips) { + if (useTexStorage && allocateMemory) { + state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height); + } + for (let i = 0, il = mipmaps.length; i < il; i++) { + mipmap = mipmaps[i]; + if (useTexStorage) { + state.texSubImage2D(_gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap); + } else { + state.texImage2D(_gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap); + } + } + texture.generateMipmaps = false; + } else { + if (useTexStorage) { + if (allocateMemory) { + state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height); + } + state.texSubImage2D(_gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image); + } else { + state.texImage2D(_gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image); + } + } + } + if (textureNeedsGenerateMipmaps(texture, supportsMips)) { + generateMipmap(textureType); + } + source.__currentVersion = source.version; + if (texture.onUpdate) + texture.onUpdate(texture); + } + textureProperties.__version = texture.version; + } + function uploadCubeTexture(textureProperties, texture, slot) { + if (texture.image.length !== 6) + return; + const forceUpload = initTexture(textureProperties, texture); + const source = texture.source; + state.activeTexture(_gl.TEXTURE0 + slot); + state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture); + if (source.version !== source.__currentVersion || forceUpload === true) { + _gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, texture.flipY); + _gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha); + _gl.pixelStorei(_gl.UNPACK_ALIGNMENT, texture.unpackAlignment); + _gl.pixelStorei(_gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE); + const isCompressed = texture.isCompressedTexture || texture.image[0].isCompressedTexture; + const isDataTexture = texture.image[0] && texture.image[0].isDataTexture; + const cubeImage = []; + for (let i = 0; i < 6; i++) { + if (!isCompressed && !isDataTexture) { + cubeImage[i] = resizeImage(texture.image[i], false, true, maxCubemapSize); + } else { + cubeImage[i] = isDataTexture ? texture.image[i].image : texture.image[i]; + } + cubeImage[i] = verifyColorSpace(texture, cubeImage[i]); + } + const image = cubeImage[0], supportsMips = isPowerOfTwo$1(image) || isWebGL2, glFormat = utils.convert(texture.format, texture.encoding), glType = utils.convert(texture.type), glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); + const useTexStorage = isWebGL2 && texture.isVideoTexture !== true; + const allocateMemory = source.__currentVersion === void 0 || forceUpload === true; + let levels = getMipLevels(texture, image, supportsMips); + setTextureParameters(_gl.TEXTURE_CUBE_MAP, texture, supportsMips); + let mipmaps; + if (isCompressed) { + if (useTexStorage && allocateMemory) { + state.texStorage2D(_gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height); + } + for (let i = 0; i < 6; i++) { + mipmaps = cubeImage[i].mipmaps; + for (let j = 0; j < mipmaps.length; j++) { + const mipmap = mipmaps[j]; + if (texture.format !== RGBAFormat2) { + if (glFormat !== null) { + if (useTexStorage) { + state.compressedTexSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data); + } else { + state.compressedTexImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data); + } + } else { + console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"); + } + } else { + if (useTexStorage) { + state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data); + } else { + state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data); + } + } + } + } + } else { + mipmaps = texture.mipmaps; + if (useTexStorage && allocateMemory) { + if (mipmaps.length > 0) + levels++; + state.texStorage2D(_gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, cubeImage[0].width, cubeImage[0].height); + } + for (let i = 0; i < 6; i++) { + if (isDataTexture) { + if (useTexStorage) { + state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[i].width, cubeImage[i].height, glFormat, glType, cubeImage[i].data); + } else { + state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[i].width, cubeImage[i].height, 0, glFormat, glType, cubeImage[i].data); + } + for (let j = 0; j < mipmaps.length; j++) { + const mipmap = mipmaps[j]; + const mipmapImage = mipmap.image[i].image; + if (useTexStorage) { + state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data); + } else { + state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data); + } + } + } else { + if (useTexStorage) { + state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[i]); + } else { + state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[i]); + } + for (let j = 0; j < mipmaps.length; j++) { + const mipmap = mipmaps[j]; + if (useTexStorage) { + state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[i]); + } else { + state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[i]); + } + } + } + } + } + if (textureNeedsGenerateMipmaps(texture, supportsMips)) { + generateMipmap(_gl.TEXTURE_CUBE_MAP); + } + source.__currentVersion = source.version; + if (texture.onUpdate) + texture.onUpdate(texture); + } + textureProperties.__version = texture.version; + } + function setupFrameBufferTexture(framebuffer, renderTarget, texture, attachment, textureTarget) { + const glFormat = utils.convert(texture.format, texture.encoding); + const glType = utils.convert(texture.type); + const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); + const renderTargetProperties = properties.get(renderTarget); + if (!renderTargetProperties.__hasExternalTextures) { + if (textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY) { + state.texImage3D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null); + } else { + state.texImage2D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null); + } + } + state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer); + if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0, getRenderTargetSamples(renderTarget)); + } else { + _gl.framebufferTexture2D(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0); + } + state.bindFramebuffer(_gl.FRAMEBUFFER, null); + } + function setupRenderBufferStorage(renderbuffer, renderTarget, isMultisample) { + _gl.bindRenderbuffer(_gl.RENDERBUFFER, renderbuffer); + if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) { + let glInternalFormat = _gl.DEPTH_COMPONENT16; + if (isMultisample || useMultisampledRTT(renderTarget)) { + const depthTexture = renderTarget.depthTexture; + if (depthTexture && depthTexture.isDepthTexture) { + if (depthTexture.type === FloatType2) { + glInternalFormat = _gl.DEPTH_COMPONENT32F; + } else if (depthTexture.type === UnsignedIntType2) { + glInternalFormat = _gl.DEPTH_COMPONENT24; + } + } + const samples = getRenderTargetSamples(renderTarget); + if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.renderbufferStorageMultisampleEXT(_gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height); + } else { + _gl.renderbufferStorageMultisample(_gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height); + } + } else { + _gl.renderbufferStorage(_gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height); + } + _gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer); + } else if (renderTarget.depthBuffer && renderTarget.stencilBuffer) { + const samples = getRenderTargetSamples(renderTarget); + if (isMultisample && useMultisampledRTT(renderTarget) === false) { + _gl.renderbufferStorageMultisample(_gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height); + } else if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.renderbufferStorageMultisampleEXT(_gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height); + } else { + _gl.renderbufferStorage(_gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height); + } + _gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer); + } else { + const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [renderTarget.texture]; + for (let i = 0; i < textures.length; i++) { + const texture = textures[i]; + const glFormat = utils.convert(texture.format, texture.encoding); + const glType = utils.convert(texture.type); + const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); + const samples = getRenderTargetSamples(renderTarget); + if (isMultisample && useMultisampledRTT(renderTarget) === false) { + _gl.renderbufferStorageMultisample(_gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height); + } else if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.renderbufferStorageMultisampleEXT(_gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height); + } else { + _gl.renderbufferStorage(_gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height); + } + } + } + _gl.bindRenderbuffer(_gl.RENDERBUFFER, null); + } + function setupDepthTexture(framebuffer, renderTarget) { + const isCube = renderTarget && renderTarget.isWebGLCubeRenderTarget; + if (isCube) + throw new Error("Depth Texture with cube render targets is not supported"); + state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer); + if (!(renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture)) { + throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture"); + } + if (!properties.get(renderTarget.depthTexture).__webglTexture || renderTarget.depthTexture.image.width !== renderTarget.width || renderTarget.depthTexture.image.height !== renderTarget.height) { + renderTarget.depthTexture.image.width = renderTarget.width; + renderTarget.depthTexture.image.height = renderTarget.height; + renderTarget.depthTexture.needsUpdate = true; + } + setTexture2D(renderTarget.depthTexture, 0); + const webglDepthTexture = properties.get(renderTarget.depthTexture).__webglTexture; + const samples = getRenderTargetSamples(renderTarget); + if (renderTarget.depthTexture.format === DepthFormat2) { + if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples); + } else { + _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0); + } + } else if (renderTarget.depthTexture.format === DepthStencilFormat2) { + if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples); + } else { + _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0); + } + } else { + throw new Error("Unknown depthTexture format"); + } + } + function setupDepthRenderbuffer(renderTarget) { + const renderTargetProperties = properties.get(renderTarget); + const isCube = renderTarget.isWebGLCubeRenderTarget === true; + if (renderTarget.depthTexture && !renderTargetProperties.__autoAllocateDepthBuffer) { + if (isCube) + throw new Error("target.depthTexture not supported in Cube render targets"); + setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget); + } else { + if (isCube) { + renderTargetProperties.__webglDepthbuffer = []; + for (let i = 0; i < 6; i++) { + state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[i]); + renderTargetProperties.__webglDepthbuffer[i] = _gl.createRenderbuffer(); + setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer[i], renderTarget, false); + } + } else { + state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer); + renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer, renderTarget, false); + } + } + state.bindFramebuffer(_gl.FRAMEBUFFER, null); + } + function rebindTextures(renderTarget, colorTexture, depthTexture) { + const renderTargetProperties = properties.get(renderTarget); + if (colorTexture !== void 0) { + setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D); + } + if (depthTexture !== void 0) { + setupDepthRenderbuffer(renderTarget); + } + } + function setupRenderTarget(renderTarget) { + const texture = renderTarget.texture; + const renderTargetProperties = properties.get(renderTarget); + const textureProperties = properties.get(texture); + renderTarget.addEventListener("dispose", onRenderTargetDispose); + if (renderTarget.isWebGLMultipleRenderTargets !== true) { + if (textureProperties.__webglTexture === void 0) { + textureProperties.__webglTexture = _gl.createTexture(); + } + textureProperties.__version = texture.version; + info.memory.textures++; + } + const isCube = renderTarget.isWebGLCubeRenderTarget === true; + const isMultipleRenderTargets = renderTarget.isWebGLMultipleRenderTargets === true; + const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2; + if (isCube) { + renderTargetProperties.__webglFramebuffer = []; + for (let i = 0; i < 6; i++) { + renderTargetProperties.__webglFramebuffer[i] = _gl.createFramebuffer(); + } + } else { + renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); + if (isMultipleRenderTargets) { + if (capabilities.drawBuffers) { + const textures = renderTarget.texture; + for (let i = 0, il = textures.length; i < il; i++) { + const attachmentProperties = properties.get(textures[i]); + if (attachmentProperties.__webglTexture === void 0) { + attachmentProperties.__webglTexture = _gl.createTexture(); + info.memory.textures++; + } + } + } else { + console.warn("THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension."); + } + } + if (isWebGL2 && renderTarget.samples > 0 && useMultisampledRTT(renderTarget) === false) { + const textures = isMultipleRenderTargets ? texture : [texture]; + renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer(); + renderTargetProperties.__webglColorRenderbuffer = []; + state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer); + for (let i = 0; i < textures.length; i++) { + const texture2 = textures[i]; + renderTargetProperties.__webglColorRenderbuffer[i] = _gl.createRenderbuffer(); + _gl.bindRenderbuffer(_gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[i]); + const glFormat = utils.convert(texture2.format, texture2.encoding); + const glType = utils.convert(texture2.type); + const glInternalFormat = getInternalFormat(texture2.internalFormat, glFormat, glType, texture2.encoding); + const samples = getRenderTargetSamples(renderTarget); + _gl.renderbufferStorageMultisample(_gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height); + _gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[i]); + } + _gl.bindRenderbuffer(_gl.RENDERBUFFER, null); + if (renderTarget.depthBuffer) { + renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage(renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true); + } + state.bindFramebuffer(_gl.FRAMEBUFFER, null); + } + } + if (isCube) { + state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture); + setTextureParameters(_gl.TEXTURE_CUBE_MAP, texture, supportsMips); + for (let i = 0; i < 6; i++) { + setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[i], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i); + } + if (textureNeedsGenerateMipmaps(texture, supportsMips)) { + generateMipmap(_gl.TEXTURE_CUBE_MAP); + } + state.unbindTexture(); + } else if (isMultipleRenderTargets) { + const textures = renderTarget.texture; + for (let i = 0, il = textures.length; i < il; i++) { + const attachment = textures[i]; + const attachmentProperties = properties.get(attachment); + state.bindTexture(_gl.TEXTURE_2D, attachmentProperties.__webglTexture); + setTextureParameters(_gl.TEXTURE_2D, attachment, supportsMips); + setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D); + if (textureNeedsGenerateMipmaps(attachment, supportsMips)) { + generateMipmap(_gl.TEXTURE_2D); + } + } + state.unbindTexture(); + } else { + let glTextureType = _gl.TEXTURE_2D; + if (renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget) { + if (isWebGL2) { + glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY; + } else { + console.error("THREE.WebGLTextures: THREE.Data3DTexture and THREE.DataArrayTexture only supported with WebGL2."); + } + } + state.bindTexture(glTextureType, textureProperties.__webglTexture); + setTextureParameters(glTextureType, texture, supportsMips); + setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType); + if (textureNeedsGenerateMipmaps(texture, supportsMips)) { + generateMipmap(glTextureType); + } + state.unbindTexture(); + } + if (renderTarget.depthBuffer) { + setupDepthRenderbuffer(renderTarget); + } + } + function updateRenderTargetMipmap(renderTarget) { + const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2; + const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [renderTarget.texture]; + for (let i = 0, il = textures.length; i < il; i++) { + const texture = textures[i]; + if (textureNeedsGenerateMipmaps(texture, supportsMips)) { + const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; + const webglTexture = properties.get(texture).__webglTexture; + state.bindTexture(target, webglTexture); + generateMipmap(target); + state.unbindTexture(); + } + } + } + function updateMultisampleRenderTarget(renderTarget) { + if (isWebGL2 && renderTarget.samples > 0 && useMultisampledRTT(renderTarget) === false) { + const textures = renderTarget.isWebGLMultipleRenderTargets ? renderTarget.texture : [renderTarget.texture]; + const width = renderTarget.width; + const height = renderTarget.height; + let mask = _gl.COLOR_BUFFER_BIT; + const invalidationArray = []; + const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; + const renderTargetProperties = properties.get(renderTarget); + const isMultipleRenderTargets = renderTarget.isWebGLMultipleRenderTargets === true; + if (isMultipleRenderTargets) { + for (let i = 0; i < textures.length; i++) { + state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer); + _gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null); + state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer); + _gl.framebufferTexture2D(_gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0); + } + } + state.bindFramebuffer(_gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer); + state.bindFramebuffer(_gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer); + for (let i = 0; i < textures.length; i++) { + invalidationArray.push(_gl.COLOR_ATTACHMENT0 + i); + if (renderTarget.depthBuffer) { + invalidationArray.push(depthStyle); + } + const ignoreDepthValues = renderTargetProperties.__ignoreDepthValues !== void 0 ? renderTargetProperties.__ignoreDepthValues : false; + if (ignoreDepthValues === false) { + if (renderTarget.depthBuffer) + mask |= _gl.DEPTH_BUFFER_BIT; + if (renderTarget.stencilBuffer) + mask |= _gl.STENCIL_BUFFER_BIT; + } + if (isMultipleRenderTargets) { + _gl.framebufferRenderbuffer(_gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[i]); + } + if (ignoreDepthValues === true) { + _gl.invalidateFramebuffer(_gl.READ_FRAMEBUFFER, [depthStyle]); + _gl.invalidateFramebuffer(_gl.DRAW_FRAMEBUFFER, [depthStyle]); + } + if (isMultipleRenderTargets) { + const webglTexture = properties.get(textures[i]).__webglTexture; + _gl.framebufferTexture2D(_gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0); + } + _gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST); + if (supportsInvalidateFramebuffer) { + _gl.invalidateFramebuffer(_gl.READ_FRAMEBUFFER, invalidationArray); + } + } + state.bindFramebuffer(_gl.READ_FRAMEBUFFER, null); + state.bindFramebuffer(_gl.DRAW_FRAMEBUFFER, null); + if (isMultipleRenderTargets) { + for (let i = 0; i < textures.length; i++) { + state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer); + _gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[i]); + const webglTexture = properties.get(textures[i]).__webglTexture; + state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer); + _gl.framebufferTexture2D(_gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, webglTexture, 0); + } + } + state.bindFramebuffer(_gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer); + } + } + function getRenderTargetSamples(renderTarget) { + return Math.min(maxSamples, renderTarget.samples); + } + function useMultisampledRTT(renderTarget) { + const renderTargetProperties = properties.get(renderTarget); + return isWebGL2 && renderTarget.samples > 0 && extensions.has("WEBGL_multisampled_render_to_texture") === true && renderTargetProperties.__useRenderToTexture !== false; + } + function updateVideoTexture(texture) { + const frame2 = info.render.frame; + if (_videoTextures.get(texture) !== frame2) { + _videoTextures.set(texture, frame2); + texture.update(); + } + } + function verifyColorSpace(texture, image) { + const encoding = texture.encoding; + const format2 = texture.format; + const type2 = texture.type; + if (texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat2) + return image; + if (encoding !== LinearEncoding2) { + if (encoding === sRGBEncoding2) { + if (isWebGL2 === false) { + if (extensions.has("EXT_sRGB") === true && format2 === RGBAFormat2) { + texture.format = _SRGBAFormat2; + texture.minFilter = LinearFilter2; + texture.generateMipmaps = false; + } else { + image = ImageUtils2.sRGBToLinear(image); + } + } else { + if (format2 !== RGBAFormat2 || type2 !== UnsignedByteType2) { + console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."); + } + } + } else { + console.error("THREE.WebGLTextures: Unsupported texture encoding:", encoding); + } + } + return image; + } + this.allocateTextureUnit = allocateTextureUnit; + this.resetTextureUnits = resetTextureUnits; + this.setTexture2D = setTexture2D; + this.setTexture2DArray = setTexture2DArray; + this.setTexture3D = setTexture3D; + this.setTextureCube = setTextureCube; + this.rebindTextures = rebindTextures; + this.setupRenderTarget = setupRenderTarget; + this.updateRenderTargetMipmap = updateRenderTargetMipmap; + this.updateMultisampleRenderTarget = updateMultisampleRenderTarget; + this.setupDepthRenderbuffer = setupDepthRenderbuffer; + this.setupFrameBufferTexture = setupFrameBufferTexture; + this.useMultisampledRTT = useMultisampledRTT; + } + function WebGLUtils2(gl, extensions, capabilities) { + const isWebGL2 = capabilities.isWebGL2; + function convert(p, encoding = null) { + let extension; + if (p === UnsignedByteType2) + return gl.UNSIGNED_BYTE; + if (p === UnsignedShort4444Type2) + return gl.UNSIGNED_SHORT_4_4_4_4; + if (p === UnsignedShort5551Type2) + return gl.UNSIGNED_SHORT_5_5_5_1; + if (p === ByteType2) + return gl.BYTE; + if (p === ShortType2) + return gl.SHORT; + if (p === UnsignedShortType2) + return gl.UNSIGNED_SHORT; + if (p === IntType2) + return gl.INT; + if (p === UnsignedIntType2) + return gl.UNSIGNED_INT; + if (p === FloatType2) + return gl.FLOAT; + if (p === HalfFloatType2) { + if (isWebGL2) + return gl.HALF_FLOAT; + extension = extensions.get("OES_texture_half_float"); + if (extension !== null) { + return extension.HALF_FLOAT_OES; + } else { + return null; + } + } + if (p === AlphaFormat2) + return gl.ALPHA; + if (p === RGBAFormat2) + return gl.RGBA; + if (p === LuminanceFormat2) + return gl.LUMINANCE; + if (p === LuminanceAlphaFormat2) + return gl.LUMINANCE_ALPHA; + if (p === DepthFormat2) + return gl.DEPTH_COMPONENT; + if (p === DepthStencilFormat2) + return gl.DEPTH_STENCIL; + if (p === RedFormat2) + return gl.RED; + if (p === RGBFormat2) { + console.warn("THREE.WebGLRenderer: THREE.RGBFormat has been removed. Use THREE.RGBAFormat instead. https://github.com/mrdoob/three.js/pull/23228"); + return gl.RGBA; + } + if (p === _SRGBAFormat2) { + extension = extensions.get("EXT_sRGB"); + if (extension !== null) { + return extension.SRGB_ALPHA_EXT; + } else { + return null; + } + } + if (p === RedIntegerFormat2) + return gl.RED_INTEGER; + if (p === RGFormat2) + return gl.RG; + if (p === RGIntegerFormat2) + return gl.RG_INTEGER; + if (p === RGBAIntegerFormat2) + return gl.RGBA_INTEGER; + if (p === RGB_S3TC_DXT1_Format2 || p === RGBA_S3TC_DXT1_Format2 || p === RGBA_S3TC_DXT3_Format2 || p === RGBA_S3TC_DXT5_Format2) { + if (encoding === sRGBEncoding2) { + extension = extensions.get("WEBGL_compressed_texture_s3tc_srgb"); + if (extension !== null) { + if (p === RGB_S3TC_DXT1_Format2) + return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT1_Format2) + return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT3_Format2) + return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + if (p === RGBA_S3TC_DXT5_Format2) + return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + } else { + return null; + } + } else { + extension = extensions.get("WEBGL_compressed_texture_s3tc"); + if (extension !== null) { + if (p === RGB_S3TC_DXT1_Format2) + return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT1_Format2) + return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT3_Format2) + return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; + if (p === RGBA_S3TC_DXT5_Format2) + return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + } else { + return null; + } + } + } + if (p === RGB_PVRTC_4BPPV1_Format2 || p === RGB_PVRTC_2BPPV1_Format2 || p === RGBA_PVRTC_4BPPV1_Format2 || p === RGBA_PVRTC_2BPPV1_Format2) { + extension = extensions.get("WEBGL_compressed_texture_pvrtc"); + if (extension !== null) { + if (p === RGB_PVRTC_4BPPV1_Format2) + return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; + if (p === RGB_PVRTC_2BPPV1_Format2) + return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; + if (p === RGBA_PVRTC_4BPPV1_Format2) + return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; + if (p === RGBA_PVRTC_2BPPV1_Format2) + return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + } else { + return null; + } + } + if (p === RGB_ETC1_Format2) { + extension = extensions.get("WEBGL_compressed_texture_etc1"); + if (extension !== null) { + return extension.COMPRESSED_RGB_ETC1_WEBGL; + } else { + return null; + } + } + if (p === RGB_ETC2_Format2 || p === RGBA_ETC2_EAC_Format2) { + extension = extensions.get("WEBGL_compressed_texture_etc"); + if (extension !== null) { + if (p === RGB_ETC2_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if (p === RGBA_ETC2_EAC_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + } else { + return null; + } + } + if (p === RGBA_ASTC_4x4_Format2 || p === RGBA_ASTC_5x4_Format2 || p === RGBA_ASTC_5x5_Format2 || p === RGBA_ASTC_6x5_Format2 || p === RGBA_ASTC_6x6_Format2 || p === RGBA_ASTC_8x5_Format2 || p === RGBA_ASTC_8x6_Format2 || p === RGBA_ASTC_8x8_Format2 || p === RGBA_ASTC_10x5_Format2 || p === RGBA_ASTC_10x6_Format2 || p === RGBA_ASTC_10x8_Format2 || p === RGBA_ASTC_10x10_Format2 || p === RGBA_ASTC_12x10_Format2 || p === RGBA_ASTC_12x12_Format2) { + extension = extensions.get("WEBGL_compressed_texture_astc"); + if (extension !== null) { + if (p === RGBA_ASTC_4x4_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if (p === RGBA_ASTC_5x4_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if (p === RGBA_ASTC_5x5_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if (p === RGBA_ASTC_6x5_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if (p === RGBA_ASTC_6x6_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if (p === RGBA_ASTC_8x5_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if (p === RGBA_ASTC_8x6_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if (p === RGBA_ASTC_8x8_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if (p === RGBA_ASTC_10x5_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if (p === RGBA_ASTC_10x6_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if (p === RGBA_ASTC_10x8_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if (p === RGBA_ASTC_10x10_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if (p === RGBA_ASTC_12x10_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if (p === RGBA_ASTC_12x12_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; + } else { + return null; + } + } + if (p === RGBA_BPTC_Format2) { + extension = extensions.get("EXT_texture_compression_bptc"); + if (extension !== null) { + if (p === RGBA_BPTC_Format2) + return encoding === sRGBEncoding2 ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; + } else { + return null; + } + } + if (p === UnsignedInt248Type2) { + if (isWebGL2) + return gl.UNSIGNED_INT_24_8; + extension = extensions.get("WEBGL_depth_texture"); + if (extension !== null) { + return extension.UNSIGNED_INT_24_8_WEBGL; + } else { + return null; + } + } + return gl[p] !== void 0 ? gl[p] : null; + } + return { + convert + }; + } + var ArrayCamera2 = class extends PerspectiveCamera2 { + constructor(array2 = []) { + super(); + this.isArrayCamera = true; + this.cameras = array2; + } + }; + var Group2 = class extends Object3D2 { + constructor() { + super(); + this.isGroup = true; + this.type = "Group"; + } + }; + var _moveEvent2 = { + type: "move" + }; + var WebXRController2 = class { + constructor() { + this._targetRay = null; + this._grip = null; + this._hand = null; + } + getHandSpace() { + if (this._hand === null) { + this._hand = new Group2(); + this._hand.matrixAutoUpdate = false; + this._hand.visible = false; + this._hand.joints = {}; + this._hand.inputState = { + pinching: false + }; + } + return this._hand; + } + getTargetRaySpace() { + if (this._targetRay === null) { + this._targetRay = new Group2(); + this._targetRay.matrixAutoUpdate = false; + this._targetRay.visible = false; + this._targetRay.hasLinearVelocity = false; + this._targetRay.linearVelocity = new Vector32(); + this._targetRay.hasAngularVelocity = false; + this._targetRay.angularVelocity = new Vector32(); + } + return this._targetRay; + } + getGripSpace() { + if (this._grip === null) { + this._grip = new Group2(); + this._grip.matrixAutoUpdate = false; + this._grip.visible = false; + this._grip.hasLinearVelocity = false; + this._grip.linearVelocity = new Vector32(); + this._grip.hasAngularVelocity = false; + this._grip.angularVelocity = new Vector32(); + } + return this._grip; + } + dispatchEvent(event) { + if (this._targetRay !== null) { + this._targetRay.dispatchEvent(event); + } + if (this._grip !== null) { + this._grip.dispatchEvent(event); + } + if (this._hand !== null) { + this._hand.dispatchEvent(event); + } + return this; + } + disconnect(inputSource) { + this.dispatchEvent({ + type: "disconnected", + data: inputSource + }); + if (this._targetRay !== null) { + this._targetRay.visible = false; + } + if (this._grip !== null) { + this._grip.visible = false; + } + if (this._hand !== null) { + this._hand.visible = false; + } + return this; + } + update(inputSource, frame2, referenceSpace) { + let inputPose = null; + let gripPose = null; + let handPose = null; + const targetRay = this._targetRay; + const grip = this._grip; + const hand = this._hand; + if (inputSource && frame2.session.visibilityState !== "visible-blurred") { + if (hand && inputSource.hand) { + handPose = true; + for (const inputjoint of inputSource.hand.values()) { + const jointPose = frame2.getJointPose(inputjoint, referenceSpace); + if (hand.joints[inputjoint.jointName] === void 0) { + const joint2 = new Group2(); + joint2.matrixAutoUpdate = false; + joint2.visible = false; + hand.joints[inputjoint.jointName] = joint2; + hand.add(joint2); + } + const joint = hand.joints[inputjoint.jointName]; + if (jointPose !== null) { + joint.matrix.fromArray(jointPose.transform.matrix); + joint.matrix.decompose(joint.position, joint.rotation, joint.scale); + joint.jointRadius = jointPose.radius; + } + joint.visible = jointPose !== null; + } + const indexTip = hand.joints["index-finger-tip"]; + const thumbTip = hand.joints["thumb-tip"]; + const distance = indexTip.position.distanceTo(thumbTip.position); + const distanceToPinch = 0.02; + const threshold = 5e-3; + if (hand.inputState.pinching && distance > distanceToPinch + threshold) { + hand.inputState.pinching = false; + this.dispatchEvent({ + type: "pinchend", + handedness: inputSource.handedness, + target: this + }); + } else if (!hand.inputState.pinching && distance <= distanceToPinch - threshold) { + hand.inputState.pinching = true; + this.dispatchEvent({ + type: "pinchstart", + handedness: inputSource.handedness, + target: this + }); + } + } else { + if (grip !== null && inputSource.gripSpace) { + gripPose = frame2.getPose(inputSource.gripSpace, referenceSpace); + if (gripPose !== null) { + grip.matrix.fromArray(gripPose.transform.matrix); + grip.matrix.decompose(grip.position, grip.rotation, grip.scale); + if (gripPose.linearVelocity) { + grip.hasLinearVelocity = true; + grip.linearVelocity.copy(gripPose.linearVelocity); + } else { + grip.hasLinearVelocity = false; + } + if (gripPose.angularVelocity) { + grip.hasAngularVelocity = true; + grip.angularVelocity.copy(gripPose.angularVelocity); + } else { + grip.hasAngularVelocity = false; + } + } + } + } + if (targetRay !== null) { + inputPose = frame2.getPose(inputSource.targetRaySpace, referenceSpace); + if (inputPose === null && gripPose !== null) { + inputPose = gripPose; + } + if (inputPose !== null) { + targetRay.matrix.fromArray(inputPose.transform.matrix); + targetRay.matrix.decompose(targetRay.position, targetRay.rotation, targetRay.scale); + if (inputPose.linearVelocity) { + targetRay.hasLinearVelocity = true; + targetRay.linearVelocity.copy(inputPose.linearVelocity); + } else { + targetRay.hasLinearVelocity = false; + } + if (inputPose.angularVelocity) { + targetRay.hasAngularVelocity = true; + targetRay.angularVelocity.copy(inputPose.angularVelocity); + } else { + targetRay.hasAngularVelocity = false; + } + this.dispatchEvent(_moveEvent2); + } + } + } + if (targetRay !== null) { + targetRay.visible = inputPose !== null; + } + if (grip !== null) { + grip.visible = gripPose !== null; + } + if (hand !== null) { + hand.visible = handPose !== null; + } + return this; + } + }; + var DepthTexture2 = class extends Texture2 { + constructor(width, height, type2, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format2) { + format2 = format2 !== void 0 ? format2 : DepthFormat2; + if (format2 !== DepthFormat2 && format2 !== DepthStencilFormat2) { + throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat"); + } + if (type2 === void 0 && format2 === DepthFormat2) + type2 = UnsignedIntType2; + if (type2 === void 0 && format2 === DepthStencilFormat2) + type2 = UnsignedInt248Type2; + super(null, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy); + this.isDepthTexture = true; + this.image = { + width, + height + }; + this.magFilter = magFilter !== void 0 ? magFilter : NearestFilter2; + this.minFilter = minFilter !== void 0 ? minFilter : NearestFilter2; + this.flipY = false; + this.generateMipmaps = false; + } + }; + var WebXRManager2 = class extends EventDispatcher2 { + constructor(renderer, gl) { + super(); + const scope = this; + let session = null; + let framebufferScaleFactor = 1; + let referenceSpace = null; + let referenceSpaceType = "local-floor"; + let customReferenceSpace = null; + let pose = null; + let glBinding = null; + let glProjLayer = null; + let glBaseLayer = null; + let xrFrame = null; + const attributes = gl.getContextAttributes(); + let initialRenderTarget = null; + let newRenderTarget = null; + const controllers = []; + const controllerInputSources = []; + const cameraL = new PerspectiveCamera2(); + cameraL.layers.enable(1); + cameraL.viewport = new Vector42(); + const cameraR = new PerspectiveCamera2(); + cameraR.layers.enable(2); + cameraR.viewport = new Vector42(); + const cameras = [cameraL, cameraR]; + const cameraVR = new ArrayCamera2(); + cameraVR.layers.enable(1); + cameraVR.layers.enable(2); + let _currentDepthNear = null; + let _currentDepthFar = null; + this.cameraAutoUpdate = true; + this.enabled = false; + this.isPresenting = false; + this.getController = function(index2) { + let controller = controllers[index2]; + if (controller === void 0) { + controller = new WebXRController2(); + controllers[index2] = controller; + } + return controller.getTargetRaySpace(); + }; + this.getControllerGrip = function(index2) { + let controller = controllers[index2]; + if (controller === void 0) { + controller = new WebXRController2(); + controllers[index2] = controller; + } + return controller.getGripSpace(); + }; + this.getHand = function(index2) { + let controller = controllers[index2]; + if (controller === void 0) { + controller = new WebXRController2(); + controllers[index2] = controller; + } + return controller.getHandSpace(); + }; + function onSessionEvent(event) { + const controllerIndex = controllerInputSources.indexOf(event.inputSource); + if (controllerIndex === -1) { + return; + } + const controller = controllers[controllerIndex]; + if (controller !== void 0) { + controller.dispatchEvent({ + type: event.type, + data: event.inputSource + }); + } + } + function onSessionEnd() { + session.removeEventListener("select", onSessionEvent); + session.removeEventListener("selectstart", onSessionEvent); + session.removeEventListener("selectend", onSessionEvent); + session.removeEventListener("squeeze", onSessionEvent); + session.removeEventListener("squeezestart", onSessionEvent); + session.removeEventListener("squeezeend", onSessionEvent); + session.removeEventListener("end", onSessionEnd); + session.removeEventListener("inputsourceschange", onInputSourcesChange); + for (let i = 0; i < controllers.length; i++) { + const inputSource = controllerInputSources[i]; + if (inputSource === null) + continue; + controllerInputSources[i] = null; + controllers[i].disconnect(inputSource); + } + _currentDepthNear = null; + _currentDepthFar = null; + renderer.setRenderTarget(initialRenderTarget); + glBaseLayer = null; + glProjLayer = null; + glBinding = null; + session = null; + newRenderTarget = null; + animation.stop(); + scope.isPresenting = false; + scope.dispatchEvent({ + type: "sessionend" + }); + } + this.setFramebufferScaleFactor = function(value) { + framebufferScaleFactor = value; + if (scope.isPresenting === true) { + console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting."); + } + }; + this.setReferenceSpaceType = function(value) { + referenceSpaceType = value; + if (scope.isPresenting === true) { + console.warn("THREE.WebXRManager: Cannot change reference space type while presenting."); + } + }; + this.getReferenceSpace = function() { + return customReferenceSpace || referenceSpace; + }; + this.setReferenceSpace = function(space) { + customReferenceSpace = space; + }; + this.getBaseLayer = function() { + return glProjLayer !== null ? glProjLayer : glBaseLayer; + }; + this.getBinding = function() { + return glBinding; + }; + this.getFrame = function() { + return xrFrame; + }; + this.getSession = function() { + return session; + }; + this.setSession = async function(value) { + session = value; + if (session !== null) { + initialRenderTarget = renderer.getRenderTarget(); + session.addEventListener("select", onSessionEvent); + session.addEventListener("selectstart", onSessionEvent); + session.addEventListener("selectend", onSessionEvent); + session.addEventListener("squeeze", onSessionEvent); + session.addEventListener("squeezestart", onSessionEvent); + session.addEventListener("squeezeend", onSessionEvent); + session.addEventListener("end", onSessionEnd); + session.addEventListener("inputsourceschange", onInputSourcesChange); + if (attributes.xrCompatible !== true) { + await gl.makeXRCompatible(); + } + if (session.renderState.layers === void 0 || renderer.capabilities.isWebGL2 === false) { + const layerInit = { + antialias: session.renderState.layers === void 0 ? attributes.antialias : true, + alpha: attributes.alpha, + depth: attributes.depth, + stencil: attributes.stencil, + framebufferScaleFactor + }; + glBaseLayer = new XRWebGLLayer(session, gl, layerInit); + session.updateRenderState({ + baseLayer: glBaseLayer + }); + newRenderTarget = new WebGLRenderTarget2(glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, { + format: RGBAFormat2, + type: UnsignedByteType2, + encoding: renderer.outputEncoding + }); + } else { + let depthFormat = null; + let depthType = null; + let glDepthFormat = null; + if (attributes.depth) { + glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24; + depthFormat = attributes.stencil ? DepthStencilFormat2 : DepthFormat2; + depthType = attributes.stencil ? UnsignedInt248Type2 : UnsignedIntType2; + } + const projectionlayerInit = { + colorFormat: gl.RGBA8, + depthFormat: glDepthFormat, + scaleFactor: framebufferScaleFactor + }; + glBinding = new XRWebGLBinding(session, gl); + glProjLayer = glBinding.createProjectionLayer(projectionlayerInit); + session.updateRenderState({ + layers: [glProjLayer] + }); + newRenderTarget = new WebGLRenderTarget2(glProjLayer.textureWidth, glProjLayer.textureHeight, { + format: RGBAFormat2, + type: UnsignedByteType2, + depthTexture: new DepthTexture2(glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, void 0, void 0, void 0, void 0, void 0, void 0, depthFormat), + stencilBuffer: attributes.stencil, + encoding: renderer.outputEncoding, + samples: attributes.antialias ? 4 : 0 + }); + const renderTargetProperties = renderer.properties.get(newRenderTarget); + renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues; + } + newRenderTarget.isXRRenderTarget = true; + this.setFoveation(1); + customReferenceSpace = null; + referenceSpace = await session.requestReferenceSpace(referenceSpaceType); + animation.setContext(session); + animation.start(); + scope.isPresenting = true; + scope.dispatchEvent({ + type: "sessionstart" + }); + } + }; + function onInputSourcesChange(event) { + for (let i = 0; i < event.removed.length; i++) { + const inputSource = event.removed[i]; + const index2 = controllerInputSources.indexOf(inputSource); + if (index2 >= 0) { + controllerInputSources[index2] = null; + controllers[index2].dispatchEvent({ + type: "disconnected", + data: inputSource + }); + } + } + for (let i = 0; i < event.added.length; i++) { + const inputSource = event.added[i]; + let controllerIndex = controllerInputSources.indexOf(inputSource); + if (controllerIndex === -1) { + for (let i2 = 0; i2 < controllers.length; i2++) { + if (i2 >= controllerInputSources.length) { + controllerInputSources.push(inputSource); + controllerIndex = i2; + break; + } else if (controllerInputSources[i2] === null) { + controllerInputSources[i2] = inputSource; + controllerIndex = i2; + break; + } + } + if (controllerIndex === -1) + break; + } + const controller = controllers[controllerIndex]; + if (controller) { + controller.dispatchEvent({ + type: "connected", + data: inputSource + }); + } + } + } + const cameraLPos = new Vector32(); + const cameraRPos = new Vector32(); + function setProjectionFromUnion(camera, cameraL2, cameraR2) { + cameraLPos.setFromMatrixPosition(cameraL2.matrixWorld); + cameraRPos.setFromMatrixPosition(cameraR2.matrixWorld); + const ipd = cameraLPos.distanceTo(cameraRPos); + const projL = cameraL2.projectionMatrix.elements; + const projR = cameraR2.projectionMatrix.elements; + const near = projL[14] / (projL[10] - 1); + const far = projL[14] / (projL[10] + 1); + const topFov = (projL[9] + 1) / projL[5]; + const bottomFov = (projL[9] - 1) / projL[5]; + const leftFov = (projL[8] - 1) / projL[0]; + const rightFov = (projR[8] + 1) / projR[0]; + const left = near * leftFov; + const right = near * rightFov; + const zOffset = ipd / (-leftFov + rightFov); + const xOffset = zOffset * -leftFov; + cameraL2.matrixWorld.decompose(camera.position, camera.quaternion, camera.scale); + camera.translateX(xOffset); + camera.translateZ(zOffset); + camera.matrixWorld.compose(camera.position, camera.quaternion, camera.scale); + camera.matrixWorldInverse.copy(camera.matrixWorld).invert(); + const near2 = near + zOffset; + const far2 = far + zOffset; + const left2 = left - xOffset; + const right2 = right + (ipd - xOffset); + const top2 = topFov * far / far2 * near2; + const bottom2 = bottomFov * far / far2 * near2; + camera.projectionMatrix.makePerspective(left2, right2, top2, bottom2, near2, far2); + } + function updateCamera(camera, parent) { + if (parent === null) { + camera.matrixWorld.copy(camera.matrix); + } else { + camera.matrixWorld.multiplyMatrices(parent.matrixWorld, camera.matrix); + } + camera.matrixWorldInverse.copy(camera.matrixWorld).invert(); + } + this.updateCamera = function(camera) { + if (session === null) + return; + cameraVR.near = cameraR.near = cameraL.near = camera.near; + cameraVR.far = cameraR.far = cameraL.far = camera.far; + if (_currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far) { + session.updateRenderState({ + depthNear: cameraVR.near, + depthFar: cameraVR.far + }); + _currentDepthNear = cameraVR.near; + _currentDepthFar = cameraVR.far; + } + const parent = camera.parent; + const cameras2 = cameraVR.cameras; + updateCamera(cameraVR, parent); + for (let i = 0; i < cameras2.length; i++) { + updateCamera(cameras2[i], parent); + } + cameraVR.matrixWorld.decompose(cameraVR.position, cameraVR.quaternion, cameraVR.scale); + camera.position.copy(cameraVR.position); + camera.quaternion.copy(cameraVR.quaternion); + camera.scale.copy(cameraVR.scale); + camera.matrix.copy(cameraVR.matrix); + camera.matrixWorld.copy(cameraVR.matrixWorld); + const children2 = camera.children; + for (let i = 0, l = children2.length; i < l; i++) { + children2[i].updateMatrixWorld(true); + } + if (cameras2.length === 2) { + setProjectionFromUnion(cameraVR, cameraL, cameraR); + } else { + cameraVR.projectionMatrix.copy(cameraL.projectionMatrix); + } + }; + this.getCamera = function() { + return cameraVR; + }; + this.getFoveation = function() { + if (glProjLayer !== null) { + return glProjLayer.fixedFoveation; + } + if (glBaseLayer !== null) { + return glBaseLayer.fixedFoveation; + } + return void 0; + }; + this.setFoveation = function(foveation) { + if (glProjLayer !== null) { + glProjLayer.fixedFoveation = foveation; + } + if (glBaseLayer !== null && glBaseLayer.fixedFoveation !== void 0) { + glBaseLayer.fixedFoveation = foveation; + } + }; + let onAnimationFrameCallback = null; + function onAnimationFrame(time, frame2) { + pose = frame2.getViewerPose(customReferenceSpace || referenceSpace); + xrFrame = frame2; + if (pose !== null) { + const views = pose.views; + if (glBaseLayer !== null) { + renderer.setRenderTargetFramebuffer(newRenderTarget, glBaseLayer.framebuffer); + renderer.setRenderTarget(newRenderTarget); + } + let cameraVRNeedsUpdate = false; + if (views.length !== cameraVR.cameras.length) { + cameraVR.cameras.length = 0; + cameraVRNeedsUpdate = true; + } + for (let i = 0; i < views.length; i++) { + const view = views[i]; + let viewport = null; + if (glBaseLayer !== null) { + viewport = glBaseLayer.getViewport(view); + } else { + const glSubImage = glBinding.getViewSubImage(glProjLayer, view); + viewport = glSubImage.viewport; + if (i === 0) { + renderer.setRenderTargetTextures(newRenderTarget, glSubImage.colorTexture, glProjLayer.ignoreDepthValues ? void 0 : glSubImage.depthStencilTexture); + renderer.setRenderTarget(newRenderTarget); + } + } + let camera = cameras[i]; + if (camera === void 0) { + camera = new PerspectiveCamera2(); + camera.layers.enable(i); + camera.viewport = new Vector42(); + cameras[i] = camera; + } + camera.matrix.fromArray(view.transform.matrix); + camera.projectionMatrix.fromArray(view.projectionMatrix); + camera.viewport.set(viewport.x, viewport.y, viewport.width, viewport.height); + if (i === 0) { + cameraVR.matrix.copy(camera.matrix); + } + if (cameraVRNeedsUpdate === true) { + cameraVR.cameras.push(camera); + } + } + } + for (let i = 0; i < controllers.length; i++) { + const inputSource = controllerInputSources[i]; + const controller = controllers[i]; + if (inputSource !== null && controller !== void 0) { + controller.update(inputSource, frame2, customReferenceSpace || referenceSpace); + } + } + if (onAnimationFrameCallback) + onAnimationFrameCallback(time, frame2); + xrFrame = null; + } + const animation = new WebGLAnimation2(); + animation.setAnimationLoop(onAnimationFrame); + this.setAnimationLoop = function(callback) { + onAnimationFrameCallback = callback; + }; + this.dispose = function() { + }; + } + }; + function WebGLMaterials2(renderer, properties) { + function refreshFogUniforms(uniforms, fog) { + uniforms.fogColor.value.copy(fog.color); + if (fog.isFog) { + uniforms.fogNear.value = fog.near; + uniforms.fogFar.value = fog.far; + } else if (fog.isFogExp2) { + uniforms.fogDensity.value = fog.density; + } + } + function refreshMaterialUniforms(uniforms, material, pixelRatio, height, transmissionRenderTarget) { + if (material.isMeshBasicMaterial) { + refreshUniformsCommon(uniforms, material); + } else if (material.isMeshLambertMaterial) { + refreshUniformsCommon(uniforms, material); + } else if (material.isMeshToonMaterial) { + refreshUniformsCommon(uniforms, material); + refreshUniformsToon(uniforms, material); + } else if (material.isMeshPhongMaterial) { + refreshUniformsCommon(uniforms, material); + refreshUniformsPhong(uniforms, material); + } else if (material.isMeshStandardMaterial) { + refreshUniformsCommon(uniforms, material); + refreshUniformsStandard(uniforms, material); + if (material.isMeshPhysicalMaterial) { + refreshUniformsPhysical(uniforms, material, transmissionRenderTarget); + } + } else if (material.isMeshMatcapMaterial) { + refreshUniformsCommon(uniforms, material); + refreshUniformsMatcap(uniforms, material); + } else if (material.isMeshDepthMaterial) { + refreshUniformsCommon(uniforms, material); + } else if (material.isMeshDistanceMaterial) { + refreshUniformsCommon(uniforms, material); + refreshUniformsDistance(uniforms, material); + } else if (material.isMeshNormalMaterial) { + refreshUniformsCommon(uniforms, material); + } else if (material.isLineBasicMaterial) { + refreshUniformsLine(uniforms, material); + if (material.isLineDashedMaterial) { + refreshUniformsDash(uniforms, material); + } + } else if (material.isPointsMaterial) { + refreshUniformsPoints(uniforms, material, pixelRatio, height); + } else if (material.isSpriteMaterial) { + refreshUniformsSprites(uniforms, material); + } else if (material.isShadowMaterial) { + uniforms.color.value.copy(material.color); + uniforms.opacity.value = material.opacity; + } else if (material.isShaderMaterial) { + material.uniformsNeedUpdate = false; + } + } + function refreshUniformsCommon(uniforms, material) { + uniforms.opacity.value = material.opacity; + if (material.color) { + uniforms.diffuse.value.copy(material.color); + } + if (material.emissive) { + uniforms.emissive.value.copy(material.emissive).multiplyScalar(material.emissiveIntensity); + } + if (material.map) { + uniforms.map.value = material.map; + } + if (material.alphaMap) { + uniforms.alphaMap.value = material.alphaMap; + } + if (material.bumpMap) { + uniforms.bumpMap.value = material.bumpMap; + uniforms.bumpScale.value = material.bumpScale; + if (material.side === BackSide2) + uniforms.bumpScale.value *= -1; + } + if (material.displacementMap) { + uniforms.displacementMap.value = material.displacementMap; + uniforms.displacementScale.value = material.displacementScale; + uniforms.displacementBias.value = material.displacementBias; + } + if (material.emissiveMap) { + uniforms.emissiveMap.value = material.emissiveMap; + } + if (material.normalMap) { + uniforms.normalMap.value = material.normalMap; + uniforms.normalScale.value.copy(material.normalScale); + if (material.side === BackSide2) + uniforms.normalScale.value.negate(); + } + if (material.specularMap) { + uniforms.specularMap.value = material.specularMap; + } + if (material.alphaTest > 0) { + uniforms.alphaTest.value = material.alphaTest; + } + const envMap = properties.get(material).envMap; + if (envMap) { + uniforms.envMap.value = envMap; + uniforms.flipEnvMap.value = envMap.isCubeTexture && envMap.isRenderTargetTexture === false ? -1 : 1; + uniforms.reflectivity.value = material.reflectivity; + uniforms.ior.value = material.ior; + uniforms.refractionRatio.value = material.refractionRatio; + } + if (material.lightMap) { + uniforms.lightMap.value = material.lightMap; + const scaleFactor = renderer.physicallyCorrectLights !== true ? Math.PI : 1; + uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor; + } + if (material.aoMap) { + uniforms.aoMap.value = material.aoMap; + uniforms.aoMapIntensity.value = material.aoMapIntensity; + } + let uvScaleMap; + if (material.map) { + uvScaleMap = material.map; + } else if (material.specularMap) { + uvScaleMap = material.specularMap; + } else if (material.displacementMap) { + uvScaleMap = material.displacementMap; + } else if (material.normalMap) { + uvScaleMap = material.normalMap; + } else if (material.bumpMap) { + uvScaleMap = material.bumpMap; + } else if (material.roughnessMap) { + uvScaleMap = material.roughnessMap; + } else if (material.metalnessMap) { + uvScaleMap = material.metalnessMap; + } else if (material.alphaMap) { + uvScaleMap = material.alphaMap; + } else if (material.emissiveMap) { + uvScaleMap = material.emissiveMap; + } else if (material.clearcoatMap) { + uvScaleMap = material.clearcoatMap; + } else if (material.clearcoatNormalMap) { + uvScaleMap = material.clearcoatNormalMap; + } else if (material.clearcoatRoughnessMap) { + uvScaleMap = material.clearcoatRoughnessMap; + } else if (material.iridescenceMap) { + uvScaleMap = material.iridescenceMap; + } else if (material.iridescenceThicknessMap) { + uvScaleMap = material.iridescenceThicknessMap; + } else if (material.specularIntensityMap) { + uvScaleMap = material.specularIntensityMap; + } else if (material.specularColorMap) { + uvScaleMap = material.specularColorMap; + } else if (material.transmissionMap) { + uvScaleMap = material.transmissionMap; + } else if (material.thicknessMap) { + uvScaleMap = material.thicknessMap; + } else if (material.sheenColorMap) { + uvScaleMap = material.sheenColorMap; + } else if (material.sheenRoughnessMap) { + uvScaleMap = material.sheenRoughnessMap; + } + if (uvScaleMap !== void 0) { + if (uvScaleMap.isWebGLRenderTarget) { + uvScaleMap = uvScaleMap.texture; + } + if (uvScaleMap.matrixAutoUpdate === true) { + uvScaleMap.updateMatrix(); + } + uniforms.uvTransform.value.copy(uvScaleMap.matrix); + } + let uv2ScaleMap; + if (material.aoMap) { + uv2ScaleMap = material.aoMap; + } else if (material.lightMap) { + uv2ScaleMap = material.lightMap; + } + if (uv2ScaleMap !== void 0) { + if (uv2ScaleMap.isWebGLRenderTarget) { + uv2ScaleMap = uv2ScaleMap.texture; + } + if (uv2ScaleMap.matrixAutoUpdate === true) { + uv2ScaleMap.updateMatrix(); + } + uniforms.uv2Transform.value.copy(uv2ScaleMap.matrix); + } + } + function refreshUniformsLine(uniforms, material) { + uniforms.diffuse.value.copy(material.color); + uniforms.opacity.value = material.opacity; + } + function refreshUniformsDash(uniforms, material) { + uniforms.dashSize.value = material.dashSize; + uniforms.totalSize.value = material.dashSize + material.gapSize; + uniforms.scale.value = material.scale; + } + function refreshUniformsPoints(uniforms, material, pixelRatio, height) { + uniforms.diffuse.value.copy(material.color); + uniforms.opacity.value = material.opacity; + uniforms.size.value = material.size * pixelRatio; + uniforms.scale.value = height * 0.5; + if (material.map) { + uniforms.map.value = material.map; + } + if (material.alphaMap) { + uniforms.alphaMap.value = material.alphaMap; + } + if (material.alphaTest > 0) { + uniforms.alphaTest.value = material.alphaTest; + } + let uvScaleMap; + if (material.map) { + uvScaleMap = material.map; + } else if (material.alphaMap) { + uvScaleMap = material.alphaMap; + } + if (uvScaleMap !== void 0) { + if (uvScaleMap.matrixAutoUpdate === true) { + uvScaleMap.updateMatrix(); + } + uniforms.uvTransform.value.copy(uvScaleMap.matrix); + } + } + function refreshUniformsSprites(uniforms, material) { + uniforms.diffuse.value.copy(material.color); + uniforms.opacity.value = material.opacity; + uniforms.rotation.value = material.rotation; + if (material.map) { + uniforms.map.value = material.map; + } + if (material.alphaMap) { + uniforms.alphaMap.value = material.alphaMap; + } + if (material.alphaTest > 0) { + uniforms.alphaTest.value = material.alphaTest; + } + let uvScaleMap; + if (material.map) { + uvScaleMap = material.map; + } else if (material.alphaMap) { + uvScaleMap = material.alphaMap; + } + if (uvScaleMap !== void 0) { + if (uvScaleMap.matrixAutoUpdate === true) { + uvScaleMap.updateMatrix(); + } + uniforms.uvTransform.value.copy(uvScaleMap.matrix); + } + } + function refreshUniformsPhong(uniforms, material) { + uniforms.specular.value.copy(material.specular); + uniforms.shininess.value = Math.max(material.shininess, 1e-4); + } + function refreshUniformsToon(uniforms, material) { + if (material.gradientMap) { + uniforms.gradientMap.value = material.gradientMap; + } + } + function refreshUniformsStandard(uniforms, material) { + uniforms.roughness.value = material.roughness; + uniforms.metalness.value = material.metalness; + if (material.roughnessMap) { + uniforms.roughnessMap.value = material.roughnessMap; + } + if (material.metalnessMap) { + uniforms.metalnessMap.value = material.metalnessMap; + } + const envMap = properties.get(material).envMap; + if (envMap) { + uniforms.envMapIntensity.value = material.envMapIntensity; + } + } + function refreshUniformsPhysical(uniforms, material, transmissionRenderTarget) { + uniforms.ior.value = material.ior; + if (material.sheen > 0) { + uniforms.sheenColor.value.copy(material.sheenColor).multiplyScalar(material.sheen); + uniforms.sheenRoughness.value = material.sheenRoughness; + if (material.sheenColorMap) { + uniforms.sheenColorMap.value = material.sheenColorMap; + } + if (material.sheenRoughnessMap) { + uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; + } + } + if (material.clearcoat > 0) { + uniforms.clearcoat.value = material.clearcoat; + uniforms.clearcoatRoughness.value = material.clearcoatRoughness; + if (material.clearcoatMap) { + uniforms.clearcoatMap.value = material.clearcoatMap; + } + if (material.clearcoatRoughnessMap) { + uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; + } + if (material.clearcoatNormalMap) { + uniforms.clearcoatNormalScale.value.copy(material.clearcoatNormalScale); + uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; + if (material.side === BackSide2) { + uniforms.clearcoatNormalScale.value.negate(); + } + } + } + if (material.iridescence > 0) { + uniforms.iridescence.value = material.iridescence; + uniforms.iridescenceIOR.value = material.iridescenceIOR; + uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[0]; + uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[1]; + if (material.iridescenceMap) { + uniforms.iridescenceMap.value = material.iridescenceMap; + } + if (material.iridescenceThicknessMap) { + uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; + } + } + if (material.transmission > 0) { + uniforms.transmission.value = material.transmission; + uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture; + uniforms.transmissionSamplerSize.value.set(transmissionRenderTarget.width, transmissionRenderTarget.height); + if (material.transmissionMap) { + uniforms.transmissionMap.value = material.transmissionMap; + } + uniforms.thickness.value = material.thickness; + if (material.thicknessMap) { + uniforms.thicknessMap.value = material.thicknessMap; + } + uniforms.attenuationDistance.value = material.attenuationDistance; + uniforms.attenuationColor.value.copy(material.attenuationColor); + } + uniforms.specularIntensity.value = material.specularIntensity; + uniforms.specularColor.value.copy(material.specularColor); + if (material.specularIntensityMap) { + uniforms.specularIntensityMap.value = material.specularIntensityMap; + } + if (material.specularColorMap) { + uniforms.specularColorMap.value = material.specularColorMap; + } + } + function refreshUniformsMatcap(uniforms, material) { + if (material.matcap) { + uniforms.matcap.value = material.matcap; + } + } + function refreshUniformsDistance(uniforms, material) { + uniforms.referencePosition.value.copy(material.referencePosition); + uniforms.nearDistance.value = material.nearDistance; + uniforms.farDistance.value = material.farDistance; + } + return { + refreshFogUniforms, + refreshMaterialUniforms + }; + } + function WebGLUniformsGroups2(gl, info, capabilities, state) { + let buffers = {}; + let updateList = {}; + let allocatedBindingPoints = []; + const maxBindingPoints = capabilities.isWebGL2 ? gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS) : 0; + function bind(uniformsGroup, program) { + const webglProgram = program.program; + state.uniformBlockBinding(uniformsGroup, webglProgram); + } + function update(uniformsGroup, program) { + let buffer = buffers[uniformsGroup.id]; + if (buffer === void 0) { + prepareUniformsGroup(uniformsGroup); + buffer = createBuffer(uniformsGroup); + buffers[uniformsGroup.id] = buffer; + uniformsGroup.addEventListener("dispose", onUniformsGroupsDispose); + } + const webglProgram = program.program; + state.updateUBOMapping(uniformsGroup, webglProgram); + const frame2 = info.render.frame; + if (updateList[uniformsGroup.id] !== frame2) { + updateBufferData(uniformsGroup); + updateList[uniformsGroup.id] = frame2; + } + } + function createBuffer(uniformsGroup) { + const bindingPointIndex = allocateBindingPointIndex(); + uniformsGroup.__bindingPointIndex = bindingPointIndex; + const buffer = gl.createBuffer(); + const size = uniformsGroup.__size; + const usage = uniformsGroup.usage; + gl.bindBuffer(gl.UNIFORM_BUFFER, buffer); + gl.bufferData(gl.UNIFORM_BUFFER, size, usage); + gl.bindBuffer(gl.UNIFORM_BUFFER, null); + gl.bindBufferBase(gl.UNIFORM_BUFFER, bindingPointIndex, buffer); + return buffer; + } + function allocateBindingPointIndex() { + for (let i = 0; i < maxBindingPoints; i++) { + if (allocatedBindingPoints.indexOf(i) === -1) { + allocatedBindingPoints.push(i); + return i; + } + } + console.error("THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached."); + return 0; + } + function updateBufferData(uniformsGroup) { + const buffer = buffers[uniformsGroup.id]; + const uniforms = uniformsGroup.uniforms; + const cache2 = uniformsGroup.__cache; + gl.bindBuffer(gl.UNIFORM_BUFFER, buffer); + for (let i = 0, il = uniforms.length; i < il; i++) { + const uniform = uniforms[i]; + if (hasUniformChanged(uniform, i, cache2) === true) { + const value = uniform.value; + const offset = uniform.__offset; + if (typeof value === "number") { + uniform.__data[0] = value; + gl.bufferSubData(gl.UNIFORM_BUFFER, offset, uniform.__data); + } else { + if (uniform.value.isMatrix3) { + uniform.__data[0] = uniform.value.elements[0]; + uniform.__data[1] = uniform.value.elements[1]; + uniform.__data[2] = uniform.value.elements[2]; + uniform.__data[3] = uniform.value.elements[0]; + uniform.__data[4] = uniform.value.elements[3]; + uniform.__data[5] = uniform.value.elements[4]; + uniform.__data[6] = uniform.value.elements[5]; + uniform.__data[7] = uniform.value.elements[0]; + uniform.__data[8] = uniform.value.elements[6]; + uniform.__data[9] = uniform.value.elements[7]; + uniform.__data[10] = uniform.value.elements[8]; + uniform.__data[11] = uniform.value.elements[0]; + } else { + value.toArray(uniform.__data); + } + gl.bufferSubData(gl.UNIFORM_BUFFER, offset, uniform.__data); + } + } + } + gl.bindBuffer(gl.UNIFORM_BUFFER, null); + } + function hasUniformChanged(uniform, index2, cache2) { + const value = uniform.value; + if (cache2[index2] === void 0) { + if (typeof value === "number") { + cache2[index2] = value; + } else { + cache2[index2] = value.clone(); + } + return true; + } else { + if (typeof value === "number") { + if (cache2[index2] !== value) { + cache2[index2] = value; + return true; + } + } else { + const cachedObject = cache2[index2]; + if (cachedObject.equals(value) === false) { + cachedObject.copy(value); + return true; + } + } + } + return false; + } + function prepareUniformsGroup(uniformsGroup) { + const uniforms = uniformsGroup.uniforms; + let offset = 0; + const chunkSize = 16; + let chunkOffset = 0; + for (let i = 0, l = uniforms.length; i < l; i++) { + const uniform = uniforms[i]; + const info2 = getUniformSize(uniform); + uniform.__data = new Float32Array(info2.storage / Float32Array.BYTES_PER_ELEMENT); + uniform.__offset = offset; + if (i > 0) { + chunkOffset = offset % chunkSize; + const remainingSizeInChunk = chunkSize - chunkOffset; + if (chunkOffset !== 0 && remainingSizeInChunk - info2.boundary < 0) { + offset += chunkSize - chunkOffset; + uniform.__offset = offset; + } + } + offset += info2.storage; + } + chunkOffset = offset % chunkSize; + if (chunkOffset > 0) + offset += chunkSize - chunkOffset; + uniformsGroup.__size = offset; + uniformsGroup.__cache = {}; + return this; + } + function getUniformSize(uniform) { + const value = uniform.value; + const info2 = { + boundary: 0, + storage: 0 + }; + if (typeof value === "number") { + info2.boundary = 4; + info2.storage = 4; + } else if (value.isVector2) { + info2.boundary = 8; + info2.storage = 8; + } else if (value.isVector3 || value.isColor) { + info2.boundary = 16; + info2.storage = 12; + } else if (value.isVector4) { + info2.boundary = 16; + info2.storage = 16; + } else if (value.isMatrix3) { + info2.boundary = 48; + info2.storage = 48; + } else if (value.isMatrix4) { + info2.boundary = 64; + info2.storage = 64; + } else if (value.isTexture) { + console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."); + } else { + console.warn("THREE.WebGLRenderer: Unsupported uniform value type.", value); + } + return info2; + } + function onUniformsGroupsDispose(event) { + const uniformsGroup = event.target; + uniformsGroup.removeEventListener("dispose", onUniformsGroupsDispose); + const index2 = allocatedBindingPoints.indexOf(uniformsGroup.__bindingPointIndex); + allocatedBindingPoints.splice(index2, 1); + gl.deleteBuffer(buffers[uniformsGroup.id]); + delete buffers[uniformsGroup.id]; + delete updateList[uniformsGroup.id]; + } + function dispose() { + for (const id3 in buffers) { + gl.deleteBuffer(buffers[id3]); + } + allocatedBindingPoints = []; + buffers = {}; + updateList = {}; + } + return { + bind, + update, + dispose + }; + } + function createCanvasElement2() { + const canvas = createElementNS2("canvas"); + canvas.style.display = "block"; + return canvas; + } + function WebGLRenderer2(parameters = {}) { + this.isWebGLRenderer = true; + const _canvas3 = parameters.canvas !== void 0 ? parameters.canvas : createCanvasElement2(), _context2 = parameters.context !== void 0 ? parameters.context : null, _depth = parameters.depth !== void 0 ? parameters.depth : true, _stencil = parameters.stencil !== void 0 ? parameters.stencil : true, _antialias = parameters.antialias !== void 0 ? parameters.antialias : false, _premultipliedAlpha = parameters.premultipliedAlpha !== void 0 ? parameters.premultipliedAlpha : true, _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== void 0 ? parameters.preserveDrawingBuffer : false, _powerPreference = parameters.powerPreference !== void 0 ? parameters.powerPreference : "default", _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== void 0 ? parameters.failIfMajorPerformanceCaveat : false; + let _alpha; + if (_context2 !== null) { + _alpha = _context2.getContextAttributes().alpha; + } else { + _alpha = parameters.alpha !== void 0 ? parameters.alpha : false; + } + let currentRenderList = null; + let currentRenderState = null; + const renderListStack = []; + const renderStateStack = []; + this.domElement = _canvas3; + this.debug = { + checkShaderErrors: true + }; + this.autoClear = true; + this.autoClearColor = true; + this.autoClearDepth = true; + this.autoClearStencil = true; + this.sortObjects = true; + this.clippingPlanes = []; + this.localClippingEnabled = false; + this.outputEncoding = LinearEncoding2; + this.physicallyCorrectLights = false; + this.toneMapping = NoToneMapping2; + this.toneMappingExposure = 1; + Object.defineProperties(this, { + gammaFactor: { + get: function() { + console.warn("THREE.WebGLRenderer: .gammaFactor has been removed."); + return 2; + }, + set: function() { + console.warn("THREE.WebGLRenderer: .gammaFactor has been removed."); + } + } + }); + const _this = this; + let _isContextLost = false; + let _currentActiveCubeFace = 0; + let _currentActiveMipmapLevel = 0; + let _currentRenderTarget = null; + let _currentMaterialId = -1; + let _currentCamera = null; + const _currentViewport = new Vector42(); + const _currentScissor = new Vector42(); + let _currentScissorTest = null; + let _width = _canvas3.width; + let _height = _canvas3.height; + let _pixelRatio = 1; + let _opaqueSort = null; + let _transparentSort = null; + const _viewport = new Vector42(0, 0, _width, _height); + const _scissor = new Vector42(0, 0, _width, _height); + let _scissorTest = false; + const _frustum = new Frustum2(); + let _clippingEnabled = false; + let _localClippingEnabled = false; + let _transmissionRenderTarget = null; + const _projScreenMatrix2 = new Matrix42(); + const _vector23 = new Vector22(); + const _vector3 = new Vector32(); + const _emptyScene = { + background: null, + fog: null, + environment: null, + overrideMaterial: null, + isScene: true + }; + function getTargetPixelRatio() { + return _currentRenderTarget === null ? _pixelRatio : 1; + } + let _gl = _context2; + function getContext(contextNames, contextAttributes) { + for (let i = 0; i < contextNames.length; i++) { + const contextName = contextNames[i]; + const context = _canvas3.getContext(contextName, contextAttributes); + if (context !== null) + return context; + } + return null; + } + try { + const contextAttributes = { + alpha: true, + depth: _depth, + stencil: _stencil, + antialias: _antialias, + premultipliedAlpha: _premultipliedAlpha, + preserveDrawingBuffer: _preserveDrawingBuffer, + powerPreference: _powerPreference, + failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat + }; + if ("setAttribute" in _canvas3) + _canvas3.setAttribute("data-engine", `three.js r${REVISION2}`); + _canvas3.addEventListener("webglcontextlost", onContextLost, false); + _canvas3.addEventListener("webglcontextrestored", onContextRestore, false); + _canvas3.addEventListener("webglcontextcreationerror", onContextCreationError, false); + if (_gl === null) { + const contextNames = ["webgl2", "webgl", "experimental-webgl"]; + if (_this.isWebGL1Renderer === true) { + contextNames.shift(); + } + _gl = getContext(contextNames, contextAttributes); + if (_gl === null) { + if (getContext(contextNames)) { + throw new Error("Error creating WebGL context with your selected attributes."); + } else { + throw new Error("Error creating WebGL context."); + } + } + } + if (_gl.getShaderPrecisionFormat === void 0) { + _gl.getShaderPrecisionFormat = function() { + return { + "rangeMin": 1, + "rangeMax": 1, + "precision": 1 + }; + }; + } + } catch (error) { + console.error("THREE.WebGLRenderer: " + error.message); + throw error; + } + let extensions, capabilities, state, info; + let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let programCache, materials, renderLists, renderStates, clipping, shadowMap; + let background, morphtargets, bufferRenderer, indexedBufferRenderer; + let utils, bindingStates, uniformsGroups; + function initGLContext() { + extensions = new WebGLExtensions2(_gl); + capabilities = new WebGLCapabilities2(_gl, extensions, parameters); + extensions.init(capabilities); + utils = new WebGLUtils2(_gl, extensions, capabilities); + state = new WebGLState2(_gl, extensions, capabilities); + info = new WebGLInfo2(_gl); + properties = new WebGLProperties2(); + textures = new WebGLTextures2(_gl, extensions, state, properties, capabilities, utils, info); + cubemaps = new WebGLCubeMaps2(_this); + cubeuvmaps = new WebGLCubeUVMaps2(_this); + attributes = new WebGLAttributes2(_gl, capabilities); + bindingStates = new WebGLBindingStates2(_gl, extensions, attributes, capabilities); + geometries = new WebGLGeometries2(_gl, attributes, info, bindingStates); + objects = new WebGLObjects2(_gl, geometries, attributes, info); + morphtargets = new WebGLMorphtargets2(_gl, capabilities, textures); + clipping = new WebGLClipping2(properties); + programCache = new WebGLPrograms2(_this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping); + materials = new WebGLMaterials2(_this, properties); + renderLists = new WebGLRenderLists2(); + renderStates = new WebGLRenderStates2(extensions, capabilities); + background = new WebGLBackground2(_this, cubemaps, state, objects, _alpha, _premultipliedAlpha); + shadowMap = new WebGLShadowMap2(_this, objects, capabilities); + uniformsGroups = new WebGLUniformsGroups2(_gl, info, capabilities, state); + bufferRenderer = new WebGLBufferRenderer2(_gl, extensions, info, capabilities); + indexedBufferRenderer = new WebGLIndexedBufferRenderer2(_gl, extensions, info, capabilities); + info.programs = programCache.programs; + _this.capabilities = capabilities; + _this.extensions = extensions; + _this.properties = properties; + _this.renderLists = renderLists; + _this.shadowMap = shadowMap; + _this.state = state; + _this.info = info; + } + initGLContext(); + const xr = new WebXRManager2(_this, _gl); + this.xr = xr; + this.getContext = function() { + return _gl; + }; + this.getContextAttributes = function() { + return _gl.getContextAttributes(); + }; + this.forceContextLoss = function() { + const extension = extensions.get("WEBGL_lose_context"); + if (extension) + extension.loseContext(); + }; + this.forceContextRestore = function() { + const extension = extensions.get("WEBGL_lose_context"); + if (extension) + extension.restoreContext(); + }; + this.getPixelRatio = function() { + return _pixelRatio; + }; + this.setPixelRatio = function(value) { + if (value === void 0) + return; + _pixelRatio = value; + this.setSize(_width, _height, false); + }; + this.getSize = function(target) { + return target.set(_width, _height); + }; + this.setSize = function(width, height, updateStyle) { + if (xr.isPresenting) { + console.warn("THREE.WebGLRenderer: Can't change size while VR device is presenting."); + return; + } + _width = width; + _height = height; + _canvas3.width = Math.floor(width * _pixelRatio); + _canvas3.height = Math.floor(height * _pixelRatio); + if (updateStyle !== false) { + _canvas3.style.width = width + "px"; + _canvas3.style.height = height + "px"; + } + this.setViewport(0, 0, width, height); + }; + this.getDrawingBufferSize = function(target) { + return target.set(_width * _pixelRatio, _height * _pixelRatio).floor(); + }; + this.setDrawingBufferSize = function(width, height, pixelRatio) { + _width = width; + _height = height; + _pixelRatio = pixelRatio; + _canvas3.width = Math.floor(width * pixelRatio); + _canvas3.height = Math.floor(height * pixelRatio); + this.setViewport(0, 0, width, height); + }; + this.getCurrentViewport = function(target) { + return target.copy(_currentViewport); + }; + this.getViewport = function(target) { + return target.copy(_viewport); + }; + this.setViewport = function(x2, y2, width, height) { + if (x2.isVector4) { + _viewport.set(x2.x, x2.y, x2.z, x2.w); + } else { + _viewport.set(x2, y2, width, height); + } + state.viewport(_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor()); + }; + this.getScissor = function(target) { + return target.copy(_scissor); + }; + this.setScissor = function(x2, y2, width, height) { + if (x2.isVector4) { + _scissor.set(x2.x, x2.y, x2.z, x2.w); + } else { + _scissor.set(x2, y2, width, height); + } + state.scissor(_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor()); + }; + this.getScissorTest = function() { + return _scissorTest; + }; + this.setScissorTest = function(boolean) { + state.setScissorTest(_scissorTest = boolean); + }; + this.setOpaqueSort = function(method) { + _opaqueSort = method; + }; + this.setTransparentSort = function(method) { + _transparentSort = method; + }; + this.getClearColor = function(target) { + return target.copy(background.getClearColor()); + }; + this.setClearColor = function() { + background.setClearColor.apply(background, arguments); + }; + this.getClearAlpha = function() { + return background.getClearAlpha(); + }; + this.setClearAlpha = function() { + background.setClearAlpha.apply(background, arguments); + }; + this.clear = function(color2 = true, depth = true, stencil = true) { + let bits = 0; + if (color2) + bits |= _gl.COLOR_BUFFER_BIT; + if (depth) + bits |= _gl.DEPTH_BUFFER_BIT; + if (stencil) + bits |= _gl.STENCIL_BUFFER_BIT; + _gl.clear(bits); + }; + this.clearColor = function() { + this.clear(true, false, false); + }; + this.clearDepth = function() { + this.clear(false, true, false); + }; + this.clearStencil = function() { + this.clear(false, false, true); + }; + this.dispose = function() { + _canvas3.removeEventListener("webglcontextlost", onContextLost, false); + _canvas3.removeEventListener("webglcontextrestored", onContextRestore, false); + _canvas3.removeEventListener("webglcontextcreationerror", onContextCreationError, false); + renderLists.dispose(); + renderStates.dispose(); + properties.dispose(); + cubemaps.dispose(); + cubeuvmaps.dispose(); + objects.dispose(); + bindingStates.dispose(); + uniformsGroups.dispose(); + programCache.dispose(); + xr.dispose(); + xr.removeEventListener("sessionstart", onXRSessionStart); + xr.removeEventListener("sessionend", onXRSessionEnd); + if (_transmissionRenderTarget) { + _transmissionRenderTarget.dispose(); + _transmissionRenderTarget = null; + } + animation.stop(); + }; + function onContextLost(event) { + event.preventDefault(); + console.log("THREE.WebGLRenderer: Context Lost."); + _isContextLost = true; + } + function onContextRestore() { + console.log("THREE.WebGLRenderer: Context Restored."); + _isContextLost = false; + const infoAutoReset = info.autoReset; + const shadowMapEnabled = shadowMap.enabled; + const shadowMapAutoUpdate = shadowMap.autoUpdate; + const shadowMapNeedsUpdate = shadowMap.needsUpdate; + const shadowMapType = shadowMap.type; + initGLContext(); + info.autoReset = infoAutoReset; + shadowMap.enabled = shadowMapEnabled; + shadowMap.autoUpdate = shadowMapAutoUpdate; + shadowMap.needsUpdate = shadowMapNeedsUpdate; + shadowMap.type = shadowMapType; + } + function onContextCreationError(event) { + console.error("THREE.WebGLRenderer: A WebGL context could not be created. Reason: ", event.statusMessage); + } + function onMaterialDispose(event) { + const material = event.target; + material.removeEventListener("dispose", onMaterialDispose); + deallocateMaterial(material); + } + function deallocateMaterial(material) { + releaseMaterialProgramReferences(material); + properties.remove(material); + } + function releaseMaterialProgramReferences(material) { + const programs = properties.get(material).programs; + if (programs !== void 0) { + programs.forEach(function(program) { + programCache.releaseProgram(program); + }); + if (material.isShaderMaterial) { + programCache.releaseShaderCache(material); + } + } + } + this.renderBufferDirect = function(camera, scene, geometry, material, object, group) { + if (scene === null) + scene = _emptyScene; + const frontFaceCW = object.isMesh && object.matrixWorld.determinant() < 0; + const program = setProgram(camera, scene, geometry, material, object); + state.setMaterial(material, frontFaceCW); + let index2 = geometry.index; + const position = geometry.attributes.position; + if (index2 === null) { + if (position === void 0 || position.count === 0) + return; + } else if (index2.count === 0) { + return; + } + let rangeFactor = 1; + if (material.wireframe === true) { + index2 = geometries.getWireframeAttribute(geometry); + rangeFactor = 2; + } + bindingStates.setup(object, material, program, geometry, index2); + let attribute; + let renderer = bufferRenderer; + if (index2 !== null) { + attribute = attributes.get(index2); + renderer = indexedBufferRenderer; + renderer.setIndex(attribute); + } + const dataCount = index2 !== null ? index2.count : position.count; + const rangeStart = geometry.drawRange.start * rangeFactor; + const rangeCount = geometry.drawRange.count * rangeFactor; + const groupStart = group !== null ? group.start * rangeFactor : 0; + const groupCount = group !== null ? group.count * rangeFactor : Infinity; + const drawStart = Math.max(rangeStart, groupStart); + const drawEnd = Math.min(dataCount, rangeStart + rangeCount, groupStart + groupCount) - 1; + const drawCount = Math.max(0, drawEnd - drawStart + 1); + if (drawCount === 0) + return; + if (object.isMesh) { + if (material.wireframe === true) { + state.setLineWidth(material.wireframeLinewidth * getTargetPixelRatio()); + renderer.setMode(_gl.LINES); + } else { + renderer.setMode(_gl.TRIANGLES); + } + } else if (object.isLine) { + let lineWidth = material.linewidth; + if (lineWidth === void 0) + lineWidth = 1; + state.setLineWidth(lineWidth * getTargetPixelRatio()); + if (object.isLineSegments) { + renderer.setMode(_gl.LINES); + } else if (object.isLineLoop) { + renderer.setMode(_gl.LINE_LOOP); + } else { + renderer.setMode(_gl.LINE_STRIP); + } + } else if (object.isPoints) { + renderer.setMode(_gl.POINTS); + } else if (object.isSprite) { + renderer.setMode(_gl.TRIANGLES); + } + if (object.isInstancedMesh) { + renderer.renderInstances(drawStart, drawCount, object.count); + } else if (geometry.isInstancedBufferGeometry) { + const instanceCount = Math.min(geometry.instanceCount, geometry._maxInstanceCount); + renderer.renderInstances(drawStart, drawCount, instanceCount); + } else { + renderer.render(drawStart, drawCount); + } + }; + this.compile = function(scene, camera) { + currentRenderState = renderStates.get(scene); + currentRenderState.init(); + renderStateStack.push(currentRenderState); + scene.traverseVisible(function(object) { + if (object.isLight && object.layers.test(camera.layers)) { + currentRenderState.pushLight(object); + if (object.castShadow) { + currentRenderState.pushShadow(object); + } + } + }); + currentRenderState.setupLights(_this.physicallyCorrectLights); + scene.traverse(function(object) { + const material = object.material; + if (material) { + if (Array.isArray(material)) { + for (let i = 0; i < material.length; i++) { + const material2 = material[i]; + getProgram(material2, scene, object); + } + } else { + getProgram(material, scene, object); + } + } + }); + renderStateStack.pop(); + currentRenderState = null; + }; + let onAnimationFrameCallback = null; + function onAnimationFrame(time) { + if (onAnimationFrameCallback) + onAnimationFrameCallback(time); + } + function onXRSessionStart() { + animation.stop(); + } + function onXRSessionEnd() { + animation.start(); + } + const animation = new WebGLAnimation2(); + animation.setAnimationLoop(onAnimationFrame); + if (typeof self !== "undefined") + animation.setContext(self); + this.setAnimationLoop = function(callback) { + onAnimationFrameCallback = callback; + xr.setAnimationLoop(callback); + callback === null ? animation.stop() : animation.start(); + }; + xr.addEventListener("sessionstart", onXRSessionStart); + xr.addEventListener("sessionend", onXRSessionEnd); + this.render = function(scene, camera) { + if (camera !== void 0 && camera.isCamera !== true) { + console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera."); + return; + } + if (_isContextLost === true) + return; + if (scene.autoUpdate === true) + scene.updateMatrixWorld(); + if (camera.parent === null) + camera.updateMatrixWorld(); + if (xr.enabled === true && xr.isPresenting === true) { + if (xr.cameraAutoUpdate === true) + xr.updateCamera(camera); + camera = xr.getCamera(); + } + if (scene.isScene === true) + scene.onBeforeRender(_this, scene, camera, _currentRenderTarget); + currentRenderState = renderStates.get(scene, renderStateStack.length); + currentRenderState.init(); + renderStateStack.push(currentRenderState); + _projScreenMatrix2.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); + _frustum.setFromProjectionMatrix(_projScreenMatrix2); + _localClippingEnabled = this.localClippingEnabled; + _clippingEnabled = clipping.init(this.clippingPlanes, _localClippingEnabled, camera); + currentRenderList = renderLists.get(scene, renderListStack.length); + currentRenderList.init(); + renderListStack.push(currentRenderList); + projectObject(scene, camera, 0, _this.sortObjects); + currentRenderList.finish(); + if (_this.sortObjects === true) { + currentRenderList.sort(_opaqueSort, _transparentSort); + } + if (_clippingEnabled === true) + clipping.beginShadows(); + const shadowsArray = currentRenderState.state.shadowsArray; + shadowMap.render(shadowsArray, scene, camera); + if (_clippingEnabled === true) + clipping.endShadows(); + if (this.info.autoReset === true) + this.info.reset(); + background.render(currentRenderList, scene); + currentRenderState.setupLights(_this.physicallyCorrectLights); + if (camera.isArrayCamera) { + const cameras = camera.cameras; + for (let i = 0, l = cameras.length; i < l; i++) { + const camera2 = cameras[i]; + renderScene(currentRenderList, scene, camera2, camera2.viewport); + } + } else { + renderScene(currentRenderList, scene, camera); + } + if (_currentRenderTarget !== null) { + textures.updateMultisampleRenderTarget(_currentRenderTarget); + textures.updateRenderTargetMipmap(_currentRenderTarget); + } + if (scene.isScene === true) + scene.onAfterRender(_this, scene, camera); + bindingStates.resetDefaultState(); + _currentMaterialId = -1; + _currentCamera = null; + renderStateStack.pop(); + if (renderStateStack.length > 0) { + currentRenderState = renderStateStack[renderStateStack.length - 1]; + } else { + currentRenderState = null; + } + renderListStack.pop(); + if (renderListStack.length > 0) { + currentRenderList = renderListStack[renderListStack.length - 1]; + } else { + currentRenderList = null; + } + }; + function projectObject(object, camera, groupOrder, sortObjects) { + if (object.visible === false) + return; + const visible = object.layers.test(camera.layers); + if (visible) { + if (object.isGroup) { + groupOrder = object.renderOrder; + } else if (object.isLOD) { + if (object.autoUpdate === true) + object.update(camera); + } else if (object.isLight) { + currentRenderState.pushLight(object); + if (object.castShadow) { + currentRenderState.pushShadow(object); + } + } else if (object.isSprite) { + if (!object.frustumCulled || _frustum.intersectsSprite(object)) { + if (sortObjects) { + _vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix2); + } + const geometry = objects.update(object); + const material = object.material; + if (material.visible) { + currentRenderList.push(object, geometry, material, groupOrder, _vector3.z, null); + } + } + } else if (object.isMesh || object.isLine || object.isPoints) { + if (object.isSkinnedMesh) { + if (object.skeleton.frame !== info.render.frame) { + object.skeleton.update(); + object.skeleton.frame = info.render.frame; + } + } + if (!object.frustumCulled || _frustum.intersectsObject(object)) { + if (sortObjects) { + _vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix2); + } + const geometry = objects.update(object); + const material = object.material; + if (Array.isArray(material)) { + const groups = geometry.groups; + for (let i = 0, l = groups.length; i < l; i++) { + const group = groups[i]; + const groupMaterial = material[group.materialIndex]; + if (groupMaterial && groupMaterial.visible) { + currentRenderList.push(object, geometry, groupMaterial, groupOrder, _vector3.z, group); + } + } + } else if (material.visible) { + currentRenderList.push(object, geometry, material, groupOrder, _vector3.z, null); + } + } + } + } + const children2 = object.children; + for (let i = 0, l = children2.length; i < l; i++) { + projectObject(children2[i], camera, groupOrder, sortObjects); + } + } + function renderScene(currentRenderList2, scene, camera, viewport) { + const opaqueObjects = currentRenderList2.opaque; + const transmissiveObjects = currentRenderList2.transmissive; + const transparentObjects = currentRenderList2.transparent; + currentRenderState.setupLightsView(camera); + if (transmissiveObjects.length > 0) + renderTransmissionPass(opaqueObjects, scene, camera); + if (viewport) + state.viewport(_currentViewport.copy(viewport)); + if (opaqueObjects.length > 0) + renderObjects(opaqueObjects, scene, camera); + if (transmissiveObjects.length > 0) + renderObjects(transmissiveObjects, scene, camera); + if (transparentObjects.length > 0) + renderObjects(transparentObjects, scene, camera); + state.buffers.depth.setTest(true); + state.buffers.depth.setMask(true); + state.buffers.color.setMask(true); + state.setPolygonOffset(false); + } + function renderTransmissionPass(opaqueObjects, scene, camera) { + const isWebGL2 = capabilities.isWebGL2; + if (_transmissionRenderTarget === null) { + _transmissionRenderTarget = new WebGLRenderTarget2(1, 1, { + generateMipmaps: true, + type: extensions.has("EXT_color_buffer_half_float") ? HalfFloatType2 : UnsignedByteType2, + minFilter: LinearMipmapLinearFilter2, + samples: isWebGL2 && _antialias === true ? 4 : 0 + }); + } + _this.getDrawingBufferSize(_vector23); + if (isWebGL2) { + _transmissionRenderTarget.setSize(_vector23.x, _vector23.y); + } else { + _transmissionRenderTarget.setSize(floorPowerOfTwo2(_vector23.x), floorPowerOfTwo2(_vector23.y)); + } + const currentRenderTarget = _this.getRenderTarget(); + _this.setRenderTarget(_transmissionRenderTarget); + _this.clear(); + const currentToneMapping = _this.toneMapping; + _this.toneMapping = NoToneMapping2; + renderObjects(opaqueObjects, scene, camera); + _this.toneMapping = currentToneMapping; + textures.updateMultisampleRenderTarget(_transmissionRenderTarget); + textures.updateRenderTargetMipmap(_transmissionRenderTarget); + _this.setRenderTarget(currentRenderTarget); + } + function renderObjects(renderList, scene, camera) { + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; + for (let i = 0, l = renderList.length; i < l; i++) { + const renderItem = renderList[i]; + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = overrideMaterial === null ? renderItem.material : overrideMaterial; + const group = renderItem.group; + if (object.layers.test(camera.layers)) { + renderObject(object, scene, camera, geometry, material, group); + } + } + } + function renderObject(object, scene, camera, geometry, material, group) { + object.onBeforeRender(_this, scene, camera, geometry, material, group); + object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, object.matrixWorld); + object.normalMatrix.getNormalMatrix(object.modelViewMatrix); + material.onBeforeRender(_this, scene, camera, geometry, object, group); + if (material.transparent === true && material.side === DoubleSide2) { + material.side = BackSide2; + material.needsUpdate = true; + _this.renderBufferDirect(camera, scene, geometry, material, object, group); + material.side = FrontSide2; + material.needsUpdate = true; + _this.renderBufferDirect(camera, scene, geometry, material, object, group); + material.side = DoubleSide2; + } else { + _this.renderBufferDirect(camera, scene, geometry, material, object, group); + } + object.onAfterRender(_this, scene, camera, geometry, material, group); + } + function getProgram(material, scene, object) { + if (scene.isScene !== true) + scene = _emptyScene; + const materialProperties = properties.get(material); + const lights = currentRenderState.state.lights; + const shadowsArray = currentRenderState.state.shadowsArray; + const lightsStateVersion = lights.state.version; + const parameters2 = programCache.getParameters(material, lights.state, shadowsArray, scene, object); + const programCacheKey = programCache.getProgramCacheKey(parameters2); + let programs = materialProperties.programs; + materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; + materialProperties.fog = scene.fog; + materialProperties.envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || materialProperties.environment); + if (programs === void 0) { + material.addEventListener("dispose", onMaterialDispose); + programs = /* @__PURE__ */ new Map(); + materialProperties.programs = programs; + } + let program = programs.get(programCacheKey); + if (program !== void 0) { + if (materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion) { + updateCommonMaterialProperties(material, parameters2); + return program; + } + } else { + parameters2.uniforms = programCache.getUniforms(material); + material.onBuild(object, parameters2, _this); + material.onBeforeCompile(parameters2, _this); + program = programCache.acquireProgram(parameters2, programCacheKey); + programs.set(programCacheKey, program); + materialProperties.uniforms = parameters2.uniforms; + } + const uniforms = materialProperties.uniforms; + if (!material.isShaderMaterial && !material.isRawShaderMaterial || material.clipping === true) { + uniforms.clippingPlanes = clipping.uniform; + } + updateCommonMaterialProperties(material, parameters2); + materialProperties.needsLights = materialNeedsLights(material); + materialProperties.lightsStateVersion = lightsStateVersion; + if (materialProperties.needsLights) { + uniforms.ambientLightColor.value = lights.state.ambient; + uniforms.lightProbe.value = lights.state.probe; + uniforms.directionalLights.value = lights.state.directional; + uniforms.directionalLightShadows.value = lights.state.directionalShadow; + uniforms.spotLights.value = lights.state.spot; + uniforms.spotLightShadows.value = lights.state.spotShadow; + uniforms.rectAreaLights.value = lights.state.rectArea; + uniforms.ltc_1.value = lights.state.rectAreaLTC1; + uniforms.ltc_2.value = lights.state.rectAreaLTC2; + uniforms.pointLights.value = lights.state.point; + uniforms.pointLightShadows.value = lights.state.pointShadow; + uniforms.hemisphereLights.value = lights.state.hemi; + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; + } + const progUniforms = program.getUniforms(); + const uniformsList = WebGLUniforms2.seqWithValue(progUniforms.seq, uniforms); + materialProperties.currentProgram = program; + materialProperties.uniformsList = uniformsList; + return program; + } + function updateCommonMaterialProperties(material, parameters2) { + const materialProperties = properties.get(material); + materialProperties.outputEncoding = parameters2.outputEncoding; + materialProperties.instancing = parameters2.instancing; + materialProperties.skinning = parameters2.skinning; + materialProperties.morphTargets = parameters2.morphTargets; + materialProperties.morphNormals = parameters2.morphNormals; + materialProperties.morphColors = parameters2.morphColors; + materialProperties.morphTargetsCount = parameters2.morphTargetsCount; + materialProperties.numClippingPlanes = parameters2.numClippingPlanes; + materialProperties.numIntersection = parameters2.numClipIntersection; + materialProperties.vertexAlphas = parameters2.vertexAlphas; + materialProperties.vertexTangents = parameters2.vertexTangents; + materialProperties.toneMapping = parameters2.toneMapping; + } + function setProgram(camera, scene, geometry, material, object) { + if (scene.isScene !== true) + scene = _emptyScene; + textures.resetTextureUnits(); + const fog = scene.fog; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const encoding = _currentRenderTarget === null ? _this.outputEncoding : _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding2; + const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment); + const vertexAlphas = material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4; + const vertexTangents = !!material.normalMap && !!geometry.attributes.tangent; + const morphTargets = !!geometry.morphAttributes.position; + const morphNormals = !!geometry.morphAttributes.normal; + const morphColors = !!geometry.morphAttributes.color; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping2; + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = morphAttribute !== void 0 ? morphAttribute.length : 0; + const materialProperties = properties.get(material); + const lights = currentRenderState.state.lights; + if (_clippingEnabled === true) { + if (_localClippingEnabled === true || camera !== _currentCamera) { + const useCache = camera === _currentCamera && material.id === _currentMaterialId; + clipping.setState(material, camera, useCache); + } + } + let needsProgramChange = false; + if (material.version === materialProperties.__version) { + if (materialProperties.needsLights && materialProperties.lightsStateVersion !== lights.state.version) { + needsProgramChange = true; + } else if (materialProperties.outputEncoding !== encoding) { + needsProgramChange = true; + } else if (object.isInstancedMesh && materialProperties.instancing === false) { + needsProgramChange = true; + } else if (!object.isInstancedMesh && materialProperties.instancing === true) { + needsProgramChange = true; + } else if (object.isSkinnedMesh && materialProperties.skinning === false) { + needsProgramChange = true; + } else if (!object.isSkinnedMesh && materialProperties.skinning === true) { + needsProgramChange = true; + } else if (materialProperties.envMap !== envMap) { + needsProgramChange = true; + } else if (material.fog === true && materialProperties.fog !== fog) { + needsProgramChange = true; + } else if (materialProperties.numClippingPlanes !== void 0 && (materialProperties.numClippingPlanes !== clipping.numPlanes || materialProperties.numIntersection !== clipping.numIntersection)) { + needsProgramChange = true; + } else if (materialProperties.vertexAlphas !== vertexAlphas) { + needsProgramChange = true; + } else if (materialProperties.vertexTangents !== vertexTangents) { + needsProgramChange = true; + } else if (materialProperties.morphTargets !== morphTargets) { + needsProgramChange = true; + } else if (materialProperties.morphNormals !== morphNormals) { + needsProgramChange = true; + } else if (materialProperties.morphColors !== morphColors) { + needsProgramChange = true; + } else if (materialProperties.toneMapping !== toneMapping) { + needsProgramChange = true; + } else if (capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount) { + needsProgramChange = true; + } + } else { + needsProgramChange = true; + materialProperties.__version = material.version; + } + let program = materialProperties.currentProgram; + if (needsProgramChange === true) { + program = getProgram(material, scene, object); + } + let refreshProgram = false; + let refreshMaterial = false; + let refreshLights = false; + const p_uniforms = program.getUniforms(), m_uniforms = materialProperties.uniforms; + if (state.useProgram(program.program)) { + refreshProgram = true; + refreshMaterial = true; + refreshLights = true; + } + if (material.id !== _currentMaterialId) { + _currentMaterialId = material.id; + refreshMaterial = true; + } + if (refreshProgram || _currentCamera !== camera) { + p_uniforms.setValue(_gl, "projectionMatrix", camera.projectionMatrix); + if (capabilities.logarithmicDepthBuffer) { + p_uniforms.setValue(_gl, "logDepthBufFC", 2 / (Math.log(camera.far + 1) / Math.LN2)); + } + if (_currentCamera !== camera) { + _currentCamera = camera; + refreshMaterial = true; + refreshLights = true; + } + if (material.isShaderMaterial || material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshStandardMaterial || material.envMap) { + const uCamPos = p_uniforms.map.cameraPosition; + if (uCamPos !== void 0) { + uCamPos.setValue(_gl, _vector3.setFromMatrixPosition(camera.matrixWorld)); + } + } + if (material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshLambertMaterial || material.isMeshBasicMaterial || material.isMeshStandardMaterial || material.isShaderMaterial) { + p_uniforms.setValue(_gl, "isOrthographic", camera.isOrthographicCamera === true); + } + if (material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshLambertMaterial || material.isMeshBasicMaterial || material.isMeshStandardMaterial || material.isShaderMaterial || material.isShadowMaterial || object.isSkinnedMesh) { + p_uniforms.setValue(_gl, "viewMatrix", camera.matrixWorldInverse); + } + } + if (object.isSkinnedMesh) { + p_uniforms.setOptional(_gl, object, "bindMatrix"); + p_uniforms.setOptional(_gl, object, "bindMatrixInverse"); + const skeleton = object.skeleton; + if (skeleton) { + if (capabilities.floatVertexTextures) { + if (skeleton.boneTexture === null) + skeleton.computeBoneTexture(); + p_uniforms.setValue(_gl, "boneTexture", skeleton.boneTexture, textures); + p_uniforms.setValue(_gl, "boneTextureSize", skeleton.boneTextureSize); + } else { + console.warn("THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required."); + } + } + } + const morphAttributes = geometry.morphAttributes; + if (morphAttributes.position !== void 0 || morphAttributes.normal !== void 0 || morphAttributes.color !== void 0 && capabilities.isWebGL2 === true) { + morphtargets.update(object, geometry, material, program); + } + if (refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow) { + materialProperties.receiveShadow = object.receiveShadow; + p_uniforms.setValue(_gl, "receiveShadow", object.receiveShadow); + } + if (refreshMaterial) { + p_uniforms.setValue(_gl, "toneMappingExposure", _this.toneMappingExposure); + if (materialProperties.needsLights) { + markUniformsLightsNeedsUpdate(m_uniforms, refreshLights); + } + if (fog && material.fog === true) { + materials.refreshFogUniforms(m_uniforms, fog); + } + materials.refreshMaterialUniforms(m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget); + WebGLUniforms2.upload(_gl, materialProperties.uniformsList, m_uniforms, textures); + } + if (material.isShaderMaterial && material.uniformsNeedUpdate === true) { + WebGLUniforms2.upload(_gl, materialProperties.uniformsList, m_uniforms, textures); + material.uniformsNeedUpdate = false; + } + if (material.isSpriteMaterial) { + p_uniforms.setValue(_gl, "center", object.center); + } + p_uniforms.setValue(_gl, "modelViewMatrix", object.modelViewMatrix); + p_uniforms.setValue(_gl, "normalMatrix", object.normalMatrix); + p_uniforms.setValue(_gl, "modelMatrix", object.matrixWorld); + if (material.isShaderMaterial || material.isRawShaderMaterial) { + const groups = material.uniformsGroups; + for (let i = 0, l = groups.length; i < l; i++) { + if (capabilities.isWebGL2) { + const group = groups[i]; + uniformsGroups.update(group, program); + uniformsGroups.bind(group, program); + } else { + console.warn("THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2."); + } + } + } + return program; + } + function markUniformsLightsNeedsUpdate(uniforms, value) { + uniforms.ambientLightColor.needsUpdate = value; + uniforms.lightProbe.needsUpdate = value; + uniforms.directionalLights.needsUpdate = value; + uniforms.directionalLightShadows.needsUpdate = value; + uniforms.pointLights.needsUpdate = value; + uniforms.pointLightShadows.needsUpdate = value; + uniforms.spotLights.needsUpdate = value; + uniforms.spotLightShadows.needsUpdate = value; + uniforms.rectAreaLights.needsUpdate = value; + uniforms.hemisphereLights.needsUpdate = value; + } + function materialNeedsLights(material) { + return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial || material.isShadowMaterial || material.isShaderMaterial && material.lights === true; + } + this.getActiveCubeFace = function() { + return _currentActiveCubeFace; + }; + this.getActiveMipmapLevel = function() { + return _currentActiveMipmapLevel; + }; + this.getRenderTarget = function() { + return _currentRenderTarget; + }; + this.setRenderTargetTextures = function(renderTarget, colorTexture, depthTexture) { + properties.get(renderTarget.texture).__webglTexture = colorTexture; + properties.get(renderTarget.depthTexture).__webglTexture = depthTexture; + const renderTargetProperties = properties.get(renderTarget); + renderTargetProperties.__hasExternalTextures = true; + if (renderTargetProperties.__hasExternalTextures) { + renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === void 0; + if (!renderTargetProperties.__autoAllocateDepthBuffer) { + if (extensions.has("WEBGL_multisampled_render_to_texture") === true) { + console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"); + renderTargetProperties.__useRenderToTexture = false; + } + } + } + }; + this.setRenderTargetFramebuffer = function(renderTarget, defaultFramebuffer) { + const renderTargetProperties = properties.get(renderTarget); + renderTargetProperties.__webglFramebuffer = defaultFramebuffer; + renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === void 0; + }; + this.setRenderTarget = function(renderTarget, activeCubeFace = 0, activeMipmapLevel = 0) { + _currentRenderTarget = renderTarget; + _currentActiveCubeFace = activeCubeFace; + _currentActiveMipmapLevel = activeMipmapLevel; + let useDefaultFramebuffer = true; + if (renderTarget) { + const renderTargetProperties = properties.get(renderTarget); + if (renderTargetProperties.__useDefaultFramebuffer !== void 0) { + state.bindFramebuffer(_gl.FRAMEBUFFER, null); + useDefaultFramebuffer = false; + } else if (renderTargetProperties.__webglFramebuffer === void 0) { + textures.setupRenderTarget(renderTarget); + } else if (renderTargetProperties.__hasExternalTextures) { + textures.rebindTextures(renderTarget, properties.get(renderTarget.texture).__webglTexture, properties.get(renderTarget.depthTexture).__webglTexture); + } + } + let framebuffer = null; + let isCube = false; + let isRenderTarget3D = false; + if (renderTarget) { + const texture = renderTarget.texture; + if (texture.isData3DTexture || texture.isDataArrayTexture) { + isRenderTarget3D = true; + } + const __webglFramebuffer = properties.get(renderTarget).__webglFramebuffer; + if (renderTarget.isWebGLCubeRenderTarget) { + framebuffer = __webglFramebuffer[activeCubeFace]; + isCube = true; + } else if (capabilities.isWebGL2 && renderTarget.samples > 0 && textures.useMultisampledRTT(renderTarget) === false) { + framebuffer = properties.get(renderTarget).__webglMultisampledFramebuffer; + } else { + framebuffer = __webglFramebuffer; + } + _currentViewport.copy(renderTarget.viewport); + _currentScissor.copy(renderTarget.scissor); + _currentScissorTest = renderTarget.scissorTest; + } else { + _currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor(); + _currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor(); + _currentScissorTest = _scissorTest; + } + const framebufferBound = state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer); + if (framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer) { + state.drawBuffers(renderTarget, framebuffer); + } + state.viewport(_currentViewport); + state.scissor(_currentScissor); + state.setScissorTest(_currentScissorTest); + if (isCube) { + const textureProperties = properties.get(renderTarget.texture); + _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel); + } else if (isRenderTarget3D) { + const textureProperties = properties.get(renderTarget.texture); + const layer = activeCubeFace || 0; + _gl.framebufferTextureLayer(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer); + } + _currentMaterialId = -1; + }; + this.readRenderTargetPixels = function(renderTarget, x2, y2, width, height, buffer, activeCubeFaceIndex) { + if (!(renderTarget && renderTarget.isWebGLRenderTarget)) { + console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget."); + return; + } + let framebuffer = properties.get(renderTarget).__webglFramebuffer; + if (renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== void 0) { + framebuffer = framebuffer[activeCubeFaceIndex]; + } + if (framebuffer) { + state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer); + try { + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; + if (textureFormat !== RGBAFormat2 && utils.convert(textureFormat) !== _gl.getParameter(_gl.IMPLEMENTATION_COLOR_READ_FORMAT)) { + console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format."); + return; + } + const halfFloatSupportedByExt = textureType === HalfFloatType2 && (extensions.has("EXT_color_buffer_half_float") || capabilities.isWebGL2 && extensions.has("EXT_color_buffer_float")); + if (textureType !== UnsignedByteType2 && utils.convert(textureType) !== _gl.getParameter(_gl.IMPLEMENTATION_COLOR_READ_TYPE) && !(textureType === FloatType2 && (capabilities.isWebGL2 || extensions.has("OES_texture_float") || extensions.has("WEBGL_color_buffer_float"))) && !halfFloatSupportedByExt) { + console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type."); + return; + } + if (x2 >= 0 && x2 <= renderTarget.width - width && y2 >= 0 && y2 <= renderTarget.height - height) { + _gl.readPixels(x2, y2, width, height, utils.convert(textureFormat), utils.convert(textureType), buffer); + } + } finally { + const framebuffer2 = _currentRenderTarget !== null ? properties.get(_currentRenderTarget).__webglFramebuffer : null; + state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer2); + } + } + }; + this.copyFramebufferToTexture = function(position, texture, level = 0) { + const levelScale = Math.pow(2, -level); + const width = Math.floor(texture.image.width * levelScale); + const height = Math.floor(texture.image.height * levelScale); + textures.setTexture2D(texture, 0); + _gl.copyTexSubImage2D(_gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height); + state.unbindTexture(); + }; + this.copyTextureToTexture = function(position, srcTexture, dstTexture, level = 0) { + const width = srcTexture.image.width; + const height = srcTexture.image.height; + const glFormat = utils.convert(dstTexture.format); + const glType = utils.convert(dstTexture.type); + textures.setTexture2D(dstTexture, 0); + _gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY); + _gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha); + _gl.pixelStorei(_gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment); + if (srcTexture.isDataTexture) { + _gl.texSubImage2D(_gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data); + } else { + if (srcTexture.isCompressedTexture) { + _gl.compressedTexSubImage2D(_gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[0].width, srcTexture.mipmaps[0].height, glFormat, srcTexture.mipmaps[0].data); + } else { + _gl.texSubImage2D(_gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image); + } + } + if (level === 0 && dstTexture.generateMipmaps) + _gl.generateMipmap(_gl.TEXTURE_2D); + state.unbindTexture(); + }; + this.copyTextureToTexture3D = function(sourceBox, position, srcTexture, dstTexture, level = 0) { + if (_this.isWebGL1Renderer) { + console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2."); + return; + } + const width = sourceBox.max.x - sourceBox.min.x + 1; + const height = sourceBox.max.y - sourceBox.min.y + 1; + const depth = sourceBox.max.z - sourceBox.min.z + 1; + const glFormat = utils.convert(dstTexture.format); + const glType = utils.convert(dstTexture.type); + let glTarget; + if (dstTexture.isData3DTexture) { + textures.setTexture3D(dstTexture, 0); + glTarget = _gl.TEXTURE_3D; + } else if (dstTexture.isDataArrayTexture) { + textures.setTexture2DArray(dstTexture, 0); + glTarget = _gl.TEXTURE_2D_ARRAY; + } else { + console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray."); + return; + } + _gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY); + _gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha); + _gl.pixelStorei(_gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment); + const unpackRowLen = _gl.getParameter(_gl.UNPACK_ROW_LENGTH); + const unpackImageHeight = _gl.getParameter(_gl.UNPACK_IMAGE_HEIGHT); + const unpackSkipPixels = _gl.getParameter(_gl.UNPACK_SKIP_PIXELS); + const unpackSkipRows = _gl.getParameter(_gl.UNPACK_SKIP_ROWS); + const unpackSkipImages = _gl.getParameter(_gl.UNPACK_SKIP_IMAGES); + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[0] : srcTexture.image; + _gl.pixelStorei(_gl.UNPACK_ROW_LENGTH, image.width); + _gl.pixelStorei(_gl.UNPACK_IMAGE_HEIGHT, image.height); + _gl.pixelStorei(_gl.UNPACK_SKIP_PIXELS, sourceBox.min.x); + _gl.pixelStorei(_gl.UNPACK_SKIP_ROWS, sourceBox.min.y); + _gl.pixelStorei(_gl.UNPACK_SKIP_IMAGES, sourceBox.min.z); + if (srcTexture.isDataTexture || srcTexture.isData3DTexture) { + _gl.texSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data); + } else { + if (srcTexture.isCompressedTexture) { + console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."); + _gl.compressedTexSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data); + } else { + _gl.texSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image); + } + } + _gl.pixelStorei(_gl.UNPACK_ROW_LENGTH, unpackRowLen); + _gl.pixelStorei(_gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight); + _gl.pixelStorei(_gl.UNPACK_SKIP_PIXELS, unpackSkipPixels); + _gl.pixelStorei(_gl.UNPACK_SKIP_ROWS, unpackSkipRows); + _gl.pixelStorei(_gl.UNPACK_SKIP_IMAGES, unpackSkipImages); + if (level === 0 && dstTexture.generateMipmaps) + _gl.generateMipmap(glTarget); + state.unbindTexture(); + }; + this.initTexture = function(texture) { + if (texture.isCubeTexture) { + textures.setTextureCube(texture, 0); + } else if (texture.isData3DTexture) { + textures.setTexture3D(texture, 0); + } else if (texture.isDataArrayTexture) { + textures.setTexture2DArray(texture, 0); + } else { + textures.setTexture2D(texture, 0); + } + state.unbindTexture(); + }; + this.resetState = function() { + _currentActiveCubeFace = 0; + _currentActiveMipmapLevel = 0; + _currentRenderTarget = null; + state.reset(); + bindingStates.reset(); + }; + if (typeof __THREE_DEVTOOLS__ !== "undefined") { + __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe", { + detail: this + })); + } + } + var WebGL1Renderer2 = class extends WebGLRenderer2 { + }; + WebGL1Renderer2.prototype.isWebGL1Renderer = true; + var FogExp2 = class { + constructor(color2, density = 25e-5) { + this.isFogExp2 = true; + this.name = ""; + this.color = new Color3(color2); + this.density = density; + } + clone() { + return new FogExp2(this.color, this.density); + } + toJSON() { + return { + type: "FogExp2", + color: this.color.getHex(), + density: this.density + }; + } + }; + var Fog = class { + constructor(color2, near = 1, far = 1e3) { + this.isFog = true; + this.name = ""; + this.color = new Color3(color2); + this.near = near; + this.far = far; + } + clone() { + return new Fog(this.color, this.near, this.far); + } + toJSON() { + return { + type: "Fog", + color: this.color.getHex(), + near: this.near, + far: this.far + }; + } + }; + var Scene2 = class extends Object3D2 { + constructor() { + super(); + this.isScene = true; + this.type = "Scene"; + this.background = null; + this.environment = null; + this.fog = null; + this.overrideMaterial = null; + this.autoUpdate = true; + if (typeof __THREE_DEVTOOLS__ !== "undefined") { + __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe", { + detail: this + })); + } + } + copy(source, recursive) { + super.copy(source, recursive); + if (source.background !== null) + this.background = source.background.clone(); + if (source.environment !== null) + this.environment = source.environment.clone(); + if (source.fog !== null) + this.fog = source.fog.clone(); + if (source.overrideMaterial !== null) + this.overrideMaterial = source.overrideMaterial.clone(); + this.autoUpdate = source.autoUpdate; + this.matrixAutoUpdate = source.matrixAutoUpdate; + return this; + } + toJSON(meta) { + const data = super.toJSON(meta); + if (this.fog !== null) + data.object.fog = this.fog.toJSON(); + return data; + } + }; + var InterleavedBuffer = class { + constructor(array2, stride) { + this.isInterleavedBuffer = true; + this.array = array2; + this.stride = stride; + this.count = array2 !== void 0 ? array2.length / stride : 0; + this.usage = StaticDrawUsage2; + this.updateRange = { + offset: 0, + count: -1 + }; + this.version = 0; + this.uuid = generateUUID2(); + } + onUploadCallback() { + } + set needsUpdate(value) { + if (value === true) + this.version++; + } + setUsage(value) { + this.usage = value; + return this; + } + copy(source) { + this.array = new source.array.constructor(source.array); + this.count = source.count; + this.stride = source.stride; + this.usage = source.usage; + return this; + } + copyAt(index1, attribute, index2) { + index1 *= this.stride; + index2 *= attribute.stride; + for (let i = 0, l = this.stride; i < l; i++) { + this.array[index1 + i] = attribute.array[index2 + i]; + } + return this; + } + set(value, offset = 0) { + this.array.set(value, offset); + return this; + } + clone(data) { + if (data.arrayBuffers === void 0) { + data.arrayBuffers = {}; + } + if (this.array.buffer._uuid === void 0) { + this.array.buffer._uuid = generateUUID2(); + } + if (data.arrayBuffers[this.array.buffer._uuid] === void 0) { + data.arrayBuffers[this.array.buffer._uuid] = this.array.slice(0).buffer; + } + const array2 = new this.array.constructor(data.arrayBuffers[this.array.buffer._uuid]); + const ib = new this.constructor(array2, this.stride); + ib.setUsage(this.usage); + return ib; + } + onUpload(callback) { + this.onUploadCallback = callback; + return this; + } + toJSON(data) { + if (data.arrayBuffers === void 0) { + data.arrayBuffers = {}; + } + if (this.array.buffer._uuid === void 0) { + this.array.buffer._uuid = generateUUID2(); + } + if (data.arrayBuffers[this.array.buffer._uuid] === void 0) { + data.arrayBuffers[this.array.buffer._uuid] = Array.from(new Uint32Array(this.array.buffer)); + } + return { + uuid: this.uuid, + buffer: this.array.buffer._uuid, + type: this.array.constructor.name, + stride: this.stride + }; + } + }; + var _vector$6 = /* @__PURE__ */ new Vector32(); + var InterleavedBufferAttribute = class { + constructor(interleavedBuffer, itemSize, offset, normalized = false) { + this.isInterleavedBufferAttribute = true; + this.name = ""; + this.data = interleavedBuffer; + this.itemSize = itemSize; + this.offset = offset; + this.normalized = normalized === true; + } + get count() { + return this.data.count; + } + get array() { + return this.data.array; + } + set needsUpdate(value) { + this.data.needsUpdate = value; + } + applyMatrix4(m2) { + for (let i = 0, l = this.data.count; i < l; i++) { + _vector$6.fromBufferAttribute(this, i); + _vector$6.applyMatrix4(m2); + this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z); + } + return this; + } + applyNormalMatrix(m2) { + for (let i = 0, l = this.count; i < l; i++) { + _vector$6.fromBufferAttribute(this, i); + _vector$6.applyNormalMatrix(m2); + this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z); + } + return this; + } + transformDirection(m2) { + for (let i = 0, l = this.count; i < l; i++) { + _vector$6.fromBufferAttribute(this, i); + _vector$6.transformDirection(m2); + this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z); + } + return this; + } + setX(index2, x2) { + this.data.array[index2 * this.data.stride + this.offset] = x2; + return this; + } + setY(index2, y2) { + this.data.array[index2 * this.data.stride + this.offset + 1] = y2; + return this; + } + setZ(index2, z) { + this.data.array[index2 * this.data.stride + this.offset + 2] = z; + return this; + } + setW(index2, w) { + this.data.array[index2 * this.data.stride + this.offset + 3] = w; + return this; + } + getX(index2) { + return this.data.array[index2 * this.data.stride + this.offset]; + } + getY(index2) { + return this.data.array[index2 * this.data.stride + this.offset + 1]; + } + getZ(index2) { + return this.data.array[index2 * this.data.stride + this.offset + 2]; + } + getW(index2) { + return this.data.array[index2 * this.data.stride + this.offset + 3]; + } + setXY(index2, x2, y2) { + index2 = index2 * this.data.stride + this.offset; + this.data.array[index2 + 0] = x2; + this.data.array[index2 + 1] = y2; + return this; + } + setXYZ(index2, x2, y2, z) { + index2 = index2 * this.data.stride + this.offset; + this.data.array[index2 + 0] = x2; + this.data.array[index2 + 1] = y2; + this.data.array[index2 + 2] = z; + return this; + } + setXYZW(index2, x2, y2, z, w) { + index2 = index2 * this.data.stride + this.offset; + this.data.array[index2 + 0] = x2; + this.data.array[index2 + 1] = y2; + this.data.array[index2 + 2] = z; + this.data.array[index2 + 3] = w; + return this; + } + clone(data) { + if (data === void 0) { + console.log("THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will deinterleave buffer data."); + const array2 = []; + for (let i = 0; i < this.count; i++) { + const index2 = i * this.data.stride + this.offset; + for (let j = 0; j < this.itemSize; j++) { + array2.push(this.data.array[index2 + j]); + } + } + return new BufferAttribute2(new this.array.constructor(array2), this.itemSize, this.normalized); + } else { + if (data.interleavedBuffers === void 0) { + data.interleavedBuffers = {}; + } + if (data.interleavedBuffers[this.data.uuid] === void 0) { + data.interleavedBuffers[this.data.uuid] = this.data.clone(data); + } + return new InterleavedBufferAttribute(data.interleavedBuffers[this.data.uuid], this.itemSize, this.offset, this.normalized); + } + } + toJSON(data) { + if (data === void 0) { + console.log("THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will deinterleave buffer data."); + const array2 = []; + for (let i = 0; i < this.count; i++) { + const index2 = i * this.data.stride + this.offset; + for (let j = 0; j < this.itemSize; j++) { + array2.push(this.data.array[index2 + j]); + } + } + return { + itemSize: this.itemSize, + type: this.array.constructor.name, + array: array2, + normalized: this.normalized + }; + } else { + if (data.interleavedBuffers === void 0) { + data.interleavedBuffers = {}; + } + if (data.interleavedBuffers[this.data.uuid] === void 0) { + data.interleavedBuffers[this.data.uuid] = this.data.toJSON(data); + } + return { + isInterleavedBufferAttribute: true, + itemSize: this.itemSize, + data: this.data.uuid, + offset: this.offset, + normalized: this.normalized + }; + } + } + }; + var SpriteMaterial = class extends Material2 { + constructor(parameters) { + super(); + this.isSpriteMaterial = true; + this.type = "SpriteMaterial"; + this.color = new Color3(16777215); + this.map = null; + this.alphaMap = null; + this.rotation = 0; + this.sizeAttenuation = true; + this.transparent = true; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.color.copy(source.color); + this.map = source.map; + this.alphaMap = source.alphaMap; + this.rotation = source.rotation; + this.sizeAttenuation = source.sizeAttenuation; + this.fog = source.fog; + return this; + } + }; + var _geometry; + var _intersectPoint = /* @__PURE__ */ new Vector32(); + var _worldScale = /* @__PURE__ */ new Vector32(); + var _mvPosition = /* @__PURE__ */ new Vector32(); + var _alignedPosition = /* @__PURE__ */ new Vector22(); + var _rotatedPosition = /* @__PURE__ */ new Vector22(); + var _viewWorldMatrix = /* @__PURE__ */ new Matrix42(); + var _vA = /* @__PURE__ */ new Vector32(); + var _vB = /* @__PURE__ */ new Vector32(); + var _vC = /* @__PURE__ */ new Vector32(); + var _uvA = /* @__PURE__ */ new Vector22(); + var _uvB = /* @__PURE__ */ new Vector22(); + var _uvC = /* @__PURE__ */ new Vector22(); + var Sprite = class extends Object3D2 { + constructor(material) { + super(); + this.isSprite = true; + this.type = "Sprite"; + if (_geometry === void 0) { + _geometry = new BufferGeometry2(); + const float32Array = new Float32Array([-0.5, -0.5, 0, 0, 0, 0.5, -0.5, 0, 1, 0, 0.5, 0.5, 0, 1, 1, -0.5, 0.5, 0, 0, 1]); + const interleavedBuffer = new InterleavedBuffer(float32Array, 5); + _geometry.setIndex([0, 1, 2, 0, 2, 3]); + _geometry.setAttribute("position", new InterleavedBufferAttribute(interleavedBuffer, 3, 0, false)); + _geometry.setAttribute("uv", new InterleavedBufferAttribute(interleavedBuffer, 2, 3, false)); + } + this.geometry = _geometry; + this.material = material !== void 0 ? material : new SpriteMaterial(); + this.center = new Vector22(0.5, 0.5); + } + raycast(raycaster, intersects2) { + if (raycaster.camera === null) { + console.error('THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.'); + } + _worldScale.setFromMatrixScale(this.matrixWorld); + _viewWorldMatrix.copy(raycaster.camera.matrixWorld); + this.modelViewMatrix.multiplyMatrices(raycaster.camera.matrixWorldInverse, this.matrixWorld); + _mvPosition.setFromMatrixPosition(this.modelViewMatrix); + if (raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false) { + _worldScale.multiplyScalar(-_mvPosition.z); + } + const rotation = this.material.rotation; + let sin, cos; + if (rotation !== 0) { + cos = Math.cos(rotation); + sin = Math.sin(rotation); + } + const center = this.center; + transformVertex(_vA.set(-0.5, -0.5, 0), _mvPosition, center, _worldScale, sin, cos); + transformVertex(_vB.set(0.5, -0.5, 0), _mvPosition, center, _worldScale, sin, cos); + transformVertex(_vC.set(0.5, 0.5, 0), _mvPosition, center, _worldScale, sin, cos); + _uvA.set(0, 0); + _uvB.set(1, 0); + _uvC.set(1, 1); + let intersect = raycaster.ray.intersectTriangle(_vA, _vB, _vC, false, _intersectPoint); + if (intersect === null) { + transformVertex(_vB.set(-0.5, 0.5, 0), _mvPosition, center, _worldScale, sin, cos); + _uvB.set(0, 1); + intersect = raycaster.ray.intersectTriangle(_vA, _vC, _vB, false, _intersectPoint); + if (intersect === null) { + return; + } + } + const distance = raycaster.ray.origin.distanceTo(_intersectPoint); + if (distance < raycaster.near || distance > raycaster.far) + return; + intersects2.push({ + distance, + point: _intersectPoint.clone(), + uv: Triangle2.getUV(_intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector22()), + face: null, + object: this + }); + } + copy(source, recursive) { + super.copy(source, recursive); + if (source.center !== void 0) + this.center.copy(source.center); + this.material = source.material; + return this; + } + }; + function transformVertex(vertexPosition, mvPosition, center, scale, sin, cos) { + _alignedPosition.subVectors(vertexPosition, center).addScalar(0.5).multiply(scale); + if (sin !== void 0) { + _rotatedPosition.x = cos * _alignedPosition.x - sin * _alignedPosition.y; + _rotatedPosition.y = sin * _alignedPosition.x + cos * _alignedPosition.y; + } else { + _rotatedPosition.copy(_alignedPosition); + } + vertexPosition.copy(mvPosition); + vertexPosition.x += _rotatedPosition.x; + vertexPosition.y += _rotatedPosition.y; + vertexPosition.applyMatrix4(_viewWorldMatrix); + } + var _v1$2 = /* @__PURE__ */ new Vector32(); + var _v2$1 = /* @__PURE__ */ new Vector32(); + var LOD = class extends Object3D2 { + constructor() { + super(); + this._currentLevel = 0; + this.type = "LOD"; + Object.defineProperties(this, { + levels: { + enumerable: true, + value: [] + }, + isLOD: { + value: true + } + }); + this.autoUpdate = true; + } + copy(source) { + super.copy(source, false); + const levels = source.levels; + for (let i = 0, l = levels.length; i < l; i++) { + const level = levels[i]; + this.addLevel(level.object.clone(), level.distance); + } + this.autoUpdate = source.autoUpdate; + return this; + } + addLevel(object, distance = 0) { + distance = Math.abs(distance); + const levels = this.levels; + let l; + for (l = 0; l < levels.length; l++) { + if (distance < levels[l].distance) { + break; + } + } + levels.splice(l, 0, { + distance, + object + }); + this.add(object); + return this; + } + getCurrentLevel() { + return this._currentLevel; + } + getObjectForDistance(distance) { + const levels = this.levels; + if (levels.length > 0) { + let i, l; + for (i = 1, l = levels.length; i < l; i++) { + if (distance < levels[i].distance) { + break; + } + } + return levels[i - 1].object; + } + return null; + } + raycast(raycaster, intersects2) { + const levels = this.levels; + if (levels.length > 0) { + _v1$2.setFromMatrixPosition(this.matrixWorld); + const distance = raycaster.ray.origin.distanceTo(_v1$2); + this.getObjectForDistance(distance).raycast(raycaster, intersects2); + } + } + update(camera) { + const levels = this.levels; + if (levels.length > 1) { + _v1$2.setFromMatrixPosition(camera.matrixWorld); + _v2$1.setFromMatrixPosition(this.matrixWorld); + const distance = _v1$2.distanceTo(_v2$1) / camera.zoom; + levels[0].object.visible = true; + let i, l; + for (i = 1, l = levels.length; i < l; i++) { + if (distance >= levels[i].distance) { + levels[i - 1].object.visible = false; + levels[i].object.visible = true; + } else { + break; + } + } + this._currentLevel = i - 1; + for (; i < l; i++) { + levels[i].object.visible = false; + } + } + } + toJSON(meta) { + const data = super.toJSON(meta); + if (this.autoUpdate === false) + data.object.autoUpdate = false; + data.object.levels = []; + const levels = this.levels; + for (let i = 0, l = levels.length; i < l; i++) { + const level = levels[i]; + data.object.levels.push({ + object: level.object.uuid, + distance: level.distance + }); + } + return data; + } + }; + var _basePosition = /* @__PURE__ */ new Vector32(); + var _skinIndex = /* @__PURE__ */ new Vector42(); + var _skinWeight = /* @__PURE__ */ new Vector42(); + var _vector$5 = /* @__PURE__ */ new Vector32(); + var _matrix = /* @__PURE__ */ new Matrix42(); + var SkinnedMesh = class extends Mesh2 { + constructor(geometry, material) { + super(geometry, material); + this.isSkinnedMesh = true; + this.type = "SkinnedMesh"; + this.bindMode = "attached"; + this.bindMatrix = new Matrix42(); + this.bindMatrixInverse = new Matrix42(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.bindMode = source.bindMode; + this.bindMatrix.copy(source.bindMatrix); + this.bindMatrixInverse.copy(source.bindMatrixInverse); + this.skeleton = source.skeleton; + return this; + } + bind(skeleton, bindMatrix) { + this.skeleton = skeleton; + if (bindMatrix === void 0) { + this.updateMatrixWorld(true); + this.skeleton.calculateInverses(); + bindMatrix = this.matrixWorld; + } + this.bindMatrix.copy(bindMatrix); + this.bindMatrixInverse.copy(bindMatrix).invert(); + } + pose() { + this.skeleton.pose(); + } + normalizeSkinWeights() { + const vector = new Vector42(); + const skinWeight = this.geometry.attributes.skinWeight; + for (let i = 0, l = skinWeight.count; i < l; i++) { + vector.fromBufferAttribute(skinWeight, i); + const scale = 1 / vector.manhattanLength(); + if (scale !== Infinity) { + vector.multiplyScalar(scale); + } else { + vector.set(1, 0, 0, 0); + } + skinWeight.setXYZW(i, vector.x, vector.y, vector.z, vector.w); + } + } + updateMatrixWorld(force) { + super.updateMatrixWorld(force); + if (this.bindMode === "attached") { + this.bindMatrixInverse.copy(this.matrixWorld).invert(); + } else if (this.bindMode === "detached") { + this.bindMatrixInverse.copy(this.bindMatrix).invert(); + } else { + console.warn("THREE.SkinnedMesh: Unrecognized bindMode: " + this.bindMode); + } + } + boneTransform(index2, target) { + const skeleton = this.skeleton; + const geometry = this.geometry; + _skinIndex.fromBufferAttribute(geometry.attributes.skinIndex, index2); + _skinWeight.fromBufferAttribute(geometry.attributes.skinWeight, index2); + _basePosition.copy(target).applyMatrix4(this.bindMatrix); + target.set(0, 0, 0); + for (let i = 0; i < 4; i++) { + const weight = _skinWeight.getComponent(i); + if (weight !== 0) { + const boneIndex = _skinIndex.getComponent(i); + _matrix.multiplyMatrices(skeleton.bones[boneIndex].matrixWorld, skeleton.boneInverses[boneIndex]); + target.addScaledVector(_vector$5.copy(_basePosition).applyMatrix4(_matrix), weight); + } + } + return target.applyMatrix4(this.bindMatrixInverse); + } + }; + var Bone = class extends Object3D2 { + constructor() { + super(); + this.isBone = true; + this.type = "Bone"; + } + }; + var DataTexture = class extends Texture2 { + constructor(data = null, width = 1, height = 1, format2, type2, mapping, wrapS, wrapT, magFilter = NearestFilter2, minFilter = NearestFilter2, anisotropy, encoding) { + super(null, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy, encoding); + this.isDataTexture = true; + this.image = { + data, + width, + height + }; + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; + } + }; + var _offsetMatrix = /* @__PURE__ */ new Matrix42(); + var _identityMatrix = /* @__PURE__ */ new Matrix42(); + var Skeleton = class { + constructor(bones = [], boneInverses = []) { + this.uuid = generateUUID2(); + this.bones = bones.slice(0); + this.boneInverses = boneInverses; + this.boneMatrices = null; + this.boneTexture = null; + this.boneTextureSize = 0; + this.frame = -1; + this.init(); + } + init() { + const bones = this.bones; + const boneInverses = this.boneInverses; + this.boneMatrices = new Float32Array(bones.length * 16); + if (boneInverses.length === 0) { + this.calculateInverses(); + } else { + if (bones.length !== boneInverses.length) { + console.warn("THREE.Skeleton: Number of inverse bone matrices does not match amount of bones."); + this.boneInverses = []; + for (let i = 0, il = this.bones.length; i < il; i++) { + this.boneInverses.push(new Matrix42()); + } + } + } + } + calculateInverses() { + this.boneInverses.length = 0; + for (let i = 0, il = this.bones.length; i < il; i++) { + const inverse = new Matrix42(); + if (this.bones[i]) { + inverse.copy(this.bones[i].matrixWorld).invert(); + } + this.boneInverses.push(inverse); + } + } + pose() { + for (let i = 0, il = this.bones.length; i < il; i++) { + const bone = this.bones[i]; + if (bone) { + bone.matrixWorld.copy(this.boneInverses[i]).invert(); + } + } + for (let i = 0, il = this.bones.length; i < il; i++) { + const bone = this.bones[i]; + if (bone) { + if (bone.parent && bone.parent.isBone) { + bone.matrix.copy(bone.parent.matrixWorld).invert(); + bone.matrix.multiply(bone.matrixWorld); + } else { + bone.matrix.copy(bone.matrixWorld); + } + bone.matrix.decompose(bone.position, bone.quaternion, bone.scale); + } + } + } + update() { + const bones = this.bones; + const boneInverses = this.boneInverses; + const boneMatrices = this.boneMatrices; + const boneTexture = this.boneTexture; + for (let i = 0, il = bones.length; i < il; i++) { + const matrix = bones[i] ? bones[i].matrixWorld : _identityMatrix; + _offsetMatrix.multiplyMatrices(matrix, boneInverses[i]); + _offsetMatrix.toArray(boneMatrices, i * 16); + } + if (boneTexture !== null) { + boneTexture.needsUpdate = true; + } + } + clone() { + return new Skeleton(this.bones, this.boneInverses); + } + computeBoneTexture() { + let size = Math.sqrt(this.bones.length * 4); + size = ceilPowerOfTwo(size); + size = Math.max(size, 4); + const boneMatrices = new Float32Array(size * size * 4); + boneMatrices.set(this.boneMatrices); + const boneTexture = new DataTexture(boneMatrices, size, size, RGBAFormat2, FloatType2); + boneTexture.needsUpdate = true; + this.boneMatrices = boneMatrices; + this.boneTexture = boneTexture; + this.boneTextureSize = size; + return this; + } + getBoneByName(name) { + for (let i = 0, il = this.bones.length; i < il; i++) { + const bone = this.bones[i]; + if (bone.name === name) { + return bone; + } + } + return void 0; + } + dispose() { + if (this.boneTexture !== null) { + this.boneTexture.dispose(); + this.boneTexture = null; + } + } + fromJSON(json, bones) { + this.uuid = json.uuid; + for (let i = 0, l = json.bones.length; i < l; i++) { + const uuid = json.bones[i]; + let bone = bones[uuid]; + if (bone === void 0) { + console.warn("THREE.Skeleton: No bone found with UUID:", uuid); + bone = new Bone(); + } + this.bones.push(bone); + this.boneInverses.push(new Matrix42().fromArray(json.boneInverses[i])); + } + this.init(); + return this; + } + toJSON() { + const data = { + metadata: { + version: 4.5, + type: "Skeleton", + generator: "Skeleton.toJSON" + }, + bones: [], + boneInverses: [] + }; + data.uuid = this.uuid; + const bones = this.bones; + const boneInverses = this.boneInverses; + for (let i = 0, l = bones.length; i < l; i++) { + const bone = bones[i]; + data.bones.push(bone.uuid); + const boneInverse = boneInverses[i]; + data.boneInverses.push(boneInverse.toArray()); + } + return data; + } + }; + var InstancedBufferAttribute = class extends BufferAttribute2 { + constructor(array2, itemSize, normalized, meshPerAttribute = 1) { + if (typeof normalized === "number") { + meshPerAttribute = normalized; + normalized = false; + console.error("THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument."); + } + super(array2, itemSize, normalized); + this.isInstancedBufferAttribute = true; + this.meshPerAttribute = meshPerAttribute; + } + copy(source) { + super.copy(source); + this.meshPerAttribute = source.meshPerAttribute; + return this; + } + toJSON() { + const data = super.toJSON(); + data.meshPerAttribute = this.meshPerAttribute; + data.isInstancedBufferAttribute = true; + return data; + } + }; + var _instanceLocalMatrix = /* @__PURE__ */ new Matrix42(); + var _instanceWorldMatrix = /* @__PURE__ */ new Matrix42(); + var _instanceIntersects = []; + var _mesh = /* @__PURE__ */ new Mesh2(); + var InstancedMesh = class extends Mesh2 { + constructor(geometry, material, count) { + super(geometry, material); + this.isInstancedMesh = true; + this.instanceMatrix = new InstancedBufferAttribute(new Float32Array(count * 16), 16); + this.instanceColor = null; + this.count = count; + this.frustumCulled = false; + } + copy(source, recursive) { + super.copy(source, recursive); + this.instanceMatrix.copy(source.instanceMatrix); + if (source.instanceColor !== null) + this.instanceColor = source.instanceColor.clone(); + this.count = source.count; + return this; + } + getColorAt(index2, color2) { + color2.fromArray(this.instanceColor.array, index2 * 3); + } + getMatrixAt(index2, matrix) { + matrix.fromArray(this.instanceMatrix.array, index2 * 16); + } + raycast(raycaster, intersects2) { + const matrixWorld = this.matrixWorld; + const raycastTimes = this.count; + _mesh.geometry = this.geometry; + _mesh.material = this.material; + if (_mesh.material === void 0) + return; + for (let instanceId = 0; instanceId < raycastTimes; instanceId++) { + this.getMatrixAt(instanceId, _instanceLocalMatrix); + _instanceWorldMatrix.multiplyMatrices(matrixWorld, _instanceLocalMatrix); + _mesh.matrixWorld = _instanceWorldMatrix; + _mesh.raycast(raycaster, _instanceIntersects); + for (let i = 0, l = _instanceIntersects.length; i < l; i++) { + const intersect = _instanceIntersects[i]; + intersect.instanceId = instanceId; + intersect.object = this; + intersects2.push(intersect); + } + _instanceIntersects.length = 0; + } + } + setColorAt(index2, color2) { + if (this.instanceColor === null) { + this.instanceColor = new InstancedBufferAttribute(new Float32Array(this.instanceMatrix.count * 3), 3); + } + color2.toArray(this.instanceColor.array, index2 * 3); + } + setMatrixAt(index2, matrix) { + matrix.toArray(this.instanceMatrix.array, index2 * 16); + } + updateMorphTargets() { + } + dispose() { + this.dispatchEvent({ + type: "dispose" + }); + } + }; + var LineBasicMaterial = class extends Material2 { + constructor(parameters) { + super(); + this.isLineBasicMaterial = true; + this.type = "LineBasicMaterial"; + this.color = new Color3(16777215); + this.linewidth = 1; + this.linecap = "round"; + this.linejoin = "round"; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.color.copy(source.color); + this.linewidth = source.linewidth; + this.linecap = source.linecap; + this.linejoin = source.linejoin; + this.fog = source.fog; + return this; + } + }; + var _start$1 = /* @__PURE__ */ new Vector32(); + var _end$1 = /* @__PURE__ */ new Vector32(); + var _inverseMatrix$1 = /* @__PURE__ */ new Matrix42(); + var _ray$1 = /* @__PURE__ */ new Ray2(); + var _sphere$1 = /* @__PURE__ */ new Sphere2(); + var Line = class extends Object3D2 { + constructor(geometry = new BufferGeometry2(), material = new LineBasicMaterial()) { + super(); + this.isLine = true; + this.type = "Line"; + this.geometry = geometry; + this.material = material; + this.updateMorphTargets(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.material = source.material; + this.geometry = source.geometry; + return this; + } + computeLineDistances() { + const geometry = this.geometry; + if (geometry.index === null) { + const positionAttribute = geometry.attributes.position; + const lineDistances = [0]; + for (let i = 1, l = positionAttribute.count; i < l; i++) { + _start$1.fromBufferAttribute(positionAttribute, i - 1); + _end$1.fromBufferAttribute(positionAttribute, i); + lineDistances[i] = lineDistances[i - 1]; + lineDistances[i] += _start$1.distanceTo(_end$1); + } + geometry.setAttribute("lineDistance", new Float32BufferAttribute2(lineDistances, 1)); + } else { + console.warn("THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry."); + } + return this; + } + raycast(raycaster, intersects2) { + const geometry = this.geometry; + const matrixWorld = this.matrixWorld; + const threshold = raycaster.params.Line.threshold; + const drawRange = geometry.drawRange; + if (geometry.boundingSphere === null) + geometry.computeBoundingSphere(); + _sphere$1.copy(geometry.boundingSphere); + _sphere$1.applyMatrix4(matrixWorld); + _sphere$1.radius += threshold; + if (raycaster.ray.intersectsSphere(_sphere$1) === false) + return; + _inverseMatrix$1.copy(matrixWorld).invert(); + _ray$1.copy(raycaster.ray).applyMatrix4(_inverseMatrix$1); + const localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3); + const localThresholdSq = localThreshold * localThreshold; + const vStart = new Vector32(); + const vEnd = new Vector32(); + const interSegment = new Vector32(); + const interRay = new Vector32(); + const step = this.isLineSegments ? 2 : 1; + const index2 = geometry.index; + const attributes = geometry.attributes; + const positionAttribute = attributes.position; + if (index2 !== null) { + const start2 = Math.max(0, drawRange.start); + const end = Math.min(index2.count, drawRange.start + drawRange.count); + for (let i = start2, l = end - 1; i < l; i += step) { + const a2 = index2.getX(i); + const b = index2.getX(i + 1); + vStart.fromBufferAttribute(positionAttribute, a2); + vEnd.fromBufferAttribute(positionAttribute, b); + const distSq = _ray$1.distanceSqToSegment(vStart, vEnd, interRay, interSegment); + if (distSq > localThresholdSq) + continue; + interRay.applyMatrix4(this.matrixWorld); + const distance = raycaster.ray.origin.distanceTo(interRay); + if (distance < raycaster.near || distance > raycaster.far) + continue; + intersects2.push({ + distance, + point: interSegment.clone().applyMatrix4(this.matrixWorld), + index: i, + face: null, + faceIndex: null, + object: this + }); + } + } else { + const start2 = Math.max(0, drawRange.start); + const end = Math.min(positionAttribute.count, drawRange.start + drawRange.count); + for (let i = start2, l = end - 1; i < l; i += step) { + vStart.fromBufferAttribute(positionAttribute, i); + vEnd.fromBufferAttribute(positionAttribute, i + 1); + const distSq = _ray$1.distanceSqToSegment(vStart, vEnd, interRay, interSegment); + if (distSq > localThresholdSq) + continue; + interRay.applyMatrix4(this.matrixWorld); + const distance = raycaster.ray.origin.distanceTo(interRay); + if (distance < raycaster.near || distance > raycaster.far) + continue; + intersects2.push({ + distance, + point: interSegment.clone().applyMatrix4(this.matrixWorld), + index: i, + face: null, + faceIndex: null, + object: this + }); + } + } + } + updateMorphTargets() { + const geometry = this.geometry; + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys(morphAttributes); + if (keys.length > 0) { + const morphAttribute = morphAttributes[keys[0]]; + if (morphAttribute !== void 0) { + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; + for (let m2 = 0, ml = morphAttribute.length; m2 < ml; m2++) { + const name = morphAttribute[m2].name || String(m2); + this.morphTargetInfluences.push(0); + this.morphTargetDictionary[name] = m2; + } + } + } + } + }; + var _start = /* @__PURE__ */ new Vector32(); + var _end = /* @__PURE__ */ new Vector32(); + var LineSegments = class extends Line { + constructor(geometry, material) { + super(geometry, material); + this.isLineSegments = true; + this.type = "LineSegments"; + } + computeLineDistances() { + const geometry = this.geometry; + if (geometry.index === null) { + const positionAttribute = geometry.attributes.position; + const lineDistances = []; + for (let i = 0, l = positionAttribute.count; i < l; i += 2) { + _start.fromBufferAttribute(positionAttribute, i); + _end.fromBufferAttribute(positionAttribute, i + 1); + lineDistances[i] = i === 0 ? 0 : lineDistances[i - 1]; + lineDistances[i + 1] = lineDistances[i] + _start.distanceTo(_end); + } + geometry.setAttribute("lineDistance", new Float32BufferAttribute2(lineDistances, 1)); + } else { + console.warn("THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry."); + } + return this; + } + }; + var LineLoop = class extends Line { + constructor(geometry, material) { + super(geometry, material); + this.isLineLoop = true; + this.type = "LineLoop"; + } + }; + var PointsMaterial = class extends Material2 { + constructor(parameters) { + super(); + this.isPointsMaterial = true; + this.type = "PointsMaterial"; + this.color = new Color3(16777215); + this.map = null; + this.alphaMap = null; + this.size = 1; + this.sizeAttenuation = true; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.color.copy(source.color); + this.map = source.map; + this.alphaMap = source.alphaMap; + this.size = source.size; + this.sizeAttenuation = source.sizeAttenuation; + this.fog = source.fog; + return this; + } + }; + var _inverseMatrix = /* @__PURE__ */ new Matrix42(); + var _ray = /* @__PURE__ */ new Ray2(); + var _sphere = /* @__PURE__ */ new Sphere2(); + var _position$2 = /* @__PURE__ */ new Vector32(); + var Points = class extends Object3D2 { + constructor(geometry = new BufferGeometry2(), material = new PointsMaterial()) { + super(); + this.isPoints = true; + this.type = "Points"; + this.geometry = geometry; + this.material = material; + this.updateMorphTargets(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.material = source.material; + this.geometry = source.geometry; + return this; + } + raycast(raycaster, intersects2) { + const geometry = this.geometry; + const matrixWorld = this.matrixWorld; + const threshold = raycaster.params.Points.threshold; + const drawRange = geometry.drawRange; + if (geometry.boundingSphere === null) + geometry.computeBoundingSphere(); + _sphere.copy(geometry.boundingSphere); + _sphere.applyMatrix4(matrixWorld); + _sphere.radius += threshold; + if (raycaster.ray.intersectsSphere(_sphere) === false) + return; + _inverseMatrix.copy(matrixWorld).invert(); + _ray.copy(raycaster.ray).applyMatrix4(_inverseMatrix); + const localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3); + const localThresholdSq = localThreshold * localThreshold; + const index2 = geometry.index; + const attributes = geometry.attributes; + const positionAttribute = attributes.position; + if (index2 !== null) { + const start2 = Math.max(0, drawRange.start); + const end = Math.min(index2.count, drawRange.start + drawRange.count); + for (let i = start2, il = end; i < il; i++) { + const a2 = index2.getX(i); + _position$2.fromBufferAttribute(positionAttribute, a2); + testPoint(_position$2, a2, localThresholdSq, matrixWorld, raycaster, intersects2, this); + } + } else { + const start2 = Math.max(0, drawRange.start); + const end = Math.min(positionAttribute.count, drawRange.start + drawRange.count); + for (let i = start2, l = end; i < l; i++) { + _position$2.fromBufferAttribute(positionAttribute, i); + testPoint(_position$2, i, localThresholdSq, matrixWorld, raycaster, intersects2, this); + } + } + } + updateMorphTargets() { + const geometry = this.geometry; + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys(morphAttributes); + if (keys.length > 0) { + const morphAttribute = morphAttributes[keys[0]]; + if (morphAttribute !== void 0) { + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; + for (let m2 = 0, ml = morphAttribute.length; m2 < ml; m2++) { + const name = morphAttribute[m2].name || String(m2); + this.morphTargetInfluences.push(0); + this.morphTargetDictionary[name] = m2; + } + } + } + } + }; + function testPoint(point, index2, localThresholdSq, matrixWorld, raycaster, intersects2, object) { + const rayPointDistanceSq = _ray.distanceSqToPoint(point); + if (rayPointDistanceSq < localThresholdSq) { + const intersectPoint = new Vector32(); + _ray.closestPointToPoint(point, intersectPoint); + intersectPoint.applyMatrix4(matrixWorld); + const distance = raycaster.ray.origin.distanceTo(intersectPoint); + if (distance < raycaster.near || distance > raycaster.far) + return; + intersects2.push({ + distance, + distanceToRay: Math.sqrt(rayPointDistanceSq), + point: intersectPoint, + index: index2, + face: null, + object + }); + } + } + var VideoTexture = class extends Texture2 { + constructor(video, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy) { + super(video, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy); + this.isVideoTexture = true; + this.minFilter = minFilter !== void 0 ? minFilter : LinearFilter2; + this.magFilter = magFilter !== void 0 ? magFilter : LinearFilter2; + this.generateMipmaps = false; + const scope = this; + function updateVideo() { + scope.needsUpdate = true; + video.requestVideoFrameCallback(updateVideo); + } + if ("requestVideoFrameCallback" in video) { + video.requestVideoFrameCallback(updateVideo); + } + } + clone() { + return new this.constructor(this.image).copy(this); + } + update() { + const video = this.image; + const hasVideoFrameCallback = "requestVideoFrameCallback" in video; + if (hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA) { + this.needsUpdate = true; + } + } + }; + var FramebufferTexture = class extends Texture2 { + constructor(width, height, format2) { + super({ + width, + height + }); + this.isFramebufferTexture = true; + this.format = format2; + this.magFilter = NearestFilter2; + this.minFilter = NearestFilter2; + this.generateMipmaps = false; + this.needsUpdate = true; + } + }; + var CompressedTexture = class extends Texture2 { + constructor(mipmaps, width, height, format2, type2, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding) { + super(null, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy, encoding); + this.isCompressedTexture = true; + this.image = { + width, + height + }; + this.mipmaps = mipmaps; + this.flipY = false; + this.generateMipmaps = false; + } + }; + var CanvasTexture2 = class extends Texture2 { + constructor(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy) { + super(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy); + this.isCanvasTexture = true; + this.needsUpdate = true; + } + }; + var Curve = class { + constructor() { + this.type = "Curve"; + this.arcLengthDivisions = 200; + } + getPoint() { + console.warn("THREE.Curve: .getPoint() not implemented."); + return null; + } + getPointAt(u, optionalTarget) { + const t = this.getUtoTmapping(u); + return this.getPoint(t, optionalTarget); + } + getPoints(divisions = 5) { + const points = []; + for (let d = 0; d <= divisions; d++) { + points.push(this.getPoint(d / divisions)); + } + return points; + } + getSpacedPoints(divisions = 5) { + const points = []; + for (let d = 0; d <= divisions; d++) { + points.push(this.getPointAt(d / divisions)); + } + return points; + } + getLength() { + const lengths = this.getLengths(); + return lengths[lengths.length - 1]; + } + getLengths(divisions = this.arcLengthDivisions) { + if (this.cacheArcLengths && this.cacheArcLengths.length === divisions + 1 && !this.needsUpdate) { + return this.cacheArcLengths; + } + this.needsUpdate = false; + const cache2 = []; + let current, last = this.getPoint(0); + let sum = 0; + cache2.push(0); + for (let p = 1; p <= divisions; p++) { + current = this.getPoint(p / divisions); + sum += current.distanceTo(last); + cache2.push(sum); + last = current; + } + this.cacheArcLengths = cache2; + return cache2; + } + updateArcLengths() { + this.needsUpdate = true; + this.getLengths(); + } + getUtoTmapping(u, distance) { + const arcLengths = this.getLengths(); + let i = 0; + const il = arcLengths.length; + let targetArcLength; + if (distance) { + targetArcLength = distance; + } else { + targetArcLength = u * arcLengths[il - 1]; + } + let low = 0, high = il - 1, comparison; + while (low <= high) { + i = Math.floor(low + (high - low) / 2); + comparison = arcLengths[i] - targetArcLength; + if (comparison < 0) { + low = i + 1; + } else if (comparison > 0) { + high = i - 1; + } else { + high = i; + break; + } + } + i = high; + if (arcLengths[i] === targetArcLength) { + return i / (il - 1); + } + const lengthBefore = arcLengths[i]; + const lengthAfter = arcLengths[i + 1]; + const segmentLength = lengthAfter - lengthBefore; + const segmentFraction = (targetArcLength - lengthBefore) / segmentLength; + const t = (i + segmentFraction) / (il - 1); + return t; + } + getTangent(t, optionalTarget) { + const delta = 1e-4; + let t1 = t - delta; + let t2 = t + delta; + if (t1 < 0) + t1 = 0; + if (t2 > 1) + t2 = 1; + const pt1 = this.getPoint(t1); + const pt2 = this.getPoint(t2); + const tangent = optionalTarget || (pt1.isVector2 ? new Vector22() : new Vector32()); + tangent.copy(pt2).sub(pt1).normalize(); + return tangent; + } + getTangentAt(u, optionalTarget) { + const t = this.getUtoTmapping(u); + return this.getTangent(t, optionalTarget); + } + computeFrenetFrames(segments, closed) { + const normal = new Vector32(); + const tangents = []; + const normals = []; + const binormals = []; + const vec = new Vector32(); + const mat = new Matrix42(); + for (let i = 0; i <= segments; i++) { + const u = i / segments; + tangents[i] = this.getTangentAt(u, new Vector32()); + } + normals[0] = new Vector32(); + binormals[0] = new Vector32(); + let min2 = Number.MAX_VALUE; + const tx = Math.abs(tangents[0].x); + const ty = Math.abs(tangents[0].y); + const tz = Math.abs(tangents[0].z); + if (tx <= min2) { + min2 = tx; + normal.set(1, 0, 0); + } + if (ty <= min2) { + min2 = ty; + normal.set(0, 1, 0); + } + if (tz <= min2) { + normal.set(0, 0, 1); + } + vec.crossVectors(tangents[0], normal).normalize(); + normals[0].crossVectors(tangents[0], vec); + binormals[0].crossVectors(tangents[0], normals[0]); + for (let i = 1; i <= segments; i++) { + normals[i] = normals[i - 1].clone(); + binormals[i] = binormals[i - 1].clone(); + vec.crossVectors(tangents[i - 1], tangents[i]); + if (vec.length() > Number.EPSILON) { + vec.normalize(); + const theta = Math.acos(clamp2(tangents[i - 1].dot(tangents[i]), -1, 1)); + normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta)); + } + binormals[i].crossVectors(tangents[i], normals[i]); + } + if (closed === true) { + let theta = Math.acos(clamp2(normals[0].dot(normals[segments]), -1, 1)); + theta /= segments; + if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) { + theta = -theta; + } + for (let i = 1; i <= segments; i++) { + normals[i].applyMatrix4(mat.makeRotationAxis(tangents[i], theta * i)); + binormals[i].crossVectors(tangents[i], normals[i]); + } + } + return { + tangents, + normals, + binormals + }; + } + clone() { + return new this.constructor().copy(this); + } + copy(source) { + this.arcLengthDivisions = source.arcLengthDivisions; + return this; + } + toJSON() { + const data = { + metadata: { + version: 4.5, + type: "Curve", + generator: "Curve.toJSON" + } + }; + data.arcLengthDivisions = this.arcLengthDivisions; + data.type = this.type; + return data; + } + fromJSON(json) { + this.arcLengthDivisions = json.arcLengthDivisions; + return this; + } + }; + var EllipseCurve = class extends Curve { + constructor(aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0) { + super(); + this.isEllipseCurve = true; + this.type = "EllipseCurve"; + this.aX = aX; + this.aY = aY; + this.xRadius = xRadius; + this.yRadius = yRadius; + this.aStartAngle = aStartAngle; + this.aEndAngle = aEndAngle; + this.aClockwise = aClockwise; + this.aRotation = aRotation; + } + getPoint(t, optionalTarget) { + const point = optionalTarget || new Vector22(); + const twoPi = Math.PI * 2; + let deltaAngle = this.aEndAngle - this.aStartAngle; + const samePoints = Math.abs(deltaAngle) < Number.EPSILON; + while (deltaAngle < 0) + deltaAngle += twoPi; + while (deltaAngle > twoPi) + deltaAngle -= twoPi; + if (deltaAngle < Number.EPSILON) { + if (samePoints) { + deltaAngle = 0; + } else { + deltaAngle = twoPi; + } + } + if (this.aClockwise === true && !samePoints) { + if (deltaAngle === twoPi) { + deltaAngle = -twoPi; + } else { + deltaAngle = deltaAngle - twoPi; + } + } + const angle = this.aStartAngle + t * deltaAngle; + let x2 = this.aX + this.xRadius * Math.cos(angle); + let y2 = this.aY + this.yRadius * Math.sin(angle); + if (this.aRotation !== 0) { + const cos = Math.cos(this.aRotation); + const sin = Math.sin(this.aRotation); + const tx = x2 - this.aX; + const ty = y2 - this.aY; + x2 = tx * cos - ty * sin + this.aX; + y2 = tx * sin + ty * cos + this.aY; + } + return point.set(x2, y2); + } + copy(source) { + super.copy(source); + this.aX = source.aX; + this.aY = source.aY; + this.xRadius = source.xRadius; + this.yRadius = source.yRadius; + this.aStartAngle = source.aStartAngle; + this.aEndAngle = source.aEndAngle; + this.aClockwise = source.aClockwise; + this.aRotation = source.aRotation; + return this; + } + toJSON() { + const data = super.toJSON(); + data.aX = this.aX; + data.aY = this.aY; + data.xRadius = this.xRadius; + data.yRadius = this.yRadius; + data.aStartAngle = this.aStartAngle; + data.aEndAngle = this.aEndAngle; + data.aClockwise = this.aClockwise; + data.aRotation = this.aRotation; + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.aX = json.aX; + this.aY = json.aY; + this.xRadius = json.xRadius; + this.yRadius = json.yRadius; + this.aStartAngle = json.aStartAngle; + this.aEndAngle = json.aEndAngle; + this.aClockwise = json.aClockwise; + this.aRotation = json.aRotation; + return this; + } + }; + var ArcCurve = class extends EllipseCurve { + constructor(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) { + super(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise); + this.isArcCurve = true; + this.type = "ArcCurve"; + } + }; + function CubicPoly() { + let c0 = 0, c1 = 0, c2 = 0, c3 = 0; + function init2(x0, x1, t0, t1) { + c0 = x0; + c1 = t0; + c2 = -3 * x0 + 3 * x1 - 2 * t0 - t1; + c3 = 2 * x0 - 2 * x1 + t0 + t1; + } + return { + initCatmullRom: function(x0, x1, x2, x3, tension) { + init2(x1, x2, tension * (x2 - x0), tension * (x3 - x1)); + }, + initNonuniformCatmullRom: function(x0, x1, x2, x3, dt0, dt1, dt2) { + let t1 = (x1 - x0) / dt0 - (x2 - x0) / (dt0 + dt1) + (x2 - x1) / dt1; + let t2 = (x2 - x1) / dt1 - (x3 - x1) / (dt1 + dt2) + (x3 - x2) / dt2; + t1 *= dt1; + t2 *= dt1; + init2(x1, x2, t1, t2); + }, + calc: function(t) { + const t2 = t * t; + const t3 = t2 * t; + return c0 + c1 * t + c2 * t2 + c3 * t3; + } + }; + } + var tmp = /* @__PURE__ */ new Vector32(); + var px = /* @__PURE__ */ new CubicPoly(); + var py = /* @__PURE__ */ new CubicPoly(); + var pz = /* @__PURE__ */ new CubicPoly(); + var CatmullRomCurve3 = class extends Curve { + constructor(points = [], closed = false, curveType = "centripetal", tension = 0.5) { + super(); + this.isCatmullRomCurve3 = true; + this.type = "CatmullRomCurve3"; + this.points = points; + this.closed = closed; + this.curveType = curveType; + this.tension = tension; + } + getPoint(t, optionalTarget = new Vector32()) { + const point = optionalTarget; + const points = this.points; + const l = points.length; + const p = (l - (this.closed ? 0 : 1)) * t; + let intPoint = Math.floor(p); + let weight = p - intPoint; + if (this.closed) { + intPoint += intPoint > 0 ? 0 : (Math.floor(Math.abs(intPoint) / l) + 1) * l; + } else if (weight === 0 && intPoint === l - 1) { + intPoint = l - 2; + weight = 1; + } + let p0, p3; + if (this.closed || intPoint > 0) { + p0 = points[(intPoint - 1) % l]; + } else { + tmp.subVectors(points[0], points[1]).add(points[0]); + p0 = tmp; + } + const p1 = points[intPoint % l]; + const p2 = points[(intPoint + 1) % l]; + if (this.closed || intPoint + 2 < l) { + p3 = points[(intPoint + 2) % l]; + } else { + tmp.subVectors(points[l - 1], points[l - 2]).add(points[l - 1]); + p3 = tmp; + } + if (this.curveType === "centripetal" || this.curveType === "chordal") { + const pow = this.curveType === "chordal" ? 0.5 : 0.25; + let dt0 = Math.pow(p0.distanceToSquared(p1), pow); + let dt1 = Math.pow(p1.distanceToSquared(p2), pow); + let dt2 = Math.pow(p2.distanceToSquared(p3), pow); + if (dt1 < 1e-4) + dt1 = 1; + if (dt0 < 1e-4) + dt0 = dt1; + if (dt2 < 1e-4) + dt2 = dt1; + px.initNonuniformCatmullRom(p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2); + py.initNonuniformCatmullRom(p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2); + pz.initNonuniformCatmullRom(p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2); + } else if (this.curveType === "catmullrom") { + px.initCatmullRom(p0.x, p1.x, p2.x, p3.x, this.tension); + py.initCatmullRom(p0.y, p1.y, p2.y, p3.y, this.tension); + pz.initCatmullRom(p0.z, p1.z, p2.z, p3.z, this.tension); + } + point.set(px.calc(weight), py.calc(weight), pz.calc(weight)); + return point; + } + copy(source) { + super.copy(source); + this.points = []; + for (let i = 0, l = source.points.length; i < l; i++) { + const point = source.points[i]; + this.points.push(point.clone()); + } + this.closed = source.closed; + this.curveType = source.curveType; + this.tension = source.tension; + return this; + } + toJSON() { + const data = super.toJSON(); + data.points = []; + for (let i = 0, l = this.points.length; i < l; i++) { + const point = this.points[i]; + data.points.push(point.toArray()); + } + data.closed = this.closed; + data.curveType = this.curveType; + data.tension = this.tension; + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.points = []; + for (let i = 0, l = json.points.length; i < l; i++) { + const point = json.points[i]; + this.points.push(new Vector32().fromArray(point)); + } + this.closed = json.closed; + this.curveType = json.curveType; + this.tension = json.tension; + return this; + } + }; + function CatmullRom(t, p0, p1, p2, p3) { + const v0 = (p2 - p0) * 0.5; + const v1 = (p3 - p1) * 0.5; + const t2 = t * t; + const t3 = t * t2; + return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1; + } + function QuadraticBezierP0(t, p) { + const k = 1 - t; + return k * k * p; + } + function QuadraticBezierP1(t, p) { + return 2 * (1 - t) * t * p; + } + function QuadraticBezierP2(t, p) { + return t * t * p; + } + function QuadraticBezier(t, p0, p1, p2) { + return QuadraticBezierP0(t, p0) + QuadraticBezierP1(t, p1) + QuadraticBezierP2(t, p2); + } + function CubicBezierP0(t, p) { + const k = 1 - t; + return k * k * k * p; + } + function CubicBezierP1(t, p) { + const k = 1 - t; + return 3 * k * k * t * p; + } + function CubicBezierP2(t, p) { + return 3 * (1 - t) * t * t * p; + } + function CubicBezierP3(t, p) { + return t * t * t * p; + } + function CubicBezier(t, p0, p1, p2, p3) { + return CubicBezierP0(t, p0) + CubicBezierP1(t, p1) + CubicBezierP2(t, p2) + CubicBezierP3(t, p3); + } + var CubicBezierCurve = class extends Curve { + constructor(v0 = new Vector22(), v1 = new Vector22(), v2 = new Vector22(), v3 = new Vector22()) { + super(); + this.isCubicBezierCurve = true; + this.type = "CubicBezierCurve"; + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + getPoint(t, optionalTarget = new Vector22()) { + const point = optionalTarget; + const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; + point.set(CubicBezier(t, v0.x, v1.x, v2.x, v3.x), CubicBezier(t, v0.y, v1.y, v2.y, v3.y)); + return point; + } + copy(source) { + super.copy(source); + this.v0.copy(source.v0); + this.v1.copy(source.v1); + this.v2.copy(source.v2); + this.v3.copy(source.v3); + return this; + } + toJSON() { + const data = super.toJSON(); + data.v0 = this.v0.toArray(); + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + data.v3 = this.v3.toArray(); + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.v0.fromArray(json.v0); + this.v1.fromArray(json.v1); + this.v2.fromArray(json.v2); + this.v3.fromArray(json.v3); + return this; + } + }; + var CubicBezierCurve3 = class extends Curve { + constructor(v0 = new Vector32(), v1 = new Vector32(), v2 = new Vector32(), v3 = new Vector32()) { + super(); + this.isCubicBezierCurve3 = true; + this.type = "CubicBezierCurve3"; + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + getPoint(t, optionalTarget = new Vector32()) { + const point = optionalTarget; + const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; + point.set(CubicBezier(t, v0.x, v1.x, v2.x, v3.x), CubicBezier(t, v0.y, v1.y, v2.y, v3.y), CubicBezier(t, v0.z, v1.z, v2.z, v3.z)); + return point; + } + copy(source) { + super.copy(source); + this.v0.copy(source.v0); + this.v1.copy(source.v1); + this.v2.copy(source.v2); + this.v3.copy(source.v3); + return this; + } + toJSON() { + const data = super.toJSON(); + data.v0 = this.v0.toArray(); + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + data.v3 = this.v3.toArray(); + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.v0.fromArray(json.v0); + this.v1.fromArray(json.v1); + this.v2.fromArray(json.v2); + this.v3.fromArray(json.v3); + return this; + } + }; + var LineCurve = class extends Curve { + constructor(v1 = new Vector22(), v2 = new Vector22()) { + super(); + this.isLineCurve = true; + this.type = "LineCurve"; + this.v1 = v1; + this.v2 = v2; + } + getPoint(t, optionalTarget = new Vector22()) { + const point = optionalTarget; + if (t === 1) { + point.copy(this.v2); + } else { + point.copy(this.v2).sub(this.v1); + point.multiplyScalar(t).add(this.v1); + } + return point; + } + getPointAt(u, optionalTarget) { + return this.getPoint(u, optionalTarget); + } + getTangent(t, optionalTarget) { + const tangent = optionalTarget || new Vector22(); + tangent.copy(this.v2).sub(this.v1).normalize(); + return tangent; + } + copy(source) { + super.copy(source); + this.v1.copy(source.v1); + this.v2.copy(source.v2); + return this; + } + toJSON() { + const data = super.toJSON(); + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.v1.fromArray(json.v1); + this.v2.fromArray(json.v2); + return this; + } + }; + var LineCurve3 = class extends Curve { + constructor(v1 = new Vector32(), v2 = new Vector32()) { + super(); + this.isLineCurve3 = true; + this.type = "LineCurve3"; + this.v1 = v1; + this.v2 = v2; + } + getPoint(t, optionalTarget = new Vector32()) { + const point = optionalTarget; + if (t === 1) { + point.copy(this.v2); + } else { + point.copy(this.v2).sub(this.v1); + point.multiplyScalar(t).add(this.v1); + } + return point; + } + getPointAt(u, optionalTarget) { + return this.getPoint(u, optionalTarget); + } + copy(source) { + super.copy(source); + this.v1.copy(source.v1); + this.v2.copy(source.v2); + return this; + } + toJSON() { + const data = super.toJSON(); + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.v1.fromArray(json.v1); + this.v2.fromArray(json.v2); + return this; + } + }; + var QuadraticBezierCurve = class extends Curve { + constructor(v0 = new Vector22(), v1 = new Vector22(), v2 = new Vector22()) { + super(); + this.isQuadraticBezierCurve = true; + this.type = "QuadraticBezierCurve"; + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + } + getPoint(t, optionalTarget = new Vector22()) { + const point = optionalTarget; + const v0 = this.v0, v1 = this.v1, v2 = this.v2; + point.set(QuadraticBezier(t, v0.x, v1.x, v2.x), QuadraticBezier(t, v0.y, v1.y, v2.y)); + return point; + } + copy(source) { + super.copy(source); + this.v0.copy(source.v0); + this.v1.copy(source.v1); + this.v2.copy(source.v2); + return this; + } + toJSON() { + const data = super.toJSON(); + data.v0 = this.v0.toArray(); + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.v0.fromArray(json.v0); + this.v1.fromArray(json.v1); + this.v2.fromArray(json.v2); + return this; + } + }; + var QuadraticBezierCurve3 = class extends Curve { + constructor(v0 = new Vector32(), v1 = new Vector32(), v2 = new Vector32()) { + super(); + this.isQuadraticBezierCurve3 = true; + this.type = "QuadraticBezierCurve3"; + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + } + getPoint(t, optionalTarget = new Vector32()) { + const point = optionalTarget; + const v0 = this.v0, v1 = this.v1, v2 = this.v2; + point.set(QuadraticBezier(t, v0.x, v1.x, v2.x), QuadraticBezier(t, v0.y, v1.y, v2.y), QuadraticBezier(t, v0.z, v1.z, v2.z)); + return point; + } + copy(source) { + super.copy(source); + this.v0.copy(source.v0); + this.v1.copy(source.v1); + this.v2.copy(source.v2); + return this; + } + toJSON() { + const data = super.toJSON(); + data.v0 = this.v0.toArray(); + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.v0.fromArray(json.v0); + this.v1.fromArray(json.v1); + this.v2.fromArray(json.v2); + return this; + } + }; + var SplineCurve = class extends Curve { + constructor(points = []) { + super(); + this.isSplineCurve = true; + this.type = "SplineCurve"; + this.points = points; + } + getPoint(t, optionalTarget = new Vector22()) { + const point = optionalTarget; + const points = this.points; + const p = (points.length - 1) * t; + const intPoint = Math.floor(p); + const weight = p - intPoint; + const p0 = points[intPoint === 0 ? intPoint : intPoint - 1]; + const p1 = points[intPoint]; + const p2 = points[intPoint > points.length - 2 ? points.length - 1 : intPoint + 1]; + const p3 = points[intPoint > points.length - 3 ? points.length - 1 : intPoint + 2]; + point.set(CatmullRom(weight, p0.x, p1.x, p2.x, p3.x), CatmullRom(weight, p0.y, p1.y, p2.y, p3.y)); + return point; + } + copy(source) { + super.copy(source); + this.points = []; + for (let i = 0, l = source.points.length; i < l; i++) { + const point = source.points[i]; + this.points.push(point.clone()); + } + return this; + } + toJSON() { + const data = super.toJSON(); + data.points = []; + for (let i = 0, l = this.points.length; i < l; i++) { + const point = this.points[i]; + data.points.push(point.toArray()); + } + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.points = []; + for (let i = 0, l = json.points.length; i < l; i++) { + const point = json.points[i]; + this.points.push(new Vector22().fromArray(point)); + } + return this; + } + }; + var Curves = /* @__PURE__ */ Object.freeze({ + __proto__: null, + ArcCurve, + CatmullRomCurve3, + CubicBezierCurve, + CubicBezierCurve3, + EllipseCurve, + LineCurve, + LineCurve3, + QuadraticBezierCurve, + QuadraticBezierCurve3, + SplineCurve + }); + var CurvePath = class extends Curve { + constructor() { + super(); + this.type = "CurvePath"; + this.curves = []; + this.autoClose = false; + } + add(curve) { + this.curves.push(curve); + } + closePath() { + const startPoint = this.curves[0].getPoint(0); + const endPoint = this.curves[this.curves.length - 1].getPoint(1); + if (!startPoint.equals(endPoint)) { + this.curves.push(new LineCurve(endPoint, startPoint)); + } + } + getPoint(t, optionalTarget) { + const d = t * this.getLength(); + const curveLengths = this.getCurveLengths(); + let i = 0; + while (i < curveLengths.length) { + if (curveLengths[i] >= d) { + const diff = curveLengths[i] - d; + const curve = this.curves[i]; + const segmentLength = curve.getLength(); + const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; + return curve.getPointAt(u, optionalTarget); + } + i++; + } + return null; + } + getLength() { + const lens = this.getCurveLengths(); + return lens[lens.length - 1]; + } + updateArcLengths() { + this.needsUpdate = true; + this.cacheLengths = null; + this.getCurveLengths(); + } + getCurveLengths() { + if (this.cacheLengths && this.cacheLengths.length === this.curves.length) { + return this.cacheLengths; + } + const lengths = []; + let sums = 0; + for (let i = 0, l = this.curves.length; i < l; i++) { + sums += this.curves[i].getLength(); + lengths.push(sums); + } + this.cacheLengths = lengths; + return lengths; + } + getSpacedPoints(divisions = 40) { + const points = []; + for (let i = 0; i <= divisions; i++) { + points.push(this.getPoint(i / divisions)); + } + if (this.autoClose) { + points.push(points[0]); + } + return points; + } + getPoints(divisions = 12) { + const points = []; + let last; + for (let i = 0, curves = this.curves; i < curves.length; i++) { + const curve = curves[i]; + const resolution = curve.isEllipseCurve ? divisions * 2 : curve.isLineCurve || curve.isLineCurve3 ? 1 : curve.isSplineCurve ? divisions * curve.points.length : divisions; + const pts = curve.getPoints(resolution); + for (let j = 0; j < pts.length; j++) { + const point = pts[j]; + if (last && last.equals(point)) + continue; + points.push(point); + last = point; + } + } + if (this.autoClose && points.length > 1 && !points[points.length - 1].equals(points[0])) { + points.push(points[0]); + } + return points; + } + copy(source) { + super.copy(source); + this.curves = []; + for (let i = 0, l = source.curves.length; i < l; i++) { + const curve = source.curves[i]; + this.curves.push(curve.clone()); + } + this.autoClose = source.autoClose; + return this; + } + toJSON() { + const data = super.toJSON(); + data.autoClose = this.autoClose; + data.curves = []; + for (let i = 0, l = this.curves.length; i < l; i++) { + const curve = this.curves[i]; + data.curves.push(curve.toJSON()); + } + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.autoClose = json.autoClose; + this.curves = []; + for (let i = 0, l = json.curves.length; i < l; i++) { + const curve = json.curves[i]; + this.curves.push(new Curves[curve.type]().fromJSON(curve)); + } + return this; + } + }; + var Path = class extends CurvePath { + constructor(points) { + super(); + this.type = "Path"; + this.currentPoint = new Vector22(); + if (points) { + this.setFromPoints(points); + } + } + setFromPoints(points) { + this.moveTo(points[0].x, points[0].y); + for (let i = 1, l = points.length; i < l; i++) { + this.lineTo(points[i].x, points[i].y); + } + return this; + } + moveTo(x2, y2) { + this.currentPoint.set(x2, y2); + return this; + } + lineTo(x2, y2) { + const curve = new LineCurve(this.currentPoint.clone(), new Vector22(x2, y2)); + this.curves.push(curve); + this.currentPoint.set(x2, y2); + return this; + } + quadraticCurveTo(aCPx, aCPy, aX, aY) { + const curve = new QuadraticBezierCurve(this.currentPoint.clone(), new Vector22(aCPx, aCPy), new Vector22(aX, aY)); + this.curves.push(curve); + this.currentPoint.set(aX, aY); + return this; + } + bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) { + const curve = new CubicBezierCurve(this.currentPoint.clone(), new Vector22(aCP1x, aCP1y), new Vector22(aCP2x, aCP2y), new Vector22(aX, aY)); + this.curves.push(curve); + this.currentPoint.set(aX, aY); + return this; + } + splineThru(pts) { + const npts = [this.currentPoint.clone()].concat(pts); + const curve = new SplineCurve(npts); + this.curves.push(curve); + this.currentPoint.copy(pts[pts.length - 1]); + return this; + } + arc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) { + const x0 = this.currentPoint.x; + const y0 = this.currentPoint.y; + this.absarc(aX + x0, aY + y0, aRadius, aStartAngle, aEndAngle, aClockwise); + return this; + } + absarc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) { + this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise); + return this; + } + ellipse(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) { + const x0 = this.currentPoint.x; + const y0 = this.currentPoint.y; + this.absellipse(aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation); + return this; + } + absellipse(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) { + const curve = new EllipseCurve(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation); + if (this.curves.length > 0) { + const firstPoint = curve.getPoint(0); + if (!firstPoint.equals(this.currentPoint)) { + this.lineTo(firstPoint.x, firstPoint.y); + } + } + this.curves.push(curve); + const lastPoint = curve.getPoint(1); + this.currentPoint.copy(lastPoint); + return this; + } + copy(source) { + super.copy(source); + this.currentPoint.copy(source.currentPoint); + return this; + } + toJSON() { + const data = super.toJSON(); + data.currentPoint = this.currentPoint.toArray(); + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.currentPoint.fromArray(json.currentPoint); + return this; + } + }; + var LatheGeometry = class extends BufferGeometry2 { + constructor(points = [new Vector22(0, -0.5), new Vector22(0.5, 0), new Vector22(0, 0.5)], segments = 12, phiStart = 0, phiLength = Math.PI * 2) { + super(); + this.type = "LatheGeometry"; + this.parameters = { + points, + segments, + phiStart, + phiLength + }; + segments = Math.floor(segments); + phiLength = clamp2(phiLength, 0, Math.PI * 2); + const indices = []; + const vertices = []; + const uvs = []; + const initNormals = []; + const normals = []; + const inverseSegments = 1 / segments; + const vertex3 = new Vector32(); + const uv = new Vector22(); + const normal = new Vector32(); + const curNormal = new Vector32(); + const prevNormal = new Vector32(); + let dx = 0; + let dy = 0; + for (let j = 0; j <= points.length - 1; j++) { + switch (j) { + case 0: + dx = points[j + 1].x - points[j].x; + dy = points[j + 1].y - points[j].y; + normal.x = dy * 1; + normal.y = -dx; + normal.z = dy * 0; + prevNormal.copy(normal); + normal.normalize(); + initNormals.push(normal.x, normal.y, normal.z); + break; + case points.length - 1: + initNormals.push(prevNormal.x, prevNormal.y, prevNormal.z); + break; + default: + dx = points[j + 1].x - points[j].x; + dy = points[j + 1].y - points[j].y; + normal.x = dy * 1; + normal.y = -dx; + normal.z = dy * 0; + curNormal.copy(normal); + normal.x += prevNormal.x; + normal.y += prevNormal.y; + normal.z += prevNormal.z; + normal.normalize(); + initNormals.push(normal.x, normal.y, normal.z); + prevNormal.copy(curNormal); + } + } + for (let i = 0; i <= segments; i++) { + const phi = phiStart + i * inverseSegments * phiLength; + const sin = Math.sin(phi); + const cos = Math.cos(phi); + for (let j = 0; j <= points.length - 1; j++) { + vertex3.x = points[j].x * sin; + vertex3.y = points[j].y; + vertex3.z = points[j].x * cos; + vertices.push(vertex3.x, vertex3.y, vertex3.z); + uv.x = i / segments; + uv.y = j / (points.length - 1); + uvs.push(uv.x, uv.y); + const x2 = initNormals[3 * j + 0] * sin; + const y2 = initNormals[3 * j + 1]; + const z = initNormals[3 * j + 0] * cos; + normals.push(x2, y2, z); + } + } + for (let i = 0; i < segments; i++) { + for (let j = 0; j < points.length - 1; j++) { + const base = j + i * points.length; + const a2 = base; + const b = base + points.length; + const c2 = base + points.length + 1; + const d = base + 1; + indices.push(a2, b, d); + indices.push(c2, d, b); + } + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + } + static fromJSON(data) { + return new LatheGeometry(data.points, data.segments, data.phiStart, data.phiLength); + } + }; + var CapsuleGeometry = class extends LatheGeometry { + constructor(radius = 1, length = 1, capSegments = 4, radialSegments = 8) { + const path = new Path(); + path.absarc(0, -length / 2, radius, Math.PI * 1.5, 0); + path.absarc(0, length / 2, radius, 0, Math.PI * 0.5); + super(path.getPoints(capSegments), radialSegments); + this.type = "CapsuleGeometry"; + this.parameters = { + radius, + height: length, + capSegments, + radialSegments + }; + } + static fromJSON(data) { + return new CapsuleGeometry(data.radius, data.length, data.capSegments, data.radialSegments); + } + }; + var CircleGeometry = class extends BufferGeometry2 { + constructor(radius = 1, segments = 8, thetaStart = 0, thetaLength = Math.PI * 2) { + super(); + this.type = "CircleGeometry"; + this.parameters = { + radius, + segments, + thetaStart, + thetaLength + }; + segments = Math.max(3, segments); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + const vertex3 = new Vector32(); + const uv = new Vector22(); + vertices.push(0, 0, 0); + normals.push(0, 0, 1); + uvs.push(0.5, 0.5); + for (let s = 0, i = 3; s <= segments; s++, i += 3) { + const segment = thetaStart + s / segments * thetaLength; + vertex3.x = radius * Math.cos(segment); + vertex3.y = radius * Math.sin(segment); + vertices.push(vertex3.x, vertex3.y, vertex3.z); + normals.push(0, 0, 1); + uv.x = (vertices[i] / radius + 1) / 2; + uv.y = (vertices[i + 1] / radius + 1) / 2; + uvs.push(uv.x, uv.y); + } + for (let i = 1; i <= segments; i++) { + indices.push(i, i + 1, 0); + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + } + static fromJSON(data) { + return new CircleGeometry(data.radius, data.segments, data.thetaStart, data.thetaLength); + } + }; + var CylinderGeometry = class extends BufferGeometry2 { + constructor(radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) { + super(); + this.type = "CylinderGeometry"; + this.parameters = { + radiusTop, + radiusBottom, + height, + radialSegments, + heightSegments, + openEnded, + thetaStart, + thetaLength + }; + const scope = this; + radialSegments = Math.floor(radialSegments); + heightSegments = Math.floor(heightSegments); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + let index2 = 0; + const indexArray = []; + const halfHeight = height / 2; + let groupStart = 0; + generateTorso(); + if (openEnded === false) { + if (radiusTop > 0) + generateCap(true); + if (radiusBottom > 0) + generateCap(false); + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + function generateTorso() { + const normal = new Vector32(); + const vertex3 = new Vector32(); + let groupCount = 0; + const slope = (radiusBottom - radiusTop) / height; + for (let y2 = 0; y2 <= heightSegments; y2++) { + const indexRow = []; + const v = y2 / heightSegments; + const radius = v * (radiusBottom - radiusTop) + radiusTop; + for (let x2 = 0; x2 <= radialSegments; x2++) { + const u = x2 / radialSegments; + const theta = u * thetaLength + thetaStart; + const sinTheta = Math.sin(theta); + const cosTheta = Math.cos(theta); + vertex3.x = radius * sinTheta; + vertex3.y = -v * height + halfHeight; + vertex3.z = radius * cosTheta; + vertices.push(vertex3.x, vertex3.y, vertex3.z); + normal.set(sinTheta, slope, cosTheta).normalize(); + normals.push(normal.x, normal.y, normal.z); + uvs.push(u, 1 - v); + indexRow.push(index2++); + } + indexArray.push(indexRow); + } + for (let x2 = 0; x2 < radialSegments; x2++) { + for (let y2 = 0; y2 < heightSegments; y2++) { + const a2 = indexArray[y2][x2]; + const b = indexArray[y2 + 1][x2]; + const c2 = indexArray[y2 + 1][x2 + 1]; + const d = indexArray[y2][x2 + 1]; + indices.push(a2, b, d); + indices.push(b, c2, d); + groupCount += 6; + } + } + scope.addGroup(groupStart, groupCount, 0); + groupStart += groupCount; + } + function generateCap(top) { + const centerIndexStart = index2; + const uv = new Vector22(); + const vertex3 = new Vector32(); + let groupCount = 0; + const radius = top === true ? radiusTop : radiusBottom; + const sign2 = top === true ? 1 : -1; + for (let x2 = 1; x2 <= radialSegments; x2++) { + vertices.push(0, halfHeight * sign2, 0); + normals.push(0, sign2, 0); + uvs.push(0.5, 0.5); + index2++; + } + const centerIndexEnd = index2; + for (let x2 = 0; x2 <= radialSegments; x2++) { + const u = x2 / radialSegments; + const theta = u * thetaLength + thetaStart; + const cosTheta = Math.cos(theta); + const sinTheta = Math.sin(theta); + vertex3.x = radius * sinTheta; + vertex3.y = halfHeight * sign2; + vertex3.z = radius * cosTheta; + vertices.push(vertex3.x, vertex3.y, vertex3.z); + normals.push(0, sign2, 0); + uv.x = cosTheta * 0.5 + 0.5; + uv.y = sinTheta * 0.5 * sign2 + 0.5; + uvs.push(uv.x, uv.y); + index2++; + } + for (let x2 = 0; x2 < radialSegments; x2++) { + const c2 = centerIndexStart + x2; + const i = centerIndexEnd + x2; + if (top === true) { + indices.push(i, i + 1, c2); + } else { + indices.push(i + 1, i, c2); + } + groupCount += 3; + } + scope.addGroup(groupStart, groupCount, top === true ? 1 : 2); + groupStart += groupCount; + } + } + static fromJSON(data) { + return new CylinderGeometry(data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength); + } + }; + var ConeGeometry = class extends CylinderGeometry { + constructor(radius = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) { + super(0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength); + this.type = "ConeGeometry"; + this.parameters = { + radius, + height, + radialSegments, + heightSegments, + openEnded, + thetaStart, + thetaLength + }; + } + static fromJSON(data) { + return new ConeGeometry(data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength); + } + }; + var PolyhedronGeometry = class extends BufferGeometry2 { + constructor(vertices = [], indices = [], radius = 1, detail = 0) { + super(); + this.type = "PolyhedronGeometry"; + this.parameters = { + vertices, + indices, + radius, + detail + }; + const vertexBuffer = []; + const uvBuffer = []; + subdivide(detail); + applyRadius(radius); + generateUVs(); + this.setAttribute("position", new Float32BufferAttribute2(vertexBuffer, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(vertexBuffer.slice(), 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvBuffer, 2)); + if (detail === 0) { + this.computeVertexNormals(); + } else { + this.normalizeNormals(); + } + function subdivide(detail2) { + const a2 = new Vector32(); + const b = new Vector32(); + const c2 = new Vector32(); + for (let i = 0; i < indices.length; i += 3) { + getVertexByIndex(indices[i + 0], a2); + getVertexByIndex(indices[i + 1], b); + getVertexByIndex(indices[i + 2], c2); + subdivideFace(a2, b, c2, detail2); + } + } + function subdivideFace(a2, b, c2, detail2) { + const cols = detail2 + 1; + const v = []; + for (let i = 0; i <= cols; i++) { + v[i] = []; + const aj = a2.clone().lerp(c2, i / cols); + const bj = b.clone().lerp(c2, i / cols); + const rows = cols - i; + for (let j = 0; j <= rows; j++) { + if (j === 0 && i === cols) { + v[i][j] = aj; + } else { + v[i][j] = aj.clone().lerp(bj, j / rows); + } + } + } + for (let i = 0; i < cols; i++) { + for (let j = 0; j < 2 * (cols - i) - 1; j++) { + const k = Math.floor(j / 2); + if (j % 2 === 0) { + pushVertex(v[i][k + 1]); + pushVertex(v[i + 1][k]); + pushVertex(v[i][k]); + } else { + pushVertex(v[i][k + 1]); + pushVertex(v[i + 1][k + 1]); + pushVertex(v[i + 1][k]); + } + } + } + } + function applyRadius(radius2) { + const vertex3 = new Vector32(); + for (let i = 0; i < vertexBuffer.length; i += 3) { + vertex3.x = vertexBuffer[i + 0]; + vertex3.y = vertexBuffer[i + 1]; + vertex3.z = vertexBuffer[i + 2]; + vertex3.normalize().multiplyScalar(radius2); + vertexBuffer[i + 0] = vertex3.x; + vertexBuffer[i + 1] = vertex3.y; + vertexBuffer[i + 2] = vertex3.z; + } + } + function generateUVs() { + const vertex3 = new Vector32(); + for (let i = 0; i < vertexBuffer.length; i += 3) { + vertex3.x = vertexBuffer[i + 0]; + vertex3.y = vertexBuffer[i + 1]; + vertex3.z = vertexBuffer[i + 2]; + const u = azimuth(vertex3) / 2 / Math.PI + 0.5; + const v = inclination(vertex3) / Math.PI + 0.5; + uvBuffer.push(u, 1 - v); + } + correctUVs(); + correctSeam(); + } + function correctSeam() { + for (let i = 0; i < uvBuffer.length; i += 6) { + const x0 = uvBuffer[i + 0]; + const x1 = uvBuffer[i + 2]; + const x2 = uvBuffer[i + 4]; + const max2 = Math.max(x0, x1, x2); + const min2 = Math.min(x0, x1, x2); + if (max2 > 0.9 && min2 < 0.1) { + if (x0 < 0.2) + uvBuffer[i + 0] += 1; + if (x1 < 0.2) + uvBuffer[i + 2] += 1; + if (x2 < 0.2) + uvBuffer[i + 4] += 1; + } + } + } + function pushVertex(vertex3) { + vertexBuffer.push(vertex3.x, vertex3.y, vertex3.z); + } + function getVertexByIndex(index2, vertex3) { + const stride = index2 * 3; + vertex3.x = vertices[stride + 0]; + vertex3.y = vertices[stride + 1]; + vertex3.z = vertices[stride + 2]; + } + function correctUVs() { + const a2 = new Vector32(); + const b = new Vector32(); + const c2 = new Vector32(); + const centroid = new Vector32(); + const uvA = new Vector22(); + const uvB = new Vector22(); + const uvC = new Vector22(); + for (let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6) { + a2.set(vertexBuffer[i + 0], vertexBuffer[i + 1], vertexBuffer[i + 2]); + b.set(vertexBuffer[i + 3], vertexBuffer[i + 4], vertexBuffer[i + 5]); + c2.set(vertexBuffer[i + 6], vertexBuffer[i + 7], vertexBuffer[i + 8]); + uvA.set(uvBuffer[j + 0], uvBuffer[j + 1]); + uvB.set(uvBuffer[j + 2], uvBuffer[j + 3]); + uvC.set(uvBuffer[j + 4], uvBuffer[j + 5]); + centroid.copy(a2).add(b).add(c2).divideScalar(3); + const azi = azimuth(centroid); + correctUV(uvA, j + 0, a2, azi); + correctUV(uvB, j + 2, b, azi); + correctUV(uvC, j + 4, c2, azi); + } + } + function correctUV(uv, stride, vector, azimuth2) { + if (azimuth2 < 0 && uv.x === 1) { + uvBuffer[stride] = uv.x - 1; + } + if (vector.x === 0 && vector.z === 0) { + uvBuffer[stride] = azimuth2 / 2 / Math.PI + 0.5; + } + } + function azimuth(vector) { + return Math.atan2(vector.z, -vector.x); + } + function inclination(vector) { + return Math.atan2(-vector.y, Math.sqrt(vector.x * vector.x + vector.z * vector.z)); + } + } + static fromJSON(data) { + return new PolyhedronGeometry(data.vertices, data.indices, data.radius, data.details); + } + }; + var DodecahedronGeometry = class extends PolyhedronGeometry { + constructor(radius = 1, detail = 0) { + const t = (1 + Math.sqrt(5)) / 2; + const r = 1 / t; + const vertices = [ + -1, + -1, + -1, + -1, + -1, + 1, + -1, + 1, + -1, + -1, + 1, + 1, + 1, + -1, + -1, + 1, + -1, + 1, + 1, + 1, + -1, + 1, + 1, + 1, + 0, + -r, + -t, + 0, + -r, + t, + 0, + r, + -t, + 0, + r, + t, + -r, + -t, + 0, + -r, + t, + 0, + r, + -t, + 0, + r, + t, + 0, + -t, + 0, + -r, + t, + 0, + -r, + -t, + 0, + r, + t, + 0, + r + ]; + const indices = [3, 11, 7, 3, 7, 15, 3, 15, 13, 7, 19, 17, 7, 17, 6, 7, 6, 15, 17, 4, 8, 17, 8, 10, 17, 10, 6, 8, 0, 16, 8, 16, 2, 8, 2, 10, 0, 12, 1, 0, 1, 18, 0, 18, 16, 6, 10, 2, 6, 2, 13, 6, 13, 15, 2, 16, 18, 2, 18, 3, 2, 3, 13, 18, 1, 9, 18, 9, 11, 18, 11, 3, 4, 14, 12, 4, 12, 0, 4, 0, 8, 11, 9, 5, 11, 5, 19, 11, 19, 7, 19, 5, 14, 19, 14, 4, 19, 4, 17, 1, 12, 14, 1, 14, 5, 1, 5, 9]; + super(vertices, indices, radius, detail); + this.type = "DodecahedronGeometry"; + this.parameters = { + radius, + detail + }; + } + static fromJSON(data) { + return new DodecahedronGeometry(data.radius, data.detail); + } + }; + var _v0 = /* @__PURE__ */ new Vector32(); + var _v1$1 = /* @__PURE__ */ new Vector32(); + var _normal = /* @__PURE__ */ new Vector32(); + var _triangle = /* @__PURE__ */ new Triangle2(); + var EdgesGeometry = class extends BufferGeometry2 { + constructor(geometry = null, thresholdAngle = 1) { + super(); + this.type = "EdgesGeometry"; + this.parameters = { + geometry, + thresholdAngle + }; + if (geometry !== null) { + const precisionPoints = 4; + const precision = Math.pow(10, precisionPoints); + const thresholdDot = Math.cos(DEG2RAD2 * thresholdAngle); + const indexAttr = geometry.getIndex(); + const positionAttr = geometry.getAttribute("position"); + const indexCount = indexAttr ? indexAttr.count : positionAttr.count; + const indexArr = [0, 0, 0]; + const vertKeys = ["a", "b", "c"]; + const hashes = new Array(3); + const edgeData = {}; + const vertices = []; + for (let i = 0; i < indexCount; i += 3) { + if (indexAttr) { + indexArr[0] = indexAttr.getX(i); + indexArr[1] = indexAttr.getX(i + 1); + indexArr[2] = indexAttr.getX(i + 2); + } else { + indexArr[0] = i; + indexArr[1] = i + 1; + indexArr[2] = i + 2; + } + const { + a: a2, + b, + c: c2 + } = _triangle; + a2.fromBufferAttribute(positionAttr, indexArr[0]); + b.fromBufferAttribute(positionAttr, indexArr[1]); + c2.fromBufferAttribute(positionAttr, indexArr[2]); + _triangle.getNormal(_normal); + hashes[0] = `${Math.round(a2.x * precision)},${Math.round(a2.y * precision)},${Math.round(a2.z * precision)}`; + hashes[1] = `${Math.round(b.x * precision)},${Math.round(b.y * precision)},${Math.round(b.z * precision)}`; + hashes[2] = `${Math.round(c2.x * precision)},${Math.round(c2.y * precision)},${Math.round(c2.z * precision)}`; + if (hashes[0] === hashes[1] || hashes[1] === hashes[2] || hashes[2] === hashes[0]) { + continue; + } + for (let j = 0; j < 3; j++) { + const jNext = (j + 1) % 3; + const vecHash0 = hashes[j]; + const vecHash1 = hashes[jNext]; + const v0 = _triangle[vertKeys[j]]; + const v1 = _triangle[vertKeys[jNext]]; + const hash = `${vecHash0}_${vecHash1}`; + const reverseHash = `${vecHash1}_${vecHash0}`; + if (reverseHash in edgeData && edgeData[reverseHash]) { + if (_normal.dot(edgeData[reverseHash].normal) <= thresholdDot) { + vertices.push(v0.x, v0.y, v0.z); + vertices.push(v1.x, v1.y, v1.z); + } + edgeData[reverseHash] = null; + } else if (!(hash in edgeData)) { + edgeData[hash] = { + index0: indexArr[j], + index1: indexArr[jNext], + normal: _normal.clone() + }; + } + } + } + for (const key in edgeData) { + if (edgeData[key]) { + const { + index0, + index1 + } = edgeData[key]; + _v0.fromBufferAttribute(positionAttr, index0); + _v1$1.fromBufferAttribute(positionAttr, index1); + vertices.push(_v0.x, _v0.y, _v0.z); + vertices.push(_v1$1.x, _v1$1.y, _v1$1.z); + } + } + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + } + } + }; + var Shape = class extends Path { + constructor(points) { + super(points); + this.uuid = generateUUID2(); + this.type = "Shape"; + this.holes = []; + } + getPointsHoles(divisions) { + const holesPts = []; + for (let i = 0, l = this.holes.length; i < l; i++) { + holesPts[i] = this.holes[i].getPoints(divisions); + } + return holesPts; + } + extractPoints(divisions) { + return { + shape: this.getPoints(divisions), + holes: this.getPointsHoles(divisions) + }; + } + copy(source) { + super.copy(source); + this.holes = []; + for (let i = 0, l = source.holes.length; i < l; i++) { + const hole = source.holes[i]; + this.holes.push(hole.clone()); + } + return this; + } + toJSON() { + const data = super.toJSON(); + data.uuid = this.uuid; + data.holes = []; + for (let i = 0, l = this.holes.length; i < l; i++) { + const hole = this.holes[i]; + data.holes.push(hole.toJSON()); + } + return data; + } + fromJSON(json) { + super.fromJSON(json); + this.uuid = json.uuid; + this.holes = []; + for (let i = 0, l = json.holes.length; i < l; i++) { + const hole = json.holes[i]; + this.holes.push(new Path().fromJSON(hole)); + } + return this; + } + }; + var Earcut = { + triangulate: function(data, holeIndices, dim = 2) { + const hasHoles = holeIndices && holeIndices.length; + const outerLen = hasHoles ? holeIndices[0] * dim : data.length; + let outerNode = linkedList(data, 0, outerLen, dim, true); + const triangles = []; + if (!outerNode || outerNode.next === outerNode.prev) + return triangles; + let minX, minY, maxX, maxY, x2, y2, invSize; + if (hasHoles) + outerNode = eliminateHoles(data, holeIndices, outerNode, dim); + if (data.length > 80 * dim) { + minX = maxX = data[0]; + minY = maxY = data[1]; + for (let i = dim; i < outerLen; i += dim) { + x2 = data[i]; + y2 = data[i + 1]; + if (x2 < minX) + minX = x2; + if (y2 < minY) + minY = y2; + if (x2 > maxX) + maxX = x2; + if (y2 > maxY) + maxY = y2; + } + invSize = Math.max(maxX - minX, maxY - minY); + invSize = invSize !== 0 ? 1 / invSize : 0; + } + earcutLinked(outerNode, triangles, dim, minX, minY, invSize); + return triangles; + } + }; + function linkedList(data, start2, end, dim, clockwise) { + let i, last; + if (clockwise === signedArea(data, start2, end, dim) > 0) { + for (i = start2; i < end; i += dim) + last = insertNode(i, data[i], data[i + 1], last); + } else { + for (i = end - dim; i >= start2; i -= dim) + last = insertNode(i, data[i], data[i + 1], last); + } + if (last && equals(last, last.next)) { + removeNode(last); + last = last.next; + } + return last; + } + function filterPoints(start2, end) { + if (!start2) + return start2; + if (!end) + end = start2; + let p = start2, again; + do { + again = false; + if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { + removeNode(p); + p = end = p.prev; + if (p === p.next) + break; + again = true; + } else { + p = p.next; + } + } while (again || p !== end); + return end; + } + function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) { + if (!ear) + return; + if (!pass && invSize) + indexCurve(ear, minX, minY, invSize); + let stop = ear, prev, next; + while (ear.prev !== ear.next) { + prev = ear.prev; + next = ear.next; + if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) { + triangles.push(prev.i / dim); + triangles.push(ear.i / dim); + triangles.push(next.i / dim); + removeNode(ear); + ear = next.next; + stop = next.next; + continue; + } + ear = next; + if (ear === stop) { + if (!pass) { + earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1); + } else if (pass === 1) { + ear = cureLocalIntersections(filterPoints(ear), triangles, dim); + earcutLinked(ear, triangles, dim, minX, minY, invSize, 2); + } else if (pass === 2) { + splitEarcut(ear, triangles, dim, minX, minY, invSize); + } + break; + } + } + } + function isEar(ear) { + const a2 = ear.prev, b = ear, c2 = ear.next; + if (area(a2, b, c2) >= 0) + return false; + let p = ear.next.next; + while (p !== ear.prev) { + if (pointInTriangle(a2.x, a2.y, b.x, b.y, c2.x, c2.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) + return false; + p = p.next; + } + return true; + } + function isEarHashed(ear, minX, minY, invSize) { + const a2 = ear.prev, b = ear, c2 = ear.next; + if (area(a2, b, c2) >= 0) + return false; + const minTX = a2.x < b.x ? a2.x < c2.x ? a2.x : c2.x : b.x < c2.x ? b.x : c2.x, minTY = a2.y < b.y ? a2.y < c2.y ? a2.y : c2.y : b.y < c2.y ? b.y : c2.y, maxTX = a2.x > b.x ? a2.x > c2.x ? a2.x : c2.x : b.x > c2.x ? b.x : c2.x, maxTY = a2.y > b.y ? a2.y > c2.y ? a2.y : c2.y : b.y > c2.y ? b.y : c2.y; + const minZ = zOrder(minTX, minTY, minX, minY, invSize), maxZ = zOrder(maxTX, maxTY, minX, minY, invSize); + let p = ear.prevZ, n = ear.nextZ; + while (p && p.z >= minZ && n && n.z <= maxZ) { + if (p !== ear.prev && p !== ear.next && pointInTriangle(a2.x, a2.y, b.x, b.y, c2.x, c2.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) + return false; + p = p.prevZ; + if (n !== ear.prev && n !== ear.next && pointInTriangle(a2.x, a2.y, b.x, b.y, c2.x, c2.y, n.x, n.y) && area(n.prev, n, n.next) >= 0) + return false; + n = n.nextZ; + } + while (p && p.z >= minZ) { + if (p !== ear.prev && p !== ear.next && pointInTriangle(a2.x, a2.y, b.x, b.y, c2.x, c2.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) + return false; + p = p.prevZ; + } + while (n && n.z <= maxZ) { + if (n !== ear.prev && n !== ear.next && pointInTriangle(a2.x, a2.y, b.x, b.y, c2.x, c2.y, n.x, n.y) && area(n.prev, n, n.next) >= 0) + return false; + n = n.nextZ; + } + return true; + } + function cureLocalIntersections(start2, triangles, dim) { + let p = start2; + do { + const a2 = p.prev, b = p.next.next; + if (!equals(a2, b) && intersects(a2, p, p.next, b) && locallyInside(a2, b) && locallyInside(b, a2)) { + triangles.push(a2.i / dim); + triangles.push(p.i / dim); + triangles.push(b.i / dim); + removeNode(p); + removeNode(p.next); + p = start2 = b; + } + p = p.next; + } while (p !== start2); + return filterPoints(p); + } + function splitEarcut(start2, triangles, dim, minX, minY, invSize) { + let a2 = start2; + do { + let b = a2.next.next; + while (b !== a2.prev) { + if (a2.i !== b.i && isValidDiagonal(a2, b)) { + let c2 = splitPolygon(a2, b); + a2 = filterPoints(a2, a2.next); + c2 = filterPoints(c2, c2.next); + earcutLinked(a2, triangles, dim, minX, minY, invSize); + earcutLinked(c2, triangles, dim, minX, minY, invSize); + return; + } + b = b.next; + } + a2 = a2.next; + } while (a2 !== start2); + } + function eliminateHoles(data, holeIndices, outerNode, dim) { + const queue = []; + let i, len, start2, end, list; + for (i = 0, len = holeIndices.length; i < len; i++) { + start2 = holeIndices[i] * dim; + end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; + list = linkedList(data, start2, end, dim, false); + if (list === list.next) + list.steiner = true; + queue.push(getLeftmost(list)); + } + queue.sort(compareX); + for (i = 0; i < queue.length; i++) { + eliminateHole(queue[i], outerNode); + outerNode = filterPoints(outerNode, outerNode.next); + } + return outerNode; + } + function compareX(a2, b) { + return a2.x - b.x; + } + function eliminateHole(hole, outerNode) { + outerNode = findHoleBridge(hole, outerNode); + if (outerNode) { + const b = splitPolygon(outerNode, hole); + filterPoints(outerNode, outerNode.next); + filterPoints(b, b.next); + } + } + function findHoleBridge(hole, outerNode) { + let p = outerNode; + const hx = hole.x; + const hy = hole.y; + let qx = -Infinity, m2; + do { + if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) { + const x2 = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); + if (x2 <= hx && x2 > qx) { + qx = x2; + if (x2 === hx) { + if (hy === p.y) + return p; + if (hy === p.next.y) + return p.next; + } + m2 = p.x < p.next.x ? p : p.next; + } + } + p = p.next; + } while (p !== outerNode); + if (!m2) + return null; + if (hx === qx) + return m2; + const stop = m2, mx = m2.x, my = m2.y; + let tanMin = Infinity, tan; + p = m2; + do { + if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) { + tan = Math.abs(hy - p.y) / (hx - p.x); + if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m2.x || p.x === m2.x && sectorContainsSector(m2, p)))) { + m2 = p; + tanMin = tan; + } + } + p = p.next; + } while (p !== stop); + return m2; + } + function sectorContainsSector(m2, p) { + return area(m2.prev, m2, p.prev) < 0 && area(p.next, m2, m2.next) < 0; + } + function indexCurve(start2, minX, minY, invSize) { + let p = start2; + do { + if (p.z === null) + p.z = zOrder(p.x, p.y, minX, minY, invSize); + p.prevZ = p.prev; + p.nextZ = p.next; + p = p.next; + } while (p !== start2); + p.prevZ.nextZ = null; + p.prevZ = null; + sortLinked(p); + } + function sortLinked(list) { + let i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1; + do { + p = list; + list = null; + tail = null; + numMerges = 0; + while (p) { + numMerges++; + q = p; + pSize = 0; + for (i = 0; i < inSize; i++) { + pSize++; + q = q.nextZ; + if (!q) + break; + } + qSize = inSize; + while (pSize > 0 || qSize > 0 && q) { + if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) { + e = p; + p = p.nextZ; + pSize--; + } else { + e = q; + q = q.nextZ; + qSize--; + } + if (tail) + tail.nextZ = e; + else + list = e; + e.prevZ = tail; + tail = e; + } + p = q; + } + tail.nextZ = null; + inSize *= 2; + } while (numMerges > 1); + return list; + } + function zOrder(x2, y2, minX, minY, invSize) { + x2 = 32767 * (x2 - minX) * invSize; + y2 = 32767 * (y2 - minY) * invSize; + x2 = (x2 | x2 << 8) & 16711935; + x2 = (x2 | x2 << 4) & 252645135; + x2 = (x2 | x2 << 2) & 858993459; + x2 = (x2 | x2 << 1) & 1431655765; + y2 = (y2 | y2 << 8) & 16711935; + y2 = (y2 | y2 << 4) & 252645135; + y2 = (y2 | y2 << 2) & 858993459; + y2 = (y2 | y2 << 1) & 1431655765; + return x2 | y2 << 1; + } + function getLeftmost(start2) { + let p = start2, leftmost = start2; + do { + if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y) + leftmost = p; + p = p.next; + } while (p !== start2); + return leftmost; + } + function pointInTriangle(ax, ay, bx, by, cx, cy, px2, py2) { + return (cx - px2) * (ay - py2) - (ax - px2) * (cy - py2) >= 0 && (ax - px2) * (by - py2) - (bx - px2) * (ay - py2) >= 0 && (bx - px2) * (cy - py2) - (cx - px2) * (by - py2) >= 0; + } + function isValidDiagonal(a2, b) { + return a2.next.i !== b.i && a2.prev.i !== b.i && !intersectsPolygon(a2, b) && (locallyInside(a2, b) && locallyInside(b, a2) && middleInside(a2, b) && (area(a2.prev, a2, b.prev) || area(a2, b.prev, b)) || equals(a2, b) && area(a2.prev, a2, a2.next) > 0 && area(b.prev, b, b.next) > 0); + } + function area(p, q, r) { + return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); + } + function equals(p1, p2) { + return p1.x === p2.x && p1.y === p2.y; + } + function intersects(p1, q1, p2, q2) { + const o1 = sign(area(p1, q1, p2)); + const o2 = sign(area(p1, q1, q2)); + const o3 = sign(area(p2, q2, p1)); + const o4 = sign(area(p2, q2, q1)); + if (o1 !== o2 && o3 !== o4) + return true; + if (o1 === 0 && onSegment(p1, p2, q1)) + return true; + if (o2 === 0 && onSegment(p1, q2, q1)) + return true; + if (o3 === 0 && onSegment(p2, p1, q2)) + return true; + if (o4 === 0 && onSegment(p2, q1, q2)) + return true; + return false; + } + function onSegment(p, q, r) { + return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y); + } + function sign(num) { + return num > 0 ? 1 : num < 0 ? -1 : 0; + } + function intersectsPolygon(a2, b) { + let p = a2; + do { + if (p.i !== a2.i && p.next.i !== a2.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a2, b)) + return true; + p = p.next; + } while (p !== a2); + return false; + } + function locallyInside(a2, b) { + return area(a2.prev, a2, a2.next) < 0 ? area(a2, b, a2.next) >= 0 && area(a2, a2.prev, b) >= 0 : area(a2, b, a2.prev) < 0 || area(a2, a2.next, b) < 0; + } + function middleInside(a2, b) { + let p = a2, inside = false; + const px2 = (a2.x + b.x) / 2, py2 = (a2.y + b.y) / 2; + do { + if (p.y > py2 !== p.next.y > py2 && p.next.y !== p.y && px2 < (p.next.x - p.x) * (py2 - p.y) / (p.next.y - p.y) + p.x) + inside = !inside; + p = p.next; + } while (p !== a2); + return inside; + } + function splitPolygon(a2, b) { + const a22 = new Node(a2.i, a2.x, a2.y), b2 = new Node(b.i, b.x, b.y), an = a2.next, bp = b.prev; + a2.next = b; + b.prev = a2; + a22.next = an; + an.prev = a22; + b2.next = a22; + a22.prev = b2; + bp.next = b2; + b2.prev = bp; + return b2; + } + function insertNode(i, x2, y2, last) { + const p = new Node(i, x2, y2); + if (!last) { + p.prev = p; + p.next = p; + } else { + p.next = last.next; + p.prev = last; + last.next.prev = p; + last.next = p; + } + return p; + } + function removeNode(p) { + p.next.prev = p.prev; + p.prev.next = p.next; + if (p.prevZ) + p.prevZ.nextZ = p.nextZ; + if (p.nextZ) + p.nextZ.prevZ = p.prevZ; + } + function Node(i, x2, y2) { + this.i = i; + this.x = x2; + this.y = y2; + this.prev = null; + this.next = null; + this.z = null; + this.prevZ = null; + this.nextZ = null; + this.steiner = false; + } + function signedArea(data, start2, end, dim) { + let sum = 0; + for (let i = start2, j = end - dim; i < end; i += dim) { + sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); + j = i; + } + return sum; + } + var ShapeUtils = class { + static area(contour) { + const n = contour.length; + let a2 = 0; + for (let p = n - 1, q = 0; q < n; p = q++) { + a2 += contour[p].x * contour[q].y - contour[q].x * contour[p].y; + } + return a2 * 0.5; + } + static isClockWise(pts) { + return ShapeUtils.area(pts) < 0; + } + static triangulateShape(contour, holes) { + const vertices = []; + const holeIndices = []; + const faces = []; + removeDupEndPts(contour); + addContour(vertices, contour); + let holeIndex = contour.length; + holes.forEach(removeDupEndPts); + for (let i = 0; i < holes.length; i++) { + holeIndices.push(holeIndex); + holeIndex += holes[i].length; + addContour(vertices, holes[i]); + } + const triangles = Earcut.triangulate(vertices, holeIndices); + for (let i = 0; i < triangles.length; i += 3) { + faces.push(triangles.slice(i, i + 3)); + } + return faces; + } + }; + function removeDupEndPts(points) { + const l = points.length; + if (l > 2 && points[l - 1].equals(points[0])) { + points.pop(); + } + } + function addContour(vertices, contour) { + for (let i = 0; i < contour.length; i++) { + vertices.push(contour[i].x); + vertices.push(contour[i].y); + } + } + var ExtrudeGeometry = class extends BufferGeometry2 { + constructor(shapes = new Shape([new Vector22(0.5, 0.5), new Vector22(-0.5, 0.5), new Vector22(-0.5, -0.5), new Vector22(0.5, -0.5)]), options = {}) { + super(); + this.type = "ExtrudeGeometry"; + this.parameters = { + shapes, + options + }; + shapes = Array.isArray(shapes) ? shapes : [shapes]; + const scope = this; + const verticesArray = []; + const uvArray = []; + for (let i = 0, l = shapes.length; i < l; i++) { + const shape = shapes[i]; + addShape(shape); + } + this.setAttribute("position", new Float32BufferAttribute2(verticesArray, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvArray, 2)); + this.computeVertexNormals(); + function addShape(shape) { + const placeholder = []; + const curveSegments = options.curveSegments !== void 0 ? options.curveSegments : 12; + const steps2 = options.steps !== void 0 ? options.steps : 1; + const depth = options.depth !== void 0 ? options.depth : 1; + let bevelEnabled = options.bevelEnabled !== void 0 ? options.bevelEnabled : true; + let bevelThickness = options.bevelThickness !== void 0 ? options.bevelThickness : 0.2; + let bevelSize = options.bevelSize !== void 0 ? options.bevelSize : bevelThickness - 0.1; + let bevelOffset = options.bevelOffset !== void 0 ? options.bevelOffset : 0; + let bevelSegments = options.bevelSegments !== void 0 ? options.bevelSegments : 3; + const extrudePath = options.extrudePath; + const uvgen = options.UVGenerator !== void 0 ? options.UVGenerator : WorldUVGenerator; + let extrudePts, extrudeByPath = false; + let splineTube, binormal, normal, position2; + if (extrudePath) { + extrudePts = extrudePath.getSpacedPoints(steps2); + extrudeByPath = true; + bevelEnabled = false; + splineTube = extrudePath.computeFrenetFrames(steps2, false); + binormal = new Vector32(); + normal = new Vector32(); + position2 = new Vector32(); + } + if (!bevelEnabled) { + bevelSegments = 0; + bevelThickness = 0; + bevelSize = 0; + bevelOffset = 0; + } + const shapePoints = shape.extractPoints(curveSegments); + let vertices = shapePoints.shape; + const holes = shapePoints.holes; + const reverse = !ShapeUtils.isClockWise(vertices); + if (reverse) { + vertices = vertices.reverse(); + for (let h = 0, hl = holes.length; h < hl; h++) { + const ahole = holes[h]; + if (ShapeUtils.isClockWise(ahole)) { + holes[h] = ahole.reverse(); + } + } + } + const faces = ShapeUtils.triangulateShape(vertices, holes); + const contour = vertices; + for (let h = 0, hl = holes.length; h < hl; h++) { + const ahole = holes[h]; + vertices = vertices.concat(ahole); + } + function scalePt2(pt, vec, size) { + if (!vec) + console.error("THREE.ExtrudeGeometry: vec does not exist"); + return vec.clone().multiplyScalar(size).add(pt); + } + const vlen = vertices.length, flen = faces.length; + function getBevelVec(inPt, inPrev, inNext) { + let v_trans_x, v_trans_y, shrink_by; + const v_prev_x = inPt.x - inPrev.x, v_prev_y = inPt.y - inPrev.y; + const v_next_x = inNext.x - inPt.x, v_next_y = inNext.y - inPt.y; + const v_prev_lensq = v_prev_x * v_prev_x + v_prev_y * v_prev_y; + const collinear0 = v_prev_x * v_next_y - v_prev_y * v_next_x; + if (Math.abs(collinear0) > Number.EPSILON) { + const v_prev_len = Math.sqrt(v_prev_lensq); + const v_next_len = Math.sqrt(v_next_x * v_next_x + v_next_y * v_next_y); + const ptPrevShift_x = inPrev.x - v_prev_y / v_prev_len; + const ptPrevShift_y = inPrev.y + v_prev_x / v_prev_len; + const ptNextShift_x = inNext.x - v_next_y / v_next_len; + const ptNextShift_y = inNext.y + v_next_x / v_next_len; + const sf = ((ptNextShift_x - ptPrevShift_x) * v_next_y - (ptNextShift_y - ptPrevShift_y) * v_next_x) / (v_prev_x * v_next_y - v_prev_y * v_next_x); + v_trans_x = ptPrevShift_x + v_prev_x * sf - inPt.x; + v_trans_y = ptPrevShift_y + v_prev_y * sf - inPt.y; + const v_trans_lensq = v_trans_x * v_trans_x + v_trans_y * v_trans_y; + if (v_trans_lensq <= 2) { + return new Vector22(v_trans_x, v_trans_y); + } else { + shrink_by = Math.sqrt(v_trans_lensq / 2); + } + } else { + let direction_eq = false; + if (v_prev_x > Number.EPSILON) { + if (v_next_x > Number.EPSILON) { + direction_eq = true; + } + } else { + if (v_prev_x < -Number.EPSILON) { + if (v_next_x < -Number.EPSILON) { + direction_eq = true; + } + } else { + if (Math.sign(v_prev_y) === Math.sign(v_next_y)) { + direction_eq = true; + } + } + } + if (direction_eq) { + v_trans_x = -v_prev_y; + v_trans_y = v_prev_x; + shrink_by = Math.sqrt(v_prev_lensq); + } else { + v_trans_x = v_prev_x; + v_trans_y = v_prev_y; + shrink_by = Math.sqrt(v_prev_lensq / 2); + } + } + return new Vector22(v_trans_x / shrink_by, v_trans_y / shrink_by); + } + const contourMovements = []; + for (let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) { + if (j === il) + j = 0; + if (k === il) + k = 0; + contourMovements[i] = getBevelVec(contour[i], contour[j], contour[k]); + } + const holesMovements = []; + let oneHoleMovements, verticesMovements = contourMovements.concat(); + for (let h = 0, hl = holes.length; h < hl; h++) { + const ahole = holes[h]; + oneHoleMovements = []; + for (let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) { + if (j === il) + j = 0; + if (k === il) + k = 0; + oneHoleMovements[i] = getBevelVec(ahole[i], ahole[j], ahole[k]); + } + holesMovements.push(oneHoleMovements); + verticesMovements = verticesMovements.concat(oneHoleMovements); + } + for (let b = 0; b < bevelSegments; b++) { + const t = b / bevelSegments; + const z = bevelThickness * Math.cos(t * Math.PI / 2); + const bs2 = bevelSize * Math.sin(t * Math.PI / 2) + bevelOffset; + for (let i = 0, il = contour.length; i < il; i++) { + const vert = scalePt2(contour[i], contourMovements[i], bs2); + v(vert.x, vert.y, -z); + } + for (let h = 0, hl = holes.length; h < hl; h++) { + const ahole = holes[h]; + oneHoleMovements = holesMovements[h]; + for (let i = 0, il = ahole.length; i < il; i++) { + const vert = scalePt2(ahole[i], oneHoleMovements[i], bs2); + v(vert.x, vert.y, -z); + } + } + } + const bs = bevelSize + bevelOffset; + for (let i = 0; i < vlen; i++) { + const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i]; + if (!extrudeByPath) { + v(vert.x, vert.y, 0); + } else { + normal.copy(splineTube.normals[0]).multiplyScalar(vert.x); + binormal.copy(splineTube.binormals[0]).multiplyScalar(vert.y); + position2.copy(extrudePts[0]).add(normal).add(binormal); + v(position2.x, position2.y, position2.z); + } + } + for (let s = 1; s <= steps2; s++) { + for (let i = 0; i < vlen; i++) { + const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i]; + if (!extrudeByPath) { + v(vert.x, vert.y, depth / steps2 * s); + } else { + normal.copy(splineTube.normals[s]).multiplyScalar(vert.x); + binormal.copy(splineTube.binormals[s]).multiplyScalar(vert.y); + position2.copy(extrudePts[s]).add(normal).add(binormal); + v(position2.x, position2.y, position2.z); + } + } + } + for (let b = bevelSegments - 1; b >= 0; b--) { + const t = b / bevelSegments; + const z = bevelThickness * Math.cos(t * Math.PI / 2); + const bs2 = bevelSize * Math.sin(t * Math.PI / 2) + bevelOffset; + for (let i = 0, il = contour.length; i < il; i++) { + const vert = scalePt2(contour[i], contourMovements[i], bs2); + v(vert.x, vert.y, depth + z); + } + for (let h = 0, hl = holes.length; h < hl; h++) { + const ahole = holes[h]; + oneHoleMovements = holesMovements[h]; + for (let i = 0, il = ahole.length; i < il; i++) { + const vert = scalePt2(ahole[i], oneHoleMovements[i], bs2); + if (!extrudeByPath) { + v(vert.x, vert.y, depth + z); + } else { + v(vert.x, vert.y + extrudePts[steps2 - 1].y, extrudePts[steps2 - 1].x + z); + } + } + } + } + buildLidFaces(); + buildSideFaces(); + function buildLidFaces() { + const start2 = verticesArray.length / 3; + if (bevelEnabled) { + let layer = 0; + let offset = vlen * layer; + for (let i = 0; i < flen; i++) { + const face = faces[i]; + f3(face[2] + offset, face[1] + offset, face[0] + offset); + } + layer = steps2 + bevelSegments * 2; + offset = vlen * layer; + for (let i = 0; i < flen; i++) { + const face = faces[i]; + f3(face[0] + offset, face[1] + offset, face[2] + offset); + } + } else { + for (let i = 0; i < flen; i++) { + const face = faces[i]; + f3(face[2], face[1], face[0]); + } + for (let i = 0; i < flen; i++) { + const face = faces[i]; + f3(face[0] + vlen * steps2, face[1] + vlen * steps2, face[2] + vlen * steps2); + } + } + scope.addGroup(start2, verticesArray.length / 3 - start2, 0); + } + function buildSideFaces() { + const start2 = verticesArray.length / 3; + let layeroffset = 0; + sidewalls(contour, layeroffset); + layeroffset += contour.length; + for (let h = 0, hl = holes.length; h < hl; h++) { + const ahole = holes[h]; + sidewalls(ahole, layeroffset); + layeroffset += ahole.length; + } + scope.addGroup(start2, verticesArray.length / 3 - start2, 1); + } + function sidewalls(contour2, layeroffset) { + let i = contour2.length; + while (--i >= 0) { + const j = i; + let k = i - 1; + if (k < 0) + k = contour2.length - 1; + for (let s = 0, sl = steps2 + bevelSegments * 2; s < sl; s++) { + const slen1 = vlen * s; + const slen2 = vlen * (s + 1); + const a2 = layeroffset + j + slen1, b = layeroffset + k + slen1, c2 = layeroffset + k + slen2, d = layeroffset + j + slen2; + f4(a2, b, c2, d); + } + } + } + function v(x2, y2, z) { + placeholder.push(x2); + placeholder.push(y2); + placeholder.push(z); + } + function f3(a2, b, c2) { + addVertex(a2); + addVertex(b); + addVertex(c2); + const nextIndex = verticesArray.length / 3; + const uvs = uvgen.generateTopUV(scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1); + addUV(uvs[0]); + addUV(uvs[1]); + addUV(uvs[2]); + } + function f4(a2, b, c2, d) { + addVertex(a2); + addVertex(b); + addVertex(d); + addVertex(b); + addVertex(c2); + addVertex(d); + const nextIndex = verticesArray.length / 3; + const uvs = uvgen.generateSideWallUV(scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1); + addUV(uvs[0]); + addUV(uvs[1]); + addUV(uvs[3]); + addUV(uvs[1]); + addUV(uvs[2]); + addUV(uvs[3]); + } + function addVertex(index2) { + verticesArray.push(placeholder[index2 * 3 + 0]); + verticesArray.push(placeholder[index2 * 3 + 1]); + verticesArray.push(placeholder[index2 * 3 + 2]); + } + function addUV(vector2) { + uvArray.push(vector2.x); + uvArray.push(vector2.y); + } + } + } + toJSON() { + const data = super.toJSON(); + const shapes = this.parameters.shapes; + const options = this.parameters.options; + return toJSON$1(shapes, options, data); + } + static fromJSON(data, shapes) { + const geometryShapes = []; + for (let j = 0, jl = data.shapes.length; j < jl; j++) { + const shape = shapes[data.shapes[j]]; + geometryShapes.push(shape); + } + const extrudePath = data.options.extrudePath; + if (extrudePath !== void 0) { + data.options.extrudePath = new Curves[extrudePath.type]().fromJSON(extrudePath); + } + return new ExtrudeGeometry(geometryShapes, data.options); + } + }; + var WorldUVGenerator = { + generateTopUV: function(geometry, vertices, indexA, indexB, indexC) { + const a_x = vertices[indexA * 3]; + const a_y = vertices[indexA * 3 + 1]; + const b_x = vertices[indexB * 3]; + const b_y = vertices[indexB * 3 + 1]; + const c_x = vertices[indexC * 3]; + const c_y = vertices[indexC * 3 + 1]; + return [new Vector22(a_x, a_y), new Vector22(b_x, b_y), new Vector22(c_x, c_y)]; + }, + generateSideWallUV: function(geometry, vertices, indexA, indexB, indexC, indexD) { + const a_x = vertices[indexA * 3]; + const a_y = vertices[indexA * 3 + 1]; + const a_z = vertices[indexA * 3 + 2]; + const b_x = vertices[indexB * 3]; + const b_y = vertices[indexB * 3 + 1]; + const b_z = vertices[indexB * 3 + 2]; + const c_x = vertices[indexC * 3]; + const c_y = vertices[indexC * 3 + 1]; + const c_z = vertices[indexC * 3 + 2]; + const d_x = vertices[indexD * 3]; + const d_y = vertices[indexD * 3 + 1]; + const d_z = vertices[indexD * 3 + 2]; + if (Math.abs(a_y - b_y) < Math.abs(a_x - b_x)) { + return [new Vector22(a_x, 1 - a_z), new Vector22(b_x, 1 - b_z), new Vector22(c_x, 1 - c_z), new Vector22(d_x, 1 - d_z)]; + } else { + return [new Vector22(a_y, 1 - a_z), new Vector22(b_y, 1 - b_z), new Vector22(c_y, 1 - c_z), new Vector22(d_y, 1 - d_z)]; + } + } + }; + function toJSON$1(shapes, options, data) { + data.shapes = []; + if (Array.isArray(shapes)) { + for (let i = 0, l = shapes.length; i < l; i++) { + const shape = shapes[i]; + data.shapes.push(shape.uuid); + } + } else { + data.shapes.push(shapes.uuid); + } + data.options = Object.assign({}, options); + if (options.extrudePath !== void 0) + data.options.extrudePath = options.extrudePath.toJSON(); + return data; + } + var IcosahedronGeometry = class extends PolyhedronGeometry { + constructor(radius = 1, detail = 0) { + const t = (1 + Math.sqrt(5)) / 2; + const vertices = [-1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, 0, 0, -1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, t, 0, -1, t, 0, 1, -t, 0, -1, -t, 0, 1]; + const indices = [0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1]; + super(vertices, indices, radius, detail); + this.type = "IcosahedronGeometry"; + this.parameters = { + radius, + detail + }; + } + static fromJSON(data) { + return new IcosahedronGeometry(data.radius, data.detail); + } + }; + var OctahedronGeometry = class extends PolyhedronGeometry { + constructor(radius = 1, detail = 0) { + const vertices = [1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1]; + const indices = [0, 2, 4, 0, 4, 3, 0, 3, 5, 0, 5, 2, 1, 2, 5, 1, 5, 3, 1, 3, 4, 1, 4, 2]; + super(vertices, indices, radius, detail); + this.type = "OctahedronGeometry"; + this.parameters = { + radius, + detail + }; + } + static fromJSON(data) { + return new OctahedronGeometry(data.radius, data.detail); + } + }; + var RingGeometry = class extends BufferGeometry2 { + constructor(innerRadius = 0.5, outerRadius = 1, thetaSegments = 8, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2) { + super(); + this.type = "RingGeometry"; + this.parameters = { + innerRadius, + outerRadius, + thetaSegments, + phiSegments, + thetaStart, + thetaLength + }; + thetaSegments = Math.max(3, thetaSegments); + phiSegments = Math.max(1, phiSegments); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + let radius = innerRadius; + const radiusStep = (outerRadius - innerRadius) / phiSegments; + const vertex3 = new Vector32(); + const uv = new Vector22(); + for (let j = 0; j <= phiSegments; j++) { + for (let i = 0; i <= thetaSegments; i++) { + const segment = thetaStart + i / thetaSegments * thetaLength; + vertex3.x = radius * Math.cos(segment); + vertex3.y = radius * Math.sin(segment); + vertices.push(vertex3.x, vertex3.y, vertex3.z); + normals.push(0, 0, 1); + uv.x = (vertex3.x / outerRadius + 1) / 2; + uv.y = (vertex3.y / outerRadius + 1) / 2; + uvs.push(uv.x, uv.y); + } + radius += radiusStep; + } + for (let j = 0; j < phiSegments; j++) { + const thetaSegmentLevel = j * (thetaSegments + 1); + for (let i = 0; i < thetaSegments; i++) { + const segment = i + thetaSegmentLevel; + const a2 = segment; + const b = segment + thetaSegments + 1; + const c2 = segment + thetaSegments + 2; + const d = segment + 1; + indices.push(a2, b, d); + indices.push(b, c2, d); + } + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + } + static fromJSON(data) { + return new RingGeometry(data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength); + } + }; + var ShapeGeometry = class extends BufferGeometry2 { + constructor(shapes = new Shape([new Vector22(0, 0.5), new Vector22(-0.5, -0.5), new Vector22(0.5, -0.5)]), curveSegments = 12) { + super(); + this.type = "ShapeGeometry"; + this.parameters = { + shapes, + curveSegments + }; + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + let groupStart = 0; + let groupCount = 0; + if (Array.isArray(shapes) === false) { + addShape(shapes); + } else { + for (let i = 0; i < shapes.length; i++) { + addShape(shapes[i]); + this.addGroup(groupStart, groupCount, i); + groupStart += groupCount; + groupCount = 0; + } + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + function addShape(shape) { + const indexOffset = vertices.length / 3; + const points = shape.extractPoints(curveSegments); + let shapeVertices = points.shape; + const shapeHoles = points.holes; + if (ShapeUtils.isClockWise(shapeVertices) === false) { + shapeVertices = shapeVertices.reverse(); + } + for (let i = 0, l = shapeHoles.length; i < l; i++) { + const shapeHole = shapeHoles[i]; + if (ShapeUtils.isClockWise(shapeHole) === true) { + shapeHoles[i] = shapeHole.reverse(); + } + } + const faces = ShapeUtils.triangulateShape(shapeVertices, shapeHoles); + for (let i = 0, l = shapeHoles.length; i < l; i++) { + const shapeHole = shapeHoles[i]; + shapeVertices = shapeVertices.concat(shapeHole); + } + for (let i = 0, l = shapeVertices.length; i < l; i++) { + const vertex3 = shapeVertices[i]; + vertices.push(vertex3.x, vertex3.y, 0); + normals.push(0, 0, 1); + uvs.push(vertex3.x, vertex3.y); + } + for (let i = 0, l = faces.length; i < l; i++) { + const face = faces[i]; + const a2 = face[0] + indexOffset; + const b = face[1] + indexOffset; + const c2 = face[2] + indexOffset; + indices.push(a2, b, c2); + groupCount += 3; + } + } + } + toJSON() { + const data = super.toJSON(); + const shapes = this.parameters.shapes; + return toJSON(shapes, data); + } + static fromJSON(data, shapes) { + const geometryShapes = []; + for (let j = 0, jl = data.shapes.length; j < jl; j++) { + const shape = shapes[data.shapes[j]]; + geometryShapes.push(shape); + } + return new ShapeGeometry(geometryShapes, data.curveSegments); + } + }; + function toJSON(shapes, data) { + data.shapes = []; + if (Array.isArray(shapes)) { + for (let i = 0, l = shapes.length; i < l; i++) { + const shape = shapes[i]; + data.shapes.push(shape.uuid); + } + } else { + data.shapes.push(shapes.uuid); + } + return data; + } + var SphereGeometry2 = class extends BufferGeometry2 { + constructor(radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI) { + super(); + this.type = "SphereGeometry"; + this.parameters = { + radius, + widthSegments, + heightSegments, + phiStart, + phiLength, + thetaStart, + thetaLength + }; + widthSegments = Math.max(3, Math.floor(widthSegments)); + heightSegments = Math.max(2, Math.floor(heightSegments)); + const thetaEnd = Math.min(thetaStart + thetaLength, Math.PI); + let index2 = 0; + const grid = []; + const vertex3 = new Vector32(); + const normal = new Vector32(); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + for (let iy = 0; iy <= heightSegments; iy++) { + const verticesRow = []; + const v = iy / heightSegments; + let uOffset = 0; + if (iy == 0 && thetaStart == 0) { + uOffset = 0.5 / widthSegments; + } else if (iy == heightSegments && thetaEnd == Math.PI) { + uOffset = -0.5 / widthSegments; + } + for (let ix = 0; ix <= widthSegments; ix++) { + const u = ix / widthSegments; + vertex3.x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); + vertex3.y = radius * Math.cos(thetaStart + v * thetaLength); + vertex3.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); + vertices.push(vertex3.x, vertex3.y, vertex3.z); + normal.copy(vertex3).normalize(); + normals.push(normal.x, normal.y, normal.z); + uvs.push(u + uOffset, 1 - v); + verticesRow.push(index2++); + } + grid.push(verticesRow); + } + for (let iy = 0; iy < heightSegments; iy++) { + for (let ix = 0; ix < widthSegments; ix++) { + const a2 = grid[iy][ix + 1]; + const b = grid[iy][ix]; + const c2 = grid[iy + 1][ix]; + const d = grid[iy + 1][ix + 1]; + if (iy !== 0 || thetaStart > 0) + indices.push(a2, b, d); + if (iy !== heightSegments - 1 || thetaEnd < Math.PI) + indices.push(b, c2, d); + } + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + } + static fromJSON(data) { + return new SphereGeometry2(data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength); + } + }; + var TetrahedronGeometry = class extends PolyhedronGeometry { + constructor(radius = 1, detail = 0) { + const vertices = [1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1]; + const indices = [2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1]; + super(vertices, indices, radius, detail); + this.type = "TetrahedronGeometry"; + this.parameters = { + radius, + detail + }; + } + static fromJSON(data) { + return new TetrahedronGeometry(data.radius, data.detail); + } + }; + var TorusGeometry = class extends BufferGeometry2 { + constructor(radius = 1, tube = 0.4, radialSegments = 8, tubularSegments = 6, arc = Math.PI * 2) { + super(); + this.type = "TorusGeometry"; + this.parameters = { + radius, + tube, + radialSegments, + tubularSegments, + arc + }; + radialSegments = Math.floor(radialSegments); + tubularSegments = Math.floor(tubularSegments); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + const center = new Vector32(); + const vertex3 = new Vector32(); + const normal = new Vector32(); + for (let j = 0; j <= radialSegments; j++) { + for (let i = 0; i <= tubularSegments; i++) { + const u = i / tubularSegments * arc; + const v = j / radialSegments * Math.PI * 2; + vertex3.x = (radius + tube * Math.cos(v)) * Math.cos(u); + vertex3.y = (radius + tube * Math.cos(v)) * Math.sin(u); + vertex3.z = tube * Math.sin(v); + vertices.push(vertex3.x, vertex3.y, vertex3.z); + center.x = radius * Math.cos(u); + center.y = radius * Math.sin(u); + normal.subVectors(vertex3, center).normalize(); + normals.push(normal.x, normal.y, normal.z); + uvs.push(i / tubularSegments); + uvs.push(j / radialSegments); + } + } + for (let j = 1; j <= radialSegments; j++) { + for (let i = 1; i <= tubularSegments; i++) { + const a2 = (tubularSegments + 1) * j + i - 1; + const b = (tubularSegments + 1) * (j - 1) + i - 1; + const c2 = (tubularSegments + 1) * (j - 1) + i; + const d = (tubularSegments + 1) * j + i; + indices.push(a2, b, d); + indices.push(b, c2, d); + } + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + } + static fromJSON(data) { + return new TorusGeometry(data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc); + } + }; + var TorusKnotGeometry = class extends BufferGeometry2 { + constructor(radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3) { + super(); + this.type = "TorusKnotGeometry"; + this.parameters = { + radius, + tube, + tubularSegments, + radialSegments, + p, + q + }; + tubularSegments = Math.floor(tubularSegments); + radialSegments = Math.floor(radialSegments); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + const vertex3 = new Vector32(); + const normal = new Vector32(); + const P1 = new Vector32(); + const P2 = new Vector32(); + const B = new Vector32(); + const T = new Vector32(); + const N = new Vector32(); + for (let i = 0; i <= tubularSegments; ++i) { + const u = i / tubularSegments * p * Math.PI * 2; + calculatePositionOnCurve(u, p, q, radius, P1); + calculatePositionOnCurve(u + 0.01, p, q, radius, P2); + T.subVectors(P2, P1); + N.addVectors(P2, P1); + B.crossVectors(T, N); + N.crossVectors(B, T); + B.normalize(); + N.normalize(); + for (let j = 0; j <= radialSegments; ++j) { + const v = j / radialSegments * Math.PI * 2; + const cx = -tube * Math.cos(v); + const cy = tube * Math.sin(v); + vertex3.x = P1.x + (cx * N.x + cy * B.x); + vertex3.y = P1.y + (cx * N.y + cy * B.y); + vertex3.z = P1.z + (cx * N.z + cy * B.z); + vertices.push(vertex3.x, vertex3.y, vertex3.z); + normal.subVectors(vertex3, P1).normalize(); + normals.push(normal.x, normal.y, normal.z); + uvs.push(i / tubularSegments); + uvs.push(j / radialSegments); + } + } + for (let j = 1; j <= tubularSegments; j++) { + for (let i = 1; i <= radialSegments; i++) { + const a2 = (radialSegments + 1) * (j - 1) + (i - 1); + const b = (radialSegments + 1) * j + (i - 1); + const c2 = (radialSegments + 1) * j + i; + const d = (radialSegments + 1) * (j - 1) + i; + indices.push(a2, b, d); + indices.push(b, c2, d); + } + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + function calculatePositionOnCurve(u, p2, q2, radius2, position) { + const cu = Math.cos(u); + const su = Math.sin(u); + const quOverP = q2 / p2 * u; + const cs = Math.cos(quOverP); + position.x = radius2 * (2 + cs) * 0.5 * cu; + position.y = radius2 * (2 + cs) * su * 0.5; + position.z = radius2 * Math.sin(quOverP) * 0.5; + } + } + static fromJSON(data) { + return new TorusKnotGeometry(data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q); + } + }; + var TubeGeometry = class extends BufferGeometry2 { + constructor(path = new QuadraticBezierCurve3(new Vector32(-1, -1, 0), new Vector32(-1, 1, 0), new Vector32(1, 1, 0)), tubularSegments = 64, radius = 1, radialSegments = 8, closed = false) { + super(); + this.type = "TubeGeometry"; + this.parameters = { + path, + tubularSegments, + radius, + radialSegments, + closed + }; + const frames = path.computeFrenetFrames(tubularSegments, closed); + this.tangents = frames.tangents; + this.normals = frames.normals; + this.binormals = frames.binormals; + const vertex3 = new Vector32(); + const normal = new Vector32(); + const uv = new Vector22(); + let P = new Vector32(); + const vertices = []; + const normals = []; + const uvs = []; + const indices = []; + generateBufferData(); + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute2(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute2(uvs, 2)); + function generateBufferData() { + for (let i = 0; i < tubularSegments; i++) { + generateSegment(i); + } + generateSegment(closed === false ? tubularSegments : 0); + generateUVs(); + generateIndices(); + } + function generateSegment(i) { + P = path.getPointAt(i / tubularSegments, P); + const N = frames.normals[i]; + const B = frames.binormals[i]; + for (let j = 0; j <= radialSegments; j++) { + const v = j / radialSegments * Math.PI * 2; + const sin = Math.sin(v); + const cos = -Math.cos(v); + normal.x = cos * N.x + sin * B.x; + normal.y = cos * N.y + sin * B.y; + normal.z = cos * N.z + sin * B.z; + normal.normalize(); + normals.push(normal.x, normal.y, normal.z); + vertex3.x = P.x + radius * normal.x; + vertex3.y = P.y + radius * normal.y; + vertex3.z = P.z + radius * normal.z; + vertices.push(vertex3.x, vertex3.y, vertex3.z); + } + } + function generateIndices() { + for (let j = 1; j <= tubularSegments; j++) { + for (let i = 1; i <= radialSegments; i++) { + const a2 = (radialSegments + 1) * (j - 1) + (i - 1); + const b = (radialSegments + 1) * j + (i - 1); + const c2 = (radialSegments + 1) * j + i; + const d = (radialSegments + 1) * (j - 1) + i; + indices.push(a2, b, d); + indices.push(b, c2, d); + } + } + } + function generateUVs() { + for (let i = 0; i <= tubularSegments; i++) { + for (let j = 0; j <= radialSegments; j++) { + uv.x = i / tubularSegments; + uv.y = j / radialSegments; + uvs.push(uv.x, uv.y); + } + } + } + } + toJSON() { + const data = super.toJSON(); + data.path = this.parameters.path.toJSON(); + return data; + } + static fromJSON(data) { + return new TubeGeometry(new Curves[data.path.type]().fromJSON(data.path), data.tubularSegments, data.radius, data.radialSegments, data.closed); + } + }; + var WireframeGeometry = class extends BufferGeometry2 { + constructor(geometry = null) { + super(); + this.type = "WireframeGeometry"; + this.parameters = { + geometry + }; + if (geometry !== null) { + const vertices = []; + const edges = /* @__PURE__ */ new Set(); + const start2 = new Vector32(); + const end = new Vector32(); + if (geometry.index !== null) { + const position = geometry.attributes.position; + const indices = geometry.index; + let groups = geometry.groups; + if (groups.length === 0) { + groups = [{ + start: 0, + count: indices.count, + materialIndex: 0 + }]; + } + for (let o = 0, ol = groups.length; o < ol; ++o) { + const group = groups[o]; + const groupStart = group.start; + const groupCount = group.count; + for (let i = groupStart, l = groupStart + groupCount; i < l; i += 3) { + for (let j = 0; j < 3; j++) { + const index1 = indices.getX(i + j); + const index2 = indices.getX(i + (j + 1) % 3); + start2.fromBufferAttribute(position, index1); + end.fromBufferAttribute(position, index2); + if (isUniqueEdge(start2, end, edges) === true) { + vertices.push(start2.x, start2.y, start2.z); + vertices.push(end.x, end.y, end.z); + } + } + } + } + } else { + const position = geometry.attributes.position; + for (let i = 0, l = position.count / 3; i < l; i++) { + for (let j = 0; j < 3; j++) { + const index1 = 3 * i + j; + const index2 = 3 * i + (j + 1) % 3; + start2.fromBufferAttribute(position, index1); + end.fromBufferAttribute(position, index2); + if (isUniqueEdge(start2, end, edges) === true) { + vertices.push(start2.x, start2.y, start2.z); + vertices.push(end.x, end.y, end.z); + } + } + } + } + this.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + } + } + }; + function isUniqueEdge(start2, end, edges) { + const hash1 = `${start2.x},${start2.y},${start2.z}-${end.x},${end.y},${end.z}`; + const hash2 = `${end.x},${end.y},${end.z}-${start2.x},${start2.y},${start2.z}`; + if (edges.has(hash1) === true || edges.has(hash2) === true) { + return false; + } else { + edges.add(hash1); + edges.add(hash2); + return true; + } + } + var Geometries = /* @__PURE__ */ Object.freeze({ + __proto__: null, + BoxGeometry: BoxGeometry2, + BoxBufferGeometry: BoxGeometry2, + CapsuleGeometry, + CapsuleBufferGeometry: CapsuleGeometry, + CircleGeometry, + CircleBufferGeometry: CircleGeometry, + ConeGeometry, + ConeBufferGeometry: ConeGeometry, + CylinderGeometry, + CylinderBufferGeometry: CylinderGeometry, + DodecahedronGeometry, + DodecahedronBufferGeometry: DodecahedronGeometry, + EdgesGeometry, + ExtrudeGeometry, + ExtrudeBufferGeometry: ExtrudeGeometry, + IcosahedronGeometry, + IcosahedronBufferGeometry: IcosahedronGeometry, + LatheGeometry, + LatheBufferGeometry: LatheGeometry, + OctahedronGeometry, + OctahedronBufferGeometry: OctahedronGeometry, + PlaneGeometry: PlaneGeometry2, + PlaneBufferGeometry: PlaneGeometry2, + PolyhedronGeometry, + PolyhedronBufferGeometry: PolyhedronGeometry, + RingGeometry, + RingBufferGeometry: RingGeometry, + ShapeGeometry, + ShapeBufferGeometry: ShapeGeometry, + SphereGeometry: SphereGeometry2, + SphereBufferGeometry: SphereGeometry2, + TetrahedronGeometry, + TetrahedronBufferGeometry: TetrahedronGeometry, + TorusGeometry, + TorusBufferGeometry: TorusGeometry, + TorusKnotGeometry, + TorusKnotBufferGeometry: TorusKnotGeometry, + TubeGeometry, + TubeBufferGeometry: TubeGeometry, + WireframeGeometry + }); + var ShadowMaterial = class extends Material2 { + constructor(parameters) { + super(); + this.isShadowMaterial = true; + this.type = "ShadowMaterial"; + this.color = new Color3(0); + this.transparent = true; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.color.copy(source.color); + this.fog = source.fog; + return this; + } + }; + var RawShaderMaterial = class extends ShaderMaterial2 { + constructor(parameters) { + super(parameters); + this.isRawShaderMaterial = true; + this.type = "RawShaderMaterial"; + } + }; + var MeshStandardMaterial = class extends Material2 { + constructor(parameters) { + super(); + this.isMeshStandardMaterial = true; + this.defines = { + "STANDARD": "" + }; + this.type = "MeshStandardMaterial"; + this.color = new Color3(16777215); + this.roughness = 1; + this.metalness = 0; + this.map = null; + this.lightMap = null; + this.lightMapIntensity = 1; + this.aoMap = null; + this.aoMapIntensity = 1; + this.emissive = new Color3(0); + this.emissiveIntensity = 1; + this.emissiveMap = null; + this.bumpMap = null; + this.bumpScale = 1; + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap2; + this.normalScale = new Vector22(1, 1); + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + this.roughnessMap = null; + this.metalnessMap = null; + this.alphaMap = null; + this.envMap = null; + this.envMapIntensity = 1; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = "round"; + this.wireframeLinejoin = "round"; + this.flatShading = false; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.defines = { + "STANDARD": "" + }; + this.color.copy(source.color); + this.roughness = source.roughness; + this.metalness = source.metalness; + this.map = source.map; + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + this.emissive.copy(source.emissive); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy(source.normalScale); + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + this.roughnessMap = source.roughnessMap; + this.metalnessMap = source.metalnessMap; + this.alphaMap = source.alphaMap; + this.envMap = source.envMap; + this.envMapIntensity = source.envMapIntensity; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + this.flatShading = source.flatShading; + this.fog = source.fog; + return this; + } + }; + var MeshPhysicalMaterial = class extends MeshStandardMaterial { + constructor(parameters) { + super(); + this.isMeshPhysicalMaterial = true; + this.defines = { + "STANDARD": "", + "PHYSICAL": "" + }; + this.type = "MeshPhysicalMaterial"; + this.clearcoatMap = null; + this.clearcoatRoughness = 0; + this.clearcoatRoughnessMap = null; + this.clearcoatNormalScale = new Vector22(1, 1); + this.clearcoatNormalMap = null; + this.ior = 1.5; + Object.defineProperty(this, "reflectivity", { + get: function() { + return clamp2(2.5 * (this.ior - 1) / (this.ior + 1), 0, 1); + }, + set: function(reflectivity) { + this.ior = (1 + 0.4 * reflectivity) / (1 - 0.4 * reflectivity); + } + }); + this.iridescenceMap = null; + this.iridescenceIOR = 1.3; + this.iridescenceThicknessRange = [100, 400]; + this.iridescenceThicknessMap = null; + this.sheenColor = new Color3(0); + this.sheenColorMap = null; + this.sheenRoughness = 1; + this.sheenRoughnessMap = null; + this.transmissionMap = null; + this.thickness = 0; + this.thicknessMap = null; + this.attenuationDistance = 0; + this.attenuationColor = new Color3(1, 1, 1); + this.specularIntensity = 1; + this.specularIntensityMap = null; + this.specularColor = new Color3(1, 1, 1); + this.specularColorMap = null; + this._sheen = 0; + this._clearcoat = 0; + this._iridescence = 0; + this._transmission = 0; + this.setValues(parameters); + } + get sheen() { + return this._sheen; + } + set sheen(value) { + if (this._sheen > 0 !== value > 0) { + this.version++; + } + this._sheen = value; + } + get clearcoat() { + return this._clearcoat; + } + set clearcoat(value) { + if (this._clearcoat > 0 !== value > 0) { + this.version++; + } + this._clearcoat = value; + } + get iridescence() { + return this._iridescence; + } + set iridescence(value) { + if (this._iridescence > 0 !== value > 0) { + this.version++; + } + this._iridescence = value; + } + get transmission() { + return this._transmission; + } + set transmission(value) { + if (this._transmission > 0 !== value > 0) { + this.version++; + } + this._transmission = value; + } + copy(source) { + super.copy(source); + this.defines = { + "STANDARD": "", + "PHYSICAL": "" + }; + this.clearcoat = source.clearcoat; + this.clearcoatMap = source.clearcoatMap; + this.clearcoatRoughness = source.clearcoatRoughness; + this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; + this.clearcoatNormalMap = source.clearcoatNormalMap; + this.clearcoatNormalScale.copy(source.clearcoatNormalScale); + this.ior = source.ior; + this.iridescence = source.iridescence; + this.iridescenceMap = source.iridescenceMap; + this.iridescenceIOR = source.iridescenceIOR; + this.iridescenceThicknessRange = [...source.iridescenceThicknessRange]; + this.iridescenceThicknessMap = source.iridescenceThicknessMap; + this.sheen = source.sheen; + this.sheenColor.copy(source.sheenColor); + this.sheenColorMap = source.sheenColorMap; + this.sheenRoughness = source.sheenRoughness; + this.sheenRoughnessMap = source.sheenRoughnessMap; + this.transmission = source.transmission; + this.transmissionMap = source.transmissionMap; + this.thickness = source.thickness; + this.thicknessMap = source.thicknessMap; + this.attenuationDistance = source.attenuationDistance; + this.attenuationColor.copy(source.attenuationColor); + this.specularIntensity = source.specularIntensity; + this.specularIntensityMap = source.specularIntensityMap; + this.specularColor.copy(source.specularColor); + this.specularColorMap = source.specularColorMap; + return this; + } + }; + var MeshPhongMaterial = class extends Material2 { + constructor(parameters) { + super(); + this.isMeshPhongMaterial = true; + this.type = "MeshPhongMaterial"; + this.color = new Color3(16777215); + this.specular = new Color3(1118481); + this.shininess = 30; + this.map = null; + this.lightMap = null; + this.lightMapIntensity = 1; + this.aoMap = null; + this.aoMapIntensity = 1; + this.emissive = new Color3(0); + this.emissiveIntensity = 1; + this.emissiveMap = null; + this.bumpMap = null; + this.bumpScale = 1; + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap2; + this.normalScale = new Vector22(1, 1); + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + this.specularMap = null; + this.alphaMap = null; + this.envMap = null; + this.combine = MultiplyOperation2; + this.reflectivity = 1; + this.refractionRatio = 0.98; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = "round"; + this.wireframeLinejoin = "round"; + this.flatShading = false; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.color.copy(source.color); + this.specular.copy(source.specular); + this.shininess = source.shininess; + this.map = source.map; + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + this.emissive.copy(source.emissive); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy(source.normalScale); + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + this.specularMap = source.specularMap; + this.alphaMap = source.alphaMap; + this.envMap = source.envMap; + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + this.flatShading = source.flatShading; + this.fog = source.fog; + return this; + } + }; + var MeshToonMaterial = class extends Material2 { + constructor(parameters) { + super(); + this.isMeshToonMaterial = true; + this.defines = { + "TOON": "" + }; + this.type = "MeshToonMaterial"; + this.color = new Color3(16777215); + this.map = null; + this.gradientMap = null; + this.lightMap = null; + this.lightMapIntensity = 1; + this.aoMap = null; + this.aoMapIntensity = 1; + this.emissive = new Color3(0); + this.emissiveIntensity = 1; + this.emissiveMap = null; + this.bumpMap = null; + this.bumpScale = 1; + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap2; + this.normalScale = new Vector22(1, 1); + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + this.alphaMap = null; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = "round"; + this.wireframeLinejoin = "round"; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.color.copy(source.color); + this.map = source.map; + this.gradientMap = source.gradientMap; + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + this.emissive.copy(source.emissive); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy(source.normalScale); + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + this.alphaMap = source.alphaMap; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + this.fog = source.fog; + return this; + } + }; + var MeshNormalMaterial = class extends Material2 { + constructor(parameters) { + super(); + this.isMeshNormalMaterial = true; + this.type = "MeshNormalMaterial"; + this.bumpMap = null; + this.bumpScale = 1; + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap2; + this.normalScale = new Vector22(1, 1); + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.flatShading = false; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy(source.normalScale); + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.flatShading = source.flatShading; + return this; + } + }; + var MeshLambertMaterial = class extends Material2 { + constructor(parameters) { + super(); + this.isMeshLambertMaterial = true; + this.type = "MeshLambertMaterial"; + this.color = new Color3(16777215); + this.map = null; + this.lightMap = null; + this.lightMapIntensity = 1; + this.aoMap = null; + this.aoMapIntensity = 1; + this.emissive = new Color3(0); + this.emissiveIntensity = 1; + this.emissiveMap = null; + this.specularMap = null; + this.alphaMap = null; + this.envMap = null; + this.combine = MultiplyOperation2; + this.reflectivity = 1; + this.refractionRatio = 0.98; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = "round"; + this.wireframeLinejoin = "round"; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.color.copy(source.color); + this.map = source.map; + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + this.emissive.copy(source.emissive); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; + this.specularMap = source.specularMap; + this.alphaMap = source.alphaMap; + this.envMap = source.envMap; + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + this.fog = source.fog; + return this; + } + }; + var MeshMatcapMaterial = class extends Material2 { + constructor(parameters) { + super(); + this.isMeshMatcapMaterial = true; + this.defines = { + "MATCAP": "" + }; + this.type = "MeshMatcapMaterial"; + this.color = new Color3(16777215); + this.matcap = null; + this.map = null; + this.bumpMap = null; + this.bumpScale = 1; + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap2; + this.normalScale = new Vector22(1, 1); + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + this.alphaMap = null; + this.flatShading = false; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.defines = { + "MATCAP": "" + }; + this.color.copy(source.color); + this.matcap = source.matcap; + this.map = source.map; + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy(source.normalScale); + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + this.alphaMap = source.alphaMap; + this.flatShading = source.flatShading; + this.fog = source.fog; + return this; + } + }; + var LineDashedMaterial = class extends LineBasicMaterial { + constructor(parameters) { + super(); + this.isLineDashedMaterial = true; + this.type = "LineDashedMaterial"; + this.scale = 1; + this.dashSize = 3; + this.gapSize = 1; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.scale = source.scale; + this.dashSize = source.dashSize; + this.gapSize = source.gapSize; + return this; + } + }; + function arraySlice2(array2, from, to) { + if (isTypedArray2(array2)) { + return new array2.constructor(array2.subarray(from, to !== void 0 ? to : array2.length)); + } + return array2.slice(from, to); + } + function convertArray2(array2, type2, forceClone) { + if (!array2 || !forceClone && array2.constructor === type2) + return array2; + if (typeof type2.BYTES_PER_ELEMENT === "number") { + return new type2(array2); + } + return Array.prototype.slice.call(array2); + } + function isTypedArray2(object) { + return ArrayBuffer.isView(object) && !(object instanceof DataView); + } + function getKeyframeOrder(times) { + function compareTime(i, j) { + return times[i] - times[j]; + } + const n = times.length; + const result = new Array(n); + for (let i = 0; i !== n; ++i) + result[i] = i; + result.sort(compareTime); + return result; + } + function sortedArray(values, stride, order) { + const nValues = values.length; + const result = new values.constructor(nValues); + for (let i = 0, dstOffset = 0; dstOffset !== nValues; ++i) { + const srcOffset = order[i] * stride; + for (let j = 0; j !== stride; ++j) { + result[dstOffset++] = values[srcOffset + j]; + } + } + return result; + } + function flattenJSON(jsonKeys, times, values, valuePropertyName) { + let i = 1, key = jsonKeys[0]; + while (key !== void 0 && key[valuePropertyName] === void 0) { + key = jsonKeys[i++]; + } + if (key === void 0) + return; + let value = key[valuePropertyName]; + if (value === void 0) + return; + if (Array.isArray(value)) { + do { + value = key[valuePropertyName]; + if (value !== void 0) { + times.push(key.time); + values.push.apply(values, value); + } + key = jsonKeys[i++]; + } while (key !== void 0); + } else if (value.toArray !== void 0) { + do { + value = key[valuePropertyName]; + if (value !== void 0) { + times.push(key.time); + value.toArray(values, values.length); + } + key = jsonKeys[i++]; + } while (key !== void 0); + } else { + do { + value = key[valuePropertyName]; + if (value !== void 0) { + times.push(key.time); + values.push(value); + } + key = jsonKeys[i++]; + } while (key !== void 0); + } + } + function subclip(sourceClip, name, startFrame, endFrame, fps = 30) { + const clip = sourceClip.clone(); + clip.name = name; + const tracks = []; + for (let i = 0; i < clip.tracks.length; ++i) { + const track = clip.tracks[i]; + const valueSize = track.getValueSize(); + const times = []; + const values = []; + for (let j = 0; j < track.times.length; ++j) { + const frame2 = track.times[j] * fps; + if (frame2 < startFrame || frame2 >= endFrame) + continue; + times.push(track.times[j]); + for (let k = 0; k < valueSize; ++k) { + values.push(track.values[j * valueSize + k]); + } + } + if (times.length === 0) + continue; + track.times = convertArray2(times, track.times.constructor); + track.values = convertArray2(values, track.values.constructor); + tracks.push(track); + } + clip.tracks = tracks; + let minStartTime = Infinity; + for (let i = 0; i < clip.tracks.length; ++i) { + if (minStartTime > clip.tracks[i].times[0]) { + minStartTime = clip.tracks[i].times[0]; + } + } + for (let i = 0; i < clip.tracks.length; ++i) { + clip.tracks[i].shift(-1 * minStartTime); + } + clip.resetDuration(); + return clip; + } + function makeClipAdditive(targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30) { + if (fps <= 0) + fps = 30; + const numTracks = referenceClip.tracks.length; + const referenceTime = referenceFrame / fps; + for (let i = 0; i < numTracks; ++i) { + const referenceTrack = referenceClip.tracks[i]; + const referenceTrackType = referenceTrack.ValueTypeName; + if (referenceTrackType === "bool" || referenceTrackType === "string") + continue; + const targetTrack = targetClip.tracks.find(function(track) { + return track.name === referenceTrack.name && track.ValueTypeName === referenceTrackType; + }); + if (targetTrack === void 0) + continue; + let referenceOffset = 0; + const referenceValueSize = referenceTrack.getValueSize(); + if (referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline) { + referenceOffset = referenceValueSize / 3; + } + let targetOffset = 0; + const targetValueSize = targetTrack.getValueSize(); + if (targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline) { + targetOffset = targetValueSize / 3; + } + const lastIndex = referenceTrack.times.length - 1; + let referenceValue; + if (referenceTime <= referenceTrack.times[0]) { + const startIndex = referenceOffset; + const endIndex = referenceValueSize - referenceOffset; + referenceValue = arraySlice2(referenceTrack.values, startIndex, endIndex); + } else if (referenceTime >= referenceTrack.times[lastIndex]) { + const startIndex = lastIndex * referenceValueSize + referenceOffset; + const endIndex = startIndex + referenceValueSize - referenceOffset; + referenceValue = arraySlice2(referenceTrack.values, startIndex, endIndex); + } else { + const interpolant = referenceTrack.createInterpolant(); + const startIndex = referenceOffset; + const endIndex = referenceValueSize - referenceOffset; + interpolant.evaluate(referenceTime); + referenceValue = arraySlice2(interpolant.resultBuffer, startIndex, endIndex); + } + if (referenceTrackType === "quaternion") { + const referenceQuat = new Quaternion2().fromArray(referenceValue).normalize().conjugate(); + referenceQuat.toArray(referenceValue); + } + const numTimes = targetTrack.times.length; + for (let j = 0; j < numTimes; ++j) { + const valueStart = j * targetValueSize + targetOffset; + if (referenceTrackType === "quaternion") { + Quaternion2.multiplyQuaternionsFlat(targetTrack.values, valueStart, referenceValue, 0, targetTrack.values, valueStart); + } else { + const valueEnd = targetValueSize - targetOffset * 2; + for (let k = 0; k < valueEnd; ++k) { + targetTrack.values[valueStart + k] -= referenceValue[k]; + } + } + } + } + targetClip.blendMode = AdditiveAnimationBlendMode; + return targetClip; + } + var AnimationUtils = /* @__PURE__ */ Object.freeze({ + __proto__: null, + arraySlice: arraySlice2, + convertArray: convertArray2, + isTypedArray: isTypedArray2, + getKeyframeOrder, + sortedArray, + flattenJSON, + subclip, + makeClipAdditive + }); + var Interpolant2 = class { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + this.parameterPositions = parameterPositions; + this._cachedIndex = 0; + this.resultBuffer = resultBuffer !== void 0 ? resultBuffer : new sampleValues.constructor(sampleSize); + this.sampleValues = sampleValues; + this.valueSize = sampleSize; + this.settings = null; + this.DefaultSettings_ = {}; + } + evaluate(t) { + const pp = this.parameterPositions; + let i1 = this._cachedIndex, t1 = pp[i1], t0 = pp[i1 - 1]; + validate_interval: { + seek: { + let right; + linear_scan: { + forward_scan: + if (!(t < t1)) { + for (let giveUpAt = i1 + 2; ; ) { + if (t1 === void 0) { + if (t < t0) + break forward_scan; + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_(i1 - 1); + } + if (i1 === giveUpAt) + break; + t0 = t1; + t1 = pp[++i1]; + if (t < t1) { + break seek; + } + } + right = pp.length; + break linear_scan; + } + if (!(t >= t0)) { + const t1global = pp[1]; + if (t < t1global) { + i1 = 2; + t0 = t1global; + } + for (let giveUpAt = i1 - 2; ; ) { + if (t0 === void 0) { + this._cachedIndex = 0; + return this.copySampleValue_(0); + } + if (i1 === giveUpAt) + break; + t1 = t0; + t0 = pp[--i1 - 1]; + if (t >= t0) { + break seek; + } + } + right = i1; + i1 = 0; + break linear_scan; + } + break validate_interval; + } + while (i1 < right) { + const mid = i1 + right >>> 1; + if (t < pp[mid]) { + right = mid; + } else { + i1 = mid + 1; + } + } + t1 = pp[i1]; + t0 = pp[i1 - 1]; + if (t0 === void 0) { + this._cachedIndex = 0; + return this.copySampleValue_(0); + } + if (t1 === void 0) { + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_(i1 - 1); + } + } + this._cachedIndex = i1; + this.intervalChanged_(i1, t0, t1); + } + return this.interpolate_(i1, t0, t, t1); + } + getSettings_() { + return this.settings || this.DefaultSettings_; + } + copySampleValue_(index2) { + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, offset = index2 * stride; + for (let i = 0; i !== stride; ++i) { + result[i] = values[offset + i]; + } + return result; + } + interpolate_() { + throw new Error("call to abstract method"); + } + intervalChanged_() { + } + }; + var CubicInterpolant2 = class extends Interpolant2 { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + this._weightPrev = -0; + this._offsetPrev = -0; + this._weightNext = -0; + this._offsetNext = -0; + this.DefaultSettings_ = { + endingStart: ZeroCurvatureEnding2, + endingEnd: ZeroCurvatureEnding2 + }; + } + intervalChanged_(i1, t0, t1) { + const pp = this.parameterPositions; + let iPrev = i1 - 2, iNext = i1 + 1, tPrev = pp[iPrev], tNext = pp[iNext]; + if (tPrev === void 0) { + switch (this.getSettings_().endingStart) { + case ZeroSlopeEnding2: + iPrev = i1; + tPrev = 2 * t0 - t1; + break; + case WrapAroundEnding2: + iPrev = pp.length - 2; + tPrev = t0 + pp[iPrev] - pp[iPrev + 1]; + break; + default: + iPrev = i1; + tPrev = t1; + } + } + if (tNext === void 0) { + switch (this.getSettings_().endingEnd) { + case ZeroSlopeEnding2: + iNext = i1; + tNext = 2 * t1 - t0; + break; + case WrapAroundEnding2: + iNext = 1; + tNext = t1 + pp[1] - pp[0]; + break; + default: + iNext = i1 - 1; + tNext = t0; + } + } + const halfDt = (t1 - t0) * 0.5, stride = this.valueSize; + this._weightPrev = halfDt / (t0 - tPrev); + this._weightNext = halfDt / (tNext - t1); + this._offsetPrev = iPrev * stride; + this._offsetNext = iNext * stride; + } + interpolate_(i1, t0, t, t1) { + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, o1 = i1 * stride, o0 = o1 - stride, oP = this._offsetPrev, oN = this._offsetNext, wP = this._weightPrev, wN = this._weightNext, p = (t - t0) / (t1 - t0), pp = p * p, ppp = pp * p; + const sP = -wP * ppp + 2 * wP * pp - wP * p; + const s0 = (1 + wP) * ppp + (-1.5 - 2 * wP) * pp + (-0.5 + wP) * p + 1; + const s1 = (-1 - wN) * ppp + (1.5 + wN) * pp + 0.5 * p; + const sN = wN * ppp - wN * pp; + for (let i = 0; i !== stride; ++i) { + result[i] = sP * values[oP + i] + s0 * values[o0 + i] + s1 * values[o1 + i] + sN * values[oN + i]; + } + return result; + } + }; + var LinearInterpolant2 = class extends Interpolant2 { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + } + interpolate_(i1, t0, t, t1) { + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, offset1 = i1 * stride, offset0 = offset1 - stride, weight1 = (t - t0) / (t1 - t0), weight0 = 1 - weight1; + for (let i = 0; i !== stride; ++i) { + result[i] = values[offset0 + i] * weight0 + values[offset1 + i] * weight1; + } + return result; + } + }; + var DiscreteInterpolant2 = class extends Interpolant2 { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + } + interpolate_(i1) { + return this.copySampleValue_(i1 - 1); + } + }; + var KeyframeTrack2 = class { + constructor(name, times, values, interpolation) { + if (name === void 0) + throw new Error("THREE.KeyframeTrack: track name is undefined"); + if (times === void 0 || times.length === 0) + throw new Error("THREE.KeyframeTrack: no keyframes in track named " + name); + this.name = name; + this.times = convertArray2(times, this.TimeBufferType); + this.values = convertArray2(values, this.ValueBufferType); + this.setInterpolation(interpolation || this.DefaultInterpolation); + } + static toJSON(track) { + const trackType = track.constructor; + let json; + if (trackType.toJSON !== this.toJSON) { + json = trackType.toJSON(track); + } else { + json = { + "name": track.name, + "times": convertArray2(track.times, Array), + "values": convertArray2(track.values, Array) + }; + const interpolation = track.getInterpolation(); + if (interpolation !== track.DefaultInterpolation) { + json.interpolation = interpolation; + } + } + json.type = track.ValueTypeName; + return json; + } + InterpolantFactoryMethodDiscrete(result) { + return new DiscreteInterpolant2(this.times, this.values, this.getValueSize(), result); + } + InterpolantFactoryMethodLinear(result) { + return new LinearInterpolant2(this.times, this.values, this.getValueSize(), result); + } + InterpolantFactoryMethodSmooth(result) { + return new CubicInterpolant2(this.times, this.values, this.getValueSize(), result); + } + setInterpolation(interpolation) { + let factoryMethod; + switch (interpolation) { + case InterpolateDiscrete2: + factoryMethod = this.InterpolantFactoryMethodDiscrete; + break; + case InterpolateLinear2: + factoryMethod = this.InterpolantFactoryMethodLinear; + break; + case InterpolateSmooth2: + factoryMethod = this.InterpolantFactoryMethodSmooth; + break; + } + if (factoryMethod === void 0) { + const message = "unsupported interpolation for " + this.ValueTypeName + " keyframe track named " + this.name; + if (this.createInterpolant === void 0) { + if (interpolation !== this.DefaultInterpolation) { + this.setInterpolation(this.DefaultInterpolation); + } else { + throw new Error(message); + } + } + console.warn("THREE.KeyframeTrack:", message); + return this; + } + this.createInterpolant = factoryMethod; + return this; + } + getInterpolation() { + switch (this.createInterpolant) { + case this.InterpolantFactoryMethodDiscrete: + return InterpolateDiscrete2; + case this.InterpolantFactoryMethodLinear: + return InterpolateLinear2; + case this.InterpolantFactoryMethodSmooth: + return InterpolateSmooth2; + } + } + getValueSize() { + return this.values.length / this.times.length; + } + shift(timeOffset) { + if (timeOffset !== 0) { + const times = this.times; + for (let i = 0, n = times.length; i !== n; ++i) { + times[i] += timeOffset; + } + } + return this; + } + scale(timeScale) { + if (timeScale !== 1) { + const times = this.times; + for (let i = 0, n = times.length; i !== n; ++i) { + times[i] *= timeScale; + } + } + return this; + } + trim(startTime, endTime) { + const times = this.times, nKeys = times.length; + let from = 0, to = nKeys - 1; + while (from !== nKeys && times[from] < startTime) { + ++from; + } + while (to !== -1 && times[to] > endTime) { + --to; + } + ++to; + if (from !== 0 || to !== nKeys) { + if (from >= to) { + to = Math.max(to, 1); + from = to - 1; + } + const stride = this.getValueSize(); + this.times = arraySlice2(times, from, to); + this.values = arraySlice2(this.values, from * stride, to * stride); + } + return this; + } + validate() { + let valid = true; + const valueSize = this.getValueSize(); + if (valueSize - Math.floor(valueSize) !== 0) { + console.error("THREE.KeyframeTrack: Invalid value size in track.", this); + valid = false; + } + const times = this.times, values = this.values, nKeys = times.length; + if (nKeys === 0) { + console.error("THREE.KeyframeTrack: Track is empty.", this); + valid = false; + } + let prevTime = null; + for (let i = 0; i !== nKeys; i++) { + const currTime = times[i]; + if (typeof currTime === "number" && isNaN(currTime)) { + console.error("THREE.KeyframeTrack: Time is not a valid number.", this, i, currTime); + valid = false; + break; + } + if (prevTime !== null && prevTime > currTime) { + console.error("THREE.KeyframeTrack: Out of order keys.", this, i, currTime, prevTime); + valid = false; + break; + } + prevTime = currTime; + } + if (values !== void 0) { + if (isTypedArray2(values)) { + for (let i = 0, n = values.length; i !== n; ++i) { + const value = values[i]; + if (isNaN(value)) { + console.error("THREE.KeyframeTrack: Value is not a valid number.", this, i, value); + valid = false; + break; + } + } + } + } + return valid; + } + optimize() { + const times = arraySlice2(this.times), values = arraySlice2(this.values), stride = this.getValueSize(), smoothInterpolation = this.getInterpolation() === InterpolateSmooth2, lastIndex = times.length - 1; + let writeIndex = 1; + for (let i = 1; i < lastIndex; ++i) { + let keep = false; + const time = times[i]; + const timeNext = times[i + 1]; + if (time !== timeNext && (i !== 1 || time !== times[0])) { + if (!smoothInterpolation) { + const offset = i * stride, offsetP = offset - stride, offsetN = offset + stride; + for (let j = 0; j !== stride; ++j) { + const value = values[offset + j]; + if (value !== values[offsetP + j] || value !== values[offsetN + j]) { + keep = true; + break; + } + } + } else { + keep = true; + } + } + if (keep) { + if (i !== writeIndex) { + times[writeIndex] = times[i]; + const readOffset = i * stride, writeOffset = writeIndex * stride; + for (let j = 0; j !== stride; ++j) { + values[writeOffset + j] = values[readOffset + j]; + } + } + ++writeIndex; + } + } + if (lastIndex > 0) { + times[writeIndex] = times[lastIndex]; + for (let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++j) { + values[writeOffset + j] = values[readOffset + j]; + } + ++writeIndex; + } + if (writeIndex !== times.length) { + this.times = arraySlice2(times, 0, writeIndex); + this.values = arraySlice2(values, 0, writeIndex * stride); + } else { + this.times = times; + this.values = values; + } + return this; + } + clone() { + const times = arraySlice2(this.times, 0); + const values = arraySlice2(this.values, 0); + const TypedKeyframeTrack = this.constructor; + const track = new TypedKeyframeTrack(this.name, times, values); + track.createInterpolant = this.createInterpolant; + return track; + } + }; + KeyframeTrack2.prototype.TimeBufferType = Float32Array; + KeyframeTrack2.prototype.ValueBufferType = Float32Array; + KeyframeTrack2.prototype.DefaultInterpolation = InterpolateLinear2; + var BooleanKeyframeTrack2 = class extends KeyframeTrack2 { + }; + BooleanKeyframeTrack2.prototype.ValueTypeName = "bool"; + BooleanKeyframeTrack2.prototype.ValueBufferType = Array; + BooleanKeyframeTrack2.prototype.DefaultInterpolation = InterpolateDiscrete2; + BooleanKeyframeTrack2.prototype.InterpolantFactoryMethodLinear = void 0; + BooleanKeyframeTrack2.prototype.InterpolantFactoryMethodSmooth = void 0; + var ColorKeyframeTrack2 = class extends KeyframeTrack2 { + }; + ColorKeyframeTrack2.prototype.ValueTypeName = "color"; + var NumberKeyframeTrack2 = class extends KeyframeTrack2 { + }; + NumberKeyframeTrack2.prototype.ValueTypeName = "number"; + var QuaternionLinearInterpolant2 = class extends Interpolant2 { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + } + interpolate_(i1, t0, t, t1) { + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, alpha = (t - t0) / (t1 - t0); + let offset = i1 * stride; + for (let end = offset + stride; offset !== end; offset += 4) { + Quaternion2.slerpFlat(result, 0, values, offset - stride, values, offset, alpha); + } + return result; + } + }; + var QuaternionKeyframeTrack2 = class extends KeyframeTrack2 { + InterpolantFactoryMethodLinear(result) { + return new QuaternionLinearInterpolant2(this.times, this.values, this.getValueSize(), result); + } + }; + QuaternionKeyframeTrack2.prototype.ValueTypeName = "quaternion"; + QuaternionKeyframeTrack2.prototype.DefaultInterpolation = InterpolateLinear2; + QuaternionKeyframeTrack2.prototype.InterpolantFactoryMethodSmooth = void 0; + var StringKeyframeTrack2 = class extends KeyframeTrack2 { + }; + StringKeyframeTrack2.prototype.ValueTypeName = "string"; + StringKeyframeTrack2.prototype.ValueBufferType = Array; + StringKeyframeTrack2.prototype.DefaultInterpolation = InterpolateDiscrete2; + StringKeyframeTrack2.prototype.InterpolantFactoryMethodLinear = void 0; + StringKeyframeTrack2.prototype.InterpolantFactoryMethodSmooth = void 0; + var VectorKeyframeTrack2 = class extends KeyframeTrack2 { + }; + VectorKeyframeTrack2.prototype.ValueTypeName = "vector"; + var AnimationClip = class { + constructor(name, duration = -1, tracks, blendMode = NormalAnimationBlendMode) { + this.name = name; + this.tracks = tracks; + this.duration = duration; + this.blendMode = blendMode; + this.uuid = generateUUID2(); + if (this.duration < 0) { + this.resetDuration(); + } + } + static parse(json) { + const tracks = [], jsonTracks = json.tracks, frameTime = 1 / (json.fps || 1); + for (let i = 0, n = jsonTracks.length; i !== n; ++i) { + tracks.push(parseKeyframeTrack(jsonTracks[i]).scale(frameTime)); + } + const clip = new this(json.name, json.duration, tracks, json.blendMode); + clip.uuid = json.uuid; + return clip; + } + static toJSON(clip) { + const tracks = [], clipTracks = clip.tracks; + const json = { + "name": clip.name, + "duration": clip.duration, + "tracks": tracks, + "uuid": clip.uuid, + "blendMode": clip.blendMode + }; + for (let i = 0, n = clipTracks.length; i !== n; ++i) { + tracks.push(KeyframeTrack2.toJSON(clipTracks[i])); + } + return json; + } + static CreateFromMorphTargetSequence(name, morphTargetSequence, fps, noLoop) { + const numMorphTargets = morphTargetSequence.length; + const tracks = []; + for (let i = 0; i < numMorphTargets; i++) { + let times = []; + let values = []; + times.push((i + numMorphTargets - 1) % numMorphTargets, i, (i + 1) % numMorphTargets); + values.push(0, 1, 0); + const order = getKeyframeOrder(times); + times = sortedArray(times, 1, order); + values = sortedArray(values, 1, order); + if (!noLoop && times[0] === 0) { + times.push(numMorphTargets); + values.push(values[0]); + } + tracks.push(new NumberKeyframeTrack2(".morphTargetInfluences[" + morphTargetSequence[i].name + "]", times, values).scale(1 / fps)); + } + return new this(name, -1, tracks); + } + static findByName(objectOrClipArray, name) { + let clipArray = objectOrClipArray; + if (!Array.isArray(objectOrClipArray)) { + const o = objectOrClipArray; + clipArray = o.geometry && o.geometry.animations || o.animations; + } + for (let i = 0; i < clipArray.length; i++) { + if (clipArray[i].name === name) { + return clipArray[i]; + } + } + return null; + } + static CreateClipsFromMorphTargetSequences(morphTargets, fps, noLoop) { + const animationToMorphTargets = {}; + const pattern = /^([\w-]*?)([\d]+)$/; + for (let i = 0, il = morphTargets.length; i < il; i++) { + const morphTarget = morphTargets[i]; + const parts = morphTarget.name.match(pattern); + if (parts && parts.length > 1) { + const name = parts[1]; + let animationMorphTargets = animationToMorphTargets[name]; + if (!animationMorphTargets) { + animationToMorphTargets[name] = animationMorphTargets = []; + } + animationMorphTargets.push(morphTarget); + } + } + const clips = []; + for (const name in animationToMorphTargets) { + clips.push(this.CreateFromMorphTargetSequence(name, animationToMorphTargets[name], fps, noLoop)); + } + return clips; + } + static parseAnimation(animation, bones) { + if (!animation) { + console.error("THREE.AnimationClip: No animation in JSONLoader data."); + return null; + } + const addNonemptyTrack = function(trackType, trackName, animationKeys, propertyName, destTracks) { + if (animationKeys.length !== 0) { + const times = []; + const values = []; + flattenJSON(animationKeys, times, values, propertyName); + if (times.length !== 0) { + destTracks.push(new trackType(trackName, times, values)); + } + } + }; + const tracks = []; + const clipName = animation.name || "default"; + const fps = animation.fps || 30; + const blendMode = animation.blendMode; + let duration = animation.length || -1; + const hierarchyTracks = animation.hierarchy || []; + for (let h = 0; h < hierarchyTracks.length; h++) { + const animationKeys = hierarchyTracks[h].keys; + if (!animationKeys || animationKeys.length === 0) + continue; + if (animationKeys[0].morphTargets) { + const morphTargetNames = {}; + let k; + for (k = 0; k < animationKeys.length; k++) { + if (animationKeys[k].morphTargets) { + for (let m2 = 0; m2 < animationKeys[k].morphTargets.length; m2++) { + morphTargetNames[animationKeys[k].morphTargets[m2]] = -1; + } + } + } + for (const morphTargetName in morphTargetNames) { + const times = []; + const values = []; + for (let m2 = 0; m2 !== animationKeys[k].morphTargets.length; ++m2) { + const animationKey = animationKeys[k]; + times.push(animationKey.time); + values.push(animationKey.morphTarget === morphTargetName ? 1 : 0); + } + tracks.push(new NumberKeyframeTrack2(".morphTargetInfluence[" + morphTargetName + "]", times, values)); + } + duration = morphTargetNames.length * fps; + } else { + const boneName = ".bones[" + bones[h].name + "]"; + addNonemptyTrack(VectorKeyframeTrack2, boneName + ".position", animationKeys, "pos", tracks); + addNonemptyTrack(QuaternionKeyframeTrack2, boneName + ".quaternion", animationKeys, "rot", tracks); + addNonemptyTrack(VectorKeyframeTrack2, boneName + ".scale", animationKeys, "scl", tracks); + } + } + if (tracks.length === 0) { + return null; + } + const clip = new this(clipName, duration, tracks, blendMode); + return clip; + } + resetDuration() { + const tracks = this.tracks; + let duration = 0; + for (let i = 0, n = tracks.length; i !== n; ++i) { + const track = this.tracks[i]; + duration = Math.max(duration, track.times[track.times.length - 1]); + } + this.duration = duration; + return this; + } + trim() { + for (let i = 0; i < this.tracks.length; i++) { + this.tracks[i].trim(0, this.duration); + } + return this; + } + validate() { + let valid = true; + for (let i = 0; i < this.tracks.length; i++) { + valid = valid && this.tracks[i].validate(); + } + return valid; + } + optimize() { + for (let i = 0; i < this.tracks.length; i++) { + this.tracks[i].optimize(); + } + return this; + } + clone() { + const tracks = []; + for (let i = 0; i < this.tracks.length; i++) { + tracks.push(this.tracks[i].clone()); + } + return new this.constructor(this.name, this.duration, tracks, this.blendMode); + } + toJSON() { + return this.constructor.toJSON(this); + } + }; + function getTrackTypeForValueTypeName(typeName) { + switch (typeName.toLowerCase()) { + case "scalar": + case "double": + case "float": + case "number": + case "integer": + return NumberKeyframeTrack2; + case "vector": + case "vector2": + case "vector3": + case "vector4": + return VectorKeyframeTrack2; + case "color": + return ColorKeyframeTrack2; + case "quaternion": + return QuaternionKeyframeTrack2; + case "bool": + case "boolean": + return BooleanKeyframeTrack2; + case "string": + return StringKeyframeTrack2; + } + throw new Error("THREE.KeyframeTrack: Unsupported typeName: " + typeName); + } + function parseKeyframeTrack(json) { + if (json.type === void 0) { + throw new Error("THREE.KeyframeTrack: track type undefined, can not parse"); + } + const trackType = getTrackTypeForValueTypeName(json.type); + if (json.times === void 0) { + const times = [], values = []; + flattenJSON(json.keys, times, values, "value"); + json.times = times; + json.values = values; + } + if (trackType.parse !== void 0) { + return trackType.parse(json); + } else { + return new trackType(json.name, json.times, json.values, json.interpolation); + } + } + var Cache = { + enabled: false, + files: {}, + add: function(key, file) { + if (this.enabled === false) + return; + this.files[key] = file; + }, + get: function(key) { + if (this.enabled === false) + return; + return this.files[key]; + }, + remove: function(key) { + delete this.files[key]; + }, + clear: function() { + this.files = {}; + } + }; + var LoadingManager = class { + constructor(onLoad, onProgress, onError) { + const scope = this; + let isLoading = false; + let itemsLoaded = 0; + let itemsTotal = 0; + let urlModifier = void 0; + const handlers = []; + this.onStart = void 0; + this.onLoad = onLoad; + this.onProgress = onProgress; + this.onError = onError; + this.itemStart = function(url) { + itemsTotal++; + if (isLoading === false) { + if (scope.onStart !== void 0) { + scope.onStart(url, itemsLoaded, itemsTotal); + } + } + isLoading = true; + }; + this.itemEnd = function(url) { + itemsLoaded++; + if (scope.onProgress !== void 0) { + scope.onProgress(url, itemsLoaded, itemsTotal); + } + if (itemsLoaded === itemsTotal) { + isLoading = false; + if (scope.onLoad !== void 0) { + scope.onLoad(); + } + } + }; + this.itemError = function(url) { + if (scope.onError !== void 0) { + scope.onError(url); + } + }; + this.resolveURL = function(url) { + if (urlModifier) { + return urlModifier(url); + } + return url; + }; + this.setURLModifier = function(transform2) { + urlModifier = transform2; + return this; + }; + this.addHandler = function(regex, loader) { + handlers.push(regex, loader); + return this; + }; + this.removeHandler = function(regex) { + const index2 = handlers.indexOf(regex); + if (index2 !== -1) { + handlers.splice(index2, 2); + } + return this; + }; + this.getHandler = function(file) { + for (let i = 0, l = handlers.length; i < l; i += 2) { + const regex = handlers[i]; + const loader = handlers[i + 1]; + if (regex.global) + regex.lastIndex = 0; + if (regex.test(file)) { + return loader; + } + } + return null; + }; + } + }; + var DefaultLoadingManager = /* @__PURE__ */ new LoadingManager(); + var Loader = class { + constructor(manager) { + this.manager = manager !== void 0 ? manager : DefaultLoadingManager; + this.crossOrigin = "anonymous"; + this.withCredentials = false; + this.path = ""; + this.resourcePath = ""; + this.requestHeader = {}; + } + load() { + } + loadAsync(url, onProgress) { + const scope = this; + return new Promise(function(resolve, reject) { + scope.load(url, resolve, onProgress, reject); + }); + } + parse() { + } + setCrossOrigin(crossOrigin) { + this.crossOrigin = crossOrigin; + return this; + } + setWithCredentials(value) { + this.withCredentials = value; + return this; + } + setPath(path) { + this.path = path; + return this; + } + setResourcePath(resourcePath) { + this.resourcePath = resourcePath; + return this; + } + setRequestHeader(requestHeader) { + this.requestHeader = requestHeader; + return this; + } + }; + var loading = {}; + var HttpError = class extends Error { + constructor(message, response) { + super(message); + this.response = response; + } + }; + var FileLoader = class extends Loader { + constructor(manager) { + super(manager); + } + load(url, onLoad, onProgress, onError) { + if (url === void 0) + url = ""; + if (this.path !== void 0) + url = this.path + url; + url = this.manager.resolveURL(url); + const cached = Cache.get(url); + if (cached !== void 0) { + this.manager.itemStart(url); + setTimeout(() => { + if (onLoad) + onLoad(cached); + this.manager.itemEnd(url); + }, 0); + return cached; + } + if (loading[url] !== void 0) { + loading[url].push({ + onLoad, + onProgress, + onError + }); + return; + } + loading[url] = []; + loading[url].push({ + onLoad, + onProgress, + onError + }); + const req = new Request(url, { + headers: new Headers(this.requestHeader), + credentials: this.withCredentials ? "include" : "same-origin" + }); + const mimeType = this.mimeType; + const responseType = this.responseType; + fetch(req).then((response) => { + if (response.status === 200 || response.status === 0) { + if (response.status === 0) { + console.warn("THREE.FileLoader: HTTP Status 0 received."); + } + if (typeof ReadableStream === "undefined" || response.body === void 0 || response.body.getReader === void 0) { + return response; + } + const callbacks = loading[url]; + const reader = response.body.getReader(); + const contentLength = response.headers.get("Content-Length"); + const total = contentLength ? parseInt(contentLength) : 0; + const lengthComputable = total !== 0; + let loaded = 0; + const stream = new ReadableStream({ + start(controller) { + readData(); + function readData() { + reader.read().then(({ + done, + value + }) => { + if (done) { + controller.close(); + } else { + loaded += value.byteLength; + const event = new ProgressEvent("progress", { + lengthComputable, + loaded, + total + }); + for (let i = 0, il = callbacks.length; i < il; i++) { + const callback = callbacks[i]; + if (callback.onProgress) + callback.onProgress(event); + } + controller.enqueue(value); + readData(); + } + }); + } + } + }); + return new Response(stream); + } else { + throw new HttpError(`fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response); + } + }).then((response) => { + switch (responseType) { + case "arraybuffer": + return response.arrayBuffer(); + case "blob": + return response.blob(); + case "document": + return response.text().then((text) => { + const parser = new DOMParser(); + return parser.parseFromString(text, mimeType); + }); + case "json": + return response.json(); + default: + if (mimeType === void 0) { + return response.text(); + } else { + const re2 = /charset="?([^;"\s]*)"?/i; + const exec = re2.exec(mimeType); + const label = exec && exec[1] ? exec[1].toLowerCase() : void 0; + const decoder = new TextDecoder(label); + return response.arrayBuffer().then((ab) => decoder.decode(ab)); + } + } + }).then((data) => { + Cache.add(url, data); + const callbacks = loading[url]; + delete loading[url]; + for (let i = 0, il = callbacks.length; i < il; i++) { + const callback = callbacks[i]; + if (callback.onLoad) + callback.onLoad(data); + } + }).catch((err) => { + const callbacks = loading[url]; + if (callbacks === void 0) { + this.manager.itemError(url); + throw err; + } + delete loading[url]; + for (let i = 0, il = callbacks.length; i < il; i++) { + const callback = callbacks[i]; + if (callback.onError) + callback.onError(err); + } + this.manager.itemError(url); + }).finally(() => { + this.manager.itemEnd(url); + }); + this.manager.itemStart(url); + } + setResponseType(value) { + this.responseType = value; + return this; + } + setMimeType(value) { + this.mimeType = value; + return this; + } + }; + var AnimationLoader = class extends Loader { + constructor(manager) { + super(manager); + } + load(url, onLoad, onProgress, onError) { + const scope = this; + const loader = new FileLoader(this.manager); + loader.setPath(this.path); + loader.setRequestHeader(this.requestHeader); + loader.setWithCredentials(this.withCredentials); + loader.load(url, function(text) { + try { + onLoad(scope.parse(JSON.parse(text))); + } catch (e) { + if (onError) { + onError(e); + } else { + console.error(e); + } + scope.manager.itemError(url); + } + }, onProgress, onError); + } + parse(json) { + const animations = []; + for (let i = 0; i < json.length; i++) { + const clip = AnimationClip.parse(json[i]); + animations.push(clip); + } + return animations; + } + }; + var CompressedTextureLoader = class extends Loader { + constructor(manager) { + super(manager); + } + load(url, onLoad, onProgress, onError) { + const scope = this; + const images = []; + const texture = new CompressedTexture(); + const loader = new FileLoader(this.manager); + loader.setPath(this.path); + loader.setResponseType("arraybuffer"); + loader.setRequestHeader(this.requestHeader); + loader.setWithCredentials(scope.withCredentials); + let loaded = 0; + function loadTexture(i) { + loader.load(url[i], function(buffer) { + const texDatas = scope.parse(buffer, true); + images[i] = { + width: texDatas.width, + height: texDatas.height, + format: texDatas.format, + mipmaps: texDatas.mipmaps + }; + loaded += 1; + if (loaded === 6) { + if (texDatas.mipmapCount === 1) + texture.minFilter = LinearFilter2; + texture.image = images; + texture.format = texDatas.format; + texture.needsUpdate = true; + if (onLoad) + onLoad(texture); + } + }, onProgress, onError); + } + if (Array.isArray(url)) { + for (let i = 0, il = url.length; i < il; ++i) { + loadTexture(i); + } + } else { + loader.load(url, function(buffer) { + const texDatas = scope.parse(buffer, true); + if (texDatas.isCubemap) { + const faces = texDatas.mipmaps.length / texDatas.mipmapCount; + for (let f = 0; f < faces; f++) { + images[f] = { + mipmaps: [] + }; + for (let i = 0; i < texDatas.mipmapCount; i++) { + images[f].mipmaps.push(texDatas.mipmaps[f * texDatas.mipmapCount + i]); + images[f].format = texDatas.format; + images[f].width = texDatas.width; + images[f].height = texDatas.height; + } + } + texture.image = images; + } else { + texture.image.width = texDatas.width; + texture.image.height = texDatas.height; + texture.mipmaps = texDatas.mipmaps; + } + if (texDatas.mipmapCount === 1) { + texture.minFilter = LinearFilter2; + } + texture.format = texDatas.format; + texture.needsUpdate = true; + if (onLoad) + onLoad(texture); + }, onProgress, onError); + } + return texture; + } + }; + var ImageLoader = class extends Loader { + constructor(manager) { + super(manager); + } + load(url, onLoad, onProgress, onError) { + if (this.path !== void 0) + url = this.path + url; + url = this.manager.resolveURL(url); + const scope = this; + const cached = Cache.get(url); + if (cached !== void 0) { + scope.manager.itemStart(url); + setTimeout(function() { + if (onLoad) + onLoad(cached); + scope.manager.itemEnd(url); + }, 0); + return cached; + } + const image = createElementNS2("img"); + function onImageLoad() { + removeEventListeners(); + Cache.add(url, this); + if (onLoad) + onLoad(this); + scope.manager.itemEnd(url); + } + function onImageError(event) { + removeEventListeners(); + if (onError) + onError(event); + scope.manager.itemError(url); + scope.manager.itemEnd(url); + } + function removeEventListeners() { + image.removeEventListener("load", onImageLoad, false); + image.removeEventListener("error", onImageError, false); + } + image.addEventListener("load", onImageLoad, false); + image.addEventListener("error", onImageError, false); + if (url.slice(0, 5) !== "data:") { + if (this.crossOrigin !== void 0) + image.crossOrigin = this.crossOrigin; + } + scope.manager.itemStart(url); + image.src = url; + return image; + } + }; + var CubeTextureLoader = class extends Loader { + constructor(manager) { + super(manager); + } + load(urls, onLoad, onProgress, onError) { + const texture = new CubeTexture2(); + const loader = new ImageLoader(this.manager); + loader.setCrossOrigin(this.crossOrigin); + loader.setPath(this.path); + let loaded = 0; + function loadTexture(i) { + loader.load(urls[i], function(image) { + texture.images[i] = image; + loaded++; + if (loaded === 6) { + texture.needsUpdate = true; + if (onLoad) + onLoad(texture); + } + }, void 0, onError); + } + for (let i = 0; i < urls.length; ++i) { + loadTexture(i); + } + return texture; + } + }; + var DataTextureLoader = class extends Loader { + constructor(manager) { + super(manager); + } + load(url, onLoad, onProgress, onError) { + const scope = this; + const texture = new DataTexture(); + const loader = new FileLoader(this.manager); + loader.setResponseType("arraybuffer"); + loader.setRequestHeader(this.requestHeader); + loader.setPath(this.path); + loader.setWithCredentials(scope.withCredentials); + loader.load(url, function(buffer) { + const texData = scope.parse(buffer); + if (!texData) + return; + if (texData.image !== void 0) { + texture.image = texData.image; + } else if (texData.data !== void 0) { + texture.image.width = texData.width; + texture.image.height = texData.height; + texture.image.data = texData.data; + } + texture.wrapS = texData.wrapS !== void 0 ? texData.wrapS : ClampToEdgeWrapping2; + texture.wrapT = texData.wrapT !== void 0 ? texData.wrapT : ClampToEdgeWrapping2; + texture.magFilter = texData.magFilter !== void 0 ? texData.magFilter : LinearFilter2; + texture.minFilter = texData.minFilter !== void 0 ? texData.minFilter : LinearFilter2; + texture.anisotropy = texData.anisotropy !== void 0 ? texData.anisotropy : 1; + if (texData.encoding !== void 0) { + texture.encoding = texData.encoding; + } + if (texData.flipY !== void 0) { + texture.flipY = texData.flipY; + } + if (texData.format !== void 0) { + texture.format = texData.format; + } + if (texData.type !== void 0) { + texture.type = texData.type; + } + if (texData.mipmaps !== void 0) { + texture.mipmaps = texData.mipmaps; + texture.minFilter = LinearMipmapLinearFilter2; + } + if (texData.mipmapCount === 1) { + texture.minFilter = LinearFilter2; + } + if (texData.generateMipmaps !== void 0) { + texture.generateMipmaps = texData.generateMipmaps; + } + texture.needsUpdate = true; + if (onLoad) + onLoad(texture, texData); + }, onProgress, onError); + return texture; + } + }; + var TextureLoader = class extends Loader { + constructor(manager) { + super(manager); + } + load(url, onLoad, onProgress, onError) { + const texture = new Texture2(); + const loader = new ImageLoader(this.manager); + loader.setCrossOrigin(this.crossOrigin); + loader.setPath(this.path); + loader.load(url, function(image) { + texture.image = image; + texture.needsUpdate = true; + if (onLoad !== void 0) { + onLoad(texture); + } + }, onProgress, onError); + return texture; + } + }; + var Light = class extends Object3D2 { + constructor(color2, intensity = 1) { + super(); + this.isLight = true; + this.type = "Light"; + this.color = new Color3(color2); + this.intensity = intensity; + } + dispose() { + } + copy(source, recursive) { + super.copy(source, recursive); + this.color.copy(source.color); + this.intensity = source.intensity; + return this; + } + toJSON(meta) { + const data = super.toJSON(meta); + data.object.color = this.color.getHex(); + data.object.intensity = this.intensity; + if (this.groundColor !== void 0) + data.object.groundColor = this.groundColor.getHex(); + if (this.distance !== void 0) + data.object.distance = this.distance; + if (this.angle !== void 0) + data.object.angle = this.angle; + if (this.decay !== void 0) + data.object.decay = this.decay; + if (this.penumbra !== void 0) + data.object.penumbra = this.penumbra; + if (this.shadow !== void 0) + data.object.shadow = this.shadow.toJSON(); + return data; + } + }; + var HemisphereLight = class extends Light { + constructor(skyColor, groundColor, intensity) { + super(skyColor, intensity); + this.isHemisphereLight = true; + this.type = "HemisphereLight"; + this.position.copy(Object3D2.DefaultUp); + this.updateMatrix(); + this.groundColor = new Color3(groundColor); + } + copy(source, recursive) { + super.copy(source, recursive); + this.groundColor.copy(source.groundColor); + return this; + } + }; + var _projScreenMatrix$1 = /* @__PURE__ */ new Matrix42(); + var _lightPositionWorld$1 = /* @__PURE__ */ new Vector32(); + var _lookTarget$1 = /* @__PURE__ */ new Vector32(); + var LightShadow = class { + constructor(camera) { + this.camera = camera; + this.bias = 0; + this.normalBias = 0; + this.radius = 1; + this.blurSamples = 8; + this.mapSize = new Vector22(512, 512); + this.map = null; + this.mapPass = null; + this.matrix = new Matrix42(); + this.autoUpdate = true; + this.needsUpdate = false; + this._frustum = new Frustum2(); + this._frameExtents = new Vector22(1, 1); + this._viewportCount = 1; + this._viewports = [new Vector42(0, 0, 1, 1)]; + } + getViewportCount() { + return this._viewportCount; + } + getFrustum() { + return this._frustum; + } + updateMatrices(light) { + const shadowCamera = this.camera; + const shadowMatrix = this.matrix; + _lightPositionWorld$1.setFromMatrixPosition(light.matrixWorld); + shadowCamera.position.copy(_lightPositionWorld$1); + _lookTarget$1.setFromMatrixPosition(light.target.matrixWorld); + shadowCamera.lookAt(_lookTarget$1); + shadowCamera.updateMatrixWorld(); + _projScreenMatrix$1.multiplyMatrices(shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse); + this._frustum.setFromProjectionMatrix(_projScreenMatrix$1); + shadowMatrix.set(0.5, 0, 0, 0.5, 0, 0.5, 0, 0.5, 0, 0, 0.5, 0.5, 0, 0, 0, 1); + shadowMatrix.multiply(shadowCamera.projectionMatrix); + shadowMatrix.multiply(shadowCamera.matrixWorldInverse); + } + getViewport(viewportIndex) { + return this._viewports[viewportIndex]; + } + getFrameExtents() { + return this._frameExtents; + } + dispose() { + if (this.map) { + this.map.dispose(); + } + if (this.mapPass) { + this.mapPass.dispose(); + } + } + copy(source) { + this.camera = source.camera.clone(); + this.bias = source.bias; + this.radius = source.radius; + this.mapSize.copy(source.mapSize); + return this; + } + clone() { + return new this.constructor().copy(this); + } + toJSON() { + const object = {}; + if (this.bias !== 0) + object.bias = this.bias; + if (this.normalBias !== 0) + object.normalBias = this.normalBias; + if (this.radius !== 1) + object.radius = this.radius; + if (this.mapSize.x !== 512 || this.mapSize.y !== 512) + object.mapSize = this.mapSize.toArray(); + object.camera = this.camera.toJSON(false).object; + delete object.camera.matrix; + return object; + } + }; + var SpotLightShadow = class extends LightShadow { + constructor() { + super(new PerspectiveCamera2(50, 1, 0.5, 500)); + this.isSpotLightShadow = true; + this.focus = 1; + } + updateMatrices(light) { + const camera = this.camera; + const fov3 = RAD2DEG2 * 2 * light.angle * this.focus; + const aspect3 = this.mapSize.width / this.mapSize.height; + const far = light.distance || camera.far; + if (fov3 !== camera.fov || aspect3 !== camera.aspect || far !== camera.far) { + camera.fov = fov3; + camera.aspect = aspect3; + camera.far = far; + camera.updateProjectionMatrix(); + } + super.updateMatrices(light); + } + copy(source) { + super.copy(source); + this.focus = source.focus; + return this; + } + }; + var SpotLight = class extends Light { + constructor(color2, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 1) { + super(color2, intensity); + this.isSpotLight = true; + this.type = "SpotLight"; + this.position.copy(Object3D2.DefaultUp); + this.updateMatrix(); + this.target = new Object3D2(); + this.distance = distance; + this.angle = angle; + this.penumbra = penumbra; + this.decay = decay; + this.shadow = new SpotLightShadow(); + } + get power() { + return this.intensity * Math.PI; + } + set power(power) { + this.intensity = power / Math.PI; + } + dispose() { + this.shadow.dispose(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.distance = source.distance; + this.angle = source.angle; + this.penumbra = source.penumbra; + this.decay = source.decay; + this.target = source.target.clone(); + this.shadow = source.shadow.clone(); + return this; + } + }; + var _projScreenMatrix = /* @__PURE__ */ new Matrix42(); + var _lightPositionWorld = /* @__PURE__ */ new Vector32(); + var _lookTarget = /* @__PURE__ */ new Vector32(); + var PointLightShadow = class extends LightShadow { + constructor() { + super(new PerspectiveCamera2(90, 1, 0.5, 500)); + this.isPointLightShadow = true; + this._frameExtents = new Vector22(4, 2); + this._viewportCount = 6; + this._viewports = [ + new Vector42(2, 1, 1, 1), + new Vector42(0, 1, 1, 1), + new Vector42(3, 1, 1, 1), + new Vector42(1, 1, 1, 1), + new Vector42(3, 0, 1, 1), + new Vector42(1, 0, 1, 1) + ]; + this._cubeDirections = [new Vector32(1, 0, 0), new Vector32(-1, 0, 0), new Vector32(0, 0, 1), new Vector32(0, 0, -1), new Vector32(0, 1, 0), new Vector32(0, -1, 0)]; + this._cubeUps = [new Vector32(0, 1, 0), new Vector32(0, 1, 0), new Vector32(0, 1, 0), new Vector32(0, 1, 0), new Vector32(0, 0, 1), new Vector32(0, 0, -1)]; + } + updateMatrices(light, viewportIndex = 0) { + const camera = this.camera; + const shadowMatrix = this.matrix; + const far = light.distance || camera.far; + if (far !== camera.far) { + camera.far = far; + camera.updateProjectionMatrix(); + } + _lightPositionWorld.setFromMatrixPosition(light.matrixWorld); + camera.position.copy(_lightPositionWorld); + _lookTarget.copy(camera.position); + _lookTarget.add(this._cubeDirections[viewportIndex]); + camera.up.copy(this._cubeUps[viewportIndex]); + camera.lookAt(_lookTarget); + camera.updateMatrixWorld(); + shadowMatrix.makeTranslation(-_lightPositionWorld.x, -_lightPositionWorld.y, -_lightPositionWorld.z); + _projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); + this._frustum.setFromProjectionMatrix(_projScreenMatrix); + } + }; + var PointLight = class extends Light { + constructor(color2, intensity, distance = 0, decay = 1) { + super(color2, intensity); + this.isPointLight = true; + this.type = "PointLight"; + this.distance = distance; + this.decay = decay; + this.shadow = new PointLightShadow(); + } + get power() { + return this.intensity * 4 * Math.PI; + } + set power(power) { + this.intensity = power / (4 * Math.PI); + } + dispose() { + this.shadow.dispose(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.distance = source.distance; + this.decay = source.decay; + this.shadow = source.shadow.clone(); + return this; + } + }; + var DirectionalLightShadow = class extends LightShadow { + constructor() { + super(new OrthographicCamera2(-5, 5, 5, -5, 0.5, 500)); + this.isDirectionalLightShadow = true; + } + }; + var DirectionalLight = class extends Light { + constructor(color2, intensity) { + super(color2, intensity); + this.isDirectionalLight = true; + this.type = "DirectionalLight"; + this.position.copy(Object3D2.DefaultUp); + this.updateMatrix(); + this.target = new Object3D2(); + this.shadow = new DirectionalLightShadow(); + } + dispose() { + this.shadow.dispose(); + } + copy(source) { + super.copy(source); + this.target = source.target.clone(); + this.shadow = source.shadow.clone(); + return this; + } + }; + var AmbientLight = class extends Light { + constructor(color2, intensity) { + super(color2, intensity); + this.isAmbientLight = true; + this.type = "AmbientLight"; + } + }; + var RectAreaLight = class extends Light { + constructor(color2, intensity, width = 10, height = 10) { + super(color2, intensity); + this.isRectAreaLight = true; + this.type = "RectAreaLight"; + this.width = width; + this.height = height; + } + get power() { + return this.intensity * this.width * this.height * Math.PI; + } + set power(power) { + this.intensity = power / (this.width * this.height * Math.PI); + } + copy(source) { + super.copy(source); + this.width = source.width; + this.height = source.height; + return this; + } + toJSON(meta) { + const data = super.toJSON(meta); + data.object.width = this.width; + data.object.height = this.height; + return data; + } + }; + var SphericalHarmonics3 = class { + constructor() { + this.isSphericalHarmonics3 = true; + this.coefficients = []; + for (let i = 0; i < 9; i++) { + this.coefficients.push(new Vector32()); + } + } + set(coefficients) { + for (let i = 0; i < 9; i++) { + this.coefficients[i].copy(coefficients[i]); + } + return this; + } + zero() { + for (let i = 0; i < 9; i++) { + this.coefficients[i].set(0, 0, 0); + } + return this; + } + getAt(normal, target) { + const x2 = normal.x, y2 = normal.y, z = normal.z; + const coeff = this.coefficients; + target.copy(coeff[0]).multiplyScalar(0.282095); + target.addScaledVector(coeff[1], 0.488603 * y2); + target.addScaledVector(coeff[2], 0.488603 * z); + target.addScaledVector(coeff[3], 0.488603 * x2); + target.addScaledVector(coeff[4], 1.092548 * (x2 * y2)); + target.addScaledVector(coeff[5], 1.092548 * (y2 * z)); + target.addScaledVector(coeff[6], 0.315392 * (3 * z * z - 1)); + target.addScaledVector(coeff[7], 1.092548 * (x2 * z)); + target.addScaledVector(coeff[8], 0.546274 * (x2 * x2 - y2 * y2)); + return target; + } + getIrradianceAt(normal, target) { + const x2 = normal.x, y2 = normal.y, z = normal.z; + const coeff = this.coefficients; + target.copy(coeff[0]).multiplyScalar(0.886227); + target.addScaledVector(coeff[1], 2 * 0.511664 * y2); + target.addScaledVector(coeff[2], 2 * 0.511664 * z); + target.addScaledVector(coeff[3], 2 * 0.511664 * x2); + target.addScaledVector(coeff[4], 2 * 0.429043 * x2 * y2); + target.addScaledVector(coeff[5], 2 * 0.429043 * y2 * z); + target.addScaledVector(coeff[6], 0.743125 * z * z - 0.247708); + target.addScaledVector(coeff[7], 2 * 0.429043 * x2 * z); + target.addScaledVector(coeff[8], 0.429043 * (x2 * x2 - y2 * y2)); + return target; + } + add(sh) { + for (let i = 0; i < 9; i++) { + this.coefficients[i].add(sh.coefficients[i]); + } + return this; + } + addScaledSH(sh, s) { + for (let i = 0; i < 9; i++) { + this.coefficients[i].addScaledVector(sh.coefficients[i], s); + } + return this; + } + scale(s) { + for (let i = 0; i < 9; i++) { + this.coefficients[i].multiplyScalar(s); + } + return this; + } + lerp(sh, alpha) { + for (let i = 0; i < 9; i++) { + this.coefficients[i].lerp(sh.coefficients[i], alpha); + } + return this; + } + equals(sh) { + for (let i = 0; i < 9; i++) { + if (!this.coefficients[i].equals(sh.coefficients[i])) { + return false; + } + } + return true; + } + copy(sh) { + return this.set(sh.coefficients); + } + clone() { + return new this.constructor().copy(this); + } + fromArray(array2, offset = 0) { + const coefficients = this.coefficients; + for (let i = 0; i < 9; i++) { + coefficients[i].fromArray(array2, offset + i * 3); + } + return this; + } + toArray(array2 = [], offset = 0) { + const coefficients = this.coefficients; + for (let i = 0; i < 9; i++) { + coefficients[i].toArray(array2, offset + i * 3); + } + return array2; + } + static getBasisAt(normal, shBasis) { + const x2 = normal.x, y2 = normal.y, z = normal.z; + shBasis[0] = 0.282095; + shBasis[1] = 0.488603 * y2; + shBasis[2] = 0.488603 * z; + shBasis[3] = 0.488603 * x2; + shBasis[4] = 1.092548 * x2 * y2; + shBasis[5] = 1.092548 * y2 * z; + shBasis[6] = 0.315392 * (3 * z * z - 1); + shBasis[7] = 1.092548 * x2 * z; + shBasis[8] = 0.546274 * (x2 * x2 - y2 * y2); + } + }; + var LightProbe = class extends Light { + constructor(sh = new SphericalHarmonics3(), intensity = 1) { + super(void 0, intensity); + this.isLightProbe = true; + this.sh = sh; + } + copy(source) { + super.copy(source); + this.sh.copy(source.sh); + return this; + } + fromJSON(json) { + this.intensity = json.intensity; + this.sh.fromArray(json.sh); + return this; + } + toJSON(meta) { + const data = super.toJSON(meta); + data.object.sh = this.sh.toArray(); + return data; + } + }; + var MaterialLoader = class extends Loader { + constructor(manager) { + super(manager); + this.textures = {}; + } + load(url, onLoad, onProgress, onError) { + const scope = this; + const loader = new FileLoader(scope.manager); + loader.setPath(scope.path); + loader.setRequestHeader(scope.requestHeader); + loader.setWithCredentials(scope.withCredentials); + loader.load(url, function(text) { + try { + onLoad(scope.parse(JSON.parse(text))); + } catch (e) { + if (onError) { + onError(e); + } else { + console.error(e); + } + scope.manager.itemError(url); + } + }, onProgress, onError); + } + parse(json) { + const textures = this.textures; + function getTexture(name) { + if (textures[name] === void 0) { + console.warn("THREE.MaterialLoader: Undefined texture", name); + } + return textures[name]; + } + const material = MaterialLoader.createMaterialFromType(json.type); + if (json.uuid !== void 0) + material.uuid = json.uuid; + if (json.name !== void 0) + material.name = json.name; + if (json.color !== void 0 && material.color !== void 0) + material.color.setHex(json.color); + if (json.roughness !== void 0) + material.roughness = json.roughness; + if (json.metalness !== void 0) + material.metalness = json.metalness; + if (json.sheen !== void 0) + material.sheen = json.sheen; + if (json.sheenColor !== void 0) + material.sheenColor = new Color3().setHex(json.sheenColor); + if (json.sheenRoughness !== void 0) + material.sheenRoughness = json.sheenRoughness; + if (json.emissive !== void 0 && material.emissive !== void 0) + material.emissive.setHex(json.emissive); + if (json.specular !== void 0 && material.specular !== void 0) + material.specular.setHex(json.specular); + if (json.specularIntensity !== void 0) + material.specularIntensity = json.specularIntensity; + if (json.specularColor !== void 0 && material.specularColor !== void 0) + material.specularColor.setHex(json.specularColor); + if (json.shininess !== void 0) + material.shininess = json.shininess; + if (json.clearcoat !== void 0) + material.clearcoat = json.clearcoat; + if (json.clearcoatRoughness !== void 0) + material.clearcoatRoughness = json.clearcoatRoughness; + if (json.iridescence !== void 0) + material.iridescence = json.iridescence; + if (json.iridescenceIOR !== void 0) + material.iridescenceIOR = json.iridescenceIOR; + if (json.iridescenceThicknessRange !== void 0) + material.iridescenceThicknessRange = json.iridescenceThicknessRange; + if (json.transmission !== void 0) + material.transmission = json.transmission; + if (json.thickness !== void 0) + material.thickness = json.thickness; + if (json.attenuationDistance !== void 0) + material.attenuationDistance = json.attenuationDistance; + if (json.attenuationColor !== void 0 && material.attenuationColor !== void 0) + material.attenuationColor.setHex(json.attenuationColor); + if (json.fog !== void 0) + material.fog = json.fog; + if (json.flatShading !== void 0) + material.flatShading = json.flatShading; + if (json.blending !== void 0) + material.blending = json.blending; + if (json.combine !== void 0) + material.combine = json.combine; + if (json.side !== void 0) + material.side = json.side; + if (json.shadowSide !== void 0) + material.shadowSide = json.shadowSide; + if (json.opacity !== void 0) + material.opacity = json.opacity; + if (json.transparent !== void 0) + material.transparent = json.transparent; + if (json.alphaTest !== void 0) + material.alphaTest = json.alphaTest; + if (json.depthTest !== void 0) + material.depthTest = json.depthTest; + if (json.depthWrite !== void 0) + material.depthWrite = json.depthWrite; + if (json.colorWrite !== void 0) + material.colorWrite = json.colorWrite; + if (json.stencilWrite !== void 0) + material.stencilWrite = json.stencilWrite; + if (json.stencilWriteMask !== void 0) + material.stencilWriteMask = json.stencilWriteMask; + if (json.stencilFunc !== void 0) + material.stencilFunc = json.stencilFunc; + if (json.stencilRef !== void 0) + material.stencilRef = json.stencilRef; + if (json.stencilFuncMask !== void 0) + material.stencilFuncMask = json.stencilFuncMask; + if (json.stencilFail !== void 0) + material.stencilFail = json.stencilFail; + if (json.stencilZFail !== void 0) + material.stencilZFail = json.stencilZFail; + if (json.stencilZPass !== void 0) + material.stencilZPass = json.stencilZPass; + if (json.wireframe !== void 0) + material.wireframe = json.wireframe; + if (json.wireframeLinewidth !== void 0) + material.wireframeLinewidth = json.wireframeLinewidth; + if (json.wireframeLinecap !== void 0) + material.wireframeLinecap = json.wireframeLinecap; + if (json.wireframeLinejoin !== void 0) + material.wireframeLinejoin = json.wireframeLinejoin; + if (json.rotation !== void 0) + material.rotation = json.rotation; + if (json.linewidth !== 1) + material.linewidth = json.linewidth; + if (json.dashSize !== void 0) + material.dashSize = json.dashSize; + if (json.gapSize !== void 0) + material.gapSize = json.gapSize; + if (json.scale !== void 0) + material.scale = json.scale; + if (json.polygonOffset !== void 0) + material.polygonOffset = json.polygonOffset; + if (json.polygonOffsetFactor !== void 0) + material.polygonOffsetFactor = json.polygonOffsetFactor; + if (json.polygonOffsetUnits !== void 0) + material.polygonOffsetUnits = json.polygonOffsetUnits; + if (json.dithering !== void 0) + material.dithering = json.dithering; + if (json.alphaToCoverage !== void 0) + material.alphaToCoverage = json.alphaToCoverage; + if (json.premultipliedAlpha !== void 0) + material.premultipliedAlpha = json.premultipliedAlpha; + if (json.visible !== void 0) + material.visible = json.visible; + if (json.toneMapped !== void 0) + material.toneMapped = json.toneMapped; + if (json.userData !== void 0) + material.userData = json.userData; + if (json.vertexColors !== void 0) { + if (typeof json.vertexColors === "number") { + material.vertexColors = json.vertexColors > 0 ? true : false; + } else { + material.vertexColors = json.vertexColors; + } + } + if (json.uniforms !== void 0) { + for (const name in json.uniforms) { + const uniform = json.uniforms[name]; + material.uniforms[name] = {}; + switch (uniform.type) { + case "t": + material.uniforms[name].value = getTexture(uniform.value); + break; + case "c": + material.uniforms[name].value = new Color3().setHex(uniform.value); + break; + case "v2": + material.uniforms[name].value = new Vector22().fromArray(uniform.value); + break; + case "v3": + material.uniforms[name].value = new Vector32().fromArray(uniform.value); + break; + case "v4": + material.uniforms[name].value = new Vector42().fromArray(uniform.value); + break; + case "m3": + material.uniforms[name].value = new Matrix32().fromArray(uniform.value); + break; + case "m4": + material.uniforms[name].value = new Matrix42().fromArray(uniform.value); + break; + default: + material.uniforms[name].value = uniform.value; + } + } + } + if (json.defines !== void 0) + material.defines = json.defines; + if (json.vertexShader !== void 0) + material.vertexShader = json.vertexShader; + if (json.fragmentShader !== void 0) + material.fragmentShader = json.fragmentShader; + if (json.extensions !== void 0) { + for (const key in json.extensions) { + material.extensions[key] = json.extensions[key]; + } + } + if (json.shading !== void 0) + material.flatShading = json.shading === 1; + if (json.size !== void 0) + material.size = json.size; + if (json.sizeAttenuation !== void 0) + material.sizeAttenuation = json.sizeAttenuation; + if (json.map !== void 0) + material.map = getTexture(json.map); + if (json.matcap !== void 0) + material.matcap = getTexture(json.matcap); + if (json.alphaMap !== void 0) + material.alphaMap = getTexture(json.alphaMap); + if (json.bumpMap !== void 0) + material.bumpMap = getTexture(json.bumpMap); + if (json.bumpScale !== void 0) + material.bumpScale = json.bumpScale; + if (json.normalMap !== void 0) + material.normalMap = getTexture(json.normalMap); + if (json.normalMapType !== void 0) + material.normalMapType = json.normalMapType; + if (json.normalScale !== void 0) { + let normalScale = json.normalScale; + if (Array.isArray(normalScale) === false) { + normalScale = [normalScale, normalScale]; + } + material.normalScale = new Vector22().fromArray(normalScale); + } + if (json.displacementMap !== void 0) + material.displacementMap = getTexture(json.displacementMap); + if (json.displacementScale !== void 0) + material.displacementScale = json.displacementScale; + if (json.displacementBias !== void 0) + material.displacementBias = json.displacementBias; + if (json.roughnessMap !== void 0) + material.roughnessMap = getTexture(json.roughnessMap); + if (json.metalnessMap !== void 0) + material.metalnessMap = getTexture(json.metalnessMap); + if (json.emissiveMap !== void 0) + material.emissiveMap = getTexture(json.emissiveMap); + if (json.emissiveIntensity !== void 0) + material.emissiveIntensity = json.emissiveIntensity; + if (json.specularMap !== void 0) + material.specularMap = getTexture(json.specularMap); + if (json.specularIntensityMap !== void 0) + material.specularIntensityMap = getTexture(json.specularIntensityMap); + if (json.specularColorMap !== void 0) + material.specularColorMap = getTexture(json.specularColorMap); + if (json.envMap !== void 0) + material.envMap = getTexture(json.envMap); + if (json.envMapIntensity !== void 0) + material.envMapIntensity = json.envMapIntensity; + if (json.reflectivity !== void 0) + material.reflectivity = json.reflectivity; + if (json.refractionRatio !== void 0) + material.refractionRatio = json.refractionRatio; + if (json.lightMap !== void 0) + material.lightMap = getTexture(json.lightMap); + if (json.lightMapIntensity !== void 0) + material.lightMapIntensity = json.lightMapIntensity; + if (json.aoMap !== void 0) + material.aoMap = getTexture(json.aoMap); + if (json.aoMapIntensity !== void 0) + material.aoMapIntensity = json.aoMapIntensity; + if (json.gradientMap !== void 0) + material.gradientMap = getTexture(json.gradientMap); + if (json.clearcoatMap !== void 0) + material.clearcoatMap = getTexture(json.clearcoatMap); + if (json.clearcoatRoughnessMap !== void 0) + material.clearcoatRoughnessMap = getTexture(json.clearcoatRoughnessMap); + if (json.clearcoatNormalMap !== void 0) + material.clearcoatNormalMap = getTexture(json.clearcoatNormalMap); + if (json.clearcoatNormalScale !== void 0) + material.clearcoatNormalScale = new Vector22().fromArray(json.clearcoatNormalScale); + if (json.iridescenceMap !== void 0) + material.iridescenceMap = getTexture(json.iridescenceMap); + if (json.iridescenceThicknessMap !== void 0) + material.iridescenceThicknessMap = getTexture(json.iridescenceThicknessMap); + if (json.transmissionMap !== void 0) + material.transmissionMap = getTexture(json.transmissionMap); + if (json.thicknessMap !== void 0) + material.thicknessMap = getTexture(json.thicknessMap); + if (json.sheenColorMap !== void 0) + material.sheenColorMap = getTexture(json.sheenColorMap); + if (json.sheenRoughnessMap !== void 0) + material.sheenRoughnessMap = getTexture(json.sheenRoughnessMap); + return material; + } + setTextures(value) { + this.textures = value; + return this; + } + static createMaterialFromType(type2) { + const materialLib = { + ShadowMaterial, + SpriteMaterial, + RawShaderMaterial, + ShaderMaterial: ShaderMaterial2, + PointsMaterial, + MeshPhysicalMaterial, + MeshStandardMaterial, + MeshPhongMaterial, + MeshToonMaterial, + MeshNormalMaterial, + MeshLambertMaterial, + MeshDepthMaterial: MeshDepthMaterial2, + MeshDistanceMaterial: MeshDistanceMaterial2, + MeshBasicMaterial: MeshBasicMaterial2, + MeshMatcapMaterial, + LineDashedMaterial, + LineBasicMaterial, + Material: Material2 + }; + return new materialLib[type2](); + } + }; + var LoaderUtils = class { + static decodeText(array2) { + if (typeof TextDecoder !== "undefined") { + return new TextDecoder().decode(array2); + } + let s = ""; + for (let i = 0, il = array2.length; i < il; i++) { + s += String.fromCharCode(array2[i]); + } + try { + return decodeURIComponent(escape(s)); + } catch (e) { + return s; + } + } + static extractUrlBase(url) { + const index2 = url.lastIndexOf("/"); + if (index2 === -1) + return "./"; + return url.slice(0, index2 + 1); + } + static resolveURL(url, path) { + if (typeof url !== "string" || url === "") + return ""; + if (/^https?:\/\//i.test(path) && /^\//.test(url)) { + path = path.replace(/(^https?:\/\/[^\/]+).*/i, "$1"); + } + if (/^(https?:)?\/\//i.test(url)) + return url; + if (/^data:.*,.*$/i.test(url)) + return url; + if (/^blob:.*$/i.test(url)) + return url; + return path + url; + } + }; + var InstancedBufferGeometry = class extends BufferGeometry2 { + constructor() { + super(); + this.isInstancedBufferGeometry = true; + this.type = "InstancedBufferGeometry"; + this.instanceCount = Infinity; + } + copy(source) { + super.copy(source); + this.instanceCount = source.instanceCount; + return this; + } + clone() { + return new this.constructor().copy(this); + } + toJSON() { + const data = super.toJSON(this); + data.instanceCount = this.instanceCount; + data.isInstancedBufferGeometry = true; + return data; + } + }; + var BufferGeometryLoader = class extends Loader { + constructor(manager) { + super(manager); + } + load(url, onLoad, onProgress, onError) { + const scope = this; + const loader = new FileLoader(scope.manager); + loader.setPath(scope.path); + loader.setRequestHeader(scope.requestHeader); + loader.setWithCredentials(scope.withCredentials); + loader.load(url, function(text) { + try { + onLoad(scope.parse(JSON.parse(text))); + } catch (e) { + if (onError) { + onError(e); + } else { + console.error(e); + } + scope.manager.itemError(url); + } + }, onProgress, onError); + } + parse(json) { + const interleavedBufferMap = {}; + const arrayBufferMap = {}; + function getInterleavedBuffer(json2, uuid) { + if (interleavedBufferMap[uuid] !== void 0) + return interleavedBufferMap[uuid]; + const interleavedBuffers = json2.interleavedBuffers; + const interleavedBuffer = interleavedBuffers[uuid]; + const buffer = getArrayBuffer(json2, interleavedBuffer.buffer); + const array2 = getTypedArray(interleavedBuffer.type, buffer); + const ib = new InterleavedBuffer(array2, interleavedBuffer.stride); + ib.uuid = interleavedBuffer.uuid; + interleavedBufferMap[uuid] = ib; + return ib; + } + function getArrayBuffer(json2, uuid) { + if (arrayBufferMap[uuid] !== void 0) + return arrayBufferMap[uuid]; + const arrayBuffers = json2.arrayBuffers; + const arrayBuffer = arrayBuffers[uuid]; + const ab = new Uint32Array(arrayBuffer).buffer; + arrayBufferMap[uuid] = ab; + return ab; + } + const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry2(); + const index2 = json.data.index; + if (index2 !== void 0) { + const typedArray = getTypedArray(index2.type, index2.array); + geometry.setIndex(new BufferAttribute2(typedArray, 1)); + } + const attributes = json.data.attributes; + for (const key in attributes) { + const attribute = attributes[key]; + let bufferAttribute; + if (attribute.isInterleavedBufferAttribute) { + const interleavedBuffer = getInterleavedBuffer(json.data, attribute.data); + bufferAttribute = new InterleavedBufferAttribute(interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized); + } else { + const typedArray = getTypedArray(attribute.type, attribute.array); + const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute2; + bufferAttribute = new bufferAttributeConstr(typedArray, attribute.itemSize, attribute.normalized); + } + if (attribute.name !== void 0) + bufferAttribute.name = attribute.name; + if (attribute.usage !== void 0) + bufferAttribute.setUsage(attribute.usage); + if (attribute.updateRange !== void 0) { + bufferAttribute.updateRange.offset = attribute.updateRange.offset; + bufferAttribute.updateRange.count = attribute.updateRange.count; + } + geometry.setAttribute(key, bufferAttribute); + } + const morphAttributes = json.data.morphAttributes; + if (morphAttributes) { + for (const key in morphAttributes) { + const attributeArray = morphAttributes[key]; + const array2 = []; + for (let i = 0, il = attributeArray.length; i < il; i++) { + const attribute = attributeArray[i]; + let bufferAttribute; + if (attribute.isInterleavedBufferAttribute) { + const interleavedBuffer = getInterleavedBuffer(json.data, attribute.data); + bufferAttribute = new InterleavedBufferAttribute(interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized); + } else { + const typedArray = getTypedArray(attribute.type, attribute.array); + bufferAttribute = new BufferAttribute2(typedArray, attribute.itemSize, attribute.normalized); + } + if (attribute.name !== void 0) + bufferAttribute.name = attribute.name; + array2.push(bufferAttribute); + } + geometry.morphAttributes[key] = array2; + } + } + const morphTargetsRelative = json.data.morphTargetsRelative; + if (morphTargetsRelative) { + geometry.morphTargetsRelative = true; + } + const groups = json.data.groups || json.data.drawcalls || json.data.offsets; + if (groups !== void 0) { + for (let i = 0, n = groups.length; i !== n; ++i) { + const group = groups[i]; + geometry.addGroup(group.start, group.count, group.materialIndex); + } + } + const boundingSphere = json.data.boundingSphere; + if (boundingSphere !== void 0) { + const center = new Vector32(); + if (boundingSphere.center !== void 0) { + center.fromArray(boundingSphere.center); + } + geometry.boundingSphere = new Sphere2(center, boundingSphere.radius); + } + if (json.name) + geometry.name = json.name; + if (json.userData) + geometry.userData = json.userData; + return geometry; + } + }; + var ObjectLoader = class extends Loader { + constructor(manager) { + super(manager); + } + load(url, onLoad, onProgress, onError) { + const scope = this; + const path = this.path === "" ? LoaderUtils.extractUrlBase(url) : this.path; + this.resourcePath = this.resourcePath || path; + const loader = new FileLoader(this.manager); + loader.setPath(this.path); + loader.setRequestHeader(this.requestHeader); + loader.setWithCredentials(this.withCredentials); + loader.load(url, function(text) { + let json = null; + try { + json = JSON.parse(text); + } catch (error) { + if (onError !== void 0) + onError(error); + console.error("THREE:ObjectLoader: Can't parse " + url + ".", error.message); + return; + } + const metadata = json.metadata; + if (metadata === void 0 || metadata.type === void 0 || metadata.type.toLowerCase() === "geometry") { + console.error("THREE.ObjectLoader: Can't load " + url); + return; + } + scope.parse(json, onLoad); + }, onProgress, onError); + } + async loadAsync(url, onProgress) { + const scope = this; + const path = this.path === "" ? LoaderUtils.extractUrlBase(url) : this.path; + this.resourcePath = this.resourcePath || path; + const loader = new FileLoader(this.manager); + loader.setPath(this.path); + loader.setRequestHeader(this.requestHeader); + loader.setWithCredentials(this.withCredentials); + const text = await loader.loadAsync(url, onProgress); + const json = JSON.parse(text); + const metadata = json.metadata; + if (metadata === void 0 || metadata.type === void 0 || metadata.type.toLowerCase() === "geometry") { + throw new Error("THREE.ObjectLoader: Can't load " + url); + } + return await scope.parseAsync(json); + } + parse(json, onLoad) { + const animations = this.parseAnimations(json.animations); + const shapes = this.parseShapes(json.shapes); + const geometries = this.parseGeometries(json.geometries, shapes); + const images = this.parseImages(json.images, function() { + if (onLoad !== void 0) + onLoad(object); + }); + const textures = this.parseTextures(json.textures, images); + const materials = this.parseMaterials(json.materials, textures); + const object = this.parseObject(json.object, geometries, materials, textures, animations); + const skeletons = this.parseSkeletons(json.skeletons, object); + this.bindSkeletons(object, skeletons); + if (onLoad !== void 0) { + let hasImages = false; + for (const uuid in images) { + if (images[uuid].data instanceof HTMLImageElement) { + hasImages = true; + break; + } + } + if (hasImages === false) + onLoad(object); + } + return object; + } + async parseAsync(json) { + const animations = this.parseAnimations(json.animations); + const shapes = this.parseShapes(json.shapes); + const geometries = this.parseGeometries(json.geometries, shapes); + const images = await this.parseImagesAsync(json.images); + const textures = this.parseTextures(json.textures, images); + const materials = this.parseMaterials(json.materials, textures); + const object = this.parseObject(json.object, geometries, materials, textures, animations); + const skeletons = this.parseSkeletons(json.skeletons, object); + this.bindSkeletons(object, skeletons); + return object; + } + parseShapes(json) { + const shapes = {}; + if (json !== void 0) { + for (let i = 0, l = json.length; i < l; i++) { + const shape = new Shape().fromJSON(json[i]); + shapes[shape.uuid] = shape; + } + } + return shapes; + } + parseSkeletons(json, object) { + const skeletons = {}; + const bones = {}; + object.traverse(function(child) { + if (child.isBone) + bones[child.uuid] = child; + }); + if (json !== void 0) { + for (let i = 0, l = json.length; i < l; i++) { + const skeleton = new Skeleton().fromJSON(json[i], bones); + skeletons[skeleton.uuid] = skeleton; + } + } + return skeletons; + } + parseGeometries(json, shapes) { + const geometries = {}; + if (json !== void 0) { + const bufferGeometryLoader = new BufferGeometryLoader(); + for (let i = 0, l = json.length; i < l; i++) { + let geometry; + const data = json[i]; + switch (data.type) { + case "BufferGeometry": + case "InstancedBufferGeometry": + geometry = bufferGeometryLoader.parse(data); + break; + case "Geometry": + console.error("THREE.ObjectLoader: The legacy Geometry type is no longer supported."); + break; + default: + if (data.type in Geometries) { + geometry = Geometries[data.type].fromJSON(data, shapes); + } else { + console.warn(`THREE.ObjectLoader: Unsupported geometry type "${data.type}"`); + } + } + geometry.uuid = data.uuid; + if (data.name !== void 0) + geometry.name = data.name; + if (geometry.isBufferGeometry === true && data.userData !== void 0) + geometry.userData = data.userData; + geometries[data.uuid] = geometry; + } + } + return geometries; + } + parseMaterials(json, textures) { + const cache2 = {}; + const materials = {}; + if (json !== void 0) { + const loader = new MaterialLoader(); + loader.setTextures(textures); + for (let i = 0, l = json.length; i < l; i++) { + const data = json[i]; + if (data.type === "MultiMaterial") { + const array2 = []; + for (let j = 0; j < data.materials.length; j++) { + const material = data.materials[j]; + if (cache2[material.uuid] === void 0) { + cache2[material.uuid] = loader.parse(material); + } + array2.push(cache2[material.uuid]); + } + materials[data.uuid] = array2; + } else { + if (cache2[data.uuid] === void 0) { + cache2[data.uuid] = loader.parse(data); + } + materials[data.uuid] = cache2[data.uuid]; + } + } + } + return materials; + } + parseAnimations(json) { + const animations = {}; + if (json !== void 0) { + for (let i = 0; i < json.length; i++) { + const data = json[i]; + const clip = AnimationClip.parse(data); + animations[clip.uuid] = clip; + } + } + return animations; + } + parseImages(json, onLoad) { + const scope = this; + const images = {}; + let loader; + function loadImage(url) { + scope.manager.itemStart(url); + return loader.load(url, function() { + scope.manager.itemEnd(url); + }, void 0, function() { + scope.manager.itemError(url); + scope.manager.itemEnd(url); + }); + } + function deserializeImage(image) { + if (typeof image === "string") { + const url = image; + const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test(url) ? url : scope.resourcePath + url; + return loadImage(path); + } else { + if (image.data) { + return { + data: getTypedArray(image.type, image.data), + width: image.width, + height: image.height + }; + } else { + return null; + } + } + } + if (json !== void 0 && json.length > 0) { + const manager = new LoadingManager(onLoad); + loader = new ImageLoader(manager); + loader.setCrossOrigin(this.crossOrigin); + for (let i = 0, il = json.length; i < il; i++) { + const image = json[i]; + const url = image.url; + if (Array.isArray(url)) { + const imageArray = []; + for (let j = 0, jl = url.length; j < jl; j++) { + const currentUrl = url[j]; + const deserializedImage = deserializeImage(currentUrl); + if (deserializedImage !== null) { + if (deserializedImage instanceof HTMLImageElement) { + imageArray.push(deserializedImage); + } else { + imageArray.push(new DataTexture(deserializedImage.data, deserializedImage.width, deserializedImage.height)); + } + } + } + images[image.uuid] = new Source2(imageArray); + } else { + const deserializedImage = deserializeImage(image.url); + images[image.uuid] = new Source2(deserializedImage); + } + } + } + return images; + } + async parseImagesAsync(json) { + const scope = this; + const images = {}; + let loader; + async function deserializeImage(image) { + if (typeof image === "string") { + const url = image; + const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test(url) ? url : scope.resourcePath + url; + return await loader.loadAsync(path); + } else { + if (image.data) { + return { + data: getTypedArray(image.type, image.data), + width: image.width, + height: image.height + }; + } else { + return null; + } + } + } + if (json !== void 0 && json.length > 0) { + loader = new ImageLoader(this.manager); + loader.setCrossOrigin(this.crossOrigin); + for (let i = 0, il = json.length; i < il; i++) { + const image = json[i]; + const url = image.url; + if (Array.isArray(url)) { + const imageArray = []; + for (let j = 0, jl = url.length; j < jl; j++) { + const currentUrl = url[j]; + const deserializedImage = await deserializeImage(currentUrl); + if (deserializedImage !== null) { + if (deserializedImage instanceof HTMLImageElement) { + imageArray.push(deserializedImage); + } else { + imageArray.push(new DataTexture(deserializedImage.data, deserializedImage.width, deserializedImage.height)); + } + } + } + images[image.uuid] = new Source2(imageArray); + } else { + const deserializedImage = await deserializeImage(image.url); + images[image.uuid] = new Source2(deserializedImage); + } + } + } + return images; + } + parseTextures(json, images) { + function parseConstant(value, type2) { + if (typeof value === "number") + return value; + console.warn("THREE.ObjectLoader.parseTexture: Constant should be in numeric form.", value); + return type2[value]; + } + const textures = {}; + if (json !== void 0) { + for (let i = 0, l = json.length; i < l; i++) { + const data = json[i]; + if (data.image === void 0) { + console.warn('THREE.ObjectLoader: No "image" specified for', data.uuid); + } + if (images[data.image] === void 0) { + console.warn("THREE.ObjectLoader: Undefined image", data.image); + } + const source = images[data.image]; + const image = source.data; + let texture; + if (Array.isArray(image)) { + texture = new CubeTexture2(); + if (image.length === 6) + texture.needsUpdate = true; + } else { + if (image && image.data) { + texture = new DataTexture(); + } else { + texture = new Texture2(); + } + if (image) + texture.needsUpdate = true; + } + texture.source = source; + texture.uuid = data.uuid; + if (data.name !== void 0) + texture.name = data.name; + if (data.mapping !== void 0) + texture.mapping = parseConstant(data.mapping, TEXTURE_MAPPING); + if (data.offset !== void 0) + texture.offset.fromArray(data.offset); + if (data.repeat !== void 0) + texture.repeat.fromArray(data.repeat); + if (data.center !== void 0) + texture.center.fromArray(data.center); + if (data.rotation !== void 0) + texture.rotation = data.rotation; + if (data.wrap !== void 0) { + texture.wrapS = parseConstant(data.wrap[0], TEXTURE_WRAPPING); + texture.wrapT = parseConstant(data.wrap[1], TEXTURE_WRAPPING); + } + if (data.format !== void 0) + texture.format = data.format; + if (data.type !== void 0) + texture.type = data.type; + if (data.encoding !== void 0) + texture.encoding = data.encoding; + if (data.minFilter !== void 0) + texture.minFilter = parseConstant(data.minFilter, TEXTURE_FILTER); + if (data.magFilter !== void 0) + texture.magFilter = parseConstant(data.magFilter, TEXTURE_FILTER); + if (data.anisotropy !== void 0) + texture.anisotropy = data.anisotropy; + if (data.flipY !== void 0) + texture.flipY = data.flipY; + if (data.premultiplyAlpha !== void 0) + texture.premultiplyAlpha = data.premultiplyAlpha; + if (data.unpackAlignment !== void 0) + texture.unpackAlignment = data.unpackAlignment; + if (data.userData !== void 0) + texture.userData = data.userData; + textures[data.uuid] = texture; + } + } + return textures; + } + parseObject(data, geometries, materials, textures, animations) { + let object; + function getGeometry(name) { + if (geometries[name] === void 0) { + console.warn("THREE.ObjectLoader: Undefined geometry", name); + } + return geometries[name]; + } + function getMaterial(name) { + if (name === void 0) + return void 0; + if (Array.isArray(name)) { + const array2 = []; + for (let i = 0, l = name.length; i < l; i++) { + const uuid = name[i]; + if (materials[uuid] === void 0) { + console.warn("THREE.ObjectLoader: Undefined material", uuid); + } + array2.push(materials[uuid]); + } + return array2; + } + if (materials[name] === void 0) { + console.warn("THREE.ObjectLoader: Undefined material", name); + } + return materials[name]; + } + function getTexture(uuid) { + if (textures[uuid] === void 0) { + console.warn("THREE.ObjectLoader: Undefined texture", uuid); + } + return textures[uuid]; + } + let geometry, material; + switch (data.type) { + case "Scene": + object = new Scene2(); + if (data.background !== void 0) { + if (Number.isInteger(data.background)) { + object.background = new Color3(data.background); + } else { + object.background = getTexture(data.background); + } + } + if (data.environment !== void 0) { + object.environment = getTexture(data.environment); + } + if (data.fog !== void 0) { + if (data.fog.type === "Fog") { + object.fog = new Fog(data.fog.color, data.fog.near, data.fog.far); + } else if (data.fog.type === "FogExp2") { + object.fog = new FogExp2(data.fog.color, data.fog.density); + } + } + break; + case "PerspectiveCamera": + object = new PerspectiveCamera2(data.fov, data.aspect, data.near, data.far); + if (data.focus !== void 0) + object.focus = data.focus; + if (data.zoom !== void 0) + object.zoom = data.zoom; + if (data.filmGauge !== void 0) + object.filmGauge = data.filmGauge; + if (data.filmOffset !== void 0) + object.filmOffset = data.filmOffset; + if (data.view !== void 0) + object.view = Object.assign({}, data.view); + break; + case "OrthographicCamera": + object = new OrthographicCamera2(data.left, data.right, data.top, data.bottom, data.near, data.far); + if (data.zoom !== void 0) + object.zoom = data.zoom; + if (data.view !== void 0) + object.view = Object.assign({}, data.view); + break; + case "AmbientLight": + object = new AmbientLight(data.color, data.intensity); + break; + case "DirectionalLight": + object = new DirectionalLight(data.color, data.intensity); + break; + case "PointLight": + object = new PointLight(data.color, data.intensity, data.distance, data.decay); + break; + case "RectAreaLight": + object = new RectAreaLight(data.color, data.intensity, data.width, data.height); + break; + case "SpotLight": + object = new SpotLight(data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay); + break; + case "HemisphereLight": + object = new HemisphereLight(data.color, data.groundColor, data.intensity); + break; + case "LightProbe": + object = new LightProbe().fromJSON(data); + break; + case "SkinnedMesh": + geometry = getGeometry(data.geometry); + material = getMaterial(data.material); + object = new SkinnedMesh(geometry, material); + if (data.bindMode !== void 0) + object.bindMode = data.bindMode; + if (data.bindMatrix !== void 0) + object.bindMatrix.fromArray(data.bindMatrix); + if (data.skeleton !== void 0) + object.skeleton = data.skeleton; + break; + case "Mesh": + geometry = getGeometry(data.geometry); + material = getMaterial(data.material); + object = new Mesh2(geometry, material); + break; + case "InstancedMesh": + geometry = getGeometry(data.geometry); + material = getMaterial(data.material); + const count = data.count; + const instanceMatrix = data.instanceMatrix; + const instanceColor = data.instanceColor; + object = new InstancedMesh(geometry, material, count); + object.instanceMatrix = new InstancedBufferAttribute(new Float32Array(instanceMatrix.array), 16); + if (instanceColor !== void 0) + object.instanceColor = new InstancedBufferAttribute(new Float32Array(instanceColor.array), instanceColor.itemSize); + break; + case "LOD": + object = new LOD(); + break; + case "Line": + object = new Line(getGeometry(data.geometry), getMaterial(data.material)); + break; + case "LineLoop": + object = new LineLoop(getGeometry(data.geometry), getMaterial(data.material)); + break; + case "LineSegments": + object = new LineSegments(getGeometry(data.geometry), getMaterial(data.material)); + break; + case "PointCloud": + case "Points": + object = new Points(getGeometry(data.geometry), getMaterial(data.material)); + break; + case "Sprite": + object = new Sprite(getMaterial(data.material)); + break; + case "Group": + object = new Group2(); + break; + case "Bone": + object = new Bone(); + break; + default: + object = new Object3D2(); + } + object.uuid = data.uuid; + if (data.name !== void 0) + object.name = data.name; + if (data.matrix !== void 0) { + object.matrix.fromArray(data.matrix); + if (data.matrixAutoUpdate !== void 0) + object.matrixAutoUpdate = data.matrixAutoUpdate; + if (object.matrixAutoUpdate) + object.matrix.decompose(object.position, object.quaternion, object.scale); + } else { + if (data.position !== void 0) + object.position.fromArray(data.position); + if (data.rotation !== void 0) + object.rotation.fromArray(data.rotation); + if (data.quaternion !== void 0) + object.quaternion.fromArray(data.quaternion); + if (data.scale !== void 0) + object.scale.fromArray(data.scale); + } + if (data.castShadow !== void 0) + object.castShadow = data.castShadow; + if (data.receiveShadow !== void 0) + object.receiveShadow = data.receiveShadow; + if (data.shadow) { + if (data.shadow.bias !== void 0) + object.shadow.bias = data.shadow.bias; + if (data.shadow.normalBias !== void 0) + object.shadow.normalBias = data.shadow.normalBias; + if (data.shadow.radius !== void 0) + object.shadow.radius = data.shadow.radius; + if (data.shadow.mapSize !== void 0) + object.shadow.mapSize.fromArray(data.shadow.mapSize); + if (data.shadow.camera !== void 0) + object.shadow.camera = this.parseObject(data.shadow.camera); + } + if (data.visible !== void 0) + object.visible = data.visible; + if (data.frustumCulled !== void 0) + object.frustumCulled = data.frustumCulled; + if (data.renderOrder !== void 0) + object.renderOrder = data.renderOrder; + if (data.userData !== void 0) + object.userData = data.userData; + if (data.layers !== void 0) + object.layers.mask = data.layers; + if (data.children !== void 0) { + const children2 = data.children; + for (let i = 0; i < children2.length; i++) { + object.add(this.parseObject(children2[i], geometries, materials, textures, animations)); + } + } + if (data.animations !== void 0) { + const objectAnimations = data.animations; + for (let i = 0; i < objectAnimations.length; i++) { + const uuid = objectAnimations[i]; + object.animations.push(animations[uuid]); + } + } + if (data.type === "LOD") { + if (data.autoUpdate !== void 0) + object.autoUpdate = data.autoUpdate; + const levels = data.levels; + for (let l = 0; l < levels.length; l++) { + const level = levels[l]; + const child = object.getObjectByProperty("uuid", level.object); + if (child !== void 0) { + object.addLevel(child, level.distance); + } + } + } + return object; + } + bindSkeletons(object, skeletons) { + if (Object.keys(skeletons).length === 0) + return; + object.traverse(function(child) { + if (child.isSkinnedMesh === true && child.skeleton !== void 0) { + const skeleton = skeletons[child.skeleton]; + if (skeleton === void 0) { + console.warn("THREE.ObjectLoader: No skeleton found with UUID:", child.skeleton); + } else { + child.bind(skeleton, child.bindMatrix); + } + } + }); + } + }; + var TEXTURE_MAPPING = { + UVMapping: UVMapping2, + CubeReflectionMapping: CubeReflectionMapping2, + CubeRefractionMapping: CubeRefractionMapping2, + EquirectangularReflectionMapping: EquirectangularReflectionMapping2, + EquirectangularRefractionMapping: EquirectangularRefractionMapping2, + CubeUVReflectionMapping: CubeUVReflectionMapping2 + }; + var TEXTURE_WRAPPING = { + RepeatWrapping: RepeatWrapping2, + ClampToEdgeWrapping: ClampToEdgeWrapping2, + MirroredRepeatWrapping: MirroredRepeatWrapping2 + }; + var TEXTURE_FILTER = { + NearestFilter: NearestFilter2, + NearestMipmapNearestFilter: NearestMipmapNearestFilter2, + NearestMipmapLinearFilter: NearestMipmapLinearFilter2, + LinearFilter: LinearFilter2, + LinearMipmapNearestFilter: LinearMipmapNearestFilter2, + LinearMipmapLinearFilter: LinearMipmapLinearFilter2 + }; + var ImageBitmapLoader = class extends Loader { + constructor(manager) { + super(manager); + this.isImageBitmapLoader = true; + if (typeof createImageBitmap === "undefined") { + console.warn("THREE.ImageBitmapLoader: createImageBitmap() not supported."); + } + if (typeof fetch === "undefined") { + console.warn("THREE.ImageBitmapLoader: fetch() not supported."); + } + this.options = { + premultiplyAlpha: "none" + }; + } + setOptions(options) { + this.options = options; + return this; + } + load(url, onLoad, onProgress, onError) { + if (url === void 0) + url = ""; + if (this.path !== void 0) + url = this.path + url; + url = this.manager.resolveURL(url); + const scope = this; + const cached = Cache.get(url); + if (cached !== void 0) { + scope.manager.itemStart(url); + setTimeout(function() { + if (onLoad) + onLoad(cached); + scope.manager.itemEnd(url); + }, 0); + return cached; + } + const fetchOptions = {}; + fetchOptions.credentials = this.crossOrigin === "anonymous" ? "same-origin" : "include"; + fetchOptions.headers = this.requestHeader; + fetch(url, fetchOptions).then(function(res) { + return res.blob(); + }).then(function(blob) { + return createImageBitmap(blob, Object.assign(scope.options, { + colorSpaceConversion: "none" + })); + }).then(function(imageBitmap) { + Cache.add(url, imageBitmap); + if (onLoad) + onLoad(imageBitmap); + scope.manager.itemEnd(url); + }).catch(function(e) { + if (onError) + onError(e); + scope.manager.itemError(url); + scope.manager.itemEnd(url); + }); + scope.manager.itemStart(url); + } + }; + var _context; + var AudioContext = { + getContext: function() { + if (_context === void 0) { + _context = new (window.AudioContext || window.webkitAudioContext)(); + } + return _context; + }, + setContext: function(value) { + _context = value; + } + }; + var AudioLoader = class extends Loader { + constructor(manager) { + super(manager); + } + load(url, onLoad, onProgress, onError) { + const scope = this; + const loader = new FileLoader(this.manager); + loader.setResponseType("arraybuffer"); + loader.setPath(this.path); + loader.setRequestHeader(this.requestHeader); + loader.setWithCredentials(this.withCredentials); + loader.load(url, function(buffer) { + try { + const bufferCopy = buffer.slice(0); + const context = AudioContext.getContext(); + context.decodeAudioData(bufferCopy, function(audioBuffer) { + onLoad(audioBuffer); + }); + } catch (e) { + if (onError) { + onError(e); + } else { + console.error(e); + } + scope.manager.itemError(url); + } + }, onProgress, onError); + } + }; + var HemisphereLightProbe = class extends LightProbe { + constructor(skyColor, groundColor, intensity = 1) { + super(void 0, intensity); + this.isHemisphereLightProbe = true; + const color1 = new Color3().set(skyColor); + const color2 = new Color3().set(groundColor); + const sky = new Vector32(color1.r, color1.g, color1.b); + const ground = new Vector32(color2.r, color2.g, color2.b); + const c0 = Math.sqrt(Math.PI); + const c1 = c0 * Math.sqrt(0.75); + this.sh.coefficients[0].copy(sky).add(ground).multiplyScalar(c0); + this.sh.coefficients[1].copy(sky).sub(ground).multiplyScalar(c1); + } + }; + var AmbientLightProbe = class extends LightProbe { + constructor(color2, intensity = 1) { + super(void 0, intensity); + this.isAmbientLightProbe = true; + const color1 = new Color3().set(color2); + this.sh.coefficients[0].set(color1.r, color1.g, color1.b).multiplyScalar(2 * Math.sqrt(Math.PI)); + } + }; + var _eyeRight = /* @__PURE__ */ new Matrix42(); + var _eyeLeft = /* @__PURE__ */ new Matrix42(); + var _projectionMatrix = /* @__PURE__ */ new Matrix42(); + var StereoCamera = class { + constructor() { + this.type = "StereoCamera"; + this.aspect = 1; + this.eyeSep = 0.064; + this.cameraL = new PerspectiveCamera2(); + this.cameraL.layers.enable(1); + this.cameraL.matrixAutoUpdate = false; + this.cameraR = new PerspectiveCamera2(); + this.cameraR.layers.enable(2); + this.cameraR.matrixAutoUpdate = false; + this._cache = { + focus: null, + fov: null, + aspect: null, + near: null, + far: null, + zoom: null, + eyeSep: null + }; + } + update(camera) { + const cache2 = this._cache; + const needsUpdate = cache2.focus !== camera.focus || cache2.fov !== camera.fov || cache2.aspect !== camera.aspect * this.aspect || cache2.near !== camera.near || cache2.far !== camera.far || cache2.zoom !== camera.zoom || cache2.eyeSep !== this.eyeSep; + if (needsUpdate) { + cache2.focus = camera.focus; + cache2.fov = camera.fov; + cache2.aspect = camera.aspect * this.aspect; + cache2.near = camera.near; + cache2.far = camera.far; + cache2.zoom = camera.zoom; + cache2.eyeSep = this.eyeSep; + _projectionMatrix.copy(camera.projectionMatrix); + const eyeSepHalf = cache2.eyeSep / 2; + const eyeSepOnProjection = eyeSepHalf * cache2.near / cache2.focus; + const ymax = cache2.near * Math.tan(DEG2RAD2 * cache2.fov * 0.5) / cache2.zoom; + let xmin, xmax; + _eyeLeft.elements[12] = -eyeSepHalf; + _eyeRight.elements[12] = eyeSepHalf; + xmin = -ymax * cache2.aspect + eyeSepOnProjection; + xmax = ymax * cache2.aspect + eyeSepOnProjection; + _projectionMatrix.elements[0] = 2 * cache2.near / (xmax - xmin); + _projectionMatrix.elements[8] = (xmax + xmin) / (xmax - xmin); + this.cameraL.projectionMatrix.copy(_projectionMatrix); + xmin = -ymax * cache2.aspect - eyeSepOnProjection; + xmax = ymax * cache2.aspect - eyeSepOnProjection; + _projectionMatrix.elements[0] = 2 * cache2.near / (xmax - xmin); + _projectionMatrix.elements[8] = (xmax + xmin) / (xmax - xmin); + this.cameraR.projectionMatrix.copy(_projectionMatrix); + } + this.cameraL.matrixWorld.copy(camera.matrixWorld).multiply(_eyeLeft); + this.cameraR.matrixWorld.copy(camera.matrixWorld).multiply(_eyeRight); + } + }; + var Clock = class { + constructor(autoStart = true) { + this.autoStart = autoStart; + this.startTime = 0; + this.oldTime = 0; + this.elapsedTime = 0; + this.running = false; + } + start() { + this.startTime = now2(); + this.oldTime = this.startTime; + this.elapsedTime = 0; + this.running = true; + } + stop() { + this.getElapsedTime(); + this.running = false; + this.autoStart = false; + } + getElapsedTime() { + this.getDelta(); + return this.elapsedTime; + } + getDelta() { + let diff = 0; + if (this.autoStart && !this.running) { + this.start(); + return 0; + } + if (this.running) { + const newTime = now2(); + diff = (newTime - this.oldTime) / 1e3; + this.oldTime = newTime; + this.elapsedTime += diff; + } + return diff; + } + }; + function now2() { + return (typeof performance === "undefined" ? Date : performance).now(); + } + var _position$1 = /* @__PURE__ */ new Vector32(); + var _quaternion$1 = /* @__PURE__ */ new Quaternion2(); + var _scale$1 = /* @__PURE__ */ new Vector32(); + var _orientation$1 = /* @__PURE__ */ new Vector32(); + var AudioListener = class extends Object3D2 { + constructor() { + super(); + this.type = "AudioListener"; + this.context = AudioContext.getContext(); + this.gain = this.context.createGain(); + this.gain.connect(this.context.destination); + this.filter = null; + this.timeDelta = 0; + this._clock = new Clock(); + } + getInput() { + return this.gain; + } + removeFilter() { + if (this.filter !== null) { + this.gain.disconnect(this.filter); + this.filter.disconnect(this.context.destination); + this.gain.connect(this.context.destination); + this.filter = null; + } + return this; + } + getFilter() { + return this.filter; + } + setFilter(value) { + if (this.filter !== null) { + this.gain.disconnect(this.filter); + this.filter.disconnect(this.context.destination); + } else { + this.gain.disconnect(this.context.destination); + } + this.filter = value; + this.gain.connect(this.filter); + this.filter.connect(this.context.destination); + return this; + } + getMasterVolume() { + return this.gain.gain.value; + } + setMasterVolume(value) { + this.gain.gain.setTargetAtTime(value, this.context.currentTime, 0.01); + return this; + } + updateMatrixWorld(force) { + super.updateMatrixWorld(force); + const listener = this.context.listener; + const up = this.up; + this.timeDelta = this._clock.getDelta(); + this.matrixWorld.decompose(_position$1, _quaternion$1, _scale$1); + _orientation$1.set(0, 0, -1).applyQuaternion(_quaternion$1); + if (listener.positionX) { + const endTime = this.context.currentTime + this.timeDelta; + listener.positionX.linearRampToValueAtTime(_position$1.x, endTime); + listener.positionY.linearRampToValueAtTime(_position$1.y, endTime); + listener.positionZ.linearRampToValueAtTime(_position$1.z, endTime); + listener.forwardX.linearRampToValueAtTime(_orientation$1.x, endTime); + listener.forwardY.linearRampToValueAtTime(_orientation$1.y, endTime); + listener.forwardZ.linearRampToValueAtTime(_orientation$1.z, endTime); + listener.upX.linearRampToValueAtTime(up.x, endTime); + listener.upY.linearRampToValueAtTime(up.y, endTime); + listener.upZ.linearRampToValueAtTime(up.z, endTime); + } else { + listener.setPosition(_position$1.x, _position$1.y, _position$1.z); + listener.setOrientation(_orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z); + } + } + }; + var Audio = class extends Object3D2 { + constructor(listener) { + super(); + this.type = "Audio"; + this.listener = listener; + this.context = listener.context; + this.gain = this.context.createGain(); + this.gain.connect(listener.getInput()); + this.autoplay = false; + this.buffer = null; + this.detune = 0; + this.loop = false; + this.loopStart = 0; + this.loopEnd = 0; + this.offset = 0; + this.duration = void 0; + this.playbackRate = 1; + this.isPlaying = false; + this.hasPlaybackControl = true; + this.source = null; + this.sourceType = "empty"; + this._startedAt = 0; + this._progress = 0; + this._connected = false; + this.filters = []; + } + getOutput() { + return this.gain; + } + setNodeSource(audioNode) { + this.hasPlaybackControl = false; + this.sourceType = "audioNode"; + this.source = audioNode; + this.connect(); + return this; + } + setMediaElementSource(mediaElement) { + this.hasPlaybackControl = false; + this.sourceType = "mediaNode"; + this.source = this.context.createMediaElementSource(mediaElement); + this.connect(); + return this; + } + setMediaStreamSource(mediaStream) { + this.hasPlaybackControl = false; + this.sourceType = "mediaStreamNode"; + this.source = this.context.createMediaStreamSource(mediaStream); + this.connect(); + return this; + } + setBuffer(audioBuffer) { + this.buffer = audioBuffer; + this.sourceType = "buffer"; + if (this.autoplay) + this.play(); + return this; + } + play(delay = 0) { + if (this.isPlaying === true) { + console.warn("THREE.Audio: Audio is already playing."); + return; + } + if (this.hasPlaybackControl === false) { + console.warn("THREE.Audio: this Audio has no playback control."); + return; + } + this._startedAt = this.context.currentTime + delay; + const source = this.context.createBufferSource(); + source.buffer = this.buffer; + source.loop = this.loop; + source.loopStart = this.loopStart; + source.loopEnd = this.loopEnd; + source.onended = this.onEnded.bind(this); + source.start(this._startedAt, this._progress + this.offset, this.duration); + this.isPlaying = true; + this.source = source; + this.setDetune(this.detune); + this.setPlaybackRate(this.playbackRate); + return this.connect(); + } + pause() { + if (this.hasPlaybackControl === false) { + console.warn("THREE.Audio: this Audio has no playback control."); + return; + } + if (this.isPlaying === true) { + this._progress += Math.max(this.context.currentTime - this._startedAt, 0) * this.playbackRate; + if (this.loop === true) { + this._progress = this._progress % (this.duration || this.buffer.duration); + } + this.source.stop(); + this.source.onended = null; + this.isPlaying = false; + } + return this; + } + stop() { + if (this.hasPlaybackControl === false) { + console.warn("THREE.Audio: this Audio has no playback control."); + return; + } + this._progress = 0; + this.source.stop(); + this.source.onended = null; + this.isPlaying = false; + return this; + } + connect() { + if (this.filters.length > 0) { + this.source.connect(this.filters[0]); + for (let i = 1, l = this.filters.length; i < l; i++) { + this.filters[i - 1].connect(this.filters[i]); + } + this.filters[this.filters.length - 1].connect(this.getOutput()); + } else { + this.source.connect(this.getOutput()); + } + this._connected = true; + return this; + } + disconnect() { + if (this.filters.length > 0) { + this.source.disconnect(this.filters[0]); + for (let i = 1, l = this.filters.length; i < l; i++) { + this.filters[i - 1].disconnect(this.filters[i]); + } + this.filters[this.filters.length - 1].disconnect(this.getOutput()); + } else { + this.source.disconnect(this.getOutput()); + } + this._connected = false; + return this; + } + getFilters() { + return this.filters; + } + setFilters(value) { + if (!value) + value = []; + if (this._connected === true) { + this.disconnect(); + this.filters = value.slice(); + this.connect(); + } else { + this.filters = value.slice(); + } + return this; + } + setDetune(value) { + this.detune = value; + if (this.source.detune === void 0) + return; + if (this.isPlaying === true) { + this.source.detune.setTargetAtTime(this.detune, this.context.currentTime, 0.01); + } + return this; + } + getDetune() { + return this.detune; + } + getFilter() { + return this.getFilters()[0]; + } + setFilter(filter2) { + return this.setFilters(filter2 ? [filter2] : []); + } + setPlaybackRate(value) { + if (this.hasPlaybackControl === false) { + console.warn("THREE.Audio: this Audio has no playback control."); + return; + } + this.playbackRate = value; + if (this.isPlaying === true) { + this.source.playbackRate.setTargetAtTime(this.playbackRate, this.context.currentTime, 0.01); + } + return this; + } + getPlaybackRate() { + return this.playbackRate; + } + onEnded() { + this.isPlaying = false; + } + getLoop() { + if (this.hasPlaybackControl === false) { + console.warn("THREE.Audio: this Audio has no playback control."); + return false; + } + return this.loop; + } + setLoop(value) { + if (this.hasPlaybackControl === false) { + console.warn("THREE.Audio: this Audio has no playback control."); + return; + } + this.loop = value; + if (this.isPlaying === true) { + this.source.loop = this.loop; + } + return this; + } + setLoopStart(value) { + this.loopStart = value; + return this; + } + setLoopEnd(value) { + this.loopEnd = value; + return this; + } + getVolume() { + return this.gain.gain.value; + } + setVolume(value) { + this.gain.gain.setTargetAtTime(value, this.context.currentTime, 0.01); + return this; + } + }; + var _position = /* @__PURE__ */ new Vector32(); + var _quaternion = /* @__PURE__ */ new Quaternion2(); + var _scale = /* @__PURE__ */ new Vector32(); + var _orientation = /* @__PURE__ */ new Vector32(); + var PositionalAudio = class extends Audio { + constructor(listener) { + super(listener); + this.panner = this.context.createPanner(); + this.panner.panningModel = "HRTF"; + this.panner.connect(this.gain); + } + disconnect() { + super.disconnect(); + this.panner.disconnect(this.gain); + } + getOutput() { + return this.panner; + } + getRefDistance() { + return this.panner.refDistance; + } + setRefDistance(value) { + this.panner.refDistance = value; + return this; + } + getRolloffFactor() { + return this.panner.rolloffFactor; + } + setRolloffFactor(value) { + this.panner.rolloffFactor = value; + return this; + } + getDistanceModel() { + return this.panner.distanceModel; + } + setDistanceModel(value) { + this.panner.distanceModel = value; + return this; + } + getMaxDistance() { + return this.panner.maxDistance; + } + setMaxDistance(value) { + this.panner.maxDistance = value; + return this; + } + setDirectionalCone(coneInnerAngle, coneOuterAngle, coneOuterGain) { + this.panner.coneInnerAngle = coneInnerAngle; + this.panner.coneOuterAngle = coneOuterAngle; + this.panner.coneOuterGain = coneOuterGain; + return this; + } + updateMatrixWorld(force) { + super.updateMatrixWorld(force); + if (this.hasPlaybackControl === true && this.isPlaying === false) + return; + this.matrixWorld.decompose(_position, _quaternion, _scale); + _orientation.set(0, 0, 1).applyQuaternion(_quaternion); + const panner = this.panner; + if (panner.positionX) { + const endTime = this.context.currentTime + this.listener.timeDelta; + panner.positionX.linearRampToValueAtTime(_position.x, endTime); + panner.positionY.linearRampToValueAtTime(_position.y, endTime); + panner.positionZ.linearRampToValueAtTime(_position.z, endTime); + panner.orientationX.linearRampToValueAtTime(_orientation.x, endTime); + panner.orientationY.linearRampToValueAtTime(_orientation.y, endTime); + panner.orientationZ.linearRampToValueAtTime(_orientation.z, endTime); + } else { + panner.setPosition(_position.x, _position.y, _position.z); + panner.setOrientation(_orientation.x, _orientation.y, _orientation.z); + } + } + }; + var AudioAnalyser = class { + constructor(audio, fftSize = 2048) { + this.analyser = audio.context.createAnalyser(); + this.analyser.fftSize = fftSize; + this.data = new Uint8Array(this.analyser.frequencyBinCount); + audio.getOutput().connect(this.analyser); + } + getFrequencyData() { + this.analyser.getByteFrequencyData(this.data); + return this.data; + } + getAverageFrequency() { + let value = 0; + const data = this.getFrequencyData(); + for (let i = 0; i < data.length; i++) { + value += data[i]; + } + return value / data.length; + } + }; + var PropertyMixer = class { + constructor(binding, typeName, valueSize) { + this.binding = binding; + this.valueSize = valueSize; + let mixFunction, mixFunctionAdditive, setIdentity; + switch (typeName) { + case "quaternion": + mixFunction = this._slerp; + mixFunctionAdditive = this._slerpAdditive; + setIdentity = this._setAdditiveIdentityQuaternion; + this.buffer = new Float64Array(valueSize * 6); + this._workIndex = 5; + break; + case "string": + case "bool": + mixFunction = this._select; + mixFunctionAdditive = this._select; + setIdentity = this._setAdditiveIdentityOther; + this.buffer = new Array(valueSize * 5); + break; + default: + mixFunction = this._lerp; + mixFunctionAdditive = this._lerpAdditive; + setIdentity = this._setAdditiveIdentityNumeric; + this.buffer = new Float64Array(valueSize * 5); + } + this._mixBufferRegion = mixFunction; + this._mixBufferRegionAdditive = mixFunctionAdditive; + this._setIdentity = setIdentity; + this._origIndex = 3; + this._addIndex = 4; + this.cumulativeWeight = 0; + this.cumulativeWeightAdditive = 0; + this.useCount = 0; + this.referenceCount = 0; + } + accumulate(accuIndex, weight) { + const buffer = this.buffer, stride = this.valueSize, offset = accuIndex * stride + stride; + let currentWeight = this.cumulativeWeight; + if (currentWeight === 0) { + for (let i = 0; i !== stride; ++i) { + buffer[offset + i] = buffer[i]; + } + currentWeight = weight; + } else { + currentWeight += weight; + const mix = weight / currentWeight; + this._mixBufferRegion(buffer, offset, 0, mix, stride); + } + this.cumulativeWeight = currentWeight; + } + accumulateAdditive(weight) { + const buffer = this.buffer, stride = this.valueSize, offset = stride * this._addIndex; + if (this.cumulativeWeightAdditive === 0) { + this._setIdentity(); + } + this._mixBufferRegionAdditive(buffer, offset, 0, weight, stride); + this.cumulativeWeightAdditive += weight; + } + apply(accuIndex) { + const stride = this.valueSize, buffer = this.buffer, offset = accuIndex * stride + stride, weight = this.cumulativeWeight, weightAdditive = this.cumulativeWeightAdditive, binding = this.binding; + this.cumulativeWeight = 0; + this.cumulativeWeightAdditive = 0; + if (weight < 1) { + const originalValueOffset = stride * this._origIndex; + this._mixBufferRegion(buffer, offset, originalValueOffset, 1 - weight, stride); + } + if (weightAdditive > 0) { + this._mixBufferRegionAdditive(buffer, offset, this._addIndex * stride, 1, stride); + } + for (let i = stride, e = stride + stride; i !== e; ++i) { + if (buffer[i] !== buffer[i + stride]) { + binding.setValue(buffer, offset); + break; + } + } + } + saveOriginalState() { + const binding = this.binding; + const buffer = this.buffer, stride = this.valueSize, originalValueOffset = stride * this._origIndex; + binding.getValue(buffer, originalValueOffset); + for (let i = stride, e = originalValueOffset; i !== e; ++i) { + buffer[i] = buffer[originalValueOffset + i % stride]; + } + this._setIdentity(); + this.cumulativeWeight = 0; + this.cumulativeWeightAdditive = 0; + } + restoreOriginalState() { + const originalValueOffset = this.valueSize * 3; + this.binding.setValue(this.buffer, originalValueOffset); + } + _setAdditiveIdentityNumeric() { + const startIndex = this._addIndex * this.valueSize; + const endIndex = startIndex + this.valueSize; + for (let i = startIndex; i < endIndex; i++) { + this.buffer[i] = 0; + } + } + _setAdditiveIdentityQuaternion() { + this._setAdditiveIdentityNumeric(); + this.buffer[this._addIndex * this.valueSize + 3] = 1; + } + _setAdditiveIdentityOther() { + const startIndex = this._origIndex * this.valueSize; + const targetIndex = this._addIndex * this.valueSize; + for (let i = 0; i < this.valueSize; i++) { + this.buffer[targetIndex + i] = this.buffer[startIndex + i]; + } + } + _select(buffer, dstOffset, srcOffset, t, stride) { + if (t >= 0.5) { + for (let i = 0; i !== stride; ++i) { + buffer[dstOffset + i] = buffer[srcOffset + i]; + } + } + } + _slerp(buffer, dstOffset, srcOffset, t) { + Quaternion2.slerpFlat(buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t); + } + _slerpAdditive(buffer, dstOffset, srcOffset, t, stride) { + const workOffset = this._workIndex * stride; + Quaternion2.multiplyQuaternionsFlat(buffer, workOffset, buffer, dstOffset, buffer, srcOffset); + Quaternion2.slerpFlat(buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t); + } + _lerp(buffer, dstOffset, srcOffset, t, stride) { + const s = 1 - t; + for (let i = 0; i !== stride; ++i) { + const j = dstOffset + i; + buffer[j] = buffer[j] * s + buffer[srcOffset + i] * t; + } + } + _lerpAdditive(buffer, dstOffset, srcOffset, t, stride) { + for (let i = 0; i !== stride; ++i) { + const j = dstOffset + i; + buffer[j] = buffer[j] + buffer[srcOffset + i] * t; + } + } + }; + var _RESERVED_CHARS_RE2 = "\\[\\]\\.:\\/"; + var _reservedRe2 = new RegExp("[" + _RESERVED_CHARS_RE2 + "]", "g"); + var _wordChar2 = "[^" + _RESERVED_CHARS_RE2 + "]"; + var _wordCharOrDot2 = "[^" + _RESERVED_CHARS_RE2.replace("\\.", "") + "]"; + var _directoryRe2 = /* @__PURE__ */ /((?:WC+[\/:])*)/.source.replace("WC", _wordChar2); + var _nodeRe2 = /* @__PURE__ */ /(WCOD+)?/.source.replace("WCOD", _wordCharOrDot2); + var _objectRe2 = /* @__PURE__ */ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC", _wordChar2); + var _propertyRe2 = /* @__PURE__ */ /\.(WC+)(?:\[(.+)\])?/.source.replace("WC", _wordChar2); + var _trackRe2 = new RegExp("^" + _directoryRe2 + _nodeRe2 + _objectRe2 + _propertyRe2 + "$"); + var _supportedObjectNames2 = ["material", "materials", "bones"]; + var Composite2 = class { + constructor(targetGroup, path, optionalParsedPath) { + const parsedPath = optionalParsedPath || PropertyBinding2.parseTrackName(path); + this._targetGroup = targetGroup; + this._bindings = targetGroup.subscribe_(path, parsedPath); + } + getValue(array2, offset) { + this.bind(); + const firstValidIndex = this._targetGroup.nCachedObjects_, binding = this._bindings[firstValidIndex]; + if (binding !== void 0) + binding.getValue(array2, offset); + } + setValue(array2, offset) { + const bindings = this._bindings; + for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) { + bindings[i].setValue(array2, offset); + } + } + bind() { + const bindings = this._bindings; + for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) { + bindings[i].bind(); + } + } + unbind() { + const bindings = this._bindings; + for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) { + bindings[i].unbind(); + } + } + }; + var PropertyBinding2 = class { + constructor(rootNode, path, parsedPath) { + this.path = path; + this.parsedPath = parsedPath || PropertyBinding2.parseTrackName(path); + this.node = PropertyBinding2.findNode(rootNode, this.parsedPath.nodeName) || rootNode; + this.rootNode = rootNode; + this.getValue = this._getValue_unbound; + this.setValue = this._setValue_unbound; + } + static create(root2, path, parsedPath) { + if (!(root2 && root2.isAnimationObjectGroup)) { + return new PropertyBinding2(root2, path, parsedPath); + } else { + return new PropertyBinding2.Composite(root2, path, parsedPath); + } + } + static sanitizeNodeName(name) { + return name.replace(/\s/g, "_").replace(_reservedRe2, ""); + } + static parseTrackName(trackName) { + const matches = _trackRe2.exec(trackName); + if (matches === null) { + throw new Error("PropertyBinding: Cannot parse trackName: " + trackName); + } + const results = { + nodeName: matches[2], + objectName: matches[3], + objectIndex: matches[4], + propertyName: matches[5], + propertyIndex: matches[6] + }; + const lastDot = results.nodeName && results.nodeName.lastIndexOf("."); + if (lastDot !== void 0 && lastDot !== -1) { + const objectName = results.nodeName.substring(lastDot + 1); + if (_supportedObjectNames2.indexOf(objectName) !== -1) { + results.nodeName = results.nodeName.substring(0, lastDot); + results.objectName = objectName; + } + } + if (results.propertyName === null || results.propertyName.length === 0) { + throw new Error("PropertyBinding: can not parse propertyName from trackName: " + trackName); + } + return results; + } + static findNode(root2, nodeName) { + if (nodeName === void 0 || nodeName === "" || nodeName === "." || nodeName === -1 || nodeName === root2.name || nodeName === root2.uuid) { + return root2; + } + if (root2.skeleton) { + const bone = root2.skeleton.getBoneByName(nodeName); + if (bone !== void 0) { + return bone; + } + } + if (root2.children) { + const searchNodeSubtree = function(children2) { + for (let i = 0; i < children2.length; i++) { + const childNode = children2[i]; + if (childNode.name === nodeName || childNode.uuid === nodeName) { + return childNode; + } + const result = searchNodeSubtree(childNode.children); + if (result) + return result; + } + return null; + }; + const subTreeNode = searchNodeSubtree(root2.children); + if (subTreeNode) { + return subTreeNode; + } + } + return null; + } + _getValue_unavailable() { + } + _setValue_unavailable() { + } + _getValue_direct(buffer, offset) { + buffer[offset] = this.targetObject[this.propertyName]; + } + _getValue_array(buffer, offset) { + const source = this.resolvedProperty; + for (let i = 0, n = source.length; i !== n; ++i) { + buffer[offset++] = source[i]; + } + } + _getValue_arrayElement(buffer, offset) { + buffer[offset] = this.resolvedProperty[this.propertyIndex]; + } + _getValue_toArray(buffer, offset) { + this.resolvedProperty.toArray(buffer, offset); + } + _setValue_direct(buffer, offset) { + this.targetObject[this.propertyName] = buffer[offset]; + } + _setValue_direct_setNeedsUpdate(buffer, offset) { + this.targetObject[this.propertyName] = buffer[offset]; + this.targetObject.needsUpdate = true; + } + _setValue_direct_setMatrixWorldNeedsUpdate(buffer, offset) { + this.targetObject[this.propertyName] = buffer[offset]; + this.targetObject.matrixWorldNeedsUpdate = true; + } + _setValue_array(buffer, offset) { + const dest = this.resolvedProperty; + for (let i = 0, n = dest.length; i !== n; ++i) { + dest[i] = buffer[offset++]; + } + } + _setValue_array_setNeedsUpdate(buffer, offset) { + const dest = this.resolvedProperty; + for (let i = 0, n = dest.length; i !== n; ++i) { + dest[i] = buffer[offset++]; + } + this.targetObject.needsUpdate = true; + } + _setValue_array_setMatrixWorldNeedsUpdate(buffer, offset) { + const dest = this.resolvedProperty; + for (let i = 0, n = dest.length; i !== n; ++i) { + dest[i] = buffer[offset++]; + } + this.targetObject.matrixWorldNeedsUpdate = true; + } + _setValue_arrayElement(buffer, offset) { + this.resolvedProperty[this.propertyIndex] = buffer[offset]; + } + _setValue_arrayElement_setNeedsUpdate(buffer, offset) { + this.resolvedProperty[this.propertyIndex] = buffer[offset]; + this.targetObject.needsUpdate = true; + } + _setValue_arrayElement_setMatrixWorldNeedsUpdate(buffer, offset) { + this.resolvedProperty[this.propertyIndex] = buffer[offset]; + this.targetObject.matrixWorldNeedsUpdate = true; + } + _setValue_fromArray(buffer, offset) { + this.resolvedProperty.fromArray(buffer, offset); + } + _setValue_fromArray_setNeedsUpdate(buffer, offset) { + this.resolvedProperty.fromArray(buffer, offset); + this.targetObject.needsUpdate = true; + } + _setValue_fromArray_setMatrixWorldNeedsUpdate(buffer, offset) { + this.resolvedProperty.fromArray(buffer, offset); + this.targetObject.matrixWorldNeedsUpdate = true; + } + _getValue_unbound(targetArray, offset) { + this.bind(); + this.getValue(targetArray, offset); + } + _setValue_unbound(sourceArray, offset) { + this.bind(); + this.setValue(sourceArray, offset); + } + bind() { + let targetObject = this.node; + const parsedPath = this.parsedPath; + const objectName = parsedPath.objectName; + const propertyName = parsedPath.propertyName; + let propertyIndex = parsedPath.propertyIndex; + if (!targetObject) { + targetObject = PropertyBinding2.findNode(this.rootNode, parsedPath.nodeName) || this.rootNode; + this.node = targetObject; + } + this.getValue = this._getValue_unavailable; + this.setValue = this._setValue_unavailable; + if (!targetObject) { + console.error("THREE.PropertyBinding: Trying to update node for track: " + this.path + " but it wasn't found."); + return; + } + if (objectName) { + let objectIndex = parsedPath.objectIndex; + switch (objectName) { + case "materials": + if (!targetObject.material) { + console.error("THREE.PropertyBinding: Can not bind to material as node does not have a material.", this); + return; + } + if (!targetObject.material.materials) { + console.error("THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.", this); + return; + } + targetObject = targetObject.material.materials; + break; + case "bones": + if (!targetObject.skeleton) { + console.error("THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.", this); + return; + } + targetObject = targetObject.skeleton.bones; + for (let i = 0; i < targetObject.length; i++) { + if (targetObject[i].name === objectIndex) { + objectIndex = i; + break; + } + } + break; + default: + if (targetObject[objectName] === void 0) { + console.error("THREE.PropertyBinding: Can not bind to objectName of node undefined.", this); + return; + } + targetObject = targetObject[objectName]; + } + if (objectIndex !== void 0) { + if (targetObject[objectIndex] === void 0) { + console.error("THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.", this, targetObject); + return; + } + targetObject = targetObject[objectIndex]; + } + } + const nodeProperty = targetObject[propertyName]; + if (nodeProperty === void 0) { + const nodeName = parsedPath.nodeName; + console.error("THREE.PropertyBinding: Trying to update property for track: " + nodeName + "." + propertyName + " but it wasn't found.", targetObject); + return; + } + let versioning = this.Versioning.None; + this.targetObject = targetObject; + if (targetObject.needsUpdate !== void 0) { + versioning = this.Versioning.NeedsUpdate; + } else if (targetObject.matrixWorldNeedsUpdate !== void 0) { + versioning = this.Versioning.MatrixWorldNeedsUpdate; + } + let bindingType = this.BindingType.Direct; + if (propertyIndex !== void 0) { + if (propertyName === "morphTargetInfluences") { + if (!targetObject.geometry) { + console.error("THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.", this); + return; + } + if (!targetObject.geometry.morphAttributes) { + console.error("THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.", this); + return; + } + if (targetObject.morphTargetDictionary[propertyIndex] !== void 0) { + propertyIndex = targetObject.morphTargetDictionary[propertyIndex]; + } + } + bindingType = this.BindingType.ArrayElement; + this.resolvedProperty = nodeProperty; + this.propertyIndex = propertyIndex; + } else if (nodeProperty.fromArray !== void 0 && nodeProperty.toArray !== void 0) { + bindingType = this.BindingType.HasFromToArray; + this.resolvedProperty = nodeProperty; + } else if (Array.isArray(nodeProperty)) { + bindingType = this.BindingType.EntireArray; + this.resolvedProperty = nodeProperty; + } else { + this.propertyName = propertyName; + } + this.getValue = this.GetterByBindingType[bindingType]; + this.setValue = this.SetterByBindingTypeAndVersioning[bindingType][versioning]; + } + unbind() { + this.node = null; + this.getValue = this._getValue_unbound; + this.setValue = this._setValue_unbound; + } + }; + PropertyBinding2.Composite = Composite2; + PropertyBinding2.prototype.BindingType = { + Direct: 0, + EntireArray: 1, + ArrayElement: 2, + HasFromToArray: 3 + }; + PropertyBinding2.prototype.Versioning = { + None: 0, + NeedsUpdate: 1, + MatrixWorldNeedsUpdate: 2 + }; + PropertyBinding2.prototype.GetterByBindingType = [PropertyBinding2.prototype._getValue_direct, PropertyBinding2.prototype._getValue_array, PropertyBinding2.prototype._getValue_arrayElement, PropertyBinding2.prototype._getValue_toArray]; + PropertyBinding2.prototype.SetterByBindingTypeAndVersioning = [[ + PropertyBinding2.prototype._setValue_direct, + PropertyBinding2.prototype._setValue_direct_setNeedsUpdate, + PropertyBinding2.prototype._setValue_direct_setMatrixWorldNeedsUpdate + ], [ + PropertyBinding2.prototype._setValue_array, + PropertyBinding2.prototype._setValue_array_setNeedsUpdate, + PropertyBinding2.prototype._setValue_array_setMatrixWorldNeedsUpdate + ], [ + PropertyBinding2.prototype._setValue_arrayElement, + PropertyBinding2.prototype._setValue_arrayElement_setNeedsUpdate, + PropertyBinding2.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate + ], [ + PropertyBinding2.prototype._setValue_fromArray, + PropertyBinding2.prototype._setValue_fromArray_setNeedsUpdate, + PropertyBinding2.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate + ]]; + var AnimationObjectGroup = class { + constructor() { + this.isAnimationObjectGroup = true; + this.uuid = generateUUID2(); + this._objects = Array.prototype.slice.call(arguments); + this.nCachedObjects_ = 0; + const indices = {}; + this._indicesByUUID = indices; + for (let i = 0, n = arguments.length; i !== n; ++i) { + indices[arguments[i].uuid] = i; + } + this._paths = []; + this._parsedPaths = []; + this._bindings = []; + this._bindingsIndicesByPath = {}; + const scope = this; + this.stats = { + objects: { + get total() { + return scope._objects.length; + }, + get inUse() { + return this.total - scope.nCachedObjects_; + } + }, + get bindingsPerObject() { + return scope._bindings.length; + } + }; + } + add() { + const objects = this._objects, indicesByUUID = this._indicesByUUID, paths = this._paths, parsedPaths = this._parsedPaths, bindings = this._bindings, nBindings = bindings.length; + let knownObject = void 0, nObjects = objects.length, nCachedObjects = this.nCachedObjects_; + for (let i = 0, n = arguments.length; i !== n; ++i) { + const object = arguments[i], uuid = object.uuid; + let index2 = indicesByUUID[uuid]; + if (index2 === void 0) { + index2 = nObjects++; + indicesByUUID[uuid] = index2; + objects.push(object); + for (let j = 0, m2 = nBindings; j !== m2; ++j) { + bindings[j].push(new PropertyBinding2(object, paths[j], parsedPaths[j])); + } + } else if (index2 < nCachedObjects) { + knownObject = objects[index2]; + const firstActiveIndex = --nCachedObjects, lastCachedObject = objects[firstActiveIndex]; + indicesByUUID[lastCachedObject.uuid] = index2; + objects[index2] = lastCachedObject; + indicesByUUID[uuid] = firstActiveIndex; + objects[firstActiveIndex] = object; + for (let j = 0, m2 = nBindings; j !== m2; ++j) { + const bindingsForPath = bindings[j], lastCached = bindingsForPath[firstActiveIndex]; + let binding = bindingsForPath[index2]; + bindingsForPath[index2] = lastCached; + if (binding === void 0) { + binding = new PropertyBinding2(object, paths[j], parsedPaths[j]); + } + bindingsForPath[firstActiveIndex] = binding; + } + } else if (objects[index2] !== knownObject) { + console.error("THREE.AnimationObjectGroup: Different objects with the same UUID detected. Clean the caches or recreate your infrastructure when reloading scenes."); + } + } + this.nCachedObjects_ = nCachedObjects; + } + remove() { + const objects = this._objects, indicesByUUID = this._indicesByUUID, bindings = this._bindings, nBindings = bindings.length; + let nCachedObjects = this.nCachedObjects_; + for (let i = 0, n = arguments.length; i !== n; ++i) { + const object = arguments[i], uuid = object.uuid, index2 = indicesByUUID[uuid]; + if (index2 !== void 0 && index2 >= nCachedObjects) { + const lastCachedIndex = nCachedObjects++, firstActiveObject = objects[lastCachedIndex]; + indicesByUUID[firstActiveObject.uuid] = index2; + objects[index2] = firstActiveObject; + indicesByUUID[uuid] = lastCachedIndex; + objects[lastCachedIndex] = object; + for (let j = 0, m2 = nBindings; j !== m2; ++j) { + const bindingsForPath = bindings[j], firstActive = bindingsForPath[lastCachedIndex], binding = bindingsForPath[index2]; + bindingsForPath[index2] = firstActive; + bindingsForPath[lastCachedIndex] = binding; + } + } + } + this.nCachedObjects_ = nCachedObjects; + } + uncache() { + const objects = this._objects, indicesByUUID = this._indicesByUUID, bindings = this._bindings, nBindings = bindings.length; + let nCachedObjects = this.nCachedObjects_, nObjects = objects.length; + for (let i = 0, n = arguments.length; i !== n; ++i) { + const object = arguments[i], uuid = object.uuid, index2 = indicesByUUID[uuid]; + if (index2 !== void 0) { + delete indicesByUUID[uuid]; + if (index2 < nCachedObjects) { + const firstActiveIndex = --nCachedObjects, lastCachedObject = objects[firstActiveIndex], lastIndex = --nObjects, lastObject = objects[lastIndex]; + indicesByUUID[lastCachedObject.uuid] = index2; + objects[index2] = lastCachedObject; + indicesByUUID[lastObject.uuid] = firstActiveIndex; + objects[firstActiveIndex] = lastObject; + objects.pop(); + for (let j = 0, m2 = nBindings; j !== m2; ++j) { + const bindingsForPath = bindings[j], lastCached = bindingsForPath[firstActiveIndex], last = bindingsForPath[lastIndex]; + bindingsForPath[index2] = lastCached; + bindingsForPath[firstActiveIndex] = last; + bindingsForPath.pop(); + } + } else { + const lastIndex = --nObjects, lastObject = objects[lastIndex]; + if (lastIndex > 0) { + indicesByUUID[lastObject.uuid] = index2; + } + objects[index2] = lastObject; + objects.pop(); + for (let j = 0, m2 = nBindings; j !== m2; ++j) { + const bindingsForPath = bindings[j]; + bindingsForPath[index2] = bindingsForPath[lastIndex]; + bindingsForPath.pop(); + } + } + } + } + this.nCachedObjects_ = nCachedObjects; + } + subscribe_(path, parsedPath) { + const indicesByPath = this._bindingsIndicesByPath; + let index2 = indicesByPath[path]; + const bindings = this._bindings; + if (index2 !== void 0) + return bindings[index2]; + const paths = this._paths, parsedPaths = this._parsedPaths, objects = this._objects, nObjects = objects.length, nCachedObjects = this.nCachedObjects_, bindingsForPath = new Array(nObjects); + index2 = bindings.length; + indicesByPath[path] = index2; + paths.push(path); + parsedPaths.push(parsedPath); + bindings.push(bindingsForPath); + for (let i = nCachedObjects, n = objects.length; i !== n; ++i) { + const object = objects[i]; + bindingsForPath[i] = new PropertyBinding2(object, path, parsedPath); + } + return bindingsForPath; + } + unsubscribe_(path) { + const indicesByPath = this._bindingsIndicesByPath, index2 = indicesByPath[path]; + if (index2 !== void 0) { + const paths = this._paths, parsedPaths = this._parsedPaths, bindings = this._bindings, lastBindingsIndex = bindings.length - 1, lastBindings = bindings[lastBindingsIndex], lastBindingsPath = path[lastBindingsIndex]; + indicesByPath[lastBindingsPath] = index2; + bindings[index2] = lastBindings; + bindings.pop(); + parsedPaths[index2] = parsedPaths[lastBindingsIndex]; + parsedPaths.pop(); + paths[index2] = paths[lastBindingsIndex]; + paths.pop(); + } + } + }; + var AnimationAction = class { + constructor(mixer, clip, localRoot = null, blendMode = clip.blendMode) { + this._mixer = mixer; + this._clip = clip; + this._localRoot = localRoot; + this.blendMode = blendMode; + const tracks = clip.tracks, nTracks = tracks.length, interpolants = new Array(nTracks); + const interpolantSettings = { + endingStart: ZeroCurvatureEnding2, + endingEnd: ZeroCurvatureEnding2 + }; + for (let i = 0; i !== nTracks; ++i) { + const interpolant = tracks[i].createInterpolant(null); + interpolants[i] = interpolant; + interpolant.settings = interpolantSettings; + } + this._interpolantSettings = interpolantSettings; + this._interpolants = interpolants; + this._propertyBindings = new Array(nTracks); + this._cacheIndex = null; + this._byClipCacheIndex = null; + this._timeScaleInterpolant = null; + this._weightInterpolant = null; + this.loop = LoopRepeat; + this._loopCount = -1; + this._startTime = null; + this.time = 0; + this.timeScale = 1; + this._effectiveTimeScale = 1; + this.weight = 1; + this._effectiveWeight = 1; + this.repetitions = Infinity; + this.paused = false; + this.enabled = true; + this.clampWhenFinished = false; + this.zeroSlopeAtStart = true; + this.zeroSlopeAtEnd = true; + } + play() { + this._mixer._activateAction(this); + return this; + } + stop() { + this._mixer._deactivateAction(this); + return this.reset(); + } + reset() { + this.paused = false; + this.enabled = true; + this.time = 0; + this._loopCount = -1; + this._startTime = null; + return this.stopFading().stopWarping(); + } + isRunning() { + return this.enabled && !this.paused && this.timeScale !== 0 && this._startTime === null && this._mixer._isActiveAction(this); + } + isScheduled() { + return this._mixer._isActiveAction(this); + } + startAt(time) { + this._startTime = time; + return this; + } + setLoop(mode, repetitions) { + this.loop = mode; + this.repetitions = repetitions; + return this; + } + setEffectiveWeight(weight) { + this.weight = weight; + this._effectiveWeight = this.enabled ? weight : 0; + return this.stopFading(); + } + getEffectiveWeight() { + return this._effectiveWeight; + } + fadeIn(duration) { + return this._scheduleFading(duration, 0, 1); + } + fadeOut(duration) { + return this._scheduleFading(duration, 1, 0); + } + crossFadeFrom(fadeOutAction, duration, warp) { + fadeOutAction.fadeOut(duration); + this.fadeIn(duration); + if (warp) { + const fadeInDuration = this._clip.duration, fadeOutDuration = fadeOutAction._clip.duration, startEndRatio = fadeOutDuration / fadeInDuration, endStartRatio = fadeInDuration / fadeOutDuration; + fadeOutAction.warp(1, startEndRatio, duration); + this.warp(endStartRatio, 1, duration); + } + return this; + } + crossFadeTo(fadeInAction, duration, warp) { + return fadeInAction.crossFadeFrom(this, duration, warp); + } + stopFading() { + const weightInterpolant = this._weightInterpolant; + if (weightInterpolant !== null) { + this._weightInterpolant = null; + this._mixer._takeBackControlInterpolant(weightInterpolant); + } + return this; + } + setEffectiveTimeScale(timeScale) { + this.timeScale = timeScale; + this._effectiveTimeScale = this.paused ? 0 : timeScale; + return this.stopWarping(); + } + getEffectiveTimeScale() { + return this._effectiveTimeScale; + } + setDuration(duration) { + this.timeScale = this._clip.duration / duration; + return this.stopWarping(); + } + syncWith(action) { + this.time = action.time; + this.timeScale = action.timeScale; + return this.stopWarping(); + } + halt(duration) { + return this.warp(this._effectiveTimeScale, 0, duration); + } + warp(startTimeScale, endTimeScale, duration) { + const mixer = this._mixer, now3 = mixer.time, timeScale = this.timeScale; + let interpolant = this._timeScaleInterpolant; + if (interpolant === null) { + interpolant = mixer._lendControlInterpolant(); + this._timeScaleInterpolant = interpolant; + } + const times = interpolant.parameterPositions, values = interpolant.sampleValues; + times[0] = now3; + times[1] = now3 + duration; + values[0] = startTimeScale / timeScale; + values[1] = endTimeScale / timeScale; + return this; + } + stopWarping() { + const timeScaleInterpolant = this._timeScaleInterpolant; + if (timeScaleInterpolant !== null) { + this._timeScaleInterpolant = null; + this._mixer._takeBackControlInterpolant(timeScaleInterpolant); + } + return this; + } + getMixer() { + return this._mixer; + } + getClip() { + return this._clip; + } + getRoot() { + return this._localRoot || this._mixer._root; + } + _update(time, deltaTime, timeDirection, accuIndex) { + if (!this.enabled) { + this._updateWeight(time); + return; + } + const startTime = this._startTime; + if (startTime !== null) { + const timeRunning = (time - startTime) * timeDirection; + if (timeRunning < 0 || timeDirection === 0) { + return; + } + this._startTime = null; + deltaTime = timeDirection * timeRunning; + } + deltaTime *= this._updateTimeScale(time); + const clipTime = this._updateTime(deltaTime); + const weight = this._updateWeight(time); + if (weight > 0) { + const interpolants = this._interpolants; + const propertyMixers = this._propertyBindings; + switch (this.blendMode) { + case AdditiveAnimationBlendMode: + for (let j = 0, m2 = interpolants.length; j !== m2; ++j) { + interpolants[j].evaluate(clipTime); + propertyMixers[j].accumulateAdditive(weight); + } + break; + case NormalAnimationBlendMode: + default: + for (let j = 0, m2 = interpolants.length; j !== m2; ++j) { + interpolants[j].evaluate(clipTime); + propertyMixers[j].accumulate(accuIndex, weight); + } + } + } + } + _updateWeight(time) { + let weight = 0; + if (this.enabled) { + weight = this.weight; + const interpolant = this._weightInterpolant; + if (interpolant !== null) { + const interpolantValue = interpolant.evaluate(time)[0]; + weight *= interpolantValue; + if (time > interpolant.parameterPositions[1]) { + this.stopFading(); + if (interpolantValue === 0) { + this.enabled = false; + } + } + } + } + this._effectiveWeight = weight; + return weight; + } + _updateTimeScale(time) { + let timeScale = 0; + if (!this.paused) { + timeScale = this.timeScale; + const interpolant = this._timeScaleInterpolant; + if (interpolant !== null) { + const interpolantValue = interpolant.evaluate(time)[0]; + timeScale *= interpolantValue; + if (time > interpolant.parameterPositions[1]) { + this.stopWarping(); + if (timeScale === 0) { + this.paused = true; + } else { + this.timeScale = timeScale; + } + } + } + } + this._effectiveTimeScale = timeScale; + return timeScale; + } + _updateTime(deltaTime) { + const duration = this._clip.duration; + const loop = this.loop; + let time = this.time + deltaTime; + let loopCount = this._loopCount; + const pingPong = loop === LoopPingPong; + if (deltaTime === 0) { + if (loopCount === -1) + return time; + return pingPong && (loopCount & 1) === 1 ? duration - time : time; + } + if (loop === LoopOnce) { + if (loopCount === -1) { + this._loopCount = 0; + this._setEndings(true, true, false); + } + handle_stop: { + if (time >= duration) { + time = duration; + } else if (time < 0) { + time = 0; + } else { + this.time = time; + break handle_stop; + } + if (this.clampWhenFinished) + this.paused = true; + else + this.enabled = false; + this.time = time; + this._mixer.dispatchEvent({ + type: "finished", + action: this, + direction: deltaTime < 0 ? -1 : 1 + }); + } + } else { + if (loopCount === -1) { + if (deltaTime >= 0) { + loopCount = 0; + this._setEndings(true, this.repetitions === 0, pingPong); + } else { + this._setEndings(this.repetitions === 0, true, pingPong); + } + } + if (time >= duration || time < 0) { + const loopDelta = Math.floor(time / duration); + time -= duration * loopDelta; + loopCount += Math.abs(loopDelta); + const pending = this.repetitions - loopCount; + if (pending <= 0) { + if (this.clampWhenFinished) + this.paused = true; + else + this.enabled = false; + time = deltaTime > 0 ? duration : 0; + this.time = time; + this._mixer.dispatchEvent({ + type: "finished", + action: this, + direction: deltaTime > 0 ? 1 : -1 + }); + } else { + if (pending === 1) { + const atStart = deltaTime < 0; + this._setEndings(atStart, !atStart, pingPong); + } else { + this._setEndings(false, false, pingPong); + } + this._loopCount = loopCount; + this.time = time; + this._mixer.dispatchEvent({ + type: "loop", + action: this, + loopDelta + }); + } + } else { + this.time = time; + } + if (pingPong && (loopCount & 1) === 1) { + return duration - time; + } + } + return time; + } + _setEndings(atStart, atEnd, pingPong) { + const settings = this._interpolantSettings; + if (pingPong) { + settings.endingStart = ZeroSlopeEnding2; + settings.endingEnd = ZeroSlopeEnding2; + } else { + if (atStart) { + settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding2 : ZeroCurvatureEnding2; + } else { + settings.endingStart = WrapAroundEnding2; + } + if (atEnd) { + settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding2 : ZeroCurvatureEnding2; + } else { + settings.endingEnd = WrapAroundEnding2; + } + } + } + _scheduleFading(duration, weightNow, weightThen) { + const mixer = this._mixer, now3 = mixer.time; + let interpolant = this._weightInterpolant; + if (interpolant === null) { + interpolant = mixer._lendControlInterpolant(); + this._weightInterpolant = interpolant; + } + const times = interpolant.parameterPositions, values = interpolant.sampleValues; + times[0] = now3; + values[0] = weightNow; + times[1] = now3 + duration; + values[1] = weightThen; + return this; + } + }; + var _controlInterpolantsResultBuffer2 = new Float32Array(1); + var AnimationMixer = class extends EventDispatcher2 { + constructor(root2) { + super(); + this._root = root2; + this._initMemoryManager(); + this._accuIndex = 0; + this.time = 0; + this.timeScale = 1; + } + _bindAction(action, prototypeAction) { + const root2 = action._localRoot || this._root, tracks = action._clip.tracks, nTracks = tracks.length, bindings = action._propertyBindings, interpolants = action._interpolants, rootUuid = root2.uuid, bindingsByRoot = this._bindingsByRootAndName; + let bindingsByName = bindingsByRoot[rootUuid]; + if (bindingsByName === void 0) { + bindingsByName = {}; + bindingsByRoot[rootUuid] = bindingsByName; + } + for (let i = 0; i !== nTracks; ++i) { + const track = tracks[i], trackName = track.name; + let binding = bindingsByName[trackName]; + if (binding !== void 0) { + ++binding.referenceCount; + bindings[i] = binding; + } else { + binding = bindings[i]; + if (binding !== void 0) { + if (binding._cacheIndex === null) { + ++binding.referenceCount; + this._addInactiveBinding(binding, rootUuid, trackName); + } + continue; + } + const path = prototypeAction && prototypeAction._propertyBindings[i].binding.parsedPath; + binding = new PropertyMixer(PropertyBinding2.create(root2, trackName, path), track.ValueTypeName, track.getValueSize()); + ++binding.referenceCount; + this._addInactiveBinding(binding, rootUuid, trackName); + bindings[i] = binding; + } + interpolants[i].resultBuffer = binding.buffer; + } + } + _activateAction(action) { + if (!this._isActiveAction(action)) { + if (action._cacheIndex === null) { + const rootUuid = (action._localRoot || this._root).uuid, clipUuid = action._clip.uuid, actionsForClip = this._actionsByClip[clipUuid]; + this._bindAction(action, actionsForClip && actionsForClip.knownActions[0]); + this._addInactiveAction(action, clipUuid, rootUuid); + } + const bindings = action._propertyBindings; + for (let i = 0, n = bindings.length; i !== n; ++i) { + const binding = bindings[i]; + if (binding.useCount++ === 0) { + this._lendBinding(binding); + binding.saveOriginalState(); + } + } + this._lendAction(action); + } + } + _deactivateAction(action) { + if (this._isActiveAction(action)) { + const bindings = action._propertyBindings; + for (let i = 0, n = bindings.length; i !== n; ++i) { + const binding = bindings[i]; + if (--binding.useCount === 0) { + binding.restoreOriginalState(); + this._takeBackBinding(binding); + } + } + this._takeBackAction(action); + } + } + _initMemoryManager() { + this._actions = []; + this._nActiveActions = 0; + this._actionsByClip = {}; + this._bindings = []; + this._nActiveBindings = 0; + this._bindingsByRootAndName = {}; + this._controlInterpolants = []; + this._nActiveControlInterpolants = 0; + const scope = this; + this.stats = { + actions: { + get total() { + return scope._actions.length; + }, + get inUse() { + return scope._nActiveActions; + } + }, + bindings: { + get total() { + return scope._bindings.length; + }, + get inUse() { + return scope._nActiveBindings; + } + }, + controlInterpolants: { + get total() { + return scope._controlInterpolants.length; + }, + get inUse() { + return scope._nActiveControlInterpolants; + } + } + }; + } + _isActiveAction(action) { + const index2 = action._cacheIndex; + return index2 !== null && index2 < this._nActiveActions; + } + _addInactiveAction(action, clipUuid, rootUuid) { + const actions = this._actions, actionsByClip = this._actionsByClip; + let actionsForClip = actionsByClip[clipUuid]; + if (actionsForClip === void 0) { + actionsForClip = { + knownActions: [action], + actionByRoot: {} + }; + action._byClipCacheIndex = 0; + actionsByClip[clipUuid] = actionsForClip; + } else { + const knownActions = actionsForClip.knownActions; + action._byClipCacheIndex = knownActions.length; + knownActions.push(action); + } + action._cacheIndex = actions.length; + actions.push(action); + actionsForClip.actionByRoot[rootUuid] = action; + } + _removeInactiveAction(action) { + const actions = this._actions, lastInactiveAction = actions[actions.length - 1], cacheIndex = action._cacheIndex; + lastInactiveAction._cacheIndex = cacheIndex; + actions[cacheIndex] = lastInactiveAction; + actions.pop(); + action._cacheIndex = null; + const clipUuid = action._clip.uuid, actionsByClip = this._actionsByClip, actionsForClip = actionsByClip[clipUuid], knownActionsForClip = actionsForClip.knownActions, lastKnownAction = knownActionsForClip[knownActionsForClip.length - 1], byClipCacheIndex = action._byClipCacheIndex; + lastKnownAction._byClipCacheIndex = byClipCacheIndex; + knownActionsForClip[byClipCacheIndex] = lastKnownAction; + knownActionsForClip.pop(); + action._byClipCacheIndex = null; + const actionByRoot = actionsForClip.actionByRoot, rootUuid = (action._localRoot || this._root).uuid; + delete actionByRoot[rootUuid]; + if (knownActionsForClip.length === 0) { + delete actionsByClip[clipUuid]; + } + this._removeInactiveBindingsForAction(action); + } + _removeInactiveBindingsForAction(action) { + const bindings = action._propertyBindings; + for (let i = 0, n = bindings.length; i !== n; ++i) { + const binding = bindings[i]; + if (--binding.referenceCount === 0) { + this._removeInactiveBinding(binding); + } + } + } + _lendAction(action) { + const actions = this._actions, prevIndex = action._cacheIndex, lastActiveIndex = this._nActiveActions++, firstInactiveAction = actions[lastActiveIndex]; + action._cacheIndex = lastActiveIndex; + actions[lastActiveIndex] = action; + firstInactiveAction._cacheIndex = prevIndex; + actions[prevIndex] = firstInactiveAction; + } + _takeBackAction(action) { + const actions = this._actions, prevIndex = action._cacheIndex, firstInactiveIndex = --this._nActiveActions, lastActiveAction = actions[firstInactiveIndex]; + action._cacheIndex = firstInactiveIndex; + actions[firstInactiveIndex] = action; + lastActiveAction._cacheIndex = prevIndex; + actions[prevIndex] = lastActiveAction; + } + _addInactiveBinding(binding, rootUuid, trackName) { + const bindingsByRoot = this._bindingsByRootAndName, bindings = this._bindings; + let bindingByName = bindingsByRoot[rootUuid]; + if (bindingByName === void 0) { + bindingByName = {}; + bindingsByRoot[rootUuid] = bindingByName; + } + bindingByName[trackName] = binding; + binding._cacheIndex = bindings.length; + bindings.push(binding); + } + _removeInactiveBinding(binding) { + const bindings = this._bindings, propBinding = binding.binding, rootUuid = propBinding.rootNode.uuid, trackName = propBinding.path, bindingsByRoot = this._bindingsByRootAndName, bindingByName = bindingsByRoot[rootUuid], lastInactiveBinding = bindings[bindings.length - 1], cacheIndex = binding._cacheIndex; + lastInactiveBinding._cacheIndex = cacheIndex; + bindings[cacheIndex] = lastInactiveBinding; + bindings.pop(); + delete bindingByName[trackName]; + if (Object.keys(bindingByName).length === 0) { + delete bindingsByRoot[rootUuid]; + } + } + _lendBinding(binding) { + const bindings = this._bindings, prevIndex = binding._cacheIndex, lastActiveIndex = this._nActiveBindings++, firstInactiveBinding = bindings[lastActiveIndex]; + binding._cacheIndex = lastActiveIndex; + bindings[lastActiveIndex] = binding; + firstInactiveBinding._cacheIndex = prevIndex; + bindings[prevIndex] = firstInactiveBinding; + } + _takeBackBinding(binding) { + const bindings = this._bindings, prevIndex = binding._cacheIndex, firstInactiveIndex = --this._nActiveBindings, lastActiveBinding = bindings[firstInactiveIndex]; + binding._cacheIndex = firstInactiveIndex; + bindings[firstInactiveIndex] = binding; + lastActiveBinding._cacheIndex = prevIndex; + bindings[prevIndex] = lastActiveBinding; + } + _lendControlInterpolant() { + const interpolants = this._controlInterpolants, lastActiveIndex = this._nActiveControlInterpolants++; + let interpolant = interpolants[lastActiveIndex]; + if (interpolant === void 0) { + interpolant = new LinearInterpolant2(new Float32Array(2), new Float32Array(2), 1, _controlInterpolantsResultBuffer2); + interpolant.__cacheIndex = lastActiveIndex; + interpolants[lastActiveIndex] = interpolant; + } + return interpolant; + } + _takeBackControlInterpolant(interpolant) { + const interpolants = this._controlInterpolants, prevIndex = interpolant.__cacheIndex, firstInactiveIndex = --this._nActiveControlInterpolants, lastActiveInterpolant = interpolants[firstInactiveIndex]; + interpolant.__cacheIndex = firstInactiveIndex; + interpolants[firstInactiveIndex] = interpolant; + lastActiveInterpolant.__cacheIndex = prevIndex; + interpolants[prevIndex] = lastActiveInterpolant; + } + clipAction(clip, optionalRoot, blendMode) { + const root2 = optionalRoot || this._root, rootUuid = root2.uuid; + let clipObject = typeof clip === "string" ? AnimationClip.findByName(root2, clip) : clip; + const clipUuid = clipObject !== null ? clipObject.uuid : clip; + const actionsForClip = this._actionsByClip[clipUuid]; + let prototypeAction = null; + if (blendMode === void 0) { + if (clipObject !== null) { + blendMode = clipObject.blendMode; + } else { + blendMode = NormalAnimationBlendMode; + } + } + if (actionsForClip !== void 0) { + const existingAction = actionsForClip.actionByRoot[rootUuid]; + if (existingAction !== void 0 && existingAction.blendMode === blendMode) { + return existingAction; + } + prototypeAction = actionsForClip.knownActions[0]; + if (clipObject === null) + clipObject = prototypeAction._clip; + } + if (clipObject === null) + return null; + const newAction = new AnimationAction(this, clipObject, optionalRoot, blendMode); + this._bindAction(newAction, prototypeAction); + this._addInactiveAction(newAction, clipUuid, rootUuid); + return newAction; + } + existingAction(clip, optionalRoot) { + const root2 = optionalRoot || this._root, rootUuid = root2.uuid, clipObject = typeof clip === "string" ? AnimationClip.findByName(root2, clip) : clip, clipUuid = clipObject ? clipObject.uuid : clip, actionsForClip = this._actionsByClip[clipUuid]; + if (actionsForClip !== void 0) { + return actionsForClip.actionByRoot[rootUuid] || null; + } + return null; + } + stopAllAction() { + const actions = this._actions, nActions = this._nActiveActions; + for (let i = nActions - 1; i >= 0; --i) { + actions[i].stop(); + } + return this; + } + update(deltaTime) { + deltaTime *= this.timeScale; + const actions = this._actions, nActions = this._nActiveActions, time = this.time += deltaTime, timeDirection = Math.sign(deltaTime), accuIndex = this._accuIndex ^= 1; + for (let i = 0; i !== nActions; ++i) { + const action = actions[i]; + action._update(time, deltaTime, timeDirection, accuIndex); + } + const bindings = this._bindings, nBindings = this._nActiveBindings; + for (let i = 0; i !== nBindings; ++i) { + bindings[i].apply(accuIndex); + } + return this; + } + setTime(timeInSeconds) { + this.time = 0; + for (let i = 0; i < this._actions.length; i++) { + this._actions[i].time = 0; + } + return this.update(timeInSeconds); + } + getRoot() { + return this._root; + } + uncacheClip(clip) { + const actions = this._actions, clipUuid = clip.uuid, actionsByClip = this._actionsByClip, actionsForClip = actionsByClip[clipUuid]; + if (actionsForClip !== void 0) { + const actionsToRemove = actionsForClip.knownActions; + for (let i = 0, n = actionsToRemove.length; i !== n; ++i) { + const action = actionsToRemove[i]; + this._deactivateAction(action); + const cacheIndex = action._cacheIndex, lastInactiveAction = actions[actions.length - 1]; + action._cacheIndex = null; + action._byClipCacheIndex = null; + lastInactiveAction._cacheIndex = cacheIndex; + actions[cacheIndex] = lastInactiveAction; + actions.pop(); + this._removeInactiveBindingsForAction(action); + } + delete actionsByClip[clipUuid]; + } + } + uncacheRoot(root2) { + const rootUuid = root2.uuid, actionsByClip = this._actionsByClip; + for (const clipUuid in actionsByClip) { + const actionByRoot = actionsByClip[clipUuid].actionByRoot, action = actionByRoot[rootUuid]; + if (action !== void 0) { + this._deactivateAction(action); + this._removeInactiveAction(action); + } + } + const bindingsByRoot = this._bindingsByRootAndName, bindingByName = bindingsByRoot[rootUuid]; + if (bindingByName !== void 0) { + for (const trackName in bindingByName) { + const binding = bindingByName[trackName]; + binding.restoreOriginalState(); + this._removeInactiveBinding(binding); + } + } + } + uncacheAction(clip, optionalRoot) { + const action = this.existingAction(clip, optionalRoot); + if (action !== null) { + this._deactivateAction(action); + this._removeInactiveAction(action); + } + } + }; + var Uniform = class { + constructor(value) { + if (typeof value === "string") { + console.warn("THREE.Uniform: Type parameter is no longer needed."); + value = arguments[1]; + } + this.value = value; + } + clone() { + return new Uniform(this.value.clone === void 0 ? this.value : this.value.clone()); + } + }; + var id2 = 0; + var UniformsGroup = class extends EventDispatcher2 { + constructor() { + super(); + this.isUniformsGroup = true; + Object.defineProperty(this, "id", { + value: id2++ + }); + this.name = ""; + this.usage = StaticDrawUsage2; + this.uniforms = []; + } + add(uniform) { + this.uniforms.push(uniform); + return this; + } + remove(uniform) { + const index2 = this.uniforms.indexOf(uniform); + if (index2 !== -1) + this.uniforms.splice(index2, 1); + return this; + } + setName(name) { + this.name = name; + return this; + } + setUsage(value) { + this.usage = value; + return this; + } + dispose() { + this.dispatchEvent({ + type: "dispose" + }); + return this; + } + copy(source) { + this.name = source.name; + this.usage = source.usage; + const uniformsSource = source.uniforms; + this.uniforms.length = 0; + for (let i = 0, l = uniformsSource.length; i < l; i++) { + this.uniforms.push(uniformsSource[i].clone()); + } + return this; + } + clone() { + return new this.constructor().copy(this); + } + }; + var InstancedInterleavedBuffer = class extends InterleavedBuffer { + constructor(array2, stride, meshPerAttribute = 1) { + super(array2, stride); + this.isInstancedInterleavedBuffer = true; + this.meshPerAttribute = meshPerAttribute; + } + copy(source) { + super.copy(source); + this.meshPerAttribute = source.meshPerAttribute; + return this; + } + clone(data) { + const ib = super.clone(data); + ib.meshPerAttribute = this.meshPerAttribute; + return ib; + } + toJSON(data) { + const json = super.toJSON(data); + json.isInstancedInterleavedBuffer = true; + json.meshPerAttribute = this.meshPerAttribute; + return json; + } + }; + var GLBufferAttribute = class { + constructor(buffer, type2, itemSize, elementSize, count) { + this.isGLBufferAttribute = true; + this.buffer = buffer; + this.type = type2; + this.itemSize = itemSize; + this.elementSize = elementSize; + this.count = count; + this.version = 0; + } + set needsUpdate(value) { + if (value === true) + this.version++; + } + setBuffer(buffer) { + this.buffer = buffer; + return this; + } + setType(type2, elementSize) { + this.type = type2; + this.elementSize = elementSize; + return this; + } + setItemSize(itemSize) { + this.itemSize = itemSize; + return this; + } + setCount(count) { + this.count = count; + return this; + } + }; + var Raycaster = class { + constructor(origin, direction, near = 0, far = Infinity) { + this.ray = new Ray2(origin, direction); + this.near = near; + this.far = far; + this.camera = null; + this.layers = new Layers2(); + this.params = { + Mesh: {}, + Line: { + threshold: 1 + }, + LOD: {}, + Points: { + threshold: 1 + }, + Sprite: {} + }; + } + set(origin, direction) { + this.ray.set(origin, direction); + } + setFromCamera(coords, camera) { + if (camera.isPerspectiveCamera) { + this.ray.origin.setFromMatrixPosition(camera.matrixWorld); + this.ray.direction.set(coords.x, coords.y, 0.5).unproject(camera).sub(this.ray.origin).normalize(); + this.camera = camera; + } else if (camera.isOrthographicCamera) { + this.ray.origin.set(coords.x, coords.y, (camera.near + camera.far) / (camera.near - camera.far)).unproject(camera); + this.ray.direction.set(0, 0, -1).transformDirection(camera.matrixWorld); + this.camera = camera; + } else { + console.error("THREE.Raycaster: Unsupported camera type: " + camera.type); + } + } + intersectObject(object, recursive = true, intersects2 = []) { + intersectObject(object, this, intersects2, recursive); + intersects2.sort(ascSort); + return intersects2; + } + intersectObjects(objects, recursive = true, intersects2 = []) { + for (let i = 0, l = objects.length; i < l; i++) { + intersectObject(objects[i], this, intersects2, recursive); + } + intersects2.sort(ascSort); + return intersects2; + } + }; + function ascSort(a2, b) { + return a2.distance - b.distance; + } + function intersectObject(object, raycaster, intersects2, recursive) { + if (object.layers.test(raycaster.layers)) { + object.raycast(raycaster, intersects2); + } + if (recursive === true) { + const children2 = object.children; + for (let i = 0, l = children2.length; i < l; i++) { + intersectObject(children2[i], raycaster, intersects2, true); + } + } + } + var Spherical2 = class { + constructor(radius = 1, phi = 0, theta = 0) { + this.radius = radius; + this.phi = phi; + this.theta = theta; + return this; + } + set(radius, phi, theta) { + this.radius = radius; + this.phi = phi; + this.theta = theta; + return this; + } + copy(other) { + this.radius = other.radius; + this.phi = other.phi; + this.theta = other.theta; + return this; + } + makeSafe() { + const EPS = 1e-6; + this.phi = Math.max(EPS, Math.min(Math.PI - EPS, this.phi)); + return this; + } + setFromVector3(v) { + return this.setFromCartesianCoords(v.x, v.y, v.z); + } + setFromCartesianCoords(x2, y2, z) { + this.radius = Math.sqrt(x2 * x2 + y2 * y2 + z * z); + if (this.radius === 0) { + this.theta = 0; + this.phi = 0; + } else { + this.theta = Math.atan2(x2, z); + this.phi = Math.acos(clamp2(y2 / this.radius, -1, 1)); + } + return this; + } + clone() { + return new this.constructor().copy(this); + } + }; + var Cylindrical = class { + constructor(radius = 1, theta = 0, y2 = 0) { + this.radius = radius; + this.theta = theta; + this.y = y2; + return this; + } + set(radius, theta, y2) { + this.radius = radius; + this.theta = theta; + this.y = y2; + return this; + } + copy(other) { + this.radius = other.radius; + this.theta = other.theta; + this.y = other.y; + return this; + } + setFromVector3(v) { + return this.setFromCartesianCoords(v.x, v.y, v.z); + } + setFromCartesianCoords(x2, y2, z) { + this.radius = Math.sqrt(x2 * x2 + z * z); + this.theta = Math.atan2(x2, z); + this.y = y2; + return this; + } + clone() { + return new this.constructor().copy(this); + } + }; + var _vector$4 = /* @__PURE__ */ new Vector22(); + var Box2 = class { + constructor(min2 = new Vector22(Infinity, Infinity), max2 = new Vector22(-Infinity, -Infinity)) { + this.isBox2 = true; + this.min = min2; + this.max = max2; + } + set(min2, max2) { + this.min.copy(min2); + this.max.copy(max2); + return this; + } + setFromPoints(points) { + this.makeEmpty(); + for (let i = 0, il = points.length; i < il; i++) { + this.expandByPoint(points[i]); + } + return this; + } + setFromCenterAndSize(center, size) { + const halfSize = _vector$4.copy(size).multiplyScalar(0.5); + this.min.copy(center).sub(halfSize); + this.max.copy(center).add(halfSize); + return this; + } + clone() { + return new this.constructor().copy(this); + } + copy(box) { + this.min.copy(box.min); + this.max.copy(box.max); + return this; + } + makeEmpty() { + this.min.x = this.min.y = Infinity; + this.max.x = this.max.y = -Infinity; + return this; + } + isEmpty() { + return this.max.x < this.min.x || this.max.y < this.min.y; + } + getCenter(target) { + return this.isEmpty() ? target.set(0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5); + } + getSize(target) { + return this.isEmpty() ? target.set(0, 0) : target.subVectors(this.max, this.min); + } + expandByPoint(point) { + this.min.min(point); + this.max.max(point); + return this; + } + expandByVector(vector) { + this.min.sub(vector); + this.max.add(vector); + return this; + } + expandByScalar(scalar) { + this.min.addScalar(-scalar); + this.max.addScalar(scalar); + return this; + } + containsPoint(point) { + return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y ? false : true; + } + containsBox(box) { + return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y; + } + getParameter(point, target) { + return target.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y)); + } + intersectsBox(box) { + return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y ? false : true; + } + clampPoint(point, target) { + return target.copy(point).clamp(this.min, this.max); + } + distanceToPoint(point) { + const clampedPoint = _vector$4.copy(point).clamp(this.min, this.max); + return clampedPoint.sub(point).length(); + } + intersect(box) { + this.min.max(box.min); + this.max.min(box.max); + return this; + } + union(box) { + this.min.min(box.min); + this.max.max(box.max); + return this; + } + translate(offset) { + this.min.add(offset); + this.max.add(offset); + return this; + } + equals(box) { + return box.min.equals(this.min) && box.max.equals(this.max); + } + }; + var _startP = /* @__PURE__ */ new Vector32(); + var _startEnd = /* @__PURE__ */ new Vector32(); + var Line3 = class { + constructor(start2 = new Vector32(), end = new Vector32()) { + this.start = start2; + this.end = end; + } + set(start2, end) { + this.start.copy(start2); + this.end.copy(end); + return this; + } + copy(line) { + this.start.copy(line.start); + this.end.copy(line.end); + return this; + } + getCenter(target) { + return target.addVectors(this.start, this.end).multiplyScalar(0.5); + } + delta(target) { + return target.subVectors(this.end, this.start); + } + distanceSq() { + return this.start.distanceToSquared(this.end); + } + distance() { + return this.start.distanceTo(this.end); + } + at(t, target) { + return this.delta(target).multiplyScalar(t).add(this.start); + } + closestPointToPointParameter(point, clampToLine) { + _startP.subVectors(point, this.start); + _startEnd.subVectors(this.end, this.start); + const startEnd2 = _startEnd.dot(_startEnd); + const startEnd_startP = _startEnd.dot(_startP); + let t = startEnd_startP / startEnd2; + if (clampToLine) { + t = clamp2(t, 0, 1); + } + return t; + } + closestPointToPoint(point, clampToLine, target) { + const t = this.closestPointToPointParameter(point, clampToLine); + return this.delta(target).multiplyScalar(t).add(this.start); + } + applyMatrix4(matrix) { + this.start.applyMatrix4(matrix); + this.end.applyMatrix4(matrix); + return this; + } + equals(line) { + return line.start.equals(this.start) && line.end.equals(this.end); + } + clone() { + return new this.constructor().copy(this); + } + }; + var _vector$3 = /* @__PURE__ */ new Vector32(); + var SpotLightHelper = class extends Object3D2 { + constructor(light, color2) { + super(); + this.light = light; + this.light.updateMatrixWorld(); + this.matrix = light.matrixWorld; + this.matrixAutoUpdate = false; + this.color = color2; + const geometry = new BufferGeometry2(); + const positions = [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, -1, 1]; + for (let i = 0, j = 1, l = 32; i < l; i++, j++) { + const p1 = i / l * Math.PI * 2; + const p2 = j / l * Math.PI * 2; + positions.push(Math.cos(p1), Math.sin(p1), 1, Math.cos(p2), Math.sin(p2), 1); + } + geometry.setAttribute("position", new Float32BufferAttribute2(positions, 3)); + const material = new LineBasicMaterial({ + fog: false, + toneMapped: false + }); + this.cone = new LineSegments(geometry, material); + this.add(this.cone); + this.update(); + } + dispose() { + this.cone.geometry.dispose(); + this.cone.material.dispose(); + } + update() { + this.light.updateMatrixWorld(); + const coneLength = this.light.distance ? this.light.distance : 1e3; + const coneWidth = coneLength * Math.tan(this.light.angle); + this.cone.scale.set(coneWidth, coneWidth, coneLength); + _vector$3.setFromMatrixPosition(this.light.target.matrixWorld); + this.cone.lookAt(_vector$3); + if (this.color !== void 0) { + this.cone.material.color.set(this.color); + } else { + this.cone.material.color.copy(this.light.color); + } + } + }; + var _vector$2 = /* @__PURE__ */ new Vector32(); + var _boneMatrix = /* @__PURE__ */ new Matrix42(); + var _matrixWorldInv = /* @__PURE__ */ new Matrix42(); + var SkeletonHelper = class extends LineSegments { + constructor(object) { + const bones = getBoneList(object); + const geometry = new BufferGeometry2(); + const vertices = []; + const colors = []; + const color1 = new Color3(0, 0, 1); + const color2 = new Color3(0, 1, 0); + for (let i = 0; i < bones.length; i++) { + const bone = bones[i]; + if (bone.parent && bone.parent.isBone) { + vertices.push(0, 0, 0); + vertices.push(0, 0, 0); + colors.push(color1.r, color1.g, color1.b); + colors.push(color2.r, color2.g, color2.b); + } + } + geometry.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + geometry.setAttribute("color", new Float32BufferAttribute2(colors, 3)); + const material = new LineBasicMaterial({ + vertexColors: true, + depthTest: false, + depthWrite: false, + toneMapped: false, + transparent: true + }); + super(geometry, material); + this.isSkeletonHelper = true; + this.type = "SkeletonHelper"; + this.root = object; + this.bones = bones; + this.matrix = object.matrixWorld; + this.matrixAutoUpdate = false; + } + updateMatrixWorld(force) { + const bones = this.bones; + const geometry = this.geometry; + const position = geometry.getAttribute("position"); + _matrixWorldInv.copy(this.root.matrixWorld).invert(); + for (let i = 0, j = 0; i < bones.length; i++) { + const bone = bones[i]; + if (bone.parent && bone.parent.isBone) { + _boneMatrix.multiplyMatrices(_matrixWorldInv, bone.matrixWorld); + _vector$2.setFromMatrixPosition(_boneMatrix); + position.setXYZ(j, _vector$2.x, _vector$2.y, _vector$2.z); + _boneMatrix.multiplyMatrices(_matrixWorldInv, bone.parent.matrixWorld); + _vector$2.setFromMatrixPosition(_boneMatrix); + position.setXYZ(j + 1, _vector$2.x, _vector$2.y, _vector$2.z); + j += 2; + } + } + geometry.getAttribute("position").needsUpdate = true; + super.updateMatrixWorld(force); + } + }; + function getBoneList(object) { + const boneList = []; + if (object.isBone === true) { + boneList.push(object); + } + for (let i = 0; i < object.children.length; i++) { + boneList.push.apply(boneList, getBoneList(object.children[i])); + } + return boneList; + } + var PointLightHelper = class extends Mesh2 { + constructor(light, sphereSize, color2) { + const geometry = new SphereGeometry2(sphereSize, 4, 2); + const material = new MeshBasicMaterial2({ + wireframe: true, + fog: false, + toneMapped: false + }); + super(geometry, material); + this.light = light; + this.light.updateMatrixWorld(); + this.color = color2; + this.type = "PointLightHelper"; + this.matrix = this.light.matrixWorld; + this.matrixAutoUpdate = false; + this.update(); + } + dispose() { + this.geometry.dispose(); + this.material.dispose(); + } + update() { + if (this.color !== void 0) { + this.material.color.set(this.color); + } else { + this.material.color.copy(this.light.color); + } + } + }; + var _vector$1 = /* @__PURE__ */ new Vector32(); + var _color1 = /* @__PURE__ */ new Color3(); + var _color2 = /* @__PURE__ */ new Color3(); + var HemisphereLightHelper = class extends Object3D2 { + constructor(light, size, color2) { + super(); + this.light = light; + this.light.updateMatrixWorld(); + this.matrix = light.matrixWorld; + this.matrixAutoUpdate = false; + this.color = color2; + const geometry = new OctahedronGeometry(size); + geometry.rotateY(Math.PI * 0.5); + this.material = new MeshBasicMaterial2({ + wireframe: true, + fog: false, + toneMapped: false + }); + if (this.color === void 0) + this.material.vertexColors = true; + const position = geometry.getAttribute("position"); + const colors = new Float32Array(position.count * 3); + geometry.setAttribute("color", new BufferAttribute2(colors, 3)); + this.add(new Mesh2(geometry, this.material)); + this.update(); + } + dispose() { + this.children[0].geometry.dispose(); + this.children[0].material.dispose(); + } + update() { + const mesh = this.children[0]; + if (this.color !== void 0) { + this.material.color.set(this.color); + } else { + const colors = mesh.geometry.getAttribute("color"); + _color1.copy(this.light.color); + _color2.copy(this.light.groundColor); + for (let i = 0, l = colors.count; i < l; i++) { + const color2 = i < l / 2 ? _color1 : _color2; + colors.setXYZ(i, color2.r, color2.g, color2.b); + } + colors.needsUpdate = true; + } + mesh.lookAt(_vector$1.setFromMatrixPosition(this.light.matrixWorld).negate()); + } + }; + var GridHelper = class extends LineSegments { + constructor(size = 10, divisions = 10, color1 = 4473924, color2 = 8947848) { + color1 = new Color3(color1); + color2 = new Color3(color2); + const center = divisions / 2; + const step = size / divisions; + const halfSize = size / 2; + const vertices = [], colors = []; + for (let i = 0, j = 0, k = -halfSize; i <= divisions; i++, k += step) { + vertices.push(-halfSize, 0, k, halfSize, 0, k); + vertices.push(k, 0, -halfSize, k, 0, halfSize); + const color3 = i === center ? color1 : color2; + color3.toArray(colors, j); + j += 3; + color3.toArray(colors, j); + j += 3; + color3.toArray(colors, j); + j += 3; + color3.toArray(colors, j); + j += 3; + } + const geometry = new BufferGeometry2(); + geometry.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + geometry.setAttribute("color", new Float32BufferAttribute2(colors, 3)); + const material = new LineBasicMaterial({ + vertexColors: true, + toneMapped: false + }); + super(geometry, material); + this.type = "GridHelper"; + } + }; + var PolarGridHelper = class extends LineSegments { + constructor(radius = 10, radials = 16, circles = 8, divisions = 64, color1 = 4473924, color2 = 8947848) { + color1 = new Color3(color1); + color2 = new Color3(color2); + const vertices = []; + const colors = []; + for (let i = 0; i <= radials; i++) { + const v = i / radials * (Math.PI * 2); + const x2 = Math.sin(v) * radius; + const z = Math.cos(v) * radius; + vertices.push(0, 0, 0); + vertices.push(x2, 0, z); + const color3 = i & 1 ? color1 : color2; + colors.push(color3.r, color3.g, color3.b); + colors.push(color3.r, color3.g, color3.b); + } + for (let i = 0; i <= circles; i++) { + const color3 = i & 1 ? color1 : color2; + const r = radius - radius / circles * i; + for (let j = 0; j < divisions; j++) { + let v = j / divisions * (Math.PI * 2); + let x2 = Math.sin(v) * r; + let z = Math.cos(v) * r; + vertices.push(x2, 0, z); + colors.push(color3.r, color3.g, color3.b); + v = (j + 1) / divisions * (Math.PI * 2); + x2 = Math.sin(v) * r; + z = Math.cos(v) * r; + vertices.push(x2, 0, z); + colors.push(color3.r, color3.g, color3.b); + } + } + const geometry = new BufferGeometry2(); + geometry.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + geometry.setAttribute("color", new Float32BufferAttribute2(colors, 3)); + const material = new LineBasicMaterial({ + vertexColors: true, + toneMapped: false + }); + super(geometry, material); + this.type = "PolarGridHelper"; + } + }; + var _v1 = /* @__PURE__ */ new Vector32(); + var _v2 = /* @__PURE__ */ new Vector32(); + var _v3 = /* @__PURE__ */ new Vector32(); + var DirectionalLightHelper = class extends Object3D2 { + constructor(light, size, color2) { + super(); + this.light = light; + this.light.updateMatrixWorld(); + this.matrix = light.matrixWorld; + this.matrixAutoUpdate = false; + this.color = color2; + if (size === void 0) + size = 1; + let geometry = new BufferGeometry2(); + geometry.setAttribute("position", new Float32BufferAttribute2([-size, size, 0, size, size, 0, size, -size, 0, -size, -size, 0, -size, size, 0], 3)); + const material = new LineBasicMaterial({ + fog: false, + toneMapped: false + }); + this.lightPlane = new Line(geometry, material); + this.add(this.lightPlane); + geometry = new BufferGeometry2(); + geometry.setAttribute("position", new Float32BufferAttribute2([0, 0, 0, 0, 0, 1], 3)); + this.targetLine = new Line(geometry, material); + this.add(this.targetLine); + this.update(); + } + dispose() { + this.lightPlane.geometry.dispose(); + this.lightPlane.material.dispose(); + this.targetLine.geometry.dispose(); + this.targetLine.material.dispose(); + } + update() { + _v1.setFromMatrixPosition(this.light.matrixWorld); + _v2.setFromMatrixPosition(this.light.target.matrixWorld); + _v3.subVectors(_v2, _v1); + this.lightPlane.lookAt(_v2); + if (this.color !== void 0) { + this.lightPlane.material.color.set(this.color); + this.targetLine.material.color.set(this.color); + } else { + this.lightPlane.material.color.copy(this.light.color); + this.targetLine.material.color.copy(this.light.color); + } + this.targetLine.lookAt(_v2); + this.targetLine.scale.z = _v3.length(); + } + }; + var _vector = /* @__PURE__ */ new Vector32(); + var _camera = /* @__PURE__ */ new Camera2(); + var CameraHelper = class extends LineSegments { + constructor(camera) { + const geometry = new BufferGeometry2(); + const material = new LineBasicMaterial({ + color: 16777215, + vertexColors: true, + toneMapped: false + }); + const vertices = []; + const colors = []; + const pointMap = {}; + addLine("n1", "n2"); + addLine("n2", "n4"); + addLine("n4", "n3"); + addLine("n3", "n1"); + addLine("f1", "f2"); + addLine("f2", "f4"); + addLine("f4", "f3"); + addLine("f3", "f1"); + addLine("n1", "f1"); + addLine("n2", "f2"); + addLine("n3", "f3"); + addLine("n4", "f4"); + addLine("p", "n1"); + addLine("p", "n2"); + addLine("p", "n3"); + addLine("p", "n4"); + addLine("u1", "u2"); + addLine("u2", "u3"); + addLine("u3", "u1"); + addLine("c", "t"); + addLine("p", "c"); + addLine("cn1", "cn2"); + addLine("cn3", "cn4"); + addLine("cf1", "cf2"); + addLine("cf3", "cf4"); + function addLine(a2, b) { + addPoint(a2); + addPoint(b); + } + function addPoint(id3) { + vertices.push(0, 0, 0); + colors.push(0, 0, 0); + if (pointMap[id3] === void 0) { + pointMap[id3] = []; + } + pointMap[id3].push(vertices.length / 3 - 1); + } + geometry.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + geometry.setAttribute("color", new Float32BufferAttribute2(colors, 3)); + super(geometry, material); + this.type = "CameraHelper"; + this.camera = camera; + if (this.camera.updateProjectionMatrix) + this.camera.updateProjectionMatrix(); + this.matrix = camera.matrixWorld; + this.matrixAutoUpdate = false; + this.pointMap = pointMap; + this.update(); + const colorFrustum = new Color3(16755200); + const colorCone = new Color3(16711680); + const colorUp = new Color3(43775); + const colorTarget = new Color3(16777215); + const colorCross = new Color3(3355443); + this.setColors(colorFrustum, colorCone, colorUp, colorTarget, colorCross); + } + setColors(frustum, cone, up, target, cross) { + const geometry = this.geometry; + const colorAttribute = geometry.getAttribute("color"); + colorAttribute.setXYZ(0, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(1, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(2, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(3, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(4, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(5, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(6, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(7, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(8, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(9, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(10, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(11, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(12, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(13, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(14, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(15, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(16, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(17, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(18, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(19, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(20, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(21, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(22, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(23, frustum.r, frustum.g, frustum.b); + colorAttribute.setXYZ(24, cone.r, cone.g, cone.b); + colorAttribute.setXYZ(25, cone.r, cone.g, cone.b); + colorAttribute.setXYZ(26, cone.r, cone.g, cone.b); + colorAttribute.setXYZ(27, cone.r, cone.g, cone.b); + colorAttribute.setXYZ(28, cone.r, cone.g, cone.b); + colorAttribute.setXYZ(29, cone.r, cone.g, cone.b); + colorAttribute.setXYZ(30, cone.r, cone.g, cone.b); + colorAttribute.setXYZ(31, cone.r, cone.g, cone.b); + colorAttribute.setXYZ(32, up.r, up.g, up.b); + colorAttribute.setXYZ(33, up.r, up.g, up.b); + colorAttribute.setXYZ(34, up.r, up.g, up.b); + colorAttribute.setXYZ(35, up.r, up.g, up.b); + colorAttribute.setXYZ(36, up.r, up.g, up.b); + colorAttribute.setXYZ(37, up.r, up.g, up.b); + colorAttribute.setXYZ(38, target.r, target.g, target.b); + colorAttribute.setXYZ(39, target.r, target.g, target.b); + colorAttribute.setXYZ(40, cross.r, cross.g, cross.b); + colorAttribute.setXYZ(41, cross.r, cross.g, cross.b); + colorAttribute.setXYZ(42, cross.r, cross.g, cross.b); + colorAttribute.setXYZ(43, cross.r, cross.g, cross.b); + colorAttribute.setXYZ(44, cross.r, cross.g, cross.b); + colorAttribute.setXYZ(45, cross.r, cross.g, cross.b); + colorAttribute.setXYZ(46, cross.r, cross.g, cross.b); + colorAttribute.setXYZ(47, cross.r, cross.g, cross.b); + colorAttribute.setXYZ(48, cross.r, cross.g, cross.b); + colorAttribute.setXYZ(49, cross.r, cross.g, cross.b); + colorAttribute.needsUpdate = true; + } + update() { + const geometry = this.geometry; + const pointMap = this.pointMap; + const w = 1, h = 1; + _camera.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse); + setPoint("c", pointMap, geometry, _camera, 0, 0, -1); + setPoint("t", pointMap, geometry, _camera, 0, 0, 1); + setPoint("n1", pointMap, geometry, _camera, -w, -h, -1); + setPoint("n2", pointMap, geometry, _camera, w, -h, -1); + setPoint("n3", pointMap, geometry, _camera, -w, h, -1); + setPoint("n4", pointMap, geometry, _camera, w, h, -1); + setPoint("f1", pointMap, geometry, _camera, -w, -h, 1); + setPoint("f2", pointMap, geometry, _camera, w, -h, 1); + setPoint("f3", pointMap, geometry, _camera, -w, h, 1); + setPoint("f4", pointMap, geometry, _camera, w, h, 1); + setPoint("u1", pointMap, geometry, _camera, w * 0.7, h * 1.1, -1); + setPoint("u2", pointMap, geometry, _camera, -w * 0.7, h * 1.1, -1); + setPoint("u3", pointMap, geometry, _camera, 0, h * 2, -1); + setPoint("cf1", pointMap, geometry, _camera, -w, 0, 1); + setPoint("cf2", pointMap, geometry, _camera, w, 0, 1); + setPoint("cf3", pointMap, geometry, _camera, 0, -h, 1); + setPoint("cf4", pointMap, geometry, _camera, 0, h, 1); + setPoint("cn1", pointMap, geometry, _camera, -w, 0, -1); + setPoint("cn2", pointMap, geometry, _camera, w, 0, -1); + setPoint("cn3", pointMap, geometry, _camera, 0, -h, -1); + setPoint("cn4", pointMap, geometry, _camera, 0, h, -1); + geometry.getAttribute("position").needsUpdate = true; + } + dispose() { + this.geometry.dispose(); + this.material.dispose(); + } + }; + function setPoint(point, pointMap, geometry, camera, x2, y2, z) { + _vector.set(x2, y2, z).unproject(camera); + const points = pointMap[point]; + if (points !== void 0) { + const position = geometry.getAttribute("position"); + for (let i = 0, l = points.length; i < l; i++) { + position.setXYZ(points[i], _vector.x, _vector.y, _vector.z); + } + } + } + var _box = /* @__PURE__ */ new Box32(); + var BoxHelper = class extends LineSegments { + constructor(object, color2 = 16776960) { + const indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7]); + const positions = new Float32Array(8 * 3); + const geometry = new BufferGeometry2(); + geometry.setIndex(new BufferAttribute2(indices, 1)); + geometry.setAttribute("position", new BufferAttribute2(positions, 3)); + super(geometry, new LineBasicMaterial({ + color: color2, + toneMapped: false + })); + this.object = object; + this.type = "BoxHelper"; + this.matrixAutoUpdate = false; + this.update(); + } + update(object) { + if (object !== void 0) { + console.warn("THREE.BoxHelper: .update() has no longer arguments."); + } + if (this.object !== void 0) { + _box.setFromObject(this.object); + } + if (_box.isEmpty()) + return; + const min2 = _box.min; + const max2 = _box.max; + const position = this.geometry.attributes.position; + const array2 = position.array; + array2[0] = max2.x; + array2[1] = max2.y; + array2[2] = max2.z; + array2[3] = min2.x; + array2[4] = max2.y; + array2[5] = max2.z; + array2[6] = min2.x; + array2[7] = min2.y; + array2[8] = max2.z; + array2[9] = max2.x; + array2[10] = min2.y; + array2[11] = max2.z; + array2[12] = max2.x; + array2[13] = max2.y; + array2[14] = min2.z; + array2[15] = min2.x; + array2[16] = max2.y; + array2[17] = min2.z; + array2[18] = min2.x; + array2[19] = min2.y; + array2[20] = min2.z; + array2[21] = max2.x; + array2[22] = min2.y; + array2[23] = min2.z; + position.needsUpdate = true; + this.geometry.computeBoundingSphere(); + } + setFromObject(object) { + this.object = object; + this.update(); + return this; + } + copy(source, recursive) { + super.copy(source, recursive); + this.object = source.object; + return this; + } + }; + var Box3Helper = class extends LineSegments { + constructor(box, color2 = 16776960) { + const indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7]); + const positions = [1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1]; + const geometry = new BufferGeometry2(); + geometry.setIndex(new BufferAttribute2(indices, 1)); + geometry.setAttribute("position", new Float32BufferAttribute2(positions, 3)); + super(geometry, new LineBasicMaterial({ + color: color2, + toneMapped: false + })); + this.box = box; + this.type = "Box3Helper"; + this.geometry.computeBoundingSphere(); + } + updateMatrixWorld(force) { + const box = this.box; + if (box.isEmpty()) + return; + box.getCenter(this.position); + box.getSize(this.scale); + this.scale.multiplyScalar(0.5); + super.updateMatrixWorld(force); + } + }; + var PlaneHelper = class extends Line { + constructor(plane, size = 1, hex2 = 16776960) { + const color2 = hex2; + const positions = [1, -1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0]; + const geometry = new BufferGeometry2(); + geometry.setAttribute("position", new Float32BufferAttribute2(positions, 3)); + geometry.computeBoundingSphere(); + super(geometry, new LineBasicMaterial({ + color: color2, + toneMapped: false + })); + this.type = "PlaneHelper"; + this.plane = plane; + this.size = size; + const positions2 = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0]; + const geometry2 = new BufferGeometry2(); + geometry2.setAttribute("position", new Float32BufferAttribute2(positions2, 3)); + geometry2.computeBoundingSphere(); + this.add(new Mesh2(geometry2, new MeshBasicMaterial2({ + color: color2, + opacity: 0.2, + transparent: true, + depthWrite: false, + toneMapped: false + }))); + } + updateMatrixWorld(force) { + this.position.set(0, 0, 0); + this.scale.set(0.5 * this.size, 0.5 * this.size, 1); + this.lookAt(this.plane.normal); + this.translateZ(-this.plane.constant); + super.updateMatrixWorld(force); + } + }; + var _axis = /* @__PURE__ */ new Vector32(); + var _lineGeometry; + var _coneGeometry; + var ArrowHelper = class extends Object3D2 { + constructor(dir = new Vector32(0, 0, 1), origin = new Vector32(0, 0, 0), length = 1, color2 = 16776960, headLength = length * 0.2, headWidth = headLength * 0.2) { + super(); + this.type = "ArrowHelper"; + if (_lineGeometry === void 0) { + _lineGeometry = new BufferGeometry2(); + _lineGeometry.setAttribute("position", new Float32BufferAttribute2([0, 0, 0, 0, 1, 0], 3)); + _coneGeometry = new CylinderGeometry(0, 0.5, 1, 5, 1); + _coneGeometry.translate(0, -0.5, 0); + } + this.position.copy(origin); + this.line = new Line(_lineGeometry, new LineBasicMaterial({ + color: color2, + toneMapped: false + })); + this.line.matrixAutoUpdate = false; + this.add(this.line); + this.cone = new Mesh2(_coneGeometry, new MeshBasicMaterial2({ + color: color2, + toneMapped: false + })); + this.cone.matrixAutoUpdate = false; + this.add(this.cone); + this.setDirection(dir); + this.setLength(length, headLength, headWidth); + } + setDirection(dir) { + if (dir.y > 0.99999) { + this.quaternion.set(0, 0, 0, 1); + } else if (dir.y < -0.99999) { + this.quaternion.set(1, 0, 0, 0); + } else { + _axis.set(dir.z, 0, -dir.x).normalize(); + const radians = Math.acos(dir.y); + this.quaternion.setFromAxisAngle(_axis, radians); + } + } + setLength(length, headLength = length * 0.2, headWidth = headLength * 0.2) { + this.line.scale.set(1, Math.max(1e-4, length - headLength), 1); + this.line.updateMatrix(); + this.cone.scale.set(headWidth, headLength, headWidth); + this.cone.position.y = length; + this.cone.updateMatrix(); + } + setColor(color2) { + this.line.material.color.set(color2); + this.cone.material.color.set(color2); + } + copy(source) { + super.copy(source, false); + this.line.copy(source.line); + this.cone.copy(source.cone); + return this; + } + }; + var AxesHelper = class extends LineSegments { + constructor(size = 1) { + const vertices = [0, 0, 0, size, 0, 0, 0, 0, 0, 0, size, 0, 0, 0, 0, 0, 0, size]; + const colors = [1, 0, 0, 1, 0.6, 0, 0, 1, 0, 0.6, 1, 0, 0, 0, 1, 0, 0.6, 1]; + const geometry = new BufferGeometry2(); + geometry.setAttribute("position", new Float32BufferAttribute2(vertices, 3)); + geometry.setAttribute("color", new Float32BufferAttribute2(colors, 3)); + const material = new LineBasicMaterial({ + vertexColors: true, + toneMapped: false + }); + super(geometry, material); + this.type = "AxesHelper"; + } + setColors(xAxisColor, yAxisColor, zAxisColor) { + const color2 = new Color3(); + const array2 = this.geometry.attributes.color.array; + color2.set(xAxisColor); + color2.toArray(array2, 0); + color2.toArray(array2, 3); + color2.set(yAxisColor); + color2.toArray(array2, 6); + color2.toArray(array2, 9); + color2.set(zAxisColor); + color2.toArray(array2, 12); + color2.toArray(array2, 15); + this.geometry.attributes.color.needsUpdate = true; + return this; + } + dispose() { + this.geometry.dispose(); + this.material.dispose(); + } + }; + var ShapePath = class { + constructor() { + this.type = "ShapePath"; + this.color = new Color3(); + this.subPaths = []; + this.currentPath = null; + } + moveTo(x2, y2) { + this.currentPath = new Path(); + this.subPaths.push(this.currentPath); + this.currentPath.moveTo(x2, y2); + return this; + } + lineTo(x2, y2) { + this.currentPath.lineTo(x2, y2); + return this; + } + quadraticCurveTo(aCPx, aCPy, aX, aY) { + this.currentPath.quadraticCurveTo(aCPx, aCPy, aX, aY); + return this; + } + bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) { + this.currentPath.bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY); + return this; + } + splineThru(pts) { + this.currentPath.splineThru(pts); + return this; + } + toShapes(isCCW, noHoles) { + function toShapesNoHoles(inSubpaths) { + const shapes2 = []; + for (let i = 0, l = inSubpaths.length; i < l; i++) { + const tmpPath2 = inSubpaths[i]; + const tmpShape2 = new Shape(); + tmpShape2.curves = tmpPath2.curves; + shapes2.push(tmpShape2); + } + return shapes2; + } + function isPointInsidePolygon(inPt, inPolygon) { + const polyLen = inPolygon.length; + let inside = false; + for (let p = polyLen - 1, q = 0; q < polyLen; p = q++) { + let edgeLowPt = inPolygon[p]; + let edgeHighPt = inPolygon[q]; + let edgeDx = edgeHighPt.x - edgeLowPt.x; + let edgeDy = edgeHighPt.y - edgeLowPt.y; + if (Math.abs(edgeDy) > Number.EPSILON) { + if (edgeDy < 0) { + edgeLowPt = inPolygon[q]; + edgeDx = -edgeDx; + edgeHighPt = inPolygon[p]; + edgeDy = -edgeDy; + } + if (inPt.y < edgeLowPt.y || inPt.y > edgeHighPt.y) + continue; + if (inPt.y === edgeLowPt.y) { + if (inPt.x === edgeLowPt.x) + return true; + } else { + const perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y); + if (perpEdge === 0) + return true; + if (perpEdge < 0) + continue; + inside = !inside; + } + } else { + if (inPt.y !== edgeLowPt.y) + continue; + if (edgeHighPt.x <= inPt.x && inPt.x <= edgeLowPt.x || edgeLowPt.x <= inPt.x && inPt.x <= edgeHighPt.x) + return true; + } + } + return inside; + } + const isClockWise = ShapeUtils.isClockWise; + const subPaths = this.subPaths; + if (subPaths.length === 0) + return []; + if (noHoles === true) + return toShapesNoHoles(subPaths); + let solid, tmpPath, tmpShape; + const shapes = []; + if (subPaths.length === 1) { + tmpPath = subPaths[0]; + tmpShape = new Shape(); + tmpShape.curves = tmpPath.curves; + shapes.push(tmpShape); + return shapes; + } + let holesFirst = !isClockWise(subPaths[0].getPoints()); + holesFirst = isCCW ? !holesFirst : holesFirst; + const betterShapeHoles = []; + const newShapes = []; + let newShapeHoles = []; + let mainIdx = 0; + let tmpPoints; + newShapes[mainIdx] = void 0; + newShapeHoles[mainIdx] = []; + for (let i = 0, l = subPaths.length; i < l; i++) { + tmpPath = subPaths[i]; + tmpPoints = tmpPath.getPoints(); + solid = isClockWise(tmpPoints); + solid = isCCW ? !solid : solid; + if (solid) { + if (!holesFirst && newShapes[mainIdx]) + mainIdx++; + newShapes[mainIdx] = { + s: new Shape(), + p: tmpPoints + }; + newShapes[mainIdx].s.curves = tmpPath.curves; + if (holesFirst) + mainIdx++; + newShapeHoles[mainIdx] = []; + } else { + newShapeHoles[mainIdx].push({ + h: tmpPath, + p: tmpPoints[0] + }); + } + } + if (!newShapes[0]) + return toShapesNoHoles(subPaths); + if (newShapes.length > 1) { + let ambiguous = false; + let toChange = 0; + for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) { + betterShapeHoles[sIdx] = []; + } + for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) { + const sho = newShapeHoles[sIdx]; + for (let hIdx = 0; hIdx < sho.length; hIdx++) { + const ho = sho[hIdx]; + let hole_unassigned = true; + for (let s2Idx = 0; s2Idx < newShapes.length; s2Idx++) { + if (isPointInsidePolygon(ho.p, newShapes[s2Idx].p)) { + if (sIdx !== s2Idx) + toChange++; + if (hole_unassigned) { + hole_unassigned = false; + betterShapeHoles[s2Idx].push(ho); + } else { + ambiguous = true; + } + } + } + if (hole_unassigned) { + betterShapeHoles[sIdx].push(ho); + } + } + } + if (toChange > 0 && ambiguous === false) { + newShapeHoles = betterShapeHoles; + } + } + let tmpHoles; + for (let i = 0, il = newShapes.length; i < il; i++) { + tmpShape = newShapes[i].s; + shapes.push(tmpShape); + tmpHoles = newShapeHoles[i]; + for (let j = 0, jl = tmpHoles.length; j < jl; j++) { + tmpShape.holes.push(tmpHoles[j].h); + } + } + return shapes; + } + }; + var _tables = /* @__PURE__ */ _generateTables(); + function _generateTables() { + const buffer = new ArrayBuffer(4); + const floatView = new Float32Array(buffer); + const uint32View = new Uint32Array(buffer); + const baseTable = new Uint32Array(512); + const shiftTable = new Uint32Array(512); + for (let i = 0; i < 256; ++i) { + const e = i - 127; + if (e < -27) { + baseTable[i] = 0; + baseTable[i | 256] = 32768; + shiftTable[i] = 24; + shiftTable[i | 256] = 24; + } else if (e < -14) { + baseTable[i] = 1024 >> -e - 14; + baseTable[i | 256] = 1024 >> -e - 14 | 32768; + shiftTable[i] = -e - 1; + shiftTable[i | 256] = -e - 1; + } else if (e <= 15) { + baseTable[i] = e + 15 << 10; + baseTable[i | 256] = e + 15 << 10 | 32768; + shiftTable[i] = 13; + shiftTable[i | 256] = 13; + } else if (e < 128) { + baseTable[i] = 31744; + baseTable[i | 256] = 64512; + shiftTable[i] = 24; + shiftTable[i | 256] = 24; + } else { + baseTable[i] = 31744; + baseTable[i | 256] = 64512; + shiftTable[i] = 13; + shiftTable[i | 256] = 13; + } + } + const mantissaTable = new Uint32Array(2048); + const exponentTable = new Uint32Array(64); + const offsetTable = new Uint32Array(64); + for (let i = 1; i < 1024; ++i) { + let m2 = i << 13; + let e = 0; + while ((m2 & 8388608) === 0) { + m2 <<= 1; + e -= 8388608; + } + m2 &= ~8388608; + e += 947912704; + mantissaTable[i] = m2 | e; + } + for (let i = 1024; i < 2048; ++i) { + mantissaTable[i] = 939524096 + (i - 1024 << 13); + } + for (let i = 1; i < 31; ++i) { + exponentTable[i] = i << 23; + } + exponentTable[31] = 1199570944; + exponentTable[32] = 2147483648; + for (let i = 33; i < 63; ++i) { + exponentTable[i] = 2147483648 + (i - 32 << 23); + } + exponentTable[63] = 3347054592; + for (let i = 1; i < 64; ++i) { + if (i !== 32) { + offsetTable[i] = 1024; + } + } + return { + floatView, + uint32View, + baseTable, + shiftTable, + mantissaTable, + exponentTable, + offsetTable + }; + } + function toHalfFloat(val) { + if (Math.abs(val) > 65504) + console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."); + val = clamp2(val, -65504, 65504); + _tables.floatView[0] = val; + const f = _tables.uint32View[0]; + const e = f >> 23 & 511; + return _tables.baseTable[e] + ((f & 8388607) >> _tables.shiftTable[e]); + } + function fromHalfFloat(val) { + const m2 = val >> 10; + _tables.uint32View[0] = _tables.mantissaTable[_tables.offsetTable[m2] + (val & 1023)] + _tables.exponentTable[m2]; + return _tables.floatView[0]; + } + var DataUtils = /* @__PURE__ */ Object.freeze({ + __proto__: null, + toHalfFloat, + fromHalfFloat + }); + var ParametricGeometry = class extends BufferGeometry2 { + constructor() { + console.error("THREE.ParametricGeometry has been moved to /examples/jsm/geometries/ParametricGeometry.js"); + super(); + } + }; + var TextGeometry = class extends BufferGeometry2 { + constructor() { + console.error("THREE.TextGeometry has been moved to /examples/jsm/geometries/TextGeometry.js"); + super(); + } + }; + function FontLoader() { + console.error("THREE.FontLoader has been moved to /examples/jsm/loaders/FontLoader.js"); + } + function Font() { + console.error("THREE.Font has been moved to /examples/jsm/loaders/FontLoader.js"); + } + function ImmediateRenderObject() { + console.error("THREE.ImmediateRenderObject has been removed."); + } + var WebGLMultisampleRenderTarget = class extends WebGLRenderTarget2 { + constructor(width, height, options) { + console.error('THREE.WebGLMultisampleRenderTarget has been removed. Use a normal render target and set the "samples" property to greater 0 to enable multisampling.'); + super(width, height, options); + this.samples = 4; + } + }; + var DataTexture2DArray = class extends DataArrayTexture2 { + constructor(data, width, height, depth) { + console.warn("THREE.DataTexture2DArray has been renamed to DataArrayTexture."); + super(data, width, height, depth); + } + }; + var DataTexture3D = class extends Data3DTexture2 { + constructor(data, width, height, depth) { + console.warn("THREE.DataTexture3D has been renamed to Data3DTexture."); + super(data, width, height, depth); + } + }; + if (typeof __THREE_DEVTOOLS__ !== "undefined") { + __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register", { + detail: { + revision: REVISION2 + } + })); + } + if (typeof window !== "undefined") { + if (window.__THREE__) { + console.warn("WARNING: Multiple instances of Three.js being imported."); + } else { + window.__THREE__ = REVISION2; + } + } + exports.ACESFilmicToneMapping = ACESFilmicToneMapping2; + exports.AddEquation = AddEquation2; + exports.AddOperation = AddOperation2; + exports.AdditiveAnimationBlendMode = AdditiveAnimationBlendMode; + exports.AdditiveBlending = AdditiveBlending2; + exports.AlphaFormat = AlphaFormat2; + exports.AlwaysDepth = AlwaysDepth2; + exports.AlwaysStencilFunc = AlwaysStencilFunc2; + exports.AmbientLight = AmbientLight; + exports.AmbientLightProbe = AmbientLightProbe; + exports.AnimationClip = AnimationClip; + exports.AnimationLoader = AnimationLoader; + exports.AnimationMixer = AnimationMixer; + exports.AnimationObjectGroup = AnimationObjectGroup; + exports.AnimationUtils = AnimationUtils; + exports.ArcCurve = ArcCurve; + exports.ArrayCamera = ArrayCamera2; + exports.ArrowHelper = ArrowHelper; + exports.Audio = Audio; + exports.AudioAnalyser = AudioAnalyser; + exports.AudioContext = AudioContext; + exports.AudioListener = AudioListener; + exports.AudioLoader = AudioLoader; + exports.AxesHelper = AxesHelper; + exports.BackSide = BackSide2; + exports.BasicDepthPacking = BasicDepthPacking2; + exports.BasicShadowMap = BasicShadowMap; + exports.Bone = Bone; + exports.BooleanKeyframeTrack = BooleanKeyframeTrack2; + exports.Box2 = Box2; + exports.Box3 = Box32; + exports.Box3Helper = Box3Helper; + exports.BoxBufferGeometry = BoxGeometry2; + exports.BoxGeometry = BoxGeometry2; + exports.BoxHelper = BoxHelper; + exports.BufferAttribute = BufferAttribute2; + exports.BufferGeometry = BufferGeometry2; + exports.BufferGeometryLoader = BufferGeometryLoader; + exports.ByteType = ByteType2; + exports.Cache = Cache; + exports.Camera = Camera2; + exports.CameraHelper = CameraHelper; + exports.CanvasTexture = CanvasTexture2; + exports.CapsuleBufferGeometry = CapsuleGeometry; + exports.CapsuleGeometry = CapsuleGeometry; + exports.CatmullRomCurve3 = CatmullRomCurve3; + exports.CineonToneMapping = CineonToneMapping2; + exports.CircleBufferGeometry = CircleGeometry; + exports.CircleGeometry = CircleGeometry; + exports.ClampToEdgeWrapping = ClampToEdgeWrapping2; + exports.Clock = Clock; + exports.Color = Color3; + exports.ColorKeyframeTrack = ColorKeyframeTrack2; + exports.ColorManagement = ColorManagement2; + exports.CompressedTexture = CompressedTexture; + exports.CompressedTextureLoader = CompressedTextureLoader; + exports.ConeBufferGeometry = ConeGeometry; + exports.ConeGeometry = ConeGeometry; + exports.CubeCamera = CubeCamera2; + exports.CubeReflectionMapping = CubeReflectionMapping2; + exports.CubeRefractionMapping = CubeRefractionMapping2; + exports.CubeTexture = CubeTexture2; + exports.CubeTextureLoader = CubeTextureLoader; + exports.CubeUVReflectionMapping = CubeUVReflectionMapping2; + exports.CubicBezierCurve = CubicBezierCurve; + exports.CubicBezierCurve3 = CubicBezierCurve3; + exports.CubicInterpolant = CubicInterpolant2; + exports.CullFaceBack = CullFaceBack2; + exports.CullFaceFront = CullFaceFront2; + exports.CullFaceFrontBack = CullFaceFrontBack; + exports.CullFaceNone = CullFaceNone2; + exports.Curve = Curve; + exports.CurvePath = CurvePath; + exports.CustomBlending = CustomBlending2; + exports.CustomToneMapping = CustomToneMapping2; + exports.CylinderBufferGeometry = CylinderGeometry; + exports.CylinderGeometry = CylinderGeometry; + exports.Cylindrical = Cylindrical; + exports.Data3DTexture = Data3DTexture2; + exports.DataArrayTexture = DataArrayTexture2; + exports.DataTexture = DataTexture; + exports.DataTexture2DArray = DataTexture2DArray; + exports.DataTexture3D = DataTexture3D; + exports.DataTextureLoader = DataTextureLoader; + exports.DataUtils = DataUtils; + exports.DecrementStencilOp = DecrementStencilOp; + exports.DecrementWrapStencilOp = DecrementWrapStencilOp; + exports.DefaultLoadingManager = DefaultLoadingManager; + exports.DepthFormat = DepthFormat2; + exports.DepthStencilFormat = DepthStencilFormat2; + exports.DepthTexture = DepthTexture2; + exports.DirectionalLight = DirectionalLight; + exports.DirectionalLightHelper = DirectionalLightHelper; + exports.DiscreteInterpolant = DiscreteInterpolant2; + exports.DodecahedronBufferGeometry = DodecahedronGeometry; + exports.DodecahedronGeometry = DodecahedronGeometry; + exports.DoubleSide = DoubleSide2; + exports.DstAlphaFactor = DstAlphaFactor2; + exports.DstColorFactor = DstColorFactor2; + exports.DynamicCopyUsage = DynamicCopyUsage; + exports.DynamicDrawUsage = DynamicDrawUsage; + exports.DynamicReadUsage = DynamicReadUsage; + exports.EdgesGeometry = EdgesGeometry; + exports.EllipseCurve = EllipseCurve; + exports.EqualDepth = EqualDepth2; + exports.EqualStencilFunc = EqualStencilFunc; + exports.EquirectangularReflectionMapping = EquirectangularReflectionMapping2; + exports.EquirectangularRefractionMapping = EquirectangularRefractionMapping2; + exports.Euler = Euler2; + exports.EventDispatcher = EventDispatcher2; + exports.ExtrudeBufferGeometry = ExtrudeGeometry; + exports.ExtrudeGeometry = ExtrudeGeometry; + exports.FileLoader = FileLoader; + exports.FlatShading = FlatShading2; + exports.Float16BufferAttribute = Float16BufferAttribute; + exports.Float32BufferAttribute = Float32BufferAttribute2; + exports.Float64BufferAttribute = Float64BufferAttribute; + exports.FloatType = FloatType2; + exports.Fog = Fog; + exports.FogExp2 = FogExp2; + exports.Font = Font; + exports.FontLoader = FontLoader; + exports.FramebufferTexture = FramebufferTexture; + exports.FrontSide = FrontSide2; + exports.Frustum = Frustum2; + exports.GLBufferAttribute = GLBufferAttribute; + exports.GLSL1 = GLSL1; + exports.GLSL3 = GLSL32; + exports.GreaterDepth = GreaterDepth2; + exports.GreaterEqualDepth = GreaterEqualDepth2; + exports.GreaterEqualStencilFunc = GreaterEqualStencilFunc; + exports.GreaterStencilFunc = GreaterStencilFunc; + exports.GridHelper = GridHelper; + exports.Group = Group2; + exports.HalfFloatType = HalfFloatType2; + exports.HemisphereLight = HemisphereLight; + exports.HemisphereLightHelper = HemisphereLightHelper; + exports.HemisphereLightProbe = HemisphereLightProbe; + exports.IcosahedronBufferGeometry = IcosahedronGeometry; + exports.IcosahedronGeometry = IcosahedronGeometry; + exports.ImageBitmapLoader = ImageBitmapLoader; + exports.ImageLoader = ImageLoader; + exports.ImageUtils = ImageUtils2; + exports.ImmediateRenderObject = ImmediateRenderObject; + exports.IncrementStencilOp = IncrementStencilOp; + exports.IncrementWrapStencilOp = IncrementWrapStencilOp; + exports.InstancedBufferAttribute = InstancedBufferAttribute; + exports.InstancedBufferGeometry = InstancedBufferGeometry; + exports.InstancedInterleavedBuffer = InstancedInterleavedBuffer; + exports.InstancedMesh = InstancedMesh; + exports.Int16BufferAttribute = Int16BufferAttribute; + exports.Int32BufferAttribute = Int32BufferAttribute; + exports.Int8BufferAttribute = Int8BufferAttribute; + exports.IntType = IntType2; + exports.InterleavedBuffer = InterleavedBuffer; + exports.InterleavedBufferAttribute = InterleavedBufferAttribute; + exports.Interpolant = Interpolant2; + exports.InterpolateDiscrete = InterpolateDiscrete2; + exports.InterpolateLinear = InterpolateLinear2; + exports.InterpolateSmooth = InterpolateSmooth2; + exports.InvertStencilOp = InvertStencilOp; + exports.KeepStencilOp = KeepStencilOp2; + exports.KeyframeTrack = KeyframeTrack2; + exports.LOD = LOD; + exports.LatheBufferGeometry = LatheGeometry; + exports.LatheGeometry = LatheGeometry; + exports.Layers = Layers2; + exports.LessDepth = LessDepth2; + exports.LessEqualDepth = LessEqualDepth2; + exports.LessEqualStencilFunc = LessEqualStencilFunc; + exports.LessStencilFunc = LessStencilFunc; + exports.Light = Light; + exports.LightProbe = LightProbe; + exports.Line = Line; + exports.Line3 = Line3; + exports.LineBasicMaterial = LineBasicMaterial; + exports.LineCurve = LineCurve; + exports.LineCurve3 = LineCurve3; + exports.LineDashedMaterial = LineDashedMaterial; + exports.LineLoop = LineLoop; + exports.LineSegments = LineSegments; + exports.LinearEncoding = LinearEncoding2; + exports.LinearFilter = LinearFilter2; + exports.LinearInterpolant = LinearInterpolant2; + exports.LinearMipMapLinearFilter = LinearMipMapLinearFilter; + exports.LinearMipMapNearestFilter = LinearMipMapNearestFilter; + exports.LinearMipmapLinearFilter = LinearMipmapLinearFilter2; + exports.LinearMipmapNearestFilter = LinearMipmapNearestFilter2; + exports.LinearSRGBColorSpace = LinearSRGBColorSpace2; + exports.LinearToneMapping = LinearToneMapping2; + exports.Loader = Loader; + exports.LoaderUtils = LoaderUtils; + exports.LoadingManager = LoadingManager; + exports.LoopOnce = LoopOnce; + exports.LoopPingPong = LoopPingPong; + exports.LoopRepeat = LoopRepeat; + exports.LuminanceAlphaFormat = LuminanceAlphaFormat2; + exports.LuminanceFormat = LuminanceFormat2; + exports.MOUSE = MOUSE2; + exports.Material = Material2; + exports.MaterialLoader = MaterialLoader; + exports.MathUtils = MathUtils; + exports.Matrix3 = Matrix32; + exports.Matrix4 = Matrix42; + exports.MaxEquation = MaxEquation2; + exports.Mesh = Mesh2; + exports.MeshBasicMaterial = MeshBasicMaterial2; + exports.MeshDepthMaterial = MeshDepthMaterial2; + exports.MeshDistanceMaterial = MeshDistanceMaterial2; + exports.MeshLambertMaterial = MeshLambertMaterial; + exports.MeshMatcapMaterial = MeshMatcapMaterial; + exports.MeshNormalMaterial = MeshNormalMaterial; + exports.MeshPhongMaterial = MeshPhongMaterial; + exports.MeshPhysicalMaterial = MeshPhysicalMaterial; + exports.MeshStandardMaterial = MeshStandardMaterial; + exports.MeshToonMaterial = MeshToonMaterial; + exports.MinEquation = MinEquation2; + exports.MirroredRepeatWrapping = MirroredRepeatWrapping2; + exports.MixOperation = MixOperation2; + exports.MultiplyBlending = MultiplyBlending2; + exports.MultiplyOperation = MultiplyOperation2; + exports.NearestFilter = NearestFilter2; + exports.NearestMipMapLinearFilter = NearestMipMapLinearFilter; + exports.NearestMipMapNearestFilter = NearestMipMapNearestFilter; + exports.NearestMipmapLinearFilter = NearestMipmapLinearFilter2; + exports.NearestMipmapNearestFilter = NearestMipmapNearestFilter2; + exports.NeverDepth = NeverDepth2; + exports.NeverStencilFunc = NeverStencilFunc; + exports.NoBlending = NoBlending2; + exports.NoColorSpace = NoColorSpace; + exports.NoToneMapping = NoToneMapping2; + exports.NormalAnimationBlendMode = NormalAnimationBlendMode; + exports.NormalBlending = NormalBlending2; + exports.NotEqualDepth = NotEqualDepth2; + exports.NotEqualStencilFunc = NotEqualStencilFunc; + exports.NumberKeyframeTrack = NumberKeyframeTrack2; + exports.Object3D = Object3D2; + exports.ObjectLoader = ObjectLoader; + exports.ObjectSpaceNormalMap = ObjectSpaceNormalMap2; + exports.OctahedronBufferGeometry = OctahedronGeometry; + exports.OctahedronGeometry = OctahedronGeometry; + exports.OneFactor = OneFactor2; + exports.OneMinusDstAlphaFactor = OneMinusDstAlphaFactor2; + exports.OneMinusDstColorFactor = OneMinusDstColorFactor2; + exports.OneMinusSrcAlphaFactor = OneMinusSrcAlphaFactor2; + exports.OneMinusSrcColorFactor = OneMinusSrcColorFactor2; + exports.OrthographicCamera = OrthographicCamera2; + exports.PCFShadowMap = PCFShadowMap2; + exports.PCFSoftShadowMap = PCFSoftShadowMap2; + exports.PMREMGenerator = PMREMGenerator2; + exports.ParametricGeometry = ParametricGeometry; + exports.Path = Path; + exports.PerspectiveCamera = PerspectiveCamera2; + exports.Plane = Plane2; + exports.PlaneBufferGeometry = PlaneGeometry2; + exports.PlaneGeometry = PlaneGeometry2; + exports.PlaneHelper = PlaneHelper; + exports.PointLight = PointLight; + exports.PointLightHelper = PointLightHelper; + exports.Points = Points; + exports.PointsMaterial = PointsMaterial; + exports.PolarGridHelper = PolarGridHelper; + exports.PolyhedronBufferGeometry = PolyhedronGeometry; + exports.PolyhedronGeometry = PolyhedronGeometry; + exports.PositionalAudio = PositionalAudio; + exports.PropertyBinding = PropertyBinding2; + exports.PropertyMixer = PropertyMixer; + exports.QuadraticBezierCurve = QuadraticBezierCurve; + exports.QuadraticBezierCurve3 = QuadraticBezierCurve3; + exports.Quaternion = Quaternion2; + exports.QuaternionKeyframeTrack = QuaternionKeyframeTrack2; + exports.QuaternionLinearInterpolant = QuaternionLinearInterpolant2; + exports.REVISION = REVISION2; + exports.RGBADepthPacking = RGBADepthPacking2; + exports.RGBAFormat = RGBAFormat2; + exports.RGBAIntegerFormat = RGBAIntegerFormat2; + exports.RGBA_ASTC_10x10_Format = RGBA_ASTC_10x10_Format2; + exports.RGBA_ASTC_10x5_Format = RGBA_ASTC_10x5_Format2; + exports.RGBA_ASTC_10x6_Format = RGBA_ASTC_10x6_Format2; + exports.RGBA_ASTC_10x8_Format = RGBA_ASTC_10x8_Format2; + exports.RGBA_ASTC_12x10_Format = RGBA_ASTC_12x10_Format2; + exports.RGBA_ASTC_12x12_Format = RGBA_ASTC_12x12_Format2; + exports.RGBA_ASTC_4x4_Format = RGBA_ASTC_4x4_Format2; + exports.RGBA_ASTC_5x4_Format = RGBA_ASTC_5x4_Format2; + exports.RGBA_ASTC_5x5_Format = RGBA_ASTC_5x5_Format2; + exports.RGBA_ASTC_6x5_Format = RGBA_ASTC_6x5_Format2; + exports.RGBA_ASTC_6x6_Format = RGBA_ASTC_6x6_Format2; + exports.RGBA_ASTC_8x5_Format = RGBA_ASTC_8x5_Format2; + exports.RGBA_ASTC_8x6_Format = RGBA_ASTC_8x6_Format2; + exports.RGBA_ASTC_8x8_Format = RGBA_ASTC_8x8_Format2; + exports.RGBA_BPTC_Format = RGBA_BPTC_Format2; + exports.RGBA_ETC2_EAC_Format = RGBA_ETC2_EAC_Format2; + exports.RGBA_PVRTC_2BPPV1_Format = RGBA_PVRTC_2BPPV1_Format2; + exports.RGBA_PVRTC_4BPPV1_Format = RGBA_PVRTC_4BPPV1_Format2; + exports.RGBA_S3TC_DXT1_Format = RGBA_S3TC_DXT1_Format2; + exports.RGBA_S3TC_DXT3_Format = RGBA_S3TC_DXT3_Format2; + exports.RGBA_S3TC_DXT5_Format = RGBA_S3TC_DXT5_Format2; + exports.RGBFormat = RGBFormat2; + exports.RGB_ETC1_Format = RGB_ETC1_Format2; + exports.RGB_ETC2_Format = RGB_ETC2_Format2; + exports.RGB_PVRTC_2BPPV1_Format = RGB_PVRTC_2BPPV1_Format2; + exports.RGB_PVRTC_4BPPV1_Format = RGB_PVRTC_4BPPV1_Format2; + exports.RGB_S3TC_DXT1_Format = RGB_S3TC_DXT1_Format2; + exports.RGFormat = RGFormat2; + exports.RGIntegerFormat = RGIntegerFormat2; + exports.RawShaderMaterial = RawShaderMaterial; + exports.Ray = Ray2; + exports.Raycaster = Raycaster; + exports.RectAreaLight = RectAreaLight; + exports.RedFormat = RedFormat2; + exports.RedIntegerFormat = RedIntegerFormat2; + exports.ReinhardToneMapping = ReinhardToneMapping2; + exports.RepeatWrapping = RepeatWrapping2; + exports.ReplaceStencilOp = ReplaceStencilOp; + exports.ReverseSubtractEquation = ReverseSubtractEquation2; + exports.RingBufferGeometry = RingGeometry; + exports.RingGeometry = RingGeometry; + exports.SRGBColorSpace = SRGBColorSpace2; + exports.Scene = Scene2; + exports.ShaderChunk = ShaderChunk2; + exports.ShaderLib = ShaderLib2; + exports.ShaderMaterial = ShaderMaterial2; + exports.ShadowMaterial = ShadowMaterial; + exports.Shape = Shape; + exports.ShapeBufferGeometry = ShapeGeometry; + exports.ShapeGeometry = ShapeGeometry; + exports.ShapePath = ShapePath; + exports.ShapeUtils = ShapeUtils; + exports.ShortType = ShortType2; + exports.Skeleton = Skeleton; + exports.SkeletonHelper = SkeletonHelper; + exports.SkinnedMesh = SkinnedMesh; + exports.SmoothShading = SmoothShading; + exports.Source = Source2; + exports.Sphere = Sphere2; + exports.SphereBufferGeometry = SphereGeometry2; + exports.SphereGeometry = SphereGeometry2; + exports.Spherical = Spherical2; + exports.SphericalHarmonics3 = SphericalHarmonics3; + exports.SplineCurve = SplineCurve; + exports.SpotLight = SpotLight; + exports.SpotLightHelper = SpotLightHelper; + exports.Sprite = Sprite; + exports.SpriteMaterial = SpriteMaterial; + exports.SrcAlphaFactor = SrcAlphaFactor2; + exports.SrcAlphaSaturateFactor = SrcAlphaSaturateFactor2; + exports.SrcColorFactor = SrcColorFactor2; + exports.StaticCopyUsage = StaticCopyUsage; + exports.StaticDrawUsage = StaticDrawUsage2; + exports.StaticReadUsage = StaticReadUsage; + exports.StereoCamera = StereoCamera; + exports.StreamCopyUsage = StreamCopyUsage; + exports.StreamDrawUsage = StreamDrawUsage; + exports.StreamReadUsage = StreamReadUsage; + exports.StringKeyframeTrack = StringKeyframeTrack2; + exports.SubtractEquation = SubtractEquation2; + exports.SubtractiveBlending = SubtractiveBlending2; + exports.TOUCH = TOUCH2; + exports.TangentSpaceNormalMap = TangentSpaceNormalMap2; + exports.TetrahedronBufferGeometry = TetrahedronGeometry; + exports.TetrahedronGeometry = TetrahedronGeometry; + exports.TextGeometry = TextGeometry; + exports.Texture = Texture2; + exports.TextureLoader = TextureLoader; + exports.TorusBufferGeometry = TorusGeometry; + exports.TorusGeometry = TorusGeometry; + exports.TorusKnotBufferGeometry = TorusKnotGeometry; + exports.TorusKnotGeometry = TorusKnotGeometry; + exports.Triangle = Triangle2; + exports.TriangleFanDrawMode = TriangleFanDrawMode; + exports.TriangleStripDrawMode = TriangleStripDrawMode; + exports.TrianglesDrawMode = TrianglesDrawMode; + exports.TubeBufferGeometry = TubeGeometry; + exports.TubeGeometry = TubeGeometry; + exports.UVMapping = UVMapping2; + exports.Uint16BufferAttribute = Uint16BufferAttribute2; + exports.Uint32BufferAttribute = Uint32BufferAttribute2; + exports.Uint8BufferAttribute = Uint8BufferAttribute; + exports.Uint8ClampedBufferAttribute = Uint8ClampedBufferAttribute; + exports.Uniform = Uniform; + exports.UniformsGroup = UniformsGroup; + exports.UniformsLib = UniformsLib2; + exports.UniformsUtils = UniformsUtils2; + exports.UnsignedByteType = UnsignedByteType2; + exports.UnsignedInt248Type = UnsignedInt248Type2; + exports.UnsignedIntType = UnsignedIntType2; + exports.UnsignedShort4444Type = UnsignedShort4444Type2; + exports.UnsignedShort5551Type = UnsignedShort5551Type2; + exports.UnsignedShortType = UnsignedShortType2; + exports.VSMShadowMap = VSMShadowMap2; + exports.Vector2 = Vector22; + exports.Vector3 = Vector32; + exports.Vector4 = Vector42; + exports.VectorKeyframeTrack = VectorKeyframeTrack2; + exports.VideoTexture = VideoTexture; + exports.WebGL1Renderer = WebGL1Renderer2; + exports.WebGL3DRenderTarget = WebGL3DRenderTarget; + exports.WebGLArrayRenderTarget = WebGLArrayRenderTarget; + exports.WebGLCubeRenderTarget = WebGLCubeRenderTarget2; + exports.WebGLMultipleRenderTargets = WebGLMultipleRenderTargets; + exports.WebGLMultisampleRenderTarget = WebGLMultisampleRenderTarget; + exports.WebGLRenderTarget = WebGLRenderTarget2; + exports.WebGLRenderer = WebGLRenderer2; + exports.WebGLUtils = WebGLUtils2; + exports.WireframeGeometry = WireframeGeometry; + exports.WrapAroundEnding = WrapAroundEnding2; + exports.ZeroCurvatureEnding = ZeroCurvatureEnding2; + exports.ZeroFactor = ZeroFactor2; + exports.ZeroSlopeEnding = ZeroSlopeEnding2; + exports.ZeroStencilOp = ZeroStencilOp; + exports._SRGBAFormat = _SRGBAFormat2; + exports.sRGBEncoding = sRGBEncoding2; + } + }); + + // node_modules/three.meshline/src/THREE.MeshLine.js + var require_THREE_MeshLine = __commonJS({ + "node_modules/three.meshline/src/THREE.MeshLine.js"(exports, module) { + (function() { + "use strict"; + var root2 = this; + var has_require = typeof __require !== "undefined"; + var THREE = root2.THREE || has_require && require_three(); + if (!THREE) + throw new Error("MeshLine requires three.js"); + class MeshLine2 extends THREE.BufferGeometry { + constructor() { + super(); + this.isMeshLine = true; + this.type = "MeshLine"; + this.positions = []; + this.previous = []; + this.next = []; + this.side = []; + this.width = []; + this.indices_array = []; + this.uvs = []; + this.counters = []; + this._points = []; + this._geom = null; + this.widthCallback = null; + this.matrixWorld = new THREE.Matrix4(); + Object.defineProperties(this, { + geometry: { + enumerable: true, + get: function() { + return this; + } + }, + geom: { + enumerable: true, + get: function() { + return this._geom; + }, + set: function(value) { + this.setGeometry(value, this.widthCallback); + } + }, + points: { + enumerable: true, + get: function() { + return this._points; + }, + set: function(value) { + this.setPoints(value, this.widthCallback); + } + } + }); + } + } + MeshLine2.prototype.setMatrixWorld = function(matrixWorld) { + this.matrixWorld = matrixWorld; + }; + MeshLine2.prototype.setGeometry = function(g, c2) { + this._geometry = g; + this.setPoints(g.getAttribute("position").array, c2); + }; + MeshLine2.prototype.setPoints = function(points, wcb) { + if (!(points instanceof Float32Array) && !(points instanceof Array)) { + console.error("ERROR: The BufferArray of points is not instancied correctly."); + return; + } + this._points = points; + this.widthCallback = wcb; + this.positions = []; + this.counters = []; + if (points.length && points[0] instanceof THREE.Vector3) { + for (var j = 0; j < points.length; j++) { + var p = points[j]; + var c2 = j / points.length; + this.positions.push(p.x, p.y, p.z); + this.positions.push(p.x, p.y, p.z); + this.counters.push(c2); + this.counters.push(c2); + } + } else { + for (var j = 0; j < points.length; j += 3) { + var c2 = j / points.length; + this.positions.push(points[j], points[j + 1], points[j + 2]); + this.positions.push(points[j], points[j + 1], points[j + 2]); + this.counters.push(c2); + this.counters.push(c2); + } + } + this.process(); + }; + function MeshLineRaycast2(raycaster, intersects) { + var inverseMatrix = new THREE.Matrix4(); + var ray = new THREE.Ray(); + var sphere = new THREE.Sphere(); + var interRay = new THREE.Vector3(); + var geometry = this.geometry; + if (!geometry.boundingSphere) + geometry.computeBoundingSphere(); + sphere.copy(geometry.boundingSphere); + sphere.applyMatrix4(this.matrixWorld); + if (raycaster.ray.intersectSphere(sphere, interRay) === false) { + return; + } + inverseMatrix.copy(this.matrixWorld).invert(); + ray.copy(raycaster.ray).applyMatrix4(inverseMatrix); + var vStart = new THREE.Vector3(); + var vEnd = new THREE.Vector3(); + var interSegment = new THREE.Vector3(); + var step = this instanceof THREE.LineSegments ? 2 : 1; + var index2 = geometry.index; + var attributes = geometry.attributes; + if (index2 !== null) { + var indices = index2.array; + var positions = attributes.position.array; + var widths = attributes.width.array; + for (var i = 0, l = indices.length - 1; i < l; i += step) { + var a2 = indices[i]; + var b = indices[i + 1]; + vStart.fromArray(positions, a2 * 3); + vEnd.fromArray(positions, b * 3); + var width = widths[Math.floor(i / 3)] !== void 0 ? widths[Math.floor(i / 3)] : 1; + var precision = raycaster.params.Line.threshold + this.material.lineWidth * width / 2; + var precisionSq = precision * precision; + var distSq = ray.distanceSqToSegment(vStart, vEnd, interRay, interSegment); + if (distSq > precisionSq) + continue; + interRay.applyMatrix4(this.matrixWorld); + var distance = raycaster.ray.origin.distanceTo(interRay); + if (distance < raycaster.near || distance > raycaster.far) + continue; + intersects.push({ + distance, + point: interSegment.clone().applyMatrix4(this.matrixWorld), + index: i, + face: null, + faceIndex: null, + object: this + }); + i = l; + } + } + } + MeshLine2.prototype.raycast = MeshLineRaycast2; + MeshLine2.prototype.compareV3 = function(a2, b) { + var aa = a2 * 6; + var ab = b * 6; + return this.positions[aa] === this.positions[ab] && this.positions[aa + 1] === this.positions[ab + 1] && this.positions[aa + 2] === this.positions[ab + 2]; + }; + MeshLine2.prototype.copyV3 = function(a2) { + var aa = a2 * 6; + return [this.positions[aa], this.positions[aa + 1], this.positions[aa + 2]]; + }; + MeshLine2.prototype.process = function() { + var l = this.positions.length / 6; + this.previous = []; + this.next = []; + this.side = []; + this.width = []; + this.indices_array = []; + this.uvs = []; + var w; + var v; + if (this.compareV3(0, l - 1)) { + v = this.copyV3(l - 2); + } else { + v = this.copyV3(0); + } + this.previous.push(v[0], v[1], v[2]); + this.previous.push(v[0], v[1], v[2]); + for (var j = 0; j < l; j++) { + this.side.push(1); + this.side.push(-1); + if (this.widthCallback) + w = this.widthCallback(j / (l - 1)); + else + w = 1; + this.width.push(w); + this.width.push(w); + this.uvs.push(j / (l - 1), 0); + this.uvs.push(j / (l - 1), 1); + if (j < l - 1) { + v = this.copyV3(j); + this.previous.push(v[0], v[1], v[2]); + this.previous.push(v[0], v[1], v[2]); + var n = j * 2; + this.indices_array.push(n, n + 1, n + 2); + this.indices_array.push(n + 2, n + 1, n + 3); + } + if (j > 0) { + v = this.copyV3(j); + this.next.push(v[0], v[1], v[2]); + this.next.push(v[0], v[1], v[2]); + } + } + if (this.compareV3(l - 1, 0)) { + v = this.copyV3(1); + } else { + v = this.copyV3(l - 1); + } + this.next.push(v[0], v[1], v[2]); + this.next.push(v[0], v[1], v[2]); + if (!this._attributes || this._attributes.position.count !== this.positions.length) { + this._attributes = { + position: new THREE.BufferAttribute(new Float32Array(this.positions), 3), + previous: new THREE.BufferAttribute(new Float32Array(this.previous), 3), + next: new THREE.BufferAttribute(new Float32Array(this.next), 3), + side: new THREE.BufferAttribute(new Float32Array(this.side), 1), + width: new THREE.BufferAttribute(new Float32Array(this.width), 1), + uv: new THREE.BufferAttribute(new Float32Array(this.uvs), 2), + index: new THREE.BufferAttribute(new Uint16Array(this.indices_array), 1), + counters: new THREE.BufferAttribute(new Float32Array(this.counters), 1) + }; + } else { + this._attributes.position.copyArray(new Float32Array(this.positions)); + this._attributes.position.needsUpdate = true; + this._attributes.previous.copyArray(new Float32Array(this.previous)); + this._attributes.previous.needsUpdate = true; + this._attributes.next.copyArray(new Float32Array(this.next)); + this._attributes.next.needsUpdate = true; + this._attributes.side.copyArray(new Float32Array(this.side)); + this._attributes.side.needsUpdate = true; + this._attributes.width.copyArray(new Float32Array(this.width)); + this._attributes.width.needsUpdate = true; + this._attributes.uv.copyArray(new Float32Array(this.uvs)); + this._attributes.uv.needsUpdate = true; + this._attributes.index.copyArray(new Uint16Array(this.indices_array)); + this._attributes.index.needsUpdate = true; + } + this.setAttribute("position", this._attributes.position); + this.setAttribute("previous", this._attributes.previous); + this.setAttribute("next", this._attributes.next); + this.setAttribute("side", this._attributes.side); + this.setAttribute("width", this._attributes.width); + this.setAttribute("uv", this._attributes.uv); + this.setAttribute("counters", this._attributes.counters); + this.setIndex(this._attributes.index); + this.computeBoundingSphere(); + this.computeBoundingBox(); + }; + function memcpy(src, srcOffset, dst, dstOffset, length) { + var i; + src = src.subarray || src.slice ? src : src.buffer; + dst = dst.subarray || dst.slice ? dst : dst.buffer; + src = srcOffset ? src.subarray ? src.subarray(srcOffset, length && srcOffset + length) : src.slice(srcOffset, length && srcOffset + length) : src; + if (dst.set) { + dst.set(src, dstOffset); + } else { + for (i = 0; i < src.length; i++) { + dst[i + dstOffset] = src[i]; + } + } + return dst; + } + MeshLine2.prototype.advance = function(position) { + var positions = this._attributes.position.array; + var previous = this._attributes.previous.array; + var next = this._attributes.next.array; + var l = positions.length; + memcpy(positions, 0, previous, 0, l); + memcpy(positions, 6, positions, 0, l - 6); + positions[l - 6] = position.x; + positions[l - 5] = position.y; + positions[l - 4] = position.z; + positions[l - 3] = position.x; + positions[l - 2] = position.y; + positions[l - 1] = position.z; + memcpy(positions, 6, next, 0, l - 6); + next[l - 6] = position.x; + next[l - 5] = position.y; + next[l - 4] = position.z; + next[l - 3] = position.x; + next[l - 2] = position.y; + next[l - 1] = position.z; + this._attributes.position.needsUpdate = true; + this._attributes.previous.needsUpdate = true; + this._attributes.next.needsUpdate = true; + }; + THREE.ShaderChunk["meshline_vert"] = [ + "", + THREE.ShaderChunk.logdepthbuf_pars_vertex, + THREE.ShaderChunk.fog_pars_vertex, + "", + "attribute vec3 previous;", + "attribute vec3 next;", + "attribute float side;", + "attribute float width;", + "attribute float counters;", + "", + "uniform vec2 resolution;", + "uniform float lineWidth;", + "uniform vec3 color;", + "uniform float opacity;", + "uniform float sizeAttenuation;", + "", + "varying vec2 vUV;", + "varying vec4 vColor;", + "varying float vCounters;", + "", + "vec2 fix( vec4 i, float aspect ) {", + "", + " vec2 res = i.xy / i.w;", + " res.x *= aspect;", + " vCounters = counters;", + " return res;", + "", + "}", + "", + "void main() {", + "", + " float aspect = resolution.x / resolution.y;", + "", + " vColor = vec4( color, opacity );", + " vUV = uv;", + "", + " mat4 m = projectionMatrix * modelViewMatrix;", + " vec4 finalPosition = m * vec4( position, 1.0 );", + " vec4 prevPos = m * vec4( previous, 1.0 );", + " vec4 nextPos = m * vec4( next, 1.0 );", + "", + " vec2 currentP = fix( finalPosition, aspect );", + " vec2 prevP = fix( prevPos, aspect );", + " vec2 nextP = fix( nextPos, aspect );", + "", + " float w = lineWidth * width;", + "", + " vec2 dir;", + " if( nextP == currentP ) dir = normalize( currentP - prevP );", + " else if( prevP == currentP ) dir = normalize( nextP - currentP );", + " else {", + " vec2 dir1 = normalize( currentP - prevP );", + " vec2 dir2 = normalize( nextP - currentP );", + " dir = normalize( dir1 + dir2 );", + "", + " vec2 perp = vec2( -dir1.y, dir1.x );", + " vec2 miter = vec2( -dir.y, dir.x );", + " //w = clamp( w / dot( miter, perp ), 0., 4. * lineWidth * width );", + "", + " }", + "", + " //vec2 normal = ( cross( vec3( dir, 0. ), vec3( 0., 0., 1. ) ) ).xy;", + " vec4 normal = vec4( -dir.y, dir.x, 0., 1. );", + " normal.xy *= .5 * w;", + " normal *= projectionMatrix;", + " if( sizeAttenuation == 0. ) {", + " normal.xy *= finalPosition.w;", + " normal.xy /= ( vec4( resolution, 0., 1. ) * projectionMatrix ).xy;", + " }", + "", + " finalPosition.xy += normal.xy * side;", + "", + " gl_Position = finalPosition;", + "", + THREE.ShaderChunk.logdepthbuf_vertex, + THREE.ShaderChunk.fog_vertex && " vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + THREE.ShaderChunk.fog_vertex, + "}" + ].join("\n"); + THREE.ShaderChunk["meshline_frag"] = [ + "", + THREE.ShaderChunk.fog_pars_fragment, + THREE.ShaderChunk.logdepthbuf_pars_fragment, + "", + "uniform sampler2D map;", + "uniform sampler2D alphaMap;", + "uniform float useMap;", + "uniform float useAlphaMap;", + "uniform float useDash;", + "uniform float dashArray;", + "uniform float dashOffset;", + "uniform float dashRatio;", + "uniform float visibility;", + "uniform float alphaTest;", + "uniform vec2 repeat;", + "", + "varying vec2 vUV;", + "varying vec4 vColor;", + "varying float vCounters;", + "", + "void main() {", + "", + THREE.ShaderChunk.logdepthbuf_fragment, + "", + " vec4 c = vColor;", + " if( useMap == 1. ) c *= texture2D( map, vUV * repeat );", + " if( useAlphaMap == 1. ) c.a *= texture2D( alphaMap, vUV * repeat ).a;", + " if( c.a < alphaTest ) discard;", + " if( useDash == 1. ){", + " c.a *= ceil(mod(vCounters + dashOffset, dashArray) - (dashArray * dashRatio));", + " }", + " gl_FragColor = c;", + " gl_FragColor.a *= step(vCounters, visibility);", + "", + THREE.ShaderChunk.fog_fragment, + "}" + ].join("\n"); + class MeshLineMaterial2 extends THREE.ShaderMaterial { + constructor(parameters) { + super({ + uniforms: Object.assign({}, THREE.UniformsLib.fog, { + lineWidth: { value: 1 }, + map: { value: null }, + useMap: { value: 0 }, + alphaMap: { value: null }, + useAlphaMap: { value: 0 }, + color: { value: new THREE.Color(16777215) }, + opacity: { value: 1 }, + resolution: { value: new THREE.Vector2(1, 1) }, + sizeAttenuation: { value: 1 }, + dashArray: { value: 0 }, + dashOffset: { value: 0 }, + dashRatio: { value: 0.5 }, + useDash: { value: 0 }, + visibility: { value: 1 }, + alphaTest: { value: 0 }, + repeat: { value: new THREE.Vector2(1, 1) } + }), + vertexShader: THREE.ShaderChunk.meshline_vert, + fragmentShader: THREE.ShaderChunk.meshline_frag + }); + this.isMeshLineMaterial = true; + this.type = "MeshLineMaterial"; + Object.defineProperties(this, { + lineWidth: { + enumerable: true, + get: function() { + return this.uniforms.lineWidth.value; + }, + set: function(value) { + this.uniforms.lineWidth.value = value; + } + }, + map: { + enumerable: true, + get: function() { + return this.uniforms.map.value; + }, + set: function(value) { + this.uniforms.map.value = value; + } + }, + useMap: { + enumerable: true, + get: function() { + return this.uniforms.useMap.value; + }, + set: function(value) { + this.uniforms.useMap.value = value; + } + }, + alphaMap: { + enumerable: true, + get: function() { + return this.uniforms.alphaMap.value; + }, + set: function(value) { + this.uniforms.alphaMap.value = value; + } + }, + useAlphaMap: { + enumerable: true, + get: function() { + return this.uniforms.useAlphaMap.value; + }, + set: function(value) { + this.uniforms.useAlphaMap.value = value; + } + }, + color: { + enumerable: true, + get: function() { + return this.uniforms.color.value; + }, + set: function(value) { + this.uniforms.color.value = value; + } + }, + opacity: { + enumerable: true, + get: function() { + return this.uniforms.opacity.value; + }, + set: function(value) { + this.uniforms.opacity.value = value; + } + }, + resolution: { + enumerable: true, + get: function() { + return this.uniforms.resolution.value; + }, + set: function(value) { + this.uniforms.resolution.value.copy(value); + } + }, + sizeAttenuation: { + enumerable: true, + get: function() { + return this.uniforms.sizeAttenuation.value; + }, + set: function(value) { + this.uniforms.sizeAttenuation.value = value; + } + }, + dashArray: { + enumerable: true, + get: function() { + return this.uniforms.dashArray.value; + }, + set: function(value) { + this.uniforms.dashArray.value = value; + this.useDash = value !== 0 ? 1 : 0; + } + }, + dashOffset: { + enumerable: true, + get: function() { + return this.uniforms.dashOffset.value; + }, + set: function(value) { + this.uniforms.dashOffset.value = value; + } + }, + dashRatio: { + enumerable: true, + get: function() { + return this.uniforms.dashRatio.value; + }, + set: function(value) { + this.uniforms.dashRatio.value = value; + } + }, + useDash: { + enumerable: true, + get: function() { + return this.uniforms.useDash.value; + }, + set: function(value) { + this.uniforms.useDash.value = value; + } + }, + visibility: { + enumerable: true, + get: function() { + return this.uniforms.visibility.value; + }, + set: function(value) { + this.uniforms.visibility.value = value; + } + }, + alphaTest: { + enumerable: true, + get: function() { + return this.uniforms.alphaTest.value; + }, + set: function(value) { + this.uniforms.alphaTest.value = value; + } + }, + repeat: { + enumerable: true, + get: function() { + return this.uniforms.repeat.value; + }, + set: function(value) { + this.uniforms.repeat.value.copy(value); + } + } + }); + this.setValues(parameters); + } + } + MeshLineMaterial2.prototype.copy = function(source) { + THREE.ShaderMaterial.prototype.copy.call(this, source); + this.lineWidth = source.lineWidth; + this.map = source.map; + this.useMap = source.useMap; + this.alphaMap = source.alphaMap; + this.useAlphaMap = source.useAlphaMap; + this.color.copy(source.color); + this.opacity = source.opacity; + this.resolution.copy(source.resolution); + this.sizeAttenuation = source.sizeAttenuation; + this.dashArray.copy(source.dashArray); + this.dashOffset.copy(source.dashOffset); + this.dashRatio.copy(source.dashRatio); + this.useDash = source.useDash; + this.visibility = source.visibility; + this.alphaTest = source.alphaTest; + this.repeat.copy(source.repeat); + return this; + }; + if (typeof exports !== "undefined") { + if (typeof module !== "undefined" && module.exports) { + exports = module.exports = { + MeshLine: MeshLine2, + MeshLineMaterial: MeshLineMaterial2, + MeshLineRaycast: MeshLineRaycast2 + }; + } + exports.MeshLine = MeshLine2; + exports.MeshLineMaterial = MeshLineMaterial2; + exports.MeshLineRaycast = MeshLineRaycast2; + } else { + root2.MeshLine = MeshLine2; + root2.MeshLineMaterial = MeshLineMaterial2; + root2.MeshLineRaycast = MeshLineRaycast2; + } + }).call(exports); + } + }); + + // federjs/FederIndex/parser/FileReader.ts + var FileReader = class { + constructor(arrayBuffer) { + this.data = arrayBuffer; + this.dataview = new DataView(arrayBuffer); + this.p = 0; + } + get isEmpty() { + return this.p >= this.data.byteLength; + } + readInt8() { + const int8 = this.dataview.getInt8(this.p); + this.p += 1; + return int8; + } + readUint8() { + const uint8 = this.dataview.getUint8(this.p); + this.p += 1; + return uint8; + } + readBool() { + const int8 = this.readInt8(); + return Boolean(int8); + } + readUint16() { + const uint16 = this.dataview.getUint16(this.p, true); + this.p += 2; + return uint16; + } + readInt32() { + const int32 = this.dataview.getInt32(this.p, true); + this.p += 4; + return int32; + } + readUint32() { + const uint32 = this.dataview.getUint32(this.p, true); + this.p += 4; + return uint32; + } + readUint64() { + const left = this.readUint32(); + const right = this.readUint32(); + const int64 = left + Math.pow(2, 32) * right; + if (!Number.isSafeInteger(int64)) + console.warn(int64, "Exceeds MAX_SAFE_INTEGER. Precision may be lost"); + return int64; + } + readFloat64() { + const float64 = this.dataview.getFloat64(this.p, true); + this.p += 8; + return float64; + } + readDouble() { + return this.readFloat64(); + } + readUint32Array(n) { + const res = Array(n).fill(0).map((_) => this.readUint32()); + return res; + } + readFloat32Array(n) { + const res = new Float32Array(this.data.slice(this.p, this.p + n * 4)); + this.p += n * 4; + return res; + } + readUint64Array(n) { + const res = Array(n).fill(0).map((_) => this.readUint64()); + return res; + } + }; + + // federjs/FederIndex/parser/hnswlibParser/HNSWlibFileReader.ts + var HNSWlibFileReader = class extends FileReader { + constructor(arrayBuffer) { + super(arrayBuffer); + } + readIsDeleted() { + return this.readUint8(); + } + readIsReused() { + return this.readUint8(); + } + readLevelOCount() { + return this.readUint16(); + } + }; + + // federjs/FederIndex/parser/hnswlibParser/index.ts + var hnswlibIndexParser = (arrayBuffer) => { + const reader = new HNSWlibFileReader(arrayBuffer); + const index2 = {}; + index2.offsetLevel0_ = reader.readUint64(); + index2.max_elements_ = reader.readUint64(); + index2.cur_element_count = reader.readUint64(); + index2.size_data_per_element_ = reader.readUint64(); + index2.label_offset_ = reader.readUint64(); + index2.offsetData_ = reader.readUint64(); + index2.dim = (index2.size_data_per_element_ - index2.offsetData_ - 8) / 4; + index2.maxlevel_ = reader.readUint32(); + index2.enterpoint_node_ = reader.readUint32(); + index2.maxM_ = reader.readUint64(); + index2.maxM0_ = reader.readUint64(); + index2.M = reader.readUint64(); + index2.mult_ = reader.readFloat64(); + index2.ef_construction_ = reader.readUint64(); + index2.size_links_per_element_ = index2.maxM_ * 4 + 4; + index2.size_links_level0_ = index2.maxM0_ * 4 + 4; + index2.revSize_ = 1 / index2.mult_; + index2.ef_ = 10; + read_data_level0_memory_(reader, index2); + const linkListSizes = []; + const linkLists_ = []; + for (let i = 0; i < index2.cur_element_count; i++) { + const linkListSize = reader.readUint32(); + linkListSizes.push(linkListSize); + if (linkListSize === 0) { + linkLists_[i] = []; + } else { + const levelCount = linkListSize / 4 / (index2.maxM_ + 1); + linkLists_[i] = Array(levelCount).fill(0).map((_) => reader.readUint32Array(index2.maxM_ + 1)).map((linkLists) => linkLists.slice(1, linkLists[0] + 1)); + } + } + index2.linkListSizes = linkListSizes; + index2.linkLists_ = linkLists_; + console.assert(reader.isEmpty, "HNSWlib Parser Failed. Not empty when the parser completes."); + return { + indexType: "hnsw" /* hnsw */, + ntotal: index2.cur_element_count, + vectors: index2.vectors, + maxLevel: index2.maxlevel_, + linkLists_level0_count: index2.linkLists_level0_count, + linkLists_level_0: index2.linkLists_level0, + linkLists_levels: index2.linkLists_, + enterPoint: index2.enterpoint_node_, + labels: index2.externalLabel, + isDeleted: index2.isDeleted, + numDeleted: index2.num_deleted_, + M: index2.M, + ef_construction: index2.ef_construction_ + }; + }; + var read_data_level0_memory_ = (reader, index2) => { + const isDeleted = []; + const linkLists_level0_count = []; + const linkLists_level0 = []; + const vectors = []; + const externalLabel = []; + for (let i = 0; i < index2.cur_element_count; i++) { + linkLists_level0_count.push(reader.readLevelOCount()); + isDeleted.push(reader.readIsDeleted()); + reader.readIsReused(); + linkLists_level0.push(reader.readUint32Array(index2.maxM0_)); + vectors.push(reader.readFloat32Array(index2.dim)); + externalLabel.push(reader.readUint64()); + } + index2.isDeleted = isDeleted; + index2.num_deleted_ = isDeleted.reduce((acc, cur) => acc + cur, 0); + index2.linkLists_level0_count = linkLists_level0_count; + index2.linkLists_level0 = linkLists_level0; + index2.vectors = vectors; + index2.externalLabel = externalLabel; + }; + + // federjs/FederIndex/parser/index.ts + var parserMap = { + ["hnswlib" /* hnswlib */]: hnswlibIndexParser + }; + var Parser = class { + constructor(indexType) { + this.parse = parserMap[indexType]; + } + }; + + // federjs/Utils/distFunc.ts + var getDisL2 = (vec1, vec2) => { + return Math.sqrt(vec1.map((num, i) => num - vec2[i]).map((num) => num * num).reduce((a2, c2) => a2 + c2, 0)); + }; + var getDisIR = (vec1, vec2) => { + return vec1.map((num, i) => num * vec2[i]).reduce((acc, cur) => acc + cur, 0); + }; + var getDisFunc = (metricType) => { + if (metricType === 1 /* METRIC_L2 */) { + return getDisL2; + } else if (metricType === 0 /* METRIC_INNER_PRODUCT */) { + return getDisIR; + } + console.warn("[getDisFunc] wrong metric_type, use L2 (default).", metricType); + return getDisL2; + }; + + // federjs/Utils/PriorityQueue.js + var PriorityQueue = class { + constructor(arr = [], key = null) { + if (typeof key == "string") { + this._key = (item) => item[key]; + } else + this._key = key; + this._tree = []; + arr.forEach((d) => this.add(d)); + } + add(item) { + this._tree.push(item); + let id2 = this._tree.length - 1; + while (id2) { + const fatherId = Math.floor((id2 - 1) / 2); + if (this._getValue(id2) >= this._getValue(fatherId)) + break; + else { + this._swap(fatherId, id2); + id2 = fatherId; + } + } + } + get top() { + return this._tree[0]; + } + pop() { + if (this.isEmpty) { + return "empty"; + } + const item = this.top; + if (this._tree.length > 1) { + const lastItem = this._tree.pop(); + let id2 = 0; + this._tree[id2] = lastItem; + while (!this._isLeaf(id2)) { + const curValue = this._getValue(id2); + const leftId = id2 * 2 + 1; + const leftValue = this._getValue(leftId); + const rightId = leftId >= this._tree.length - 1 ? leftId : id2 * 2 + 2; + const rightValue = this._getValue(rightId); + const minValue = Math.min(leftValue, rightValue); + if (curValue <= minValue) + break; + else { + const minId = leftValue < rightValue ? leftId : rightId; + this._swap(minId, id2); + id2 = minId; + } + } + } else { + this._tree = []; + } + return item; + } + get isEmpty() { + return this._tree.length === 0; + } + get size() { + return this._tree.length; + } + get _firstLeaf() { + return Math.floor(this._tree.length / 2); + } + _isLeaf(id2) { + return id2 >= this._firstLeaf; + } + _getValue(id2) { + if (this._key) { + return this._key(this._tree[id2]); + } else { + return this._tree[id2]; + } + } + _swap(id0, id1) { + const tree = this._tree; + [tree[id0], tree[id1]] = [tree[id1], tree[id0]]; + } + }; + var PriorityQueue_default = PriorityQueue; + + // federjs/FederIndex/searchHandler/hnswSearch/searchLevel0.ts + var searchLevelO = ({ + ep_id, + target, + vectors, + ef, + isDeleted, + hasDeleted, + linkLists_level_0, + disfunc, + labels + }) => { + const top_candidates = new PriorityQueue_default([], (d) => d[0]); + const candidates = new PriorityQueue_default([], (d) => d[0]); + const vis_records_level_0 = []; + const visited = /* @__PURE__ */ new Set(); + let lowerBound; + if (!hasDeleted || !isDeleted[ep_id]) { + const dist = disfunc(vectors[ep_id], target); + lowerBound = dist; + top_candidates.add([-dist, ep_id]); + candidates.add([dist, ep_id]); + } else { + lowerBound = 9999999; + candidates.add([lowerBound, ep_id]); + } + visited.add(ep_id); + vis_records_level_0.push([labels[ep_id], labels[ep_id], lowerBound]); + while (!candidates.isEmpty) { + const curNodePair = candidates.top; + if (curNodePair[0] > lowerBound && (top_candidates.size === ef || !hasDeleted)) { + break; + } + candidates.pop(); + const curNodeId = curNodePair[1]; + const curLinks = linkLists_level_0[curNodeId]; + curLinks.forEach((candidateId) => { + if (!visited.has(candidateId)) { + visited.add(candidateId); + const dist = disfunc(vectors[candidateId], target); + vis_records_level_0.push([ + labels[curNodeId], + labels[candidateId], + dist + ]); + if (top_candidates.size < ef || lowerBound > dist) { + candidates.add([dist, candidateId]); + if (!hasDeleted || !isDeleted(candidateId)) { + top_candidates.add([-dist, candidateId]); + } + if (top_candidates.size > ef) { + top_candidates.pop(); + } + if (!top_candidates.isEmpty) { + lowerBound = -top_candidates.top[0]; + } + } + } else { + vis_records_level_0.push([labels[curNodeId], labels[candidateId], -1]); + } + }); + } + return { top_candidates, vis_records_level_0 }; + }; + var searchLevel0_default = searchLevelO; + + // federjs/FederIndex/searchHandler/hnswSearch/index.ts + var hnswlibHNSWSearch = ({ + index: index2, + target, + params = {} + }) => { + const { ef = 10, k = 8, metricType = 1 /* METRIC_L2 */ } = params; + const disfunc = getDisFunc(metricType); + let topkResults = []; + const vis_records_all = []; + const { + enterPoint, + vectors, + maxLevel, + linkLists_levels, + linkLists_level_0, + numDeleted, + labels, + isDeleted + } = index2; + let curNodeId = enterPoint; + let curDist = disfunc(vectors[curNodeId], target); + for (let level = maxLevel; level > 0; level--) { + const vis_records = []; + vis_records.push([labels[curNodeId], labels[curNodeId], curDist]); + let changed = true; + while (changed) { + changed = false; + const curlinks = linkLists_levels[curNodeId][level - 1]; + curlinks.forEach((candidateId) => { + const dist = disfunc(vectors[candidateId], target); + vis_records.push([labels[curNodeId], labels[candidateId], dist]); + if (dist < curDist) { + curDist = dist; + curNodeId = candidateId; + changed = true; + } + }); + } + vis_records_all.push(vis_records); + } + const hasDeleted = numDeleted > 0; + const { top_candidates, vis_records_level_0 } = searchLevel0_default({ + ep_id: curNodeId, + target, + vectors, + ef: Math.max(ef, k), + hasDeleted, + isDeleted, + linkLists_level_0, + disfunc, + labels + }); + vis_records_all.push(vis_records_level_0); + while (top_candidates.size > k) { + top_candidates.pop(); + } + while (top_candidates.size > 0) { + const res = top_candidates.pop(); + topkResults.push({ + id: labels[res[1]], + internalId: res[1], + dis: -res[0] + }); + } + topkResults = topkResults.reverse(); + return { + searchRecords: vis_records_all, + topkResults, + searchParams: { k, ef } + }; + }; + + // federjs/FederIndex/searchHandler/index.ts + var searchFuncMap = { + ["hnsw" /* hnsw */]: hnswlibHNSWSearch + }; + var SearchHandler = class { + constructor(indexType) { + this.search = searchFuncMap[indexType]; + } + }; + + // federjs/FederIndex/index.ts + var FederIndex = class { + constructor(sourceType) { + this.parser = new Parser(sourceType); + } + initByArrayBuffer(arrayBuffer) { + this.index = this.parser.parse(arrayBuffer); + this.indexType = this.index.indexType; + this.searchHandler = new SearchHandler(this.indexType); + } + getIndexType() { + return __async(this, null, function* () { + return this.indexType; + }); + } + getIndexMeta() { + return __async(this, null, function* () { + return ""; + }); + } + getSearchRecords(target, searchParams) { + return __async(this, null, function* () { + return this.searchHandler.search({ + index: this.index, + target, + params: searchParams + }); + }); + } + }; + + // federjs/FederLayout/visDataHandler/hnsw/search/utils.ts + var connection = "---"; + var getLinkId = (sourceId, targetId) => `${sourceId}${connection}${targetId}`; + var parseLinkId = (linkId) => linkId.split(connection).map((d) => +d); + var getLinkIdWithLevel = (sourceId, targetId, level) => `link-${level}-${sourceId}-${targetId}`; + var getNodeIdWithLevel = (nodeId, level) => `node-${level}-${nodeId}`; + var getEntryLinkIdWithLevel = (nodeId, level) => `inter-level-${level}-${nodeId}`; + var deDupLink = (links, source = "source", target = "target") => { + const linkStringSet = /* @__PURE__ */ new Set(); + return links.filter((link) => { + const linkString = `${link[source]}---${link[target]}`; + const linkStringReverse = `${link[target]}---${link[source]}`; + if (linkStringSet.has(linkString) || linkStringSet.has(linkStringReverse)) { + return false; + } else { + linkStringSet.add(linkString); + return true; + } + }); + }; + + // federjs/FederLayout/visDataHandler/hnsw/search/parseVisRecords.ts + var parseVisRecords = ({ + topkResults, + searchRecords + }) => { + const visData = []; + const numLevels = searchRecords.length; + let fineIds = topkResults.map((d) => d.id); + let entryId = -1; + for (let i = numLevels - 1; i >= 0; i--) { + const level = numLevels - 1 - i; + if (level > 0) { + fineIds = [entryId]; + } + const visRecordsLevel = searchRecords[i]; + const id2nodeType = {}; + const linkId2linkType = {}; + const updateNodeType = (nodeId, type2) => { + if (id2nodeType[nodeId]) { + id2nodeType[nodeId] = Math.max(id2nodeType[nodeId], type2); + } else { + id2nodeType[nodeId] = type2; + } + }; + const updateLinkType = (sourceId, targetId, type2) => { + const linkId = getLinkId(sourceId, targetId); + if (linkId2linkType[linkId]) { + linkId2linkType[linkId] = Math.max(linkId2linkType[linkId], type2); + } else { + linkId2linkType[linkId] = type2; + } + }; + const id2dist = {}; + const sourceMap = {}; + visRecordsLevel.forEach((record) => { + const [sourceId, targetId, dist] = record; + if (sourceId === targetId) { + entryId = targetId; + id2dist[targetId] = dist; + } else { + updateNodeType(sourceId, 2 /* Candidate */); + updateNodeType(targetId, 1 /* Coarse */); + if (id2dist[targetId] >= 0) { + updateLinkType(sourceId, targetId, 1 /* Visited */); + } else { + id2dist[targetId] = dist; + updateLinkType(sourceId, targetId, 2 /* Extended */); + sourceMap[targetId] = sourceId; + if (level === 0) { + const preSourceId = sourceMap[sourceId]; + if (preSourceId >= 0) { + updateLinkType(preSourceId, sourceId, 3 /* Searched */); + } + } + } + } + }); + fineIds.forEach((fineId) => { + updateNodeType(fineId, 3 /* Fine */); + let t = fineId; + while (t in sourceMap) { + let s = sourceMap[t]; + updateLinkType(s, t, 4 /* Fine */); + t = s; + } + }); + const nodes = Object.keys(id2nodeType).map((id2) => ({ + id: `${id2}`, + type: id2nodeType[id2], + dist: id2dist[id2] + })); + const links = Object.keys(linkId2linkType).map((linkId) => { + const [source, target] = parseLinkId(linkId); + return { + source: `${source}`, + target: `${target}`, + type: linkId2linkType[linkId] + }; + }); + const visDataLevel = { + entryIds: [`${entryId}`], + fineIds: fineIds.map((id2) => `${id2}`), + links, + nodes + }; + visData.push(visDataLevel); + } + return visData; + }; + var parseVisRecords_default = parseVisRecords; + + // node_modules/d3-array/src/ascending.js + function ascending(a2, b) { + return a2 == null || b == null ? NaN : a2 < b ? -1 : a2 > b ? 1 : a2 >= b ? 0 : NaN; + } + + // node_modules/d3-array/src/descending.js + function descending(a2, b) { + return a2 == null || b == null ? NaN : b < a2 ? -1 : b > a2 ? 1 : b >= a2 ? 0 : NaN; + } + + // node_modules/d3-array/src/bisector.js + function bisector(f) { + let compare1, compare2, delta; + if (f.length !== 2) { + compare1 = ascending; + compare2 = (d, x2) => ascending(f(d), x2); + delta = (d, x2) => f(d) - x2; + } else { + compare1 = f === ascending || f === descending ? f : zero; + compare2 = f; + delta = f; + } + function left(a2, x2, lo = 0, hi = a2.length) { + if (lo < hi) { + if (compare1(x2, x2) !== 0) + return hi; + do { + const mid = lo + hi >>> 1; + if (compare2(a2[mid], x2) < 0) + lo = mid + 1; + else + hi = mid; + } while (lo < hi); + } + return lo; + } + function right(a2, x2, lo = 0, hi = a2.length) { + if (lo < hi) { + if (compare1(x2, x2) !== 0) + return hi; + do { + const mid = lo + hi >>> 1; + if (compare2(a2[mid], x2) <= 0) + lo = mid + 1; + else + hi = mid; + } while (lo < hi); + } + return lo; + } + function center(a2, x2, lo = 0, hi = a2.length) { + const i = left(a2, x2, lo, hi - 1); + return i > lo && delta(a2[i - 1], x2) > -delta(a2[i], x2) ? i - 1 : i; + } + return { left, center, right }; + } + function zero() { + return 0; + } + + // node_modules/d3-array/src/number.js + function number(x2) { + return x2 === null ? NaN : +x2; + } + + // node_modules/d3-array/src/bisect.js + var ascendingBisect = bisector(ascending); + var bisectRight = ascendingBisect.right; + var bisectLeft = ascendingBisect.left; + var bisectCenter = bisector(number).center; + var bisect_default = bisectRight; + + // node_modules/d3-array/src/extent.js + function extent(values, valueof) { + let min2; + let max2; + if (valueof === void 0) { + for (const value of values) { + if (value != null) { + if (min2 === void 0) { + if (value >= value) + min2 = max2 = value; + } else { + if (min2 > value) + min2 = value; + if (max2 < value) + max2 = value; + } + } + } + } else { + let index2 = -1; + for (let value of values) { + if ((value = valueof(value, ++index2, values)) != null) { + if (min2 === void 0) { + if (value >= value) + min2 = max2 = value; + } else { + if (min2 > value) + min2 = value; + if (max2 < value) + max2 = value; + } + } + } + } + return [min2, max2]; + } + + // node_modules/d3-array/src/ticks.js + var e10 = Math.sqrt(50); + var e5 = Math.sqrt(10); + var e2 = Math.sqrt(2); + function ticks(start2, stop, count) { + var reverse, i = -1, n, ticks2, step; + stop = +stop, start2 = +start2, count = +count; + if (start2 === stop && count > 0) + return [start2]; + if (reverse = stop < start2) + n = start2, start2 = stop, stop = n; + if ((step = tickIncrement(start2, stop, count)) === 0 || !isFinite(step)) + return []; + if (step > 0) { + let r0 = Math.round(start2 / step), r1 = Math.round(stop / step); + if (r0 * step < start2) + ++r0; + if (r1 * step > stop) + --r1; + ticks2 = new Array(n = r1 - r0 + 1); + while (++i < n) + ticks2[i] = (r0 + i) * step; + } else { + step = -step; + let r0 = Math.round(start2 * step), r1 = Math.round(stop * step); + if (r0 / step < start2) + ++r0; + if (r1 / step > stop) + --r1; + ticks2 = new Array(n = r1 - r0 + 1); + while (++i < n) + ticks2[i] = (r0 + i) / step; + } + if (reverse) + ticks2.reverse(); + return ticks2; + } + function tickIncrement(start2, stop, count) { + var step = (stop - start2) / Math.max(0, count), power = Math.floor(Math.log(step) / Math.LN10), error = step / Math.pow(10, power); + return power >= 0 ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); + } + function tickStep(start2, stop, count) { + var step0 = Math.abs(stop - start2) / Math.max(0, count), step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), error = step0 / step1; + if (error >= e10) + step1 *= 10; + else if (error >= e5) + step1 *= 5; + else if (error >= e2) + step1 *= 2; + return stop < start2 ? -step1 : step1; + } + + // node_modules/d3-array/src/range.js + function range(start2, stop, step) { + start2 = +start2, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start2, start2 = 0, 1) : n < 3 ? 1 : +step; + var i = -1, n = Math.max(0, Math.ceil((stop - start2) / step)) | 0, range2 = new Array(n); + while (++i < n) { + range2[i] = start2 + i * step; + } + return range2; + } + + // node_modules/d3-dispatch/src/dispatch.js + var noop = { value: () => { + } }; + function dispatch() { + for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { + if (!(t = arguments[i] + "") || t in _ || /[\s.]/.test(t)) + throw new Error("illegal type: " + t); + _[t] = []; + } + return new Dispatch(_); + } + function Dispatch(_) { + this._ = _; + } + function parseTypenames(typenames, types) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) + name = t.slice(i + 1), t = t.slice(0, i); + if (t && !types.hasOwnProperty(t)) + throw new Error("unknown type: " + t); + return { type: t, name }; + }); + } + Dispatch.prototype = dispatch.prototype = { + constructor: Dispatch, + on: function(typename, callback) { + var _ = this._, T = parseTypenames(typename + "", _), t, i = -1, n = T.length; + if (arguments.length < 2) { + while (++i < n) + if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) + return t; + return; + } + if (callback != null && typeof callback !== "function") + throw new Error("invalid callback: " + callback); + while (++i < n) { + if (t = (typename = T[i]).type) + _[t] = set(_[t], typename.name, callback); + else if (callback == null) + for (t in _) + _[t] = set(_[t], typename.name, null); + } + return this; + }, + copy: function() { + var copy2 = {}, _ = this._; + for (var t in _) + copy2[t] = _[t].slice(); + return new Dispatch(copy2); + }, + call: function(type2, that) { + if ((n = arguments.length - 2) > 0) + for (var args = new Array(n), i = 0, n, t; i < n; ++i) + args[i] = arguments[i + 2]; + if (!this._.hasOwnProperty(type2)) + throw new Error("unknown type: " + type2); + for (t = this._[type2], i = 0, n = t.length; i < n; ++i) + t[i].value.apply(that, args); + }, + apply: function(type2, that, args) { + if (!this._.hasOwnProperty(type2)) + throw new Error("unknown type: " + type2); + for (var t = this._[type2], i = 0, n = t.length; i < n; ++i) + t[i].value.apply(that, args); + } + }; + function get(type2, name) { + for (var i = 0, n = type2.length, c2; i < n; ++i) { + if ((c2 = type2[i]).name === name) { + return c2.value; + } + } + } + function set(type2, name, callback) { + for (var i = 0, n = type2.length; i < n; ++i) { + if (type2[i].name === name) { + type2[i] = noop, type2 = type2.slice(0, i).concat(type2.slice(i + 1)); + break; + } + } + if (callback != null) + type2.push({ name, value: callback }); + return type2; + } + var dispatch_default = dispatch; + + // node_modules/d3-selection/src/namespaces.js + var xhtml = "http://www.w3.org/1999/xhtml"; + var namespaces_default = { + svg: "http://www.w3.org/2000/svg", + xhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + + // node_modules/d3-selection/src/namespace.js + function namespace_default(name) { + var prefix = name += "", i = prefix.indexOf(":"); + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") + name = name.slice(i + 1); + return namespaces_default.hasOwnProperty(prefix) ? { space: namespaces_default[prefix], local: name } : name; + } + + // node_modules/d3-selection/src/creator.js + function creatorInherit(name) { + return function() { + var document2 = this.ownerDocument, uri = this.namespaceURI; + return uri === xhtml && document2.documentElement.namespaceURI === xhtml ? document2.createElement(name) : document2.createElementNS(uri, name); + }; + } + function creatorFixed(fullname) { + return function() { + return this.ownerDocument.createElementNS(fullname.space, fullname.local); + }; + } + function creator_default(name) { + var fullname = namespace_default(name); + return (fullname.local ? creatorFixed : creatorInherit)(fullname); + } + + // node_modules/d3-selection/src/selector.js + function none() { + } + function selector_default(selector) { + return selector == null ? none : function() { + return this.querySelector(selector); + }; + } + + // node_modules/d3-selection/src/selection/select.js + function select_default(select) { + if (typeof select !== "function") + select = selector_default(select); + for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) + subnode.__data__ = node.__data__; + subgroup[i] = subnode; + } + } + } + return new Selection(subgroups, this._parents); + } + + // node_modules/d3-selection/src/array.js + function array(x2) { + return x2 == null ? [] : Array.isArray(x2) ? x2 : Array.from(x2); + } + + // node_modules/d3-selection/src/selectorAll.js + function empty() { + return []; + } + function selectorAll_default(selector) { + return selector == null ? empty : function() { + return this.querySelectorAll(selector); + }; + } + + // node_modules/d3-selection/src/selection/selectAll.js + function arrayAll(select) { + return function() { + return array(select.apply(this, arguments)); + }; + } + function selectAll_default(select) { + if (typeof select === "function") + select = arrayAll(select); + else + select = selectorAll_default(select); + for (var groups = this._groups, m2 = groups.length, subgroups = [], parents = [], j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + subgroups.push(select.call(node, node.__data__, i, group)); + parents.push(node); + } + } + } + return new Selection(subgroups, parents); + } + + // node_modules/d3-selection/src/matcher.js + function matcher_default(selector) { + return function() { + return this.matches(selector); + }; + } + function childMatcher(selector) { + return function(node) { + return node.matches(selector); + }; + } + + // node_modules/d3-selection/src/selection/selectChild.js + var find = Array.prototype.find; + function childFind(match) { + return function() { + return find.call(this.children, match); + }; + } + function childFirst() { + return this.firstElementChild; + } + function selectChild_default(match) { + return this.select(match == null ? childFirst : childFind(typeof match === "function" ? match : childMatcher(match))); + } + + // node_modules/d3-selection/src/selection/selectChildren.js + var filter = Array.prototype.filter; + function children() { + return Array.from(this.children); + } + function childrenFilter(match) { + return function() { + return filter.call(this.children, match); + }; + } + function selectChildren_default(match) { + return this.selectAll(match == null ? children : childrenFilter(typeof match === "function" ? match : childMatcher(match))); + } + + // node_modules/d3-selection/src/selection/filter.js + function filter_default(match) { + if (typeof match !== "function") + match = matcher_default(match); + for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + return new Selection(subgroups, this._parents); + } + + // node_modules/d3-selection/src/selection/sparse.js + function sparse_default(update) { + return new Array(update.length); + } + + // node_modules/d3-selection/src/selection/enter.js + function enter_default() { + return new Selection(this._enter || this._groups.map(sparse_default), this._parents); + } + function EnterNode(parent, datum2) { + this.ownerDocument = parent.ownerDocument; + this.namespaceURI = parent.namespaceURI; + this._next = null; + this._parent = parent; + this.__data__ = datum2; + } + EnterNode.prototype = { + constructor: EnterNode, + appendChild: function(child) { + return this._parent.insertBefore(child, this._next); + }, + insertBefore: function(child, next) { + return this._parent.insertBefore(child, next); + }, + querySelector: function(selector) { + return this._parent.querySelector(selector); + }, + querySelectorAll: function(selector) { + return this._parent.querySelectorAll(selector); + } + }; + + // node_modules/d3-selection/src/constant.js + function constant_default(x2) { + return function() { + return x2; + }; + } + + // node_modules/d3-selection/src/selection/data.js + function bindIndex(parent, group, enter, update, exit, data) { + var i = 0, node, groupLength = group.length, dataLength = data.length; + for (; i < dataLength; ++i) { + if (node = group[i]) { + node.__data__ = data[i]; + update[i] = node; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + for (; i < groupLength; ++i) { + if (node = group[i]) { + exit[i] = node; + } + } + } + function bindKey(parent, group, enter, update, exit, data, key) { + var i, node, nodeByKeyValue = /* @__PURE__ */ new Map(), groupLength = group.length, dataLength = data.length, keyValues = new Array(groupLength), keyValue; + for (i = 0; i < groupLength; ++i) { + if (node = group[i]) { + keyValues[i] = keyValue = key.call(node, node.__data__, i, group) + ""; + if (nodeByKeyValue.has(keyValue)) { + exit[i] = node; + } else { + nodeByKeyValue.set(keyValue, node); + } + } + } + for (i = 0; i < dataLength; ++i) { + keyValue = key.call(parent, data[i], i, data) + ""; + if (node = nodeByKeyValue.get(keyValue)) { + update[i] = node; + node.__data__ = data[i]; + nodeByKeyValue.delete(keyValue); + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + for (i = 0; i < groupLength; ++i) { + if ((node = group[i]) && nodeByKeyValue.get(keyValues[i]) === node) { + exit[i] = node; + } + } + } + function datum(node) { + return node.__data__; + } + function data_default(value, key) { + if (!arguments.length) + return Array.from(this, datum); + var bind = key ? bindKey : bindIndex, parents = this._parents, groups = this._groups; + if (typeof value !== "function") + value = constant_default(value); + for (var m2 = groups.length, update = new Array(m2), enter = new Array(m2), exit = new Array(m2), j = 0; j < m2; ++j) { + var parent = parents[j], group = groups[j], groupLength = group.length, data = arraylike(value.call(parent, parent && parent.__data__, j, parents)), dataLength = data.length, enterGroup = enter[j] = new Array(dataLength), updateGroup = update[j] = new Array(dataLength), exitGroup = exit[j] = new Array(groupLength); + bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); + for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { + if (previous = enterGroup[i0]) { + if (i0 >= i1) + i1 = i0 + 1; + while (!(next = updateGroup[i1]) && ++i1 < dataLength) + ; + previous._next = next || null; + } + } + } + update = new Selection(update, parents); + update._enter = enter; + update._exit = exit; + return update; + } + function arraylike(data) { + return typeof data === "object" && "length" in data ? data : Array.from(data); + } + + // node_modules/d3-selection/src/selection/exit.js + function exit_default() { + return new Selection(this._exit || this._groups.map(sparse_default), this._parents); + } + + // node_modules/d3-selection/src/selection/join.js + function join_default(onenter, onupdate, onexit) { + var enter = this.enter(), update = this, exit = this.exit(); + if (typeof onenter === "function") { + enter = onenter(enter); + if (enter) + enter = enter.selection(); + } else { + enter = enter.append(onenter + ""); + } + if (onupdate != null) { + update = onupdate(update); + if (update) + update = update.selection(); + } + if (onexit == null) + exit.remove(); + else + onexit(exit); + return enter && update ? enter.merge(update).order() : update; + } + + // node_modules/d3-selection/src/selection/merge.js + function merge_default(context) { + var selection2 = context.selection ? context.selection() : context; + for (var groups0 = this._groups, groups1 = selection2._groups, m0 = groups0.length, m1 = groups1.length, m2 = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m2; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + return new Selection(merges, this._parents); + } + + // node_modules/d3-selection/src/selection/order.js + function order_default() { + for (var groups = this._groups, j = -1, m2 = groups.length; ++j < m2; ) { + for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { + if (node = group[i]) { + if (next && node.compareDocumentPosition(next) ^ 4) + next.parentNode.insertBefore(node, next); + next = node; + } + } + } + return this; + } + + // node_modules/d3-selection/src/selection/sort.js + function sort_default(compare) { + if (!compare) + compare = ascending2; + function compareNode(a2, b) { + return a2 && b ? compare(a2.__data__, b.__data__) : !a2 - !b; + } + for (var groups = this._groups, m2 = groups.length, sortgroups = new Array(m2), j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group[i]) { + sortgroup[i] = node; + } + } + sortgroup.sort(compareNode); + } + return new Selection(sortgroups, this._parents).order(); + } + function ascending2(a2, b) { + return a2 < b ? -1 : a2 > b ? 1 : a2 >= b ? 0 : NaN; + } + + // node_modules/d3-selection/src/selection/call.js + function call_default() { + var callback = arguments[0]; + arguments[0] = this; + callback.apply(null, arguments); + return this; + } + + // node_modules/d3-selection/src/selection/nodes.js + function nodes_default() { + return Array.from(this); + } + + // node_modules/d3-selection/src/selection/node.js + function node_default() { + for (var groups = this._groups, j = 0, m2 = groups.length; j < m2; ++j) { + for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { + var node = group[i]; + if (node) + return node; + } + } + return null; + } + + // node_modules/d3-selection/src/selection/size.js + function size_default() { + let size = 0; + for (const node of this) + ++size; + return size; + } + + // node_modules/d3-selection/src/selection/empty.js + function empty_default() { + return !this.node(); + } + + // node_modules/d3-selection/src/selection/each.js + function each_default(callback) { + for (var groups = this._groups, j = 0, m2 = groups.length; j < m2; ++j) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { + if (node = group[i]) + callback.call(node, node.__data__, i, group); + } + } + return this; + } + + // node_modules/d3-selection/src/selection/attr.js + function attrRemove(name) { + return function() { + this.removeAttribute(name); + }; + } + function attrRemoveNS(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; + } + function attrConstant(name, value) { + return function() { + this.setAttribute(name, value); + }; + } + function attrConstantNS(fullname, value) { + return function() { + this.setAttributeNS(fullname.space, fullname.local, value); + }; + } + function attrFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) + this.removeAttribute(name); + else + this.setAttribute(name, v); + }; + } + function attrFunctionNS(fullname, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) + this.removeAttributeNS(fullname.space, fullname.local); + else + this.setAttributeNS(fullname.space, fullname.local, v); + }; + } + function attr_default(name, value) { + var fullname = namespace_default(name); + if (arguments.length < 2) { + var node = this.node(); + return fullname.local ? node.getAttributeNS(fullname.space, fullname.local) : node.getAttribute(fullname); + } + return this.each((value == null ? fullname.local ? attrRemoveNS : attrRemove : typeof value === "function" ? fullname.local ? attrFunctionNS : attrFunction : fullname.local ? attrConstantNS : attrConstant)(fullname, value)); + } + + // node_modules/d3-selection/src/window.js + function window_default(node) { + return node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView; + } + + // node_modules/d3-selection/src/selection/style.js + function styleRemove(name) { + return function() { + this.style.removeProperty(name); + }; + } + function styleConstant(name, value, priority) { + return function() { + this.style.setProperty(name, value, priority); + }; + } + function styleFunction(name, value, priority) { + return function() { + var v = value.apply(this, arguments); + if (v == null) + this.style.removeProperty(name); + else + this.style.setProperty(name, v, priority); + }; + } + function style_default(name, value, priority) { + return arguments.length > 1 ? this.each((value == null ? styleRemove : typeof value === "function" ? styleFunction : styleConstant)(name, value, priority == null ? "" : priority)) : styleValue(this.node(), name); + } + function styleValue(node, name) { + return node.style.getPropertyValue(name) || window_default(node).getComputedStyle(node, null).getPropertyValue(name); + } + + // node_modules/d3-selection/src/selection/property.js + function propertyRemove(name) { + return function() { + delete this[name]; + }; + } + function propertyConstant(name, value) { + return function() { + this[name] = value; + }; + } + function propertyFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) + delete this[name]; + else + this[name] = v; + }; + } + function property_default(name, value) { + return arguments.length > 1 ? this.each((value == null ? propertyRemove : typeof value === "function" ? propertyFunction : propertyConstant)(name, value)) : this.node()[name]; + } + + // node_modules/d3-selection/src/selection/classed.js + function classArray(string) { + return string.trim().split(/^|\s+/); + } + function classList(node) { + return node.classList || new ClassList(node); + } + function ClassList(node) { + this._node = node; + this._names = classArray(node.getAttribute("class") || ""); + } + ClassList.prototype = { + add: function(name) { + var i = this._names.indexOf(name); + if (i < 0) { + this._names.push(name); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + remove: function(name) { + var i = this._names.indexOf(name); + if (i >= 0) { + this._names.splice(i, 1); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + contains: function(name) { + return this._names.indexOf(name) >= 0; + } + }; + function classedAdd(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) + list.add(names[i]); + } + function classedRemove(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) + list.remove(names[i]); + } + function classedTrue(names) { + return function() { + classedAdd(this, names); + }; + } + function classedFalse(names) { + return function() { + classedRemove(this, names); + }; + } + function classedFunction(names, value) { + return function() { + (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); + }; + } + function classed_default(name, value) { + var names = classArray(name + ""); + if (arguments.length < 2) { + var list = classList(this.node()), i = -1, n = names.length; + while (++i < n) + if (!list.contains(names[i])) + return false; + return true; + } + return this.each((typeof value === "function" ? classedFunction : value ? classedTrue : classedFalse)(names, value)); + } + + // node_modules/d3-selection/src/selection/text.js + function textRemove() { + this.textContent = ""; + } + function textConstant(value) { + return function() { + this.textContent = value; + }; + } + function textFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + }; + } + function text_default(value) { + return arguments.length ? this.each(value == null ? textRemove : (typeof value === "function" ? textFunction : textConstant)(value)) : this.node().textContent; + } + + // node_modules/d3-selection/src/selection/html.js + function htmlRemove() { + this.innerHTML = ""; + } + function htmlConstant(value) { + return function() { + this.innerHTML = value; + }; + } + function htmlFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + }; + } + function html_default(value) { + return arguments.length ? this.each(value == null ? htmlRemove : (typeof value === "function" ? htmlFunction : htmlConstant)(value)) : this.node().innerHTML; + } + + // node_modules/d3-selection/src/selection/raise.js + function raise() { + if (this.nextSibling) + this.parentNode.appendChild(this); + } + function raise_default() { + return this.each(raise); + } + + // node_modules/d3-selection/src/selection/lower.js + function lower() { + if (this.previousSibling) + this.parentNode.insertBefore(this, this.parentNode.firstChild); + } + function lower_default() { + return this.each(lower); + } + + // node_modules/d3-selection/src/selection/append.js + function append_default(name) { + var create2 = typeof name === "function" ? name : creator_default(name); + return this.select(function() { + return this.appendChild(create2.apply(this, arguments)); + }); + } + + // node_modules/d3-selection/src/selection/insert.js + function constantNull() { + return null; + } + function insert_default(name, before) { + var create2 = typeof name === "function" ? name : creator_default(name), select = before == null ? constantNull : typeof before === "function" ? before : selector_default(before); + return this.select(function() { + return this.insertBefore(create2.apply(this, arguments), select.apply(this, arguments) || null); + }); + } + + // node_modules/d3-selection/src/selection/remove.js + function remove() { + var parent = this.parentNode; + if (parent) + parent.removeChild(this); + } + function remove_default() { + return this.each(remove); + } + + // node_modules/d3-selection/src/selection/clone.js + function selection_cloneShallow() { + var clone = this.cloneNode(false), parent = this.parentNode; + return parent ? parent.insertBefore(clone, this.nextSibling) : clone; + } + function selection_cloneDeep() { + var clone = this.cloneNode(true), parent = this.parentNode; + return parent ? parent.insertBefore(clone, this.nextSibling) : clone; + } + function clone_default(deep) { + return this.select(deep ? selection_cloneDeep : selection_cloneShallow); + } + + // node_modules/d3-selection/src/selection/datum.js + function datum_default(value) { + return arguments.length ? this.property("__data__", value) : this.node().__data__; + } + + // node_modules/d3-selection/src/selection/on.js + function contextListener(listener) { + return function(event) { + listener.call(this, event, this.__data__); + }; + } + function parseTypenames2(typenames) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) + name = t.slice(i + 1), t = t.slice(0, i); + return { type: t, name }; + }); + } + function onRemove(typename) { + return function() { + var on = this.__on; + if (!on) + return; + for (var j = 0, i = -1, m2 = on.length, o; j < m2; ++j) { + if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.options); + } else { + on[++i] = o; + } + } + if (++i) + on.length = i; + else + delete this.__on; + }; + } + function onAdd(typename, value, options) { + return function() { + var on = this.__on, o, listener = contextListener(value); + if (on) + for (var j = 0, m2 = on.length; j < m2; ++j) { + if ((o = on[j]).type === typename.type && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.options); + this.addEventListener(o.type, o.listener = listener, o.options = options); + o.value = value; + return; + } + } + this.addEventListener(typename.type, listener, options); + o = { type: typename.type, name: typename.name, value, listener, options }; + if (!on) + this.__on = [o]; + else + on.push(o); + }; + } + function on_default(typename, value, options) { + var typenames = parseTypenames2(typename + ""), i, n = typenames.length, t; + if (arguments.length < 2) { + var on = this.node().__on; + if (on) + for (var j = 0, m2 = on.length, o; j < m2; ++j) { + for (i = 0, o = on[j]; i < n; ++i) { + if ((t = typenames[i]).type === o.type && t.name === o.name) { + return o.value; + } + } + } + return; + } + on = value ? onAdd : onRemove; + for (i = 0; i < n; ++i) + this.each(on(typenames[i], value, options)); + return this; + } + + // node_modules/d3-selection/src/selection/dispatch.js + function dispatchEvent(node, type2, params) { + var window2 = window_default(node), event = window2.CustomEvent; + if (typeof event === "function") { + event = new event(type2, params); + } else { + event = window2.document.createEvent("Event"); + if (params) + event.initEvent(type2, params.bubbles, params.cancelable), event.detail = params.detail; + else + event.initEvent(type2, false, false); + } + node.dispatchEvent(event); + } + function dispatchConstant(type2, params) { + return function() { + return dispatchEvent(this, type2, params); + }; + } + function dispatchFunction(type2, params) { + return function() { + return dispatchEvent(this, type2, params.apply(this, arguments)); + }; + } + function dispatch_default2(type2, params) { + return this.each((typeof params === "function" ? dispatchFunction : dispatchConstant)(type2, params)); + } + + // node_modules/d3-selection/src/selection/iterator.js + function* iterator_default() { + for (var groups = this._groups, j = 0, m2 = groups.length; j < m2; ++j) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { + if (node = group[i]) + yield node; + } + } + } + + // node_modules/d3-selection/src/selection/index.js + var root = [null]; + function Selection(groups, parents) { + this._groups = groups; + this._parents = parents; + } + function selection() { + return new Selection([[document.documentElement]], root); + } + function selection_selection() { + return this; + } + Selection.prototype = selection.prototype = { + constructor: Selection, + select: select_default, + selectAll: selectAll_default, + selectChild: selectChild_default, + selectChildren: selectChildren_default, + filter: filter_default, + data: data_default, + enter: enter_default, + exit: exit_default, + join: join_default, + merge: merge_default, + selection: selection_selection, + order: order_default, + sort: sort_default, + call: call_default, + nodes: nodes_default, + node: node_default, + size: size_default, + empty: empty_default, + each: each_default, + attr: attr_default, + style: style_default, + property: property_default, + classed: classed_default, + text: text_default, + html: html_default, + raise: raise_default, + lower: lower_default, + append: append_default, + insert: insert_default, + remove: remove_default, + clone: clone_default, + datum: datum_default, + on: on_default, + dispatch: dispatch_default2, + [Symbol.iterator]: iterator_default + }; + var selection_default = selection; + + // node_modules/d3-color/src/define.js + function define_default(constructor, factory, prototype) { + constructor.prototype = factory.prototype = prototype; + prototype.constructor = constructor; + } + function extend(parent, definition) { + var prototype = Object.create(parent.prototype); + for (var key in definition) + prototype[key] = definition[key]; + return prototype; + } + + // node_modules/d3-color/src/color.js + function Color() { + } + var darker = 0.7; + var brighter = 1 / darker; + var reI = "\\s*([+-]?\\d+)\\s*"; + var reN = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*"; + var reP = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*"; + var reHex = /^#([0-9a-f]{3,8})$/; + var reRgbInteger = new RegExp(`^rgb\\(${reI},${reI},${reI}\\)$`); + var reRgbPercent = new RegExp(`^rgb\\(${reP},${reP},${reP}\\)$`); + var reRgbaInteger = new RegExp(`^rgba\\(${reI},${reI},${reI},${reN}\\)$`); + var reRgbaPercent = new RegExp(`^rgba\\(${reP},${reP},${reP},${reN}\\)$`); + var reHslPercent = new RegExp(`^hsl\\(${reN},${reP},${reP}\\)$`); + var reHslaPercent = new RegExp(`^hsla\\(${reN},${reP},${reP},${reN}\\)$`); + var named = { + aliceblue: 15792383, + antiquewhite: 16444375, + aqua: 65535, + aquamarine: 8388564, + azure: 15794175, + beige: 16119260, + bisque: 16770244, + black: 0, + blanchedalmond: 16772045, + blue: 255, + blueviolet: 9055202, + brown: 10824234, + burlywood: 14596231, + cadetblue: 6266528, + chartreuse: 8388352, + chocolate: 13789470, + coral: 16744272, + cornflowerblue: 6591981, + cornsilk: 16775388, + crimson: 14423100, + cyan: 65535, + darkblue: 139, + darkcyan: 35723, + darkgoldenrod: 12092939, + darkgray: 11119017, + darkgreen: 25600, + darkgrey: 11119017, + darkkhaki: 12433259, + darkmagenta: 9109643, + darkolivegreen: 5597999, + darkorange: 16747520, + darkorchid: 10040012, + darkred: 9109504, + darksalmon: 15308410, + darkseagreen: 9419919, + darkslateblue: 4734347, + darkslategray: 3100495, + darkslategrey: 3100495, + darkturquoise: 52945, + darkviolet: 9699539, + deeppink: 16716947, + deepskyblue: 49151, + dimgray: 6908265, + dimgrey: 6908265, + dodgerblue: 2003199, + firebrick: 11674146, + floralwhite: 16775920, + forestgreen: 2263842, + fuchsia: 16711935, + gainsboro: 14474460, + ghostwhite: 16316671, + gold: 16766720, + goldenrod: 14329120, + gray: 8421504, + green: 32768, + greenyellow: 11403055, + grey: 8421504, + honeydew: 15794160, + hotpink: 16738740, + indianred: 13458524, + indigo: 4915330, + ivory: 16777200, + khaki: 15787660, + lavender: 15132410, + lavenderblush: 16773365, + lawngreen: 8190976, + lemonchiffon: 16775885, + lightblue: 11393254, + lightcoral: 15761536, + lightcyan: 14745599, + lightgoldenrodyellow: 16448210, + lightgray: 13882323, + lightgreen: 9498256, + lightgrey: 13882323, + lightpink: 16758465, + lightsalmon: 16752762, + lightseagreen: 2142890, + lightskyblue: 8900346, + lightslategray: 7833753, + lightslategrey: 7833753, + lightsteelblue: 11584734, + lightyellow: 16777184, + lime: 65280, + limegreen: 3329330, + linen: 16445670, + magenta: 16711935, + maroon: 8388608, + mediumaquamarine: 6737322, + mediumblue: 205, + mediumorchid: 12211667, + mediumpurple: 9662683, + mediumseagreen: 3978097, + mediumslateblue: 8087790, + mediumspringgreen: 64154, + mediumturquoise: 4772300, + mediumvioletred: 13047173, + midnightblue: 1644912, + mintcream: 16121850, + mistyrose: 16770273, + moccasin: 16770229, + navajowhite: 16768685, + navy: 128, + oldlace: 16643558, + olive: 8421376, + olivedrab: 7048739, + orange: 16753920, + orangered: 16729344, + orchid: 14315734, + palegoldenrod: 15657130, + palegreen: 10025880, + paleturquoise: 11529966, + palevioletred: 14381203, + papayawhip: 16773077, + peachpuff: 16767673, + peru: 13468991, + pink: 16761035, + plum: 14524637, + powderblue: 11591910, + purple: 8388736, + rebeccapurple: 6697881, + red: 16711680, + rosybrown: 12357519, + royalblue: 4286945, + saddlebrown: 9127187, + salmon: 16416882, + sandybrown: 16032864, + seagreen: 3050327, + seashell: 16774638, + sienna: 10506797, + silver: 12632256, + skyblue: 8900331, + slateblue: 6970061, + slategray: 7372944, + slategrey: 7372944, + snow: 16775930, + springgreen: 65407, + steelblue: 4620980, + tan: 13808780, + teal: 32896, + thistle: 14204888, + tomato: 16737095, + turquoise: 4251856, + violet: 15631086, + wheat: 16113331, + white: 16777215, + whitesmoke: 16119285, + yellow: 16776960, + yellowgreen: 10145074 + }; + define_default(Color, color, { + copy(channels) { + return Object.assign(new this.constructor(), this, channels); + }, + displayable() { + return this.rgb().displayable(); + }, + hex: color_formatHex, + formatHex: color_formatHex, + formatHex8: color_formatHex8, + formatHsl: color_formatHsl, + formatRgb: color_formatRgb, + toString: color_formatRgb + }); + function color_formatHex() { + return this.rgb().formatHex(); + } + function color_formatHex8() { + return this.rgb().formatHex8(); + } + function color_formatHsl() { + return hslConvert(this).formatHsl(); + } + function color_formatRgb() { + return this.rgb().formatRgb(); + } + function color(format2) { + var m2, l; + format2 = (format2 + "").trim().toLowerCase(); + return (m2 = reHex.exec(format2)) ? (l = m2[1].length, m2 = parseInt(m2[1], 16), l === 6 ? rgbn(m2) : l === 3 ? new Rgb(m2 >> 8 & 15 | m2 >> 4 & 240, m2 >> 4 & 15 | m2 & 240, (m2 & 15) << 4 | m2 & 15, 1) : l === 8 ? rgba(m2 >> 24 & 255, m2 >> 16 & 255, m2 >> 8 & 255, (m2 & 255) / 255) : l === 4 ? rgba(m2 >> 12 & 15 | m2 >> 8 & 240, m2 >> 8 & 15 | m2 >> 4 & 240, m2 >> 4 & 15 | m2 & 240, ((m2 & 15) << 4 | m2 & 15) / 255) : null) : (m2 = reRgbInteger.exec(format2)) ? new Rgb(m2[1], m2[2], m2[3], 1) : (m2 = reRgbPercent.exec(format2)) ? new Rgb(m2[1] * 255 / 100, m2[2] * 255 / 100, m2[3] * 255 / 100, 1) : (m2 = reRgbaInteger.exec(format2)) ? rgba(m2[1], m2[2], m2[3], m2[4]) : (m2 = reRgbaPercent.exec(format2)) ? rgba(m2[1] * 255 / 100, m2[2] * 255 / 100, m2[3] * 255 / 100, m2[4]) : (m2 = reHslPercent.exec(format2)) ? hsla(m2[1], m2[2] / 100, m2[3] / 100, 1) : (m2 = reHslaPercent.exec(format2)) ? hsla(m2[1], m2[2] / 100, m2[3] / 100, m2[4]) : named.hasOwnProperty(format2) ? rgbn(named[format2]) : format2 === "transparent" ? new Rgb(NaN, NaN, NaN, 0) : null; + } + function rgbn(n) { + return new Rgb(n >> 16 & 255, n >> 8 & 255, n & 255, 1); + } + function rgba(r, g, b, a2) { + if (a2 <= 0) + r = g = b = NaN; + return new Rgb(r, g, b, a2); + } + function rgbConvert(o) { + if (!(o instanceof Color)) + o = color(o); + if (!o) + return new Rgb(); + o = o.rgb(); + return new Rgb(o.r, o.g, o.b, o.opacity); + } + function rgb(r, g, b, opacity) { + return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); + } + function Rgb(r, g, b, opacity) { + this.r = +r; + this.g = +g; + this.b = +b; + this.opacity = +opacity; + } + define_default(Rgb, rgb, extend(Color, { + brighter(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + darker(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + rgb() { + return this; + }, + clamp() { + return new Rgb(clampi(this.r), clampi(this.g), clampi(this.b), clampa(this.opacity)); + }, + displayable() { + return -0.5 <= this.r && this.r < 255.5 && (-0.5 <= this.g && this.g < 255.5) && (-0.5 <= this.b && this.b < 255.5) && (0 <= this.opacity && this.opacity <= 1); + }, + hex: rgb_formatHex, + formatHex: rgb_formatHex, + formatHex8: rgb_formatHex8, + formatRgb: rgb_formatRgb, + toString: rgb_formatRgb + })); + function rgb_formatHex() { + return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`; + } + function rgb_formatHex8() { + return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`; + } + function rgb_formatRgb() { + const a2 = clampa(this.opacity); + return `${a2 === 1 ? "rgb(" : "rgba("}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a2 === 1 ? ")" : `, ${a2})`}`; + } + function clampa(opacity) { + return isNaN(opacity) ? 1 : Math.max(0, Math.min(1, opacity)); + } + function clampi(value) { + return Math.max(0, Math.min(255, Math.round(value) || 0)); + } + function hex(value) { + value = clampi(value); + return (value < 16 ? "0" : "") + value.toString(16); + } + function hsla(h, s, l, a2) { + if (a2 <= 0) + h = s = l = NaN; + else if (l <= 0 || l >= 1) + h = s = NaN; + else if (s <= 0) + h = NaN; + return new Hsl(h, s, l, a2); + } + function hslConvert(o) { + if (o instanceof Hsl) + return new Hsl(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Color)) + o = color(o); + if (!o) + return new Hsl(); + if (o instanceof Hsl) + return o; + o = o.rgb(); + var r = o.r / 255, g = o.g / 255, b = o.b / 255, min2 = Math.min(r, g, b), max2 = Math.max(r, g, b), h = NaN, s = max2 - min2, l = (max2 + min2) / 2; + if (s) { + if (r === max2) + h = (g - b) / s + (g < b) * 6; + else if (g === max2) + h = (b - r) / s + 2; + else + h = (r - g) / s + 4; + s /= l < 0.5 ? max2 + min2 : 2 - max2 - min2; + h *= 60; + } else { + s = l > 0 && l < 1 ? 0 : h; + } + return new Hsl(h, s, l, o.opacity); + } + function hsl(h, s, l, opacity) { + return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); + } + function Hsl(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; + } + define_default(Hsl, hsl, extend(Color, { + brighter(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + darker(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + rgb() { + var h = this.h % 360 + (this.h < 0) * 360, s = isNaN(h) || isNaN(this.s) ? 0 : this.s, l = this.l, m2 = l + (l < 0.5 ? l : 1 - l) * s, m1 = 2 * l - m2; + return new Rgb(hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb(h, m1, m2), hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity); + }, + clamp() { + return new Hsl(clamph(this.h), clampt(this.s), clampt(this.l), clampa(this.opacity)); + }, + displayable() { + return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && (0 <= this.l && this.l <= 1) && (0 <= this.opacity && this.opacity <= 1); + }, + formatHsl() { + const a2 = clampa(this.opacity); + return `${a2 === 1 ? "hsl(" : "hsla("}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a2 === 1 ? ")" : `, ${a2})`}`; + } + })); + function clamph(value) { + value = (value || 0) % 360; + return value < 0 ? value + 360 : value; + } + function clampt(value) { + return Math.max(0, Math.min(1, value || 0)); + } + function hsl2rgb(h, m1, m2) { + return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255; + } + + // node_modules/d3-interpolate/src/basis.js + function basis(t1, v0, v1, v2, v3) { + var t2 = t1 * t1, t3 = t2 * t1; + return ((1 - 3 * t1 + 3 * t2 - t3) * v0 + (4 - 6 * t2 + 3 * t3) * v1 + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 + t3 * v3) / 6; + } + function basis_default(values) { + var n = values.length - 1; + return function(t) { + var i = t <= 0 ? t = 0 : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), v1 = values[i], v2 = values[i + 1], v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; + } + + // node_modules/d3-interpolate/src/basisClosed.js + function basisClosed_default(values) { + var n = values.length; + return function(t) { + var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), v0 = values[(i + n - 1) % n], v1 = values[i % n], v2 = values[(i + 1) % n], v3 = values[(i + 2) % n]; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; + } + + // node_modules/d3-interpolate/src/constant.js + var constant_default2 = (x2) => () => x2; + + // node_modules/d3-interpolate/src/color.js + function linear(a2, d) { + return function(t) { + return a2 + t * d; + }; + } + function exponential(a2, b, y2) { + return a2 = Math.pow(a2, y2), b = Math.pow(b, y2) - a2, y2 = 1 / y2, function(t) { + return Math.pow(a2 + t * b, y2); + }; + } + function gamma(y2) { + return (y2 = +y2) === 1 ? nogamma : function(a2, b) { + return b - a2 ? exponential(a2, b, y2) : constant_default2(isNaN(a2) ? b : a2); + }; + } + function nogamma(a2, b) { + var d = b - a2; + return d ? linear(a2, d) : constant_default2(isNaN(a2) ? b : a2); + } + + // node_modules/d3-interpolate/src/rgb.js + var rgb_default = function rgbGamma(y2) { + var color2 = gamma(y2); + function rgb2(start2, end) { + var r = color2((start2 = rgb(start2)).r, (end = rgb(end)).r), g = color2(start2.g, end.g), b = color2(start2.b, end.b), opacity = nogamma(start2.opacity, end.opacity); + return function(t) { + start2.r = r(t); + start2.g = g(t); + start2.b = b(t); + start2.opacity = opacity(t); + return start2 + ""; + }; + } + rgb2.gamma = rgbGamma; + return rgb2; + }(1); + function rgbSpline(spline) { + return function(colors) { + var n = colors.length, r = new Array(n), g = new Array(n), b = new Array(n), i, color2; + for (i = 0; i < n; ++i) { + color2 = rgb(colors[i]); + r[i] = color2.r || 0; + g[i] = color2.g || 0; + b[i] = color2.b || 0; + } + r = spline(r); + g = spline(g); + b = spline(b); + color2.opacity = 1; + return function(t) { + color2.r = r(t); + color2.g = g(t); + color2.b = b(t); + return color2 + ""; + }; + }; + } + var rgbBasis = rgbSpline(basis_default); + var rgbBasisClosed = rgbSpline(basisClosed_default); + + // node_modules/d3-interpolate/src/numberArray.js + function numberArray_default(a2, b) { + if (!b) + b = []; + var n = a2 ? Math.min(b.length, a2.length) : 0, c2 = b.slice(), i; + return function(t) { + for (i = 0; i < n; ++i) + c2[i] = a2[i] * (1 - t) + b[i] * t; + return c2; + }; + } + function isNumberArray(x2) { + return ArrayBuffer.isView(x2) && !(x2 instanceof DataView); + } + + // node_modules/d3-interpolate/src/array.js + function genericArray(a2, b) { + var nb = b ? b.length : 0, na = a2 ? Math.min(nb, a2.length) : 0, x2 = new Array(na), c2 = new Array(nb), i; + for (i = 0; i < na; ++i) + x2[i] = value_default(a2[i], b[i]); + for (; i < nb; ++i) + c2[i] = b[i]; + return function(t) { + for (i = 0; i < na; ++i) + c2[i] = x2[i](t); + return c2; + }; + } + + // node_modules/d3-interpolate/src/date.js + function date_default(a2, b) { + var d = new Date(); + return a2 = +a2, b = +b, function(t) { + return d.setTime(a2 * (1 - t) + b * t), d; + }; + } + + // node_modules/d3-interpolate/src/number.js + function number_default(a2, b) { + return a2 = +a2, b = +b, function(t) { + return a2 * (1 - t) + b * t; + }; + } + + // node_modules/d3-interpolate/src/object.js + function object_default(a2, b) { + var i = {}, c2 = {}, k; + if (a2 === null || typeof a2 !== "object") + a2 = {}; + if (b === null || typeof b !== "object") + b = {}; + for (k in b) { + if (k in a2) { + i[k] = value_default(a2[k], b[k]); + } else { + c2[k] = b[k]; + } + } + return function(t) { + for (k in i) + c2[k] = i[k](t); + return c2; + }; + } + + // node_modules/d3-interpolate/src/string.js + var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; + var reB = new RegExp(reA.source, "g"); + function zero2(b) { + return function() { + return b; + }; + } + function one(b) { + return function(t) { + return b(t) + ""; + }; + } + function string_default(a2, b) { + var bi = reA.lastIndex = reB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; + a2 = a2 + "", b = b + ""; + while ((am = reA.exec(a2)) && (bm = reB.exec(b))) { + if ((bs = bm.index) > bi) { + bs = b.slice(bi, bs); + if (s[i]) + s[i] += bs; + else + s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { + if (s[i]) + s[i] += bm; + else + s[++i] = bm; + } else { + s[++i] = null; + q.push({ i, x: number_default(am, bm) }); + } + bi = reB.lastIndex; + } + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) + s[i] += bs; + else + s[++i] = bs; + } + return s.length < 2 ? q[0] ? one(q[0].x) : zero2(b) : (b = q.length, function(t) { + for (var i2 = 0, o; i2 < b; ++i2) + s[(o = q[i2]).i] = o.x(t); + return s.join(""); + }); + } + + // node_modules/d3-interpolate/src/value.js + function value_default(a2, b) { + var t = typeof b, c2; + return b == null || t === "boolean" ? constant_default2(b) : (t === "number" ? number_default : t === "string" ? (c2 = color(b)) ? (b = c2, rgb_default) : string_default : b instanceof color ? rgb_default : b instanceof Date ? date_default : isNumberArray(b) ? numberArray_default : Array.isArray(b) ? genericArray : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object_default : number_default)(a2, b); + } + + // node_modules/d3-interpolate/src/round.js + function round_default(a2, b) { + return a2 = +a2, b = +b, function(t) { + return Math.round(a2 * (1 - t) + b * t); + }; + } + + // node_modules/d3-interpolate/src/transform/decompose.js + var degrees = 180 / Math.PI; + var identity = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1 + }; + function decompose_default(a2, b, c2, d, e, f) { + var scaleX, scaleY, skewX; + if (scaleX = Math.sqrt(a2 * a2 + b * b)) + a2 /= scaleX, b /= scaleX; + if (skewX = a2 * c2 + b * d) + c2 -= a2 * skewX, d -= b * skewX; + if (scaleY = Math.sqrt(c2 * c2 + d * d)) + c2 /= scaleY, d /= scaleY, skewX /= scaleY; + if (a2 * d < b * c2) + a2 = -a2, b = -b, skewX = -skewX, scaleX = -scaleX; + return { + translateX: e, + translateY: f, + rotate: Math.atan2(b, a2) * degrees, + skewX: Math.atan(skewX) * degrees, + scaleX, + scaleY + }; + } + + // node_modules/d3-interpolate/src/transform/parse.js + var svgNode; + function parseCss(value) { + const m2 = new (typeof DOMMatrix === "function" ? DOMMatrix : WebKitCSSMatrix)(value + ""); + return m2.isIdentity ? identity : decompose_default(m2.a, m2.b, m2.c, m2.d, m2.e, m2.f); + } + function parseSvg(value) { + if (value == null) + return identity; + if (!svgNode) + svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svgNode.setAttribute("transform", value); + if (!(value = svgNode.transform.baseVal.consolidate())) + return identity; + value = value.matrix; + return decompose_default(value.a, value.b, value.c, value.d, value.e, value.f); + } + + // node_modules/d3-interpolate/src/transform/index.js + function interpolateTransform(parse, pxComma, pxParen, degParen) { + function pop(s) { + return s.length ? s.pop() + " " : ""; + } + function translate(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push("translate(", null, pxComma, null, pxParen); + q.push({ i: i - 4, x: number_default(xa, xb) }, { i: i - 2, x: number_default(ya, yb) }); + } else if (xb || yb) { + s.push("translate(" + xb + pxComma + yb + pxParen); + } + } + function rotate(a2, b, s, q) { + if (a2 !== b) { + if (a2 - b > 180) + b += 360; + else if (b - a2 > 180) + a2 += 360; + q.push({ i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: number_default(a2, b) }); + } else if (b) { + s.push(pop(s) + "rotate(" + b + degParen); + } + } + function skewX(a2, b, s, q) { + if (a2 !== b) { + q.push({ i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number_default(a2, b) }); + } else if (b) { + s.push(pop(s) + "skewX(" + b + degParen); + } + } + function scale(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push(pop(s) + "scale(", null, ",", null, ")"); + q.push({ i: i - 4, x: number_default(xa, xb) }, { i: i - 2, x: number_default(ya, yb) }); + } else if (xb !== 1 || yb !== 1) { + s.push(pop(s) + "scale(" + xb + "," + yb + ")"); + } + } + return function(a2, b) { + var s = [], q = []; + a2 = parse(a2), b = parse(b); + translate(a2.translateX, a2.translateY, b.translateX, b.translateY, s, q); + rotate(a2.rotate, b.rotate, s, q); + skewX(a2.skewX, b.skewX, s, q); + scale(a2.scaleX, a2.scaleY, b.scaleX, b.scaleY, s, q); + a2 = b = null; + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) + s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + }; + } + var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); + var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); + + // node_modules/d3-timer/src/timer.js + var frame = 0; + var timeout = 0; + var interval = 0; + var pokeDelay = 1e3; + var taskHead; + var taskTail; + var clockLast = 0; + var clockNow = 0; + var clockSkew = 0; + var clock = typeof performance === "object" && performance.now ? performance : Date; + var setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { + setTimeout(f, 17); + }; + function now() { + return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); + } + function clearNow() { + clockNow = 0; + } + function Timer() { + this._call = this._time = this._next = null; + } + Timer.prototype = timer.prototype = { + constructor: Timer, + restart: function(callback, delay, time) { + if (typeof callback !== "function") + throw new TypeError("callback is not a function"); + time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); + if (!this._next && taskTail !== this) { + if (taskTail) + taskTail._next = this; + else + taskHead = this; + taskTail = this; + } + this._call = callback; + this._time = time; + sleep(); + }, + stop: function() { + if (this._call) { + this._call = null; + this._time = Infinity; + sleep(); + } + } + }; + function timer(callback, delay, time) { + var t = new Timer(); + t.restart(callback, delay, time); + return t; + } + function timerFlush() { + now(); + ++frame; + var t = taskHead, e; + while (t) { + if ((e = clockNow - t._time) >= 0) + t._call.call(void 0, e); + t = t._next; + } + --frame; + } + function wake() { + clockNow = (clockLast = clock.now()) + clockSkew; + frame = timeout = 0; + try { + timerFlush(); + } finally { + frame = 0; + nap(); + clockNow = 0; + } + } + function poke() { + var now2 = clock.now(), delay = now2 - clockLast; + if (delay > pokeDelay) + clockSkew -= delay, clockLast = now2; + } + function nap() { + var t0, t1 = taskHead, t2, time = Infinity; + while (t1) { + if (t1._call) { + if (time > t1._time) + time = t1._time; + t0 = t1, t1 = t1._next; + } else { + t2 = t1._next, t1._next = null; + t1 = t0 ? t0._next = t2 : taskHead = t2; + } + } + taskTail = t0; + sleep(time); + } + function sleep(time) { + if (frame) + return; + if (timeout) + timeout = clearTimeout(timeout); + var delay = time - clockNow; + if (delay > 24) { + if (time < Infinity) + timeout = setTimeout(wake, time - clock.now() - clockSkew); + if (interval) + interval = clearInterval(interval); + } else { + if (!interval) + clockLast = clock.now(), interval = setInterval(poke, pokeDelay); + frame = 1, setFrame(wake); + } + } + + // node_modules/d3-timer/src/timeout.js + function timeout_default(callback, delay, time) { + var t = new Timer(); + delay = delay == null ? 0 : +delay; + t.restart((elapsed) => { + t.stop(); + callback(elapsed + delay); + }, delay, time); + return t; + } + + // node_modules/d3-transition/src/transition/schedule.js + var emptyOn = dispatch_default("start", "end", "cancel", "interrupt"); + var emptyTween = []; + var CREATED = 0; + var SCHEDULED = 1; + var STARTING = 2; + var STARTED = 3; + var RUNNING = 4; + var ENDING = 5; + var ENDED = 6; + function schedule_default(node, name, id2, index2, group, timing) { + var schedules = node.__transition; + if (!schedules) + node.__transition = {}; + else if (id2 in schedules) + return; + create(node, id2, { + name, + index: index2, + group, + on: emptyOn, + tween: emptyTween, + time: timing.time, + delay: timing.delay, + duration: timing.duration, + ease: timing.ease, + timer: null, + state: CREATED + }); + } + function init(node, id2) { + var schedule = get2(node, id2); + if (schedule.state > CREATED) + throw new Error("too late; already scheduled"); + return schedule; + } + function set2(node, id2) { + var schedule = get2(node, id2); + if (schedule.state > STARTED) + throw new Error("too late; already running"); + return schedule; + } + function get2(node, id2) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id2])) + throw new Error("transition not found"); + return schedule; + } + function create(node, id2, self2) { + var schedules = node.__transition, tween; + schedules[id2] = self2; + self2.timer = timer(schedule, 0, self2.time); + function schedule(elapsed) { + self2.state = SCHEDULED; + self2.timer.restart(start2, self2.delay, self2.time); + if (self2.delay <= elapsed) + start2(elapsed - self2.delay); + } + function start2(elapsed) { + var i, j, n, o; + if (self2.state !== SCHEDULED) + return stop(); + for (i in schedules) { + o = schedules[i]; + if (o.name !== self2.name) + continue; + if (o.state === STARTED) + return timeout_default(start2); + if (o.state === RUNNING) { + o.state = ENDED; + o.timer.stop(); + o.on.call("interrupt", node, node.__data__, o.index, o.group); + delete schedules[i]; + } else if (+i < id2) { + o.state = ENDED; + o.timer.stop(); + o.on.call("cancel", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + } + timeout_default(function() { + if (self2.state === STARTED) { + self2.state = RUNNING; + self2.timer.restart(tick, self2.delay, self2.time); + tick(elapsed); + } + }); + self2.state = STARTING; + self2.on.call("start", node, node.__data__, self2.index, self2.group); + if (self2.state !== STARTING) + return; + self2.state = STARTED; + tween = new Array(n = self2.tween.length); + for (i = 0, j = -1; i < n; ++i) { + if (o = self2.tween[i].value.call(node, node.__data__, self2.index, self2.group)) { + tween[++j] = o; + } + } + tween.length = j + 1; + } + function tick(elapsed) { + var t = elapsed < self2.duration ? self2.ease.call(null, elapsed / self2.duration) : (self2.timer.restart(stop), self2.state = ENDING, 1), i = -1, n = tween.length; + while (++i < n) { + tween[i].call(node, t); + } + if (self2.state === ENDING) { + self2.on.call("end", node, node.__data__, self2.index, self2.group); + stop(); + } + } + function stop() { + self2.state = ENDED; + self2.timer.stop(); + delete schedules[id2]; + for (var i in schedules) + return; + delete node.__transition; + } + } + + // node_modules/d3-transition/src/interrupt.js + function interrupt_default(node, name) { + var schedules = node.__transition, schedule, active, empty2 = true, i; + if (!schedules) + return; + name = name == null ? null : name + ""; + for (i in schedules) { + if ((schedule = schedules[i]).name !== name) { + empty2 = false; + continue; + } + active = schedule.state > STARTING && schedule.state < ENDING; + schedule.state = ENDED; + schedule.timer.stop(); + schedule.on.call(active ? "interrupt" : "cancel", node, node.__data__, schedule.index, schedule.group); + delete schedules[i]; + } + if (empty2) + delete node.__transition; + } + + // node_modules/d3-transition/src/selection/interrupt.js + function interrupt_default2(name) { + return this.each(function() { + interrupt_default(this, name); + }); + } + + // node_modules/d3-transition/src/transition/tween.js + function tweenRemove(id2, name) { + var tween0, tween1; + return function() { + var schedule = set2(this, id2), tween = schedule.tween; + if (tween !== tween0) { + tween1 = tween0 = tween; + for (var i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1 = tween1.slice(); + tween1.splice(i, 1); + break; + } + } + } + schedule.tween = tween1; + }; + } + function tweenFunction(id2, name, value) { + var tween0, tween1; + if (typeof value !== "function") + throw new Error(); + return function() { + var schedule = set2(this, id2), tween = schedule.tween; + if (tween !== tween0) { + tween1 = (tween0 = tween).slice(); + for (var t = { name, value }, i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1[i] = t; + break; + } + } + if (i === n) + tween1.push(t); + } + schedule.tween = tween1; + }; + } + function tween_default(name, value) { + var id2 = this._id; + name += ""; + if (arguments.length < 2) { + var tween = get2(this.node(), id2).tween; + for (var i = 0, n = tween.length, t; i < n; ++i) { + if ((t = tween[i]).name === name) { + return t.value; + } + } + return null; + } + return this.each((value == null ? tweenRemove : tweenFunction)(id2, name, value)); + } + function tweenValue(transition2, name, value) { + var id2 = transition2._id; + transition2.each(function() { + var schedule = set2(this, id2); + (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); + }); + return function(node) { + return get2(node, id2).value[name]; + }; + } + + // node_modules/d3-transition/src/transition/interpolate.js + function interpolate_default(a2, b) { + var c2; + return (typeof b === "number" ? number_default : b instanceof color ? rgb_default : (c2 = color(b)) ? (b = c2, rgb_default) : string_default)(a2, b); + } + + // node_modules/d3-transition/src/transition/attr.js + function attrRemove2(name) { + return function() { + this.removeAttribute(name); + }; + } + function attrRemoveNS2(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; + } + function attrConstant2(name, interpolate, value1) { + var string00, string1 = value1 + "", interpolate0; + return function() { + var string0 = this.getAttribute(name); + return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1); + }; + } + function attrConstantNS2(fullname, interpolate, value1) { + var string00, string1 = value1 + "", interpolate0; + return function() { + var string0 = this.getAttributeNS(fullname.space, fullname.local); + return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1); + }; + } + function attrFunction2(name, interpolate, value) { + var string00, string10, interpolate0; + return function() { + var string0, value1 = value(this), string1; + if (value1 == null) + return void this.removeAttribute(name); + string0 = this.getAttribute(name); + string1 = value1 + ""; + return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + function attrFunctionNS2(fullname, interpolate, value) { + var string00, string10, interpolate0; + return function() { + var string0, value1 = value(this), string1; + if (value1 == null) + return void this.removeAttributeNS(fullname.space, fullname.local); + string0 = this.getAttributeNS(fullname.space, fullname.local); + string1 = value1 + ""; + return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + function attr_default2(name, value) { + var fullname = namespace_default(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate_default; + return this.attrTween(name, typeof value === "function" ? (fullname.local ? attrFunctionNS2 : attrFunction2)(fullname, i, tweenValue(this, "attr." + name, value)) : value == null ? (fullname.local ? attrRemoveNS2 : attrRemove2)(fullname) : (fullname.local ? attrConstantNS2 : attrConstant2)(fullname, i, value)); + } + + // node_modules/d3-transition/src/transition/attrTween.js + function attrInterpolate(name, i) { + return function(t) { + this.setAttribute(name, i.call(this, t)); + }; + } + function attrInterpolateNS(fullname, i) { + return function(t) { + this.setAttributeNS(fullname.space, fullname.local, i.call(this, t)); + }; + } + function attrTweenNS(fullname, value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t0 = (i0 = i) && attrInterpolateNS(fullname, i); + return t0; + } + tween._value = value; + return tween; + } + function attrTween(name, value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t0 = (i0 = i) && attrInterpolate(name, i); + return t0; + } + tween._value = value; + return tween; + } + function attrTween_default(name, value) { + var key = "attr." + name; + if (arguments.length < 2) + return (key = this.tween(key)) && key._value; + if (value == null) + return this.tween(key, null); + if (typeof value !== "function") + throw new Error(); + var fullname = namespace_default(name); + return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); + } + + // node_modules/d3-transition/src/transition/delay.js + function delayFunction(id2, value) { + return function() { + init(this, id2).delay = +value.apply(this, arguments); + }; + } + function delayConstant(id2, value) { + return value = +value, function() { + init(this, id2).delay = value; + }; + } + function delay_default(value) { + var id2 = this._id; + return arguments.length ? this.each((typeof value === "function" ? delayFunction : delayConstant)(id2, value)) : get2(this.node(), id2).delay; + } + + // node_modules/d3-transition/src/transition/duration.js + function durationFunction(id2, value) { + return function() { + set2(this, id2).duration = +value.apply(this, arguments); + }; + } + function durationConstant(id2, value) { + return value = +value, function() { + set2(this, id2).duration = value; + }; + } + function duration_default(value) { + var id2 = this._id; + return arguments.length ? this.each((typeof value === "function" ? durationFunction : durationConstant)(id2, value)) : get2(this.node(), id2).duration; + } + + // node_modules/d3-transition/src/transition/ease.js + function easeConstant(id2, value) { + if (typeof value !== "function") + throw new Error(); + return function() { + set2(this, id2).ease = value; + }; + } + function ease_default(value) { + var id2 = this._id; + return arguments.length ? this.each(easeConstant(id2, value)) : get2(this.node(), id2).ease; + } + + // node_modules/d3-transition/src/transition/easeVarying.js + function easeVarying(id2, value) { + return function() { + var v = value.apply(this, arguments); + if (typeof v !== "function") + throw new Error(); + set2(this, id2).ease = v; + }; + } + function easeVarying_default(value) { + if (typeof value !== "function") + throw new Error(); + return this.each(easeVarying(this._id, value)); + } + + // node_modules/d3-transition/src/transition/filter.js + function filter_default2(match) { + if (typeof match !== "function") + match = matcher_default(match); + for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + return new Transition(subgroups, this._parents, this._name, this._id); + } + + // node_modules/d3-transition/src/transition/merge.js + function merge_default2(transition2) { + if (transition2._id !== this._id) + throw new Error(); + for (var groups0 = this._groups, groups1 = transition2._groups, m0 = groups0.length, m1 = groups1.length, m2 = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m2; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + return new Transition(merges, this._parents, this._name, this._id); + } + + // node_modules/d3-transition/src/transition/on.js + function start(name) { + return (name + "").trim().split(/^|\s+/).every(function(t) { + var i = t.indexOf("."); + if (i >= 0) + t = t.slice(0, i); + return !t || t === "start"; + }); + } + function onFunction(id2, name, listener) { + var on0, on1, sit = start(name) ? init : set2; + return function() { + var schedule = sit(this, id2), on = schedule.on; + if (on !== on0) + (on1 = (on0 = on).copy()).on(name, listener); + schedule.on = on1; + }; + } + function on_default2(name, listener) { + var id2 = this._id; + return arguments.length < 2 ? get2(this.node(), id2).on.on(name) : this.each(onFunction(id2, name, listener)); + } + + // node_modules/d3-transition/src/transition/remove.js + function removeFunction(id2) { + return function() { + var parent = this.parentNode; + for (var i in this.__transition) + if (+i !== id2) + return; + if (parent) + parent.removeChild(this); + }; + } + function remove_default2() { + return this.on("end.remove", removeFunction(this._id)); + } + + // node_modules/d3-transition/src/transition/select.js + function select_default2(select) { + var name = this._name, id2 = this._id; + if (typeof select !== "function") + select = selector_default(select); + for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) + subnode.__data__ = node.__data__; + subgroup[i] = subnode; + schedule_default(subgroup[i], name, id2, i, subgroup, get2(node, id2)); + } + } + } + return new Transition(subgroups, this._parents, name, id2); + } + + // node_modules/d3-transition/src/transition/selectAll.js + function selectAll_default2(select) { + var name = this._name, id2 = this._id; + if (typeof select !== "function") + select = selectorAll_default(select); + for (var groups = this._groups, m2 = groups.length, subgroups = [], parents = [], j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + for (var children2 = select.call(node, node.__data__, i, group), child, inherit2 = get2(node, id2), k = 0, l = children2.length; k < l; ++k) { + if (child = children2[k]) { + schedule_default(child, name, id2, k, children2, inherit2); + } + } + subgroups.push(children2); + parents.push(node); + } + } + } + return new Transition(subgroups, parents, name, id2); + } + + // node_modules/d3-transition/src/transition/selection.js + var Selection2 = selection_default.prototype.constructor; + function selection_default2() { + return new Selection2(this._groups, this._parents); + } + + // node_modules/d3-transition/src/transition/style.js + function styleNull(name, interpolate) { + var string00, string10, interpolate0; + return function() { + var string0 = styleValue(this, name), string1 = (this.style.removeProperty(name), styleValue(this, name)); + return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : interpolate0 = interpolate(string00 = string0, string10 = string1); + }; + } + function styleRemove2(name) { + return function() { + this.style.removeProperty(name); + }; + } + function styleConstant2(name, interpolate, value1) { + var string00, string1 = value1 + "", interpolate0; + return function() { + var string0 = styleValue(this, name); + return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1); + }; + } + function styleFunction2(name, interpolate, value) { + var string00, string10, interpolate0; + return function() { + var string0 = styleValue(this, name), value1 = value(this), string1 = value1 + ""; + if (value1 == null) + string1 = value1 = (this.style.removeProperty(name), styleValue(this, name)); + return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + function styleMaybeRemove(id2, name) { + var on0, on1, listener0, key = "style." + name, event = "end." + key, remove2; + return function() { + var schedule = set2(this, id2), on = schedule.on, listener = schedule.value[key] == null ? remove2 || (remove2 = styleRemove2(name)) : void 0; + if (on !== on0 || listener0 !== listener) + (on1 = (on0 = on).copy()).on(event, listener0 = listener); + schedule.on = on1; + }; + } + function style_default2(name, value, priority) { + var i = (name += "") === "transform" ? interpolateTransformCss : interpolate_default; + return value == null ? this.styleTween(name, styleNull(name, i)).on("end.style." + name, styleRemove2(name)) : typeof value === "function" ? this.styleTween(name, styleFunction2(name, i, tweenValue(this, "style." + name, value))).each(styleMaybeRemove(this._id, name)) : this.styleTween(name, styleConstant2(name, i, value), priority).on("end.style." + name, null); + } + + // node_modules/d3-transition/src/transition/styleTween.js + function styleInterpolate(name, i, priority) { + return function(t) { + this.style.setProperty(name, i.call(this, t), priority); + }; + } + function styleTween(name, value, priority) { + var t, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t = (i0 = i) && styleInterpolate(name, i, priority); + return t; + } + tween._value = value; + return tween; + } + function styleTween_default(name, value, priority) { + var key = "style." + (name += ""); + if (arguments.length < 2) + return (key = this.tween(key)) && key._value; + if (value == null) + return this.tween(key, null); + if (typeof value !== "function") + throw new Error(); + return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); + } + + // node_modules/d3-transition/src/transition/text.js + function textConstant2(value) { + return function() { + this.textContent = value; + }; + } + function textFunction2(value) { + return function() { + var value1 = value(this); + this.textContent = value1 == null ? "" : value1; + }; + } + function text_default2(value) { + return this.tween("text", typeof value === "function" ? textFunction2(tweenValue(this, "text", value)) : textConstant2(value == null ? "" : value + "")); + } + + // node_modules/d3-transition/src/transition/textTween.js + function textInterpolate(i) { + return function(t) { + this.textContent = i.call(this, t); + }; + } + function textTween(value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t0 = (i0 = i) && textInterpolate(i); + return t0; + } + tween._value = value; + return tween; + } + function textTween_default(value) { + var key = "text"; + if (arguments.length < 1) + return (key = this.tween(key)) && key._value; + if (value == null) + return this.tween(key, null); + if (typeof value !== "function") + throw new Error(); + return this.tween(key, textTween(value)); + } + + // node_modules/d3-transition/src/transition/transition.js + function transition_default() { + var name = this._name, id0 = this._id, id1 = newId(); + for (var groups = this._groups, m2 = groups.length, j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + var inherit2 = get2(node, id0); + schedule_default(node, name, id1, i, group, { + time: inherit2.time + inherit2.delay + inherit2.duration, + delay: 0, + duration: inherit2.duration, + ease: inherit2.ease + }); + } + } + } + return new Transition(groups, this._parents, name, id1); + } + + // node_modules/d3-transition/src/transition/end.js + function end_default() { + var on0, on1, that = this, id2 = that._id, size = that.size(); + return new Promise(function(resolve, reject) { + var cancel = { value: reject }, end = { value: function() { + if (--size === 0) + resolve(); + } }; + that.each(function() { + var schedule = set2(this, id2), on = schedule.on; + if (on !== on0) { + on1 = (on0 = on).copy(); + on1._.cancel.push(cancel); + on1._.interrupt.push(cancel); + on1._.end.push(end); + } + schedule.on = on1; + }); + if (size === 0) + resolve(); + }); + } + + // node_modules/d3-transition/src/transition/index.js + var id = 0; + function Transition(groups, parents, name, id2) { + this._groups = groups; + this._parents = parents; + this._name = name; + this._id = id2; + } + function transition(name) { + return selection_default().transition(name); + } + function newId() { + return ++id; + } + var selection_prototype = selection_default.prototype; + Transition.prototype = transition.prototype = { + constructor: Transition, + select: select_default2, + selectAll: selectAll_default2, + selectChild: selection_prototype.selectChild, + selectChildren: selection_prototype.selectChildren, + filter: filter_default2, + merge: merge_default2, + selection: selection_default2, + transition: transition_default, + call: selection_prototype.call, + nodes: selection_prototype.nodes, + node: selection_prototype.node, + size: selection_prototype.size, + empty: selection_prototype.empty, + each: selection_prototype.each, + on: on_default2, + attr: attr_default2, + attrTween: attrTween_default, + style: style_default2, + styleTween: styleTween_default, + text: text_default2, + textTween: textTween_default, + remove: remove_default2, + tween: tween_default, + delay: delay_default, + duration: duration_default, + ease: ease_default, + easeVarying: easeVarying_default, + end: end_default, + [Symbol.iterator]: selection_prototype[Symbol.iterator] + }; + + // node_modules/d3-ease/src/cubic.js + function cubicInOut(t) { + return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; + } + + // node_modules/d3-transition/src/selection/transition.js + var defaultTiming = { + time: null, + delay: 0, + duration: 250, + ease: cubicInOut + }; + function inherit(node, id2) { + var timing; + while (!(timing = node.__transition) || !(timing = timing[id2])) { + if (!(node = node.parentNode)) { + throw new Error(`transition ${id2} not found`); + } + } + return timing; + } + function transition_default2(name) { + var id2, timing; + if (name instanceof Transition) { + id2 = name._id, name = name._name; + } else { + id2 = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + ""; + } + for (var groups = this._groups, m2 = groups.length, j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + schedule_default(node, name, id2, i, group, timing || inherit(node, id2)); + } + } + } + return new Transition(groups, this._parents, name, id2); + } + + // node_modules/d3-transition/src/selection/index.js + selection_default.prototype.interrupt = interrupt_default2; + selection_default.prototype.transition = transition_default2; + + // node_modules/d3-brush/src/brush.js + var { abs, max, min } = Math; + function number1(e) { + return [+e[0], +e[1]]; + } + function number2(e) { + return [number1(e[0]), number1(e[1])]; + } + var X = { + name: "x", + handles: ["w", "e"].map(type), + input: function(x2, e) { + return x2 == null ? null : [[+x2[0], e[0][1]], [+x2[1], e[1][1]]]; + }, + output: function(xy) { + return xy && [xy[0][0], xy[1][0]]; + } + }; + var Y = { + name: "y", + handles: ["n", "s"].map(type), + input: function(y2, e) { + return y2 == null ? null : [[e[0][0], +y2[0]], [e[1][0], +y2[1]]]; + }, + output: function(xy) { + return xy && [xy[0][1], xy[1][1]]; + } + }; + var XY = { + name: "xy", + handles: ["n", "w", "e", "s", "nw", "ne", "sw", "se"].map(type), + input: function(xy) { + return xy == null ? null : number2(xy); + }, + output: function(xy) { + return xy; + } + }; + function type(t) { + return { type: t }; + } + + // node_modules/d3-quadtree/src/add.js + function add_default(d) { + const x2 = +this._x.call(null, d), y2 = +this._y.call(null, d); + return add(this.cover(x2, y2), x2, y2, d); + } + function add(tree, x2, y2, d) { + if (isNaN(x2) || isNaN(y2)) + return tree; + var parent, node = tree._root, leaf = { data: d }, x0 = tree._x0, y0 = tree._y0, x1 = tree._x1, y1 = tree._y1, xm, ym, xp, yp, right, bottom, i, j; + if (!node) + return tree._root = leaf, tree; + while (node.length) { + if (right = x2 >= (xm = (x0 + x1) / 2)) + x0 = xm; + else + x1 = xm; + if (bottom = y2 >= (ym = (y0 + y1) / 2)) + y0 = ym; + else + y1 = ym; + if (parent = node, !(node = node[i = bottom << 1 | right])) + return parent[i] = leaf, tree; + } + xp = +tree._x.call(null, node.data); + yp = +tree._y.call(null, node.data); + if (x2 === xp && y2 === yp) + return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; + do { + parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); + if (right = x2 >= (xm = (x0 + x1) / 2)) + x0 = xm; + else + x1 = xm; + if (bottom = y2 >= (ym = (y0 + y1) / 2)) + y0 = ym; + else + y1 = ym; + } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | xp >= xm)); + return parent[j] = node, parent[i] = leaf, tree; + } + function addAll(data) { + var d, i, n = data.length, x2, y2, xz = new Array(n), yz = new Array(n), x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity; + for (i = 0; i < n; ++i) { + if (isNaN(x2 = +this._x.call(null, d = data[i])) || isNaN(y2 = +this._y.call(null, d))) + continue; + xz[i] = x2; + yz[i] = y2; + if (x2 < x0) + x0 = x2; + if (x2 > x1) + x1 = x2; + if (y2 < y0) + y0 = y2; + if (y2 > y1) + y1 = y2; + } + if (x0 > x1 || y0 > y1) + return this; + this.cover(x0, y0).cover(x1, y1); + for (i = 0; i < n; ++i) { + add(this, xz[i], yz[i], data[i]); + } + return this; + } + + // node_modules/d3-quadtree/src/cover.js + function cover_default(x2, y2) { + if (isNaN(x2 = +x2) || isNaN(y2 = +y2)) + return this; + var x0 = this._x0, y0 = this._y0, x1 = this._x1, y1 = this._y1; + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x2)) + 1; + y1 = (y0 = Math.floor(y2)) + 1; + } else { + var z = x1 - x0 || 1, node = this._root, parent, i; + while (x0 > x2 || x2 >= x1 || y0 > y2 || y2 >= y1) { + i = (y2 < y0) << 1 | x2 < x0; + parent = new Array(4), parent[i] = node, node = parent, z *= 2; + switch (i) { + case 0: + x1 = x0 + z, y1 = y0 + z; + break; + case 1: + x0 = x1 - z, y1 = y0 + z; + break; + case 2: + x1 = x0 + z, y0 = y1 - z; + break; + case 3: + x0 = x1 - z, y0 = y1 - z; + break; + } + } + if (this._root && this._root.length) + this._root = node; + } + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + return this; + } + + // node_modules/d3-quadtree/src/data.js + function data_default2() { + var data = []; + this.visit(function(node) { + if (!node.length) + do + data.push(node.data); + while (node = node.next); + }); + return data; + } + + // node_modules/d3-quadtree/src/extent.js + function extent_default(_) { + return arguments.length ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) : isNaN(this._x0) ? void 0 : [[this._x0, this._y0], [this._x1, this._y1]]; + } + + // node_modules/d3-quadtree/src/quad.js + function quad_default(node, x0, y0, x1, y1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.x1 = x1; + this.y1 = y1; + } + + // node_modules/d3-quadtree/src/find.js + function find_default(x2, y2, radius) { + var data, x0 = this._x0, y0 = this._y0, x1, y1, x22, y22, x3 = this._x1, y3 = this._y1, quads = [], node = this._root, q, i; + if (node) + quads.push(new quad_default(node, x0, y0, x3, y3)); + if (radius == null) + radius = Infinity; + else { + x0 = x2 - radius, y0 = y2 - radius; + x3 = x2 + radius, y3 = y2 + radius; + radius *= radius; + } + while (q = quads.pop()) { + if (!(node = q.node) || (x1 = q.x0) > x3 || (y1 = q.y0) > y3 || (x22 = q.x1) < x0 || (y22 = q.y1) < y0) + continue; + if (node.length) { + var xm = (x1 + x22) / 2, ym = (y1 + y22) / 2; + quads.push(new quad_default(node[3], xm, ym, x22, y22), new quad_default(node[2], x1, ym, xm, y22), new quad_default(node[1], xm, y1, x22, ym), new quad_default(node[0], x1, y1, xm, ym)); + if (i = (y2 >= ym) << 1 | x2 >= xm) { + q = quads[quads.length - 1]; + quads[quads.length - 1] = quads[quads.length - 1 - i]; + quads[quads.length - 1 - i] = q; + } + } else { + var dx = x2 - +this._x.call(null, node.data), dy = y2 - +this._y.call(null, node.data), d2 = dx * dx + dy * dy; + if (d2 < radius) { + var d = Math.sqrt(radius = d2); + x0 = x2 - d, y0 = y2 - d; + x3 = x2 + d, y3 = y2 + d; + data = node.data; + } + } + } + return data; + } + + // node_modules/d3-quadtree/src/remove.js + function remove_default3(d) { + if (isNaN(x2 = +this._x.call(null, d)) || isNaN(y2 = +this._y.call(null, d))) + return this; + var parent, node = this._root, retainer, previous, next, x0 = this._x0, y0 = this._y0, x1 = this._x1, y1 = this._y1, x2, y2, xm, ym, right, bottom, i, j; + if (!node) + return this; + if (node.length) + while (true) { + if (right = x2 >= (xm = (x0 + x1) / 2)) + x0 = xm; + else + x1 = xm; + if (bottom = y2 >= (ym = (y0 + y1) / 2)) + y0 = ym; + else + y1 = ym; + if (!(parent = node, node = node[i = bottom << 1 | right])) + return this; + if (!node.length) + break; + if (parent[i + 1 & 3] || parent[i + 2 & 3] || parent[i + 3 & 3]) + retainer = parent, j = i; + } + while (node.data !== d) + if (!(previous = node, node = node.next)) + return this; + if (next = node.next) + delete node.next; + if (previous) + return next ? previous.next = next : delete previous.next, this; + if (!parent) + return this._root = next, this; + next ? parent[i] = next : delete parent[i]; + if ((node = parent[0] || parent[1] || parent[2] || parent[3]) && node === (parent[3] || parent[2] || parent[1] || parent[0]) && !node.length) { + if (retainer) + retainer[j] = node; + else + this._root = node; + } + return this; + } + function removeAll(data) { + for (var i = 0, n = data.length; i < n; ++i) + this.remove(data[i]); + return this; + } + + // node_modules/d3-quadtree/src/root.js + function root_default() { + return this._root; + } + + // node_modules/d3-quadtree/src/size.js + function size_default2() { + var size = 0; + this.visit(function(node) { + if (!node.length) + do + ++size; + while (node = node.next); + }); + return size; + } + + // node_modules/d3-quadtree/src/visit.js + function visit_default(callback) { + var quads = [], q, node = this._root, child, x0, y0, x1, y1; + if (node) + quads.push(new quad_default(node, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { + var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[3]) + quads.push(new quad_default(child, xm, ym, x1, y1)); + if (child = node[2]) + quads.push(new quad_default(child, x0, ym, xm, y1)); + if (child = node[1]) + quads.push(new quad_default(child, xm, y0, x1, ym)); + if (child = node[0]) + quads.push(new quad_default(child, x0, y0, xm, ym)); + } + } + return this; + } + + // node_modules/d3-quadtree/src/visitAfter.js + function visitAfter_default(callback) { + var quads = [], next = [], q; + if (this._root) + quads.push(new quad_default(this._root, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[0]) + quads.push(new quad_default(child, x0, y0, xm, ym)); + if (child = node[1]) + quads.push(new quad_default(child, xm, y0, x1, ym)); + if (child = node[2]) + quads.push(new quad_default(child, x0, ym, xm, y1)); + if (child = node[3]) + quads.push(new quad_default(child, xm, ym, x1, y1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.y0, q.x1, q.y1); + } + return this; + } + + // node_modules/d3-quadtree/src/x.js + function defaultX(d) { + return d[0]; + } + function x_default(_) { + return arguments.length ? (this._x = _, this) : this._x; + } + + // node_modules/d3-quadtree/src/y.js + function defaultY(d) { + return d[1]; + } + function y_default(_) { + return arguments.length ? (this._y = _, this) : this._y; + } + + // node_modules/d3-quadtree/src/quadtree.js + function quadtree(nodes, x2, y2) { + var tree = new Quadtree(x2 == null ? defaultX : x2, y2 == null ? defaultY : y2, NaN, NaN, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); + } + function Quadtree(x2, y2, x0, y0, x1, y1) { + this._x = x2; + this._y = y2; + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + this._root = void 0; + } + function leaf_copy(leaf) { + var copy2 = { data: leaf.data }, next = copy2; + while (leaf = leaf.next) + next = next.next = { data: leaf.data }; + return copy2; + } + var treeProto = quadtree.prototype = Quadtree.prototype; + treeProto.copy = function() { + var copy2 = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), node = this._root, nodes, child; + if (!node) + return copy2; + if (!node.length) + return copy2._root = leaf_copy(node), copy2; + nodes = [{ source: node, target: copy2._root = new Array(4) }]; + while (node = nodes.pop()) { + for (var i = 0; i < 4; ++i) { + if (child = node.source[i]) { + if (child.length) + nodes.push({ source: child, target: node.target[i] = new Array(4) }); + else + node.target[i] = leaf_copy(child); + } + } + } + return copy2; + }; + treeProto.add = add_default; + treeProto.addAll = addAll; + treeProto.cover = cover_default; + treeProto.data = data_default2; + treeProto.extent = extent_default; + treeProto.find = find_default; + treeProto.remove = remove_default3; + treeProto.removeAll = removeAll; + treeProto.root = root_default; + treeProto.size = size_default2; + treeProto.visit = visit_default; + treeProto.visitAfter = visitAfter_default; + treeProto.x = x_default; + treeProto.y = y_default; + + // node_modules/d3-force/src/constant.js + function constant_default4(x2) { + return function() { + return x2; + }; + } + + // node_modules/d3-force/src/jiggle.js + function jiggle_default(random) { + return (random() - 0.5) * 1e-6; + } + + // node_modules/d3-force/src/link.js + function index(d) { + return d.index; + } + function find2(nodeById, nodeId) { + var node = nodeById.get(nodeId); + if (!node) + throw new Error("node not found: " + nodeId); + return node; + } + function link_default(links) { + var id2 = index, strength = defaultStrength, strengths, distance = constant_default4(30), distances, nodes, count, bias, random, iterations = 1; + if (links == null) + links = []; + function defaultStrength(link) { + return 1 / Math.min(count[link.source.index], count[link.target.index]); + } + function force(alpha) { + for (var k = 0, n = links.length; k < iterations; ++k) { + for (var i = 0, link, source, target, x2, y2, l, b; i < n; ++i) { + link = links[i], source = link.source, target = link.target; + x2 = target.x + target.vx - source.x - source.vx || jiggle_default(random); + y2 = target.y + target.vy - source.y - source.vy || jiggle_default(random); + l = Math.sqrt(x2 * x2 + y2 * y2); + l = (l - distances[i]) / l * alpha * strengths[i]; + x2 *= l, y2 *= l; + target.vx -= x2 * (b = bias[i]); + target.vy -= y2 * b; + source.vx += x2 * (b = 1 - b); + source.vy += y2 * b; + } + } + } + function initialize() { + if (!nodes) + return; + var i, n = nodes.length, m2 = links.length, nodeById = new Map(nodes.map((d, i2) => [id2(d, i2, nodes), d])), link; + for (i = 0, count = new Array(n); i < m2; ++i) { + link = links[i], link.index = i; + if (typeof link.source !== "object") + link.source = find2(nodeById, link.source); + if (typeof link.target !== "object") + link.target = find2(nodeById, link.target); + count[link.source.index] = (count[link.source.index] || 0) + 1; + count[link.target.index] = (count[link.target.index] || 0) + 1; + } + for (i = 0, bias = new Array(m2); i < m2; ++i) { + link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + } + strengths = new Array(m2), initializeStrength(); + distances = new Array(m2), initializeDistance(); + } + function initializeStrength() { + if (!nodes) + return; + for (var i = 0, n = links.length; i < n; ++i) { + strengths[i] = +strength(links[i], i, links); + } + } + function initializeDistance() { + if (!nodes) + return; + for (var i = 0, n = links.length; i < n; ++i) { + distances[i] = +distance(links[i], i, links); + } + } + force.initialize = function(_nodes, _random) { + nodes = _nodes; + random = _random; + initialize(); + }; + force.links = function(_) { + return arguments.length ? (links = _, initialize(), force) : links; + }; + force.id = function(_) { + return arguments.length ? (id2 = _, force) : id2; + }; + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant_default4(+_), initializeStrength(), force) : strength; + }; + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant_default4(+_), initializeDistance(), force) : distance; + }; + return force; + } + + // node_modules/d3-force/src/lcg.js + var a = 1664525; + var c = 1013904223; + var m = 4294967296; + function lcg_default() { + let s = 1; + return () => (s = (a * s + c) % m) / m; + } + + // node_modules/d3-force/src/simulation.js + function x(d) { + return d.x; + } + function y(d) { + return d.y; + } + var initialRadius = 10; + var initialAngle = Math.PI * (3 - Math.sqrt(5)); + function simulation_default(nodes) { + var simulation, alpha = 1, alphaMin = 1e-3, alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), alphaTarget = 0, velocityDecay = 0.6, forces = /* @__PURE__ */ new Map(), stepper = timer(step), event = dispatch_default("tick", "end"), random = lcg_default(); + if (nodes == null) + nodes = []; + function step() { + tick(); + event.call("tick", simulation); + if (alpha < alphaMin) { + stepper.stop(); + event.call("end", simulation); + } + } + function tick(iterations) { + var i, n = nodes.length, node; + if (iterations === void 0) + iterations = 1; + for (var k = 0; k < iterations; ++k) { + alpha += (alphaTarget - alpha) * alphaDecay; + forces.forEach(function(force) { + force(alpha); + }); + for (i = 0; i < n; ++i) { + node = nodes[i]; + if (node.fx == null) + node.x += node.vx *= velocityDecay; + else + node.x = node.fx, node.vx = 0; + if (node.fy == null) + node.y += node.vy *= velocityDecay; + else + node.y = node.fy, node.vy = 0; + } + } + return simulation; + } + function initializeNodes() { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.index = i; + if (node.fx != null) + node.x = node.fx; + if (node.fy != null) + node.y = node.fy; + if (isNaN(node.x) || isNaN(node.y)) { + var radius = initialRadius * Math.sqrt(0.5 + i), angle = i * initialAngle; + node.x = radius * Math.cos(angle); + node.y = radius * Math.sin(angle); + } + if (isNaN(node.vx) || isNaN(node.vy)) { + node.vx = node.vy = 0; + } + } + } + function initializeForce(force) { + if (force.initialize) + force.initialize(nodes, random); + return force; + } + initializeNodes(); + return simulation = { + tick, + restart: function() { + return stepper.restart(step), simulation; + }, + stop: function() { + return stepper.stop(), simulation; + }, + nodes: function(_) { + return arguments.length ? (nodes = _, initializeNodes(), forces.forEach(initializeForce), simulation) : nodes; + }, + alpha: function(_) { + return arguments.length ? (alpha = +_, simulation) : alpha; + }, + alphaMin: function(_) { + return arguments.length ? (alphaMin = +_, simulation) : alphaMin; + }, + alphaDecay: function(_) { + return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; + }, + alphaTarget: function(_) { + return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; + }, + velocityDecay: function(_) { + return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; + }, + randomSource: function(_) { + return arguments.length ? (random = _, forces.forEach(initializeForce), simulation) : random; + }, + force: function(name, _) { + return arguments.length > 1 ? (_ == null ? forces.delete(name) : forces.set(name, initializeForce(_)), simulation) : forces.get(name); + }, + find: function(x2, y2, radius) { + var i = 0, n = nodes.length, dx, dy, d2, node, closest; + if (radius == null) + radius = Infinity; + else + radius *= radius; + for (i = 0; i < n; ++i) { + node = nodes[i]; + dx = x2 - node.x; + dy = y2 - node.y; + d2 = dx * dx + dy * dy; + if (d2 < radius) + closest = node, radius = d2; + } + return closest; + }, + on: function(name, _) { + return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); + } + }; + } + + // node_modules/d3-force/src/manyBody.js + function manyBody_default() { + var nodes, node, random, alpha, strength = constant_default4(-30), strengths, distanceMin2 = 1, distanceMax2 = Infinity, theta2 = 0.81; + function force(_) { + var i, n = nodes.length, tree = quadtree(nodes, x, y).visitAfter(accumulate); + for (alpha = _, i = 0; i < n; ++i) + node = nodes[i], tree.visit(apply); + } + function initialize() { + if (!nodes) + return; + var i, n = nodes.length, node2; + strengths = new Array(n); + for (i = 0; i < n; ++i) + node2 = nodes[i], strengths[node2.index] = +strength(node2, i, nodes); + } + function accumulate(quad) { + var strength2 = 0, q, c2, weight = 0, x2, y2, i; + if (quad.length) { + for (x2 = y2 = i = 0; i < 4; ++i) { + if ((q = quad[i]) && (c2 = Math.abs(q.value))) { + strength2 += q.value, weight += c2, x2 += c2 * q.x, y2 += c2 * q.y; + } + } + quad.x = x2 / weight; + quad.y = y2 / weight; + } else { + q = quad; + q.x = q.data.x; + q.y = q.data.y; + do + strength2 += strengths[q.data.index]; + while (q = q.next); + } + quad.value = strength2; + } + function apply(quad, x1, _, x2) { + if (!quad.value) + return true; + var x3 = quad.x - node.x, y2 = quad.y - node.y, w = x2 - x1, l = x3 * x3 + y2 * y2; + if (w * w / theta2 < l) { + if (l < distanceMax2) { + if (x3 === 0) + x3 = jiggle_default(random), l += x3 * x3; + if (y2 === 0) + y2 = jiggle_default(random), l += y2 * y2; + if (l < distanceMin2) + l = Math.sqrt(distanceMin2 * l); + node.vx += x3 * quad.value * alpha / l; + node.vy += y2 * quad.value * alpha / l; + } + return true; + } else if (quad.length || l >= distanceMax2) + return; + if (quad.data !== node || quad.next) { + if (x3 === 0) + x3 = jiggle_default(random), l += x3 * x3; + if (y2 === 0) + y2 = jiggle_default(random), l += y2 * y2; + if (l < distanceMin2) + l = Math.sqrt(distanceMin2 * l); + } + do + if (quad.data !== node) { + w = strengths[quad.data.index] * alpha / l; + node.vx += x3 * w; + node.vy += y2 * w; + } + while (quad = quad.next); + } + force.initialize = function(_nodes, _random) { + nodes = _nodes; + random = _random; + initialize(); + }; + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant_default4(+_), initialize(), force) : strength; + }; + force.distanceMin = function(_) { + return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); + }; + force.distanceMax = function(_) { + return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); + }; + force.theta = function(_) { + return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); + }; + return force; + } + + // node_modules/d3-force/src/radial.js + function radial_default(radius, x2, y2) { + var nodes, strength = constant_default4(0.1), strengths, radiuses; + if (typeof radius !== "function") + radius = constant_default4(+radius); + if (x2 == null) + x2 = 0; + if (y2 == null) + y2 = 0; + function force(alpha) { + for (var i = 0, n = nodes.length; i < n; ++i) { + var node = nodes[i], dx = node.x - x2 || 1e-6, dy = node.y - y2 || 1e-6, r = Math.sqrt(dx * dx + dy * dy), k = (radiuses[i] - r) * strengths[i] * alpha / r; + node.vx += dx * k; + node.vy += dy * k; + } + } + function initialize() { + if (!nodes) + return; + var i, n = nodes.length; + strengths = new Array(n); + radiuses = new Array(n); + for (i = 0; i < n; ++i) { + radiuses[i] = +radius(nodes[i], i, nodes); + strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes); + } + } + force.initialize = function(_) { + nodes = _, initialize(); + }; + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant_default4(+_), initialize(), force) : strength; + }; + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant_default4(+_), initialize(), force) : radius; + }; + force.x = function(_) { + return arguments.length ? (x2 = +_, force) : x2; + }; + force.y = function(_) { + return arguments.length ? (y2 = +_, force) : y2; + }; + return force; + } + + // node_modules/d3-format/src/formatDecimal.js + function formatDecimal_default(x2) { + return Math.abs(x2 = Math.round(x2)) >= 1e21 ? x2.toLocaleString("en").replace(/,/g, "") : x2.toString(10); + } + function formatDecimalParts(x2, p) { + if ((i = (x2 = p ? x2.toExponential(p - 1) : x2.toExponential()).indexOf("e")) < 0) + return null; + var i, coefficient = x2.slice(0, i); + return [ + coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, + +x2.slice(i + 1) + ]; + } + + // node_modules/d3-format/src/exponent.js + function exponent_default(x2) { + return x2 = formatDecimalParts(Math.abs(x2)), x2 ? x2[1] : NaN; + } + + // node_modules/d3-format/src/formatGroup.js + function formatGroup_default(grouping, thousands) { + return function(value, width) { + var i = value.length, t = [], j = 0, g = grouping[0], length = 0; + while (i > 0 && g > 0) { + if (length + g + 1 > width) + g = Math.max(1, width - length); + t.push(value.substring(i -= g, i + g)); + if ((length += g + 1) > width) + break; + g = grouping[j = (j + 1) % grouping.length]; + } + return t.reverse().join(thousands); + }; + } + + // node_modules/d3-format/src/formatNumerals.js + function formatNumerals_default(numerals) { + return function(value) { + return value.replace(/[0-9]/g, function(i) { + return numerals[+i]; + }); + }; + } + + // node_modules/d3-format/src/formatSpecifier.js + var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i; + function formatSpecifier(specifier) { + if (!(match = re.exec(specifier))) + throw new Error("invalid format: " + specifier); + var match; + return new FormatSpecifier({ + fill: match[1], + align: match[2], + sign: match[3], + symbol: match[4], + zero: match[5], + width: match[6], + comma: match[7], + precision: match[8] && match[8].slice(1), + trim: match[9], + type: match[10] + }); + } + formatSpecifier.prototype = FormatSpecifier.prototype; + function FormatSpecifier(specifier) { + this.fill = specifier.fill === void 0 ? " " : specifier.fill + ""; + this.align = specifier.align === void 0 ? ">" : specifier.align + ""; + this.sign = specifier.sign === void 0 ? "-" : specifier.sign + ""; + this.symbol = specifier.symbol === void 0 ? "" : specifier.symbol + ""; + this.zero = !!specifier.zero; + this.width = specifier.width === void 0 ? void 0 : +specifier.width; + this.comma = !!specifier.comma; + this.precision = specifier.precision === void 0 ? void 0 : +specifier.precision; + this.trim = !!specifier.trim; + this.type = specifier.type === void 0 ? "" : specifier.type + ""; + } + FormatSpecifier.prototype.toString = function() { + return this.fill + this.align + this.sign + this.symbol + (this.zero ? "0" : "") + (this.width === void 0 ? "" : Math.max(1, this.width | 0)) + (this.comma ? "," : "") + (this.precision === void 0 ? "" : "." + Math.max(0, this.precision | 0)) + (this.trim ? "~" : "") + this.type; + }; + + // node_modules/d3-format/src/formatTrim.js + function formatTrim_default(s) { + out: + for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) { + switch (s[i]) { + case ".": + i0 = i1 = i; + break; + case "0": + if (i0 === 0) + i0 = i; + i1 = i; + break; + default: + if (!+s[i]) + break out; + if (i0 > 0) + i0 = 0; + break; + } + } + return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s; + } + + // node_modules/d3-format/src/formatPrefixAuto.js + var prefixExponent; + function formatPrefixAuto_default(x2, p) { + var d = formatDecimalParts(x2, p); + if (!d) + return x2 + ""; + var coefficient = d[0], exponent = d[1], i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, n = coefficient.length; + return i === n ? coefficient : i > n ? coefficient + new Array(i - n + 1).join("0") : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) : "0." + new Array(1 - i).join("0") + formatDecimalParts(x2, Math.max(0, p + i - 1))[0]; + } + + // node_modules/d3-format/src/formatRounded.js + function formatRounded_default(x2, p) { + var d = formatDecimalParts(x2, p); + if (!d) + return x2 + ""; + var coefficient = d[0], exponent = d[1]; + return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) : coefficient + new Array(exponent - coefficient.length + 2).join("0"); + } + + // node_modules/d3-format/src/formatTypes.js + var formatTypes_default = { + "%": (x2, p) => (x2 * 100).toFixed(p), + "b": (x2) => Math.round(x2).toString(2), + "c": (x2) => x2 + "", + "d": formatDecimal_default, + "e": (x2, p) => x2.toExponential(p), + "f": (x2, p) => x2.toFixed(p), + "g": (x2, p) => x2.toPrecision(p), + "o": (x2) => Math.round(x2).toString(8), + "p": (x2, p) => formatRounded_default(x2 * 100, p), + "r": formatRounded_default, + "s": formatPrefixAuto_default, + "X": (x2) => Math.round(x2).toString(16).toUpperCase(), + "x": (x2) => Math.round(x2).toString(16) + }; + + // node_modules/d3-format/src/identity.js + function identity_default(x2) { + return x2; + } + + // node_modules/d3-format/src/locale.js + var map = Array.prototype.map; + var prefixes = ["y", "z", "a", "f", "p", "n", "\xB5", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"]; + function locale_default(locale2) { + var group = locale2.grouping === void 0 || locale2.thousands === void 0 ? identity_default : formatGroup_default(map.call(locale2.grouping, Number), locale2.thousands + ""), currencyPrefix = locale2.currency === void 0 ? "" : locale2.currency[0] + "", currencySuffix = locale2.currency === void 0 ? "" : locale2.currency[1] + "", decimal = locale2.decimal === void 0 ? "." : locale2.decimal + "", numerals = locale2.numerals === void 0 ? identity_default : formatNumerals_default(map.call(locale2.numerals, String)), percent = locale2.percent === void 0 ? "%" : locale2.percent + "", minus = locale2.minus === void 0 ? "\u2212" : locale2.minus + "", nan = locale2.nan === void 0 ? "NaN" : locale2.nan + ""; + function newFormat(specifier) { + specifier = formatSpecifier(specifier); + var fill = specifier.fill, align = specifier.align, sign = specifier.sign, symbol = specifier.symbol, zero3 = specifier.zero, width = specifier.width, comma = specifier.comma, precision = specifier.precision, trim = specifier.trim, type2 = specifier.type; + if (type2 === "n") + comma = true, type2 = "g"; + else if (!formatTypes_default[type2]) + precision === void 0 && (precision = 12), trim = true, type2 = "g"; + if (zero3 || fill === "0" && align === "=") + zero3 = true, fill = "0", align = "="; + var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type2) ? "0" + type2.toLowerCase() : "", suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type2) ? percent : ""; + var formatType = formatTypes_default[type2], maybeSuffix = /[defgprs%]/.test(type2); + precision = precision === void 0 ? 6 : /[gprs]/.test(type2) ? Math.max(1, Math.min(21, precision)) : Math.max(0, Math.min(20, precision)); + function format2(value) { + var valuePrefix = prefix, valueSuffix = suffix, i, n, c2; + if (type2 === "c") { + valueSuffix = formatType(value) + valueSuffix; + value = ""; + } else { + value = +value; + var valueNegative = value < 0 || 1 / value < 0; + value = isNaN(value) ? nan : formatType(Math.abs(value), precision); + if (trim) + value = formatTrim_default(value); + if (valueNegative && +value === 0 && sign !== "+") + valueNegative = false; + valuePrefix = (valueNegative ? sign === "(" ? sign : minus : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; + valueSuffix = (type2 === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); + if (maybeSuffix) { + i = -1, n = value.length; + while (++i < n) { + if (c2 = value.charCodeAt(i), 48 > c2 || c2 > 57) { + valueSuffix = (c2 === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; + value = value.slice(0, i); + break; + } + } + } + } + if (comma && !zero3) + value = group(value, Infinity); + var length = valuePrefix.length + value.length + valueSuffix.length, padding = length < width ? new Array(width - length + 1).join(fill) : ""; + if (comma && zero3) + value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; + switch (align) { + case "<": + value = valuePrefix + value + valueSuffix + padding; + break; + case "=": + value = valuePrefix + padding + value + valueSuffix; + break; + case "^": + value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); + break; + default: + value = padding + valuePrefix + value + valueSuffix; + break; + } + return numerals(value); + } + format2.toString = function() { + return specifier + ""; + }; + return format2; + } + function formatPrefix2(specifier, value) { + var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), e = Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3, k = Math.pow(10, -e), prefix = prefixes[8 + e / 3]; + return function(value2) { + return f(k * value2) + prefix; + }; + } + return { + format: newFormat, + formatPrefix: formatPrefix2 + }; + } + + // node_modules/d3-format/src/defaultLocale.js + var locale; + var format; + var formatPrefix; + defaultLocale({ + thousands: ",", + grouping: [3], + currency: ["$", ""] + }); + function defaultLocale(definition) { + locale = locale_default(definition); + format = locale.format; + formatPrefix = locale.formatPrefix; + return locale; + } + + // node_modules/d3-format/src/precisionFixed.js + function precisionFixed_default(step) { + return Math.max(0, -exponent_default(Math.abs(step))); + } + + // node_modules/d3-format/src/precisionPrefix.js + function precisionPrefix_default(step, value) { + return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3 - exponent_default(Math.abs(step))); + } + + // node_modules/d3-format/src/precisionRound.js + function precisionRound_default(step, max2) { + step = Math.abs(step), max2 = Math.abs(max2) - step; + return Math.max(0, exponent_default(max2) - exponent_default(step)) + 1; + } + + // node_modules/d3-scale/src/init.js + function initRange(domain, range2) { + switch (arguments.length) { + case 0: + break; + case 1: + this.range(domain); + break; + default: + this.range(range2).domain(domain); + break; + } + return this; + } + + // node_modules/d3-scale/src/constant.js + function constants(x2) { + return function() { + return x2; + }; + } + + // node_modules/d3-scale/src/number.js + function number3(x2) { + return +x2; + } + + // node_modules/d3-scale/src/continuous.js + var unit = [0, 1]; + function identity2(x2) { + return x2; + } + function normalize(a2, b) { + return (b -= a2 = +a2) ? function(x2) { + return (x2 - a2) / b; + } : constants(isNaN(b) ? NaN : 0.5); + } + function clamper(a2, b) { + var t; + if (a2 > b) + t = a2, a2 = b, b = t; + return function(x2) { + return Math.max(a2, Math.min(b, x2)); + }; + } + function bimap(domain, range2, interpolate) { + var d0 = domain[0], d1 = domain[1], r0 = range2[0], r1 = range2[1]; + if (d1 < d0) + d0 = normalize(d1, d0), r0 = interpolate(r1, r0); + else + d0 = normalize(d0, d1), r0 = interpolate(r0, r1); + return function(x2) { + return r0(d0(x2)); + }; + } + function polymap(domain, range2, interpolate) { + var j = Math.min(domain.length, range2.length) - 1, d = new Array(j), r = new Array(j), i = -1; + if (domain[j] < domain[0]) { + domain = domain.slice().reverse(); + range2 = range2.slice().reverse(); + } + while (++i < j) { + d[i] = normalize(domain[i], domain[i + 1]); + r[i] = interpolate(range2[i], range2[i + 1]); + } + return function(x2) { + var i2 = bisect_default(domain, x2, 1, j) - 1; + return r[i2](d[i2](x2)); + }; + } + function copy(source, target) { + return target.domain(source.domain()).range(source.range()).interpolate(source.interpolate()).clamp(source.clamp()).unknown(source.unknown()); + } + function transformer() { + var domain = unit, range2 = unit, interpolate = value_default, transform2, untransform, unknown, clamp2 = identity2, piecewise, output, input; + function rescale() { + var n = Math.min(domain.length, range2.length); + if (clamp2 !== identity2) + clamp2 = clamper(domain[0], domain[n - 1]); + piecewise = n > 2 ? polymap : bimap; + output = input = null; + return scale; + } + function scale(x2) { + return x2 == null || isNaN(x2 = +x2) ? unknown : (output || (output = piecewise(domain.map(transform2), range2, interpolate)))(transform2(clamp2(x2))); + } + scale.invert = function(y2) { + return clamp2(untransform((input || (input = piecewise(range2, domain.map(transform2), number_default)))(y2))); + }; + scale.domain = function(_) { + return arguments.length ? (domain = Array.from(_, number3), rescale()) : domain.slice(); + }; + scale.range = function(_) { + return arguments.length ? (range2 = Array.from(_), rescale()) : range2.slice(); + }; + scale.rangeRound = function(_) { + return range2 = Array.from(_), interpolate = round_default, rescale(); + }; + scale.clamp = function(_) { + return arguments.length ? (clamp2 = _ ? true : identity2, rescale()) : clamp2 !== identity2; + }; + scale.interpolate = function(_) { + return arguments.length ? (interpolate = _, rescale()) : interpolate; + }; + scale.unknown = function(_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + return function(t, u) { + transform2 = t, untransform = u; + return rescale(); + }; + } + function continuous() { + return transformer()(identity2, identity2); + } + + // node_modules/d3-scale/src/tickFormat.js + function tickFormat(start2, stop, count, specifier) { + var step = tickStep(start2, stop, count), precision; + specifier = formatSpecifier(specifier == null ? ",f" : specifier); + switch (specifier.type) { + case "s": { + var value = Math.max(Math.abs(start2), Math.abs(stop)); + if (specifier.precision == null && !isNaN(precision = precisionPrefix_default(step, value))) + specifier.precision = precision; + return formatPrefix(specifier, value); + } + case "": + case "e": + case "g": + case "p": + case "r": { + if (specifier.precision == null && !isNaN(precision = precisionRound_default(step, Math.max(Math.abs(start2), Math.abs(stop))))) + specifier.precision = precision - (specifier.type === "e"); + break; + } + case "f": + case "%": { + if (specifier.precision == null && !isNaN(precision = precisionFixed_default(step))) + specifier.precision = precision - (specifier.type === "%") * 2; + break; + } + } + return format(specifier); + } + + // node_modules/d3-scale/src/linear.js + function linearish(scale) { + var domain = scale.domain; + scale.ticks = function(count) { + var d = domain(); + return ticks(d[0], d[d.length - 1], count == null ? 10 : count); + }; + scale.tickFormat = function(count, specifier) { + var d = domain(); + return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier); + }; + scale.nice = function(count) { + if (count == null) + count = 10; + var d = domain(); + var i0 = 0; + var i1 = d.length - 1; + var start2 = d[i0]; + var stop = d[i1]; + var prestep; + var step; + var maxIter = 10; + if (stop < start2) { + step = start2, start2 = stop, stop = step; + step = i0, i0 = i1, i1 = step; + } + while (maxIter-- > 0) { + step = tickIncrement(start2, stop, count); + if (step === prestep) { + d[i0] = start2; + d[i1] = stop; + return domain(d); + } else if (step > 0) { + start2 = Math.floor(start2 / step) * step; + stop = Math.ceil(stop / step) * step; + } else if (step < 0) { + start2 = Math.ceil(start2 * step) / step; + stop = Math.floor(stop * step) / step; + } else { + break; + } + prestep = step; + } + return scale; + }; + return scale; + } + function linear2() { + var scale = continuous(); + scale.copy = function() { + return copy(scale, linear2()); + }; + initRange.apply(scale, arguments); + return linearish(scale); + } + + // node_modules/d3-zoom/src/transform.js + function Transform(k, x2, y2) { + this.k = k; + this.x = x2; + this.y = y2; + } + Transform.prototype = { + constructor: Transform, + scale: function(k) { + return k === 1 ? this : new Transform(this.k * k, this.x, this.y); + }, + translate: function(x2, y2) { + return x2 === 0 & y2 === 0 ? this : new Transform(this.k, this.x + this.k * x2, this.y + this.k * y2); + }, + apply: function(point) { + return [point[0] * this.k + this.x, point[1] * this.k + this.y]; + }, + applyX: function(x2) { + return x2 * this.k + this.x; + }, + applyY: function(y2) { + return y2 * this.k + this.y; + }, + invert: function(location) { + return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; + }, + invertX: function(x2) { + return (x2 - this.x) / this.k; + }, + invertY: function(y2) { + return (y2 - this.y) / this.k; + }, + rescaleX: function(x2) { + return x2.copy().domain(x2.range().map(this.invertX, this).map(x2.invert, x2)); + }, + rescaleY: function(y2) { + return y2.copy().domain(y2.range().map(this.invertY, this).map(y2.invert, y2)); + }, + toString: function() { + return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + } + }; + var identity3 = new Transform(1, 0, 0); + transform.prototype = Transform.prototype; + function transform(node) { + while (!node.__zoom) + if (!(node = node.parentNode)) + return identity3; + return node.__zoom; + } + + // federjs/FederLayout/visDataHandler/hnsw/search/forceSearchView.ts + var forceSearchView = (visData, targetOrigin = [0, 0], forceIterations = 100) => { + return new Promise((resolve) => { + const nodeId2dist = {}; + visData.forEach((levelData) => levelData.nodes.forEach((node) => nodeId2dist[node.id] = node.dist || 0)); + const nodeIds = Object.keys(nodeId2dist); + const nodes = nodeIds.map((nodeId) => ({ + nodeId, + dist: nodeId2dist[nodeId] + })); + const linksAll = visData.reduce((acc, cur) => acc.concat(cur.links), []); + const links = deDupLink(linksAll); + const targetNode = { + nodeId: "target", + dist: 0, + fx: targetOrigin[0], + fy: targetOrigin[1] + }; + nodes.push(targetNode); + const targetLinks = visData[0].fineIds.map((fineId) => ({ + source: `${fineId}`, + target: "target", + type: 0 /* None */ + })); + links.push(...targetLinks); + const rScale = linear2().domain(extent(nodes.filter((node) => node.dist > 0), (node) => node.dist)).range([10, 1e3]).clamp(true); + const simulation = simulation_default(nodes).alphaDecay(1 - Math.pow(1e-3, 1 / forceIterations)).force("link", link_default(links).id((d) => `${d.nodeId}`).strength((d) => d.type === 0 /* None */ ? 2 : 0.4)).force("r", radial_default((node) => rScale(node.dist), targetOrigin[0], targetOrigin[1]).strength(1)).force("charge", manyBody_default().strength(-1e4)).on("end", () => { + const id2forcePos = {}; + nodes.forEach((node) => id2forcePos[node.nodeId] = [node.x, node.y]); + resolve(id2forcePos); + }); + }); + }; + var forceSearchView_default = forceSearchView; + + // federjs/FederLayout/visDataHandler/hnsw/search/transformHandler.ts + var transformHandler = (nodes, { levelCount, width, height, padding, xBias = 0.65, yBias = 0.4, yOver = 0.1 }) => { + const layerWidth = width - padding[1] - padding[3]; + const layerHeight = (height - padding[0] - padding[2]) / (levelCount - (levelCount - 1) * yOver); + const xRange = extent(nodes, (node) => node.x); + const yRange = extent(nodes, (node) => node.y); + const xOffset = padding[3] + layerWidth * xBias; + const transformFunc = (x2, y2, level) => { + const _x2 = (x2 - xRange[0]) / (xRange[1] - xRange[0]); + const _y2 = (y2 - yRange[0]) / (yRange[1] - yRange[0]); + const newX = xOffset + _x2 * layerWidth * (1 - xBias) - _y2 * layerWidth * xBias; + const newY = padding[0] + layerHeight * (1 - yOver) * (levelCount - 1 - level) + _x2 * layerHeight * (1 - yBias) + _y2 * layerHeight * yBias; + return [newX, newY]; + }; + const layerPos = [ + [layerWidth * xBias, 0], + [layerWidth, layerHeight * (1 - yBias)], + [layerWidth * (1 - xBias), layerHeight], + [0, layerHeight * yBias] + ]; + const layerPosLevels = Array(levelCount).fill(0).map((_, level) => layerPos.map((coord) => [ + coord[0] + padding[3], + coord[1] + padding[0] + layerHeight * (1 - yOver) * (levelCount - 1 - level) + ])); + return { layerPosLevels, transformFunc }; + }; + var transformHandler_default = transformHandler; + + // federjs/FederLayout/visDataHandler/hnsw/search/computeSearchViewTransition.ts + var computeSearchViewTransition = ({ + linksLevels, + entryNodesLevels, + interLevelGap = 1e3, + intraLevelGap = 300 + }) => { + let currentTime = 0; + const targetShowTime = []; + const nodeShowTime = {}; + const linkShowTime = {}; + let isPreLinkImportant = true; + let isSourceChanged = true; + let preSourceIdWithLevel = ""; + for (let level = linksLevels.length - 1; level >= 0; level--) { + const links = linksLevels[level]; + if (links.length === 0) { + const sourceId = entryNodesLevels[level].id; + const sourceIdWithLevel = getNodeIdWithLevel(sourceId, level); + nodeShowTime[sourceIdWithLevel] = currentTime; + } else { + links.forEach((link) => { + const sourceId = link.source.id; + const targetId = link.target.id; + const sourceIdWithLevel = getNodeIdWithLevel(sourceId, level); + const targetIdWithLevel = getNodeIdWithLevel(targetId, level); + const linkIdWithLevel = getLinkIdWithLevel(sourceId, targetId, level); + const isCurrentLinkImportant = link.type === 3 /* Searched */ || link.type === 4 /* Fine */; + isSourceChanged = preSourceIdWithLevel !== sourceIdWithLevel; + const isSourceEntry = !(sourceIdWithLevel in nodeShowTime); + if (isSourceEntry) { + if (level < linksLevels.length - 1) { + const entryLinkIdWithLevel = getEntryLinkIdWithLevel(sourceId, level); + linkShowTime[entryLinkIdWithLevel] = currentTime; + const targetLinkIdWithLevel = getEntryLinkIdWithLevel("target", level); + linkShowTime[targetLinkIdWithLevel] = currentTime; + currentTime += interLevelGap; + isPreLinkImportant = true; + } + targetShowTime[level] = currentTime; + nodeShowTime[sourceIdWithLevel] = currentTime; + } + if (isPreLinkImportant || isCurrentLinkImportant || isSourceChanged) { + currentTime += intraLevelGap; + } else { + currentTime += intraLevelGap * 0.5; + } + linkShowTime[linkIdWithLevel] = currentTime; + if (!(targetIdWithLevel in nodeShowTime)) { + nodeShowTime[targetIdWithLevel] = currentTime += intraLevelGap; + } + isPreLinkImportant = isCurrentLinkImportant; + preSourceIdWithLevel = sourceIdWithLevel; + }); + } + currentTime += intraLevelGap; + isPreLinkImportant = true; + isSourceChanged = true; + } + return { targetShowTime, nodeShowTime, linkShowTime, duration: currentTime }; + }; + var computeSearchViewTransition_default = computeSearchViewTransition; + + // federjs/FederLayout/visDataHandler/hnsw/search/index.ts + var searchViewLayoutHandler = (searchRecords, layoutParams) => __async(void 0, null, function* () { + const visData = parseVisRecords_default(searchRecords); + const { + targetR, + canvasScale = 1, + targetOrigin, + searchViewNodeBasicR, + searchInterLevelTime, + searchIntraLevelTime, + forceIterations + } = layoutParams; + const id2forcePos = yield forceSearchView_default(visData, targetOrigin, forceIterations); + const searchNodesLevels = visData.map((levelData) => levelData.nodes); + searchNodesLevels.forEach((levelData) => levelData.forEach((node) => { + node.forcePos = id2forcePos[node.id]; + node.x = node.forcePos[0]; + node.y = node.forcePos[1]; + })); + const { layerPosLevels, transformFunc } = transformHandler_default(searchNodesLevels.reduce((acc, node) => acc.concat(node), []), layoutParams); + const searchTarget = { + id: "target", + r: targetR * canvasScale, + searchViewPosLevels: range(visData.length).map((i) => transformFunc(...targetOrigin, i)) + }; + searchNodesLevels.forEach((nodes, level) => { + nodes.forEach((node) => { + node.searchViewPosLevels = range(level + 1).map((i) => transformFunc(...node.forcePos, i)); + node.r = (searchViewNodeBasicR + node.type * 0.5) * canvasScale; + }); + }); + const id2searchNode = {}; + searchNodesLevels.forEach((levelData) => levelData.forEach((node) => id2searchNode[node.id] = node)); + const searchLinksLevels = parseVisRecords_default(searchRecords).map((levelData) => levelData.links.filter((link) => link.type !== 0 /* None */)); + searchLinksLevels.forEach((levelData) => levelData.forEach((link) => { + const sourceId = link.source; + const targetId = link.target; + const sourceNode = id2searchNode[sourceId]; + const targetNode = id2searchNode[targetId]; + link.source = sourceNode; + link.target = targetNode; + })); + const entryNodesLevels = visData.map((levelData) => levelData.entryIds.map((id2) => id2searchNode[id2])); + const { targetShowTime, nodeShowTime, linkShowTime, duration } = computeSearchViewTransition_default({ + linksLevels: searchLinksLevels, + entryNodesLevels, + interLevelGap: searchInterLevelTime, + intraLevelGap: searchIntraLevelTime + }); + return { + visData, + id2forcePos, + searchTarget, + entryNodesLevels, + searchNodesLevels, + searchLinksLevels, + searchLayerPosLevels: layerPosLevels, + searchTargetShowTime: targetShowTime, + searchNodeShowTime: nodeShowTime, + searchLinkShowTime: linkShowTime, + searchTransitionDuration: duration, + searchParams: searchRecords.searchParams + }; + }); + + // federjs/FederLayout/visDataHandler/hnsw/search/hnsw3d.ts + var searchViewLayoutHandler3d = (searchRecords, layoutParams) => __async(void 0, null, function* () { + const visData = parseVisRecords_default(searchRecords); + const { + targetR, + canvasScale = 1, + targetOrigin, + searchViewNodeBasicR, + forceIterations + } = layoutParams; + const id2forcePos = yield forceSearchView_default(visData, targetOrigin, forceIterations); + const searchNodesLevels = visData.map((levelData) => levelData.nodes); + searchNodesLevels.forEach((levelData) => levelData.forEach((node) => { + node.forcePos = id2forcePos[node.id]; + node.x = node.forcePos[0]; + node.y = node.forcePos[1]; + })); + const { layerPosLevels, transformFunc } = transformHandler_default(searchNodesLevels.reduce((acc, node) => acc.concat(node), []), layoutParams); + const searchTarget = { + id: "target", + r: targetR * canvasScale, + searchViewPosLevels: range(visData.length).map((i) => transformFunc(...targetOrigin, i)) + }; + searchNodesLevels.forEach((nodes, level) => { + nodes.forEach((node) => { + node.searchViewPosLevels = range(level + 1).map((i) => transformFunc(...node.forcePos, i)); + node.r = (searchViewNodeBasicR + node.type * 0.5) * canvasScale; + }); + }); + const id2searchNode = {}; + searchNodesLevels.forEach((levelData) => levelData.forEach((node) => id2searchNode[node.id] = node)); + const searchLinksLevels = parseVisRecords_default(searchRecords).map((levelData) => levelData.links.filter((link) => link.type !== 0 /* None */)); + searchLinksLevels.forEach((levelData) => levelData.forEach((link) => { + const sourceId = link.source; + const targetId = link.target; + const sourceNode = id2searchNode[sourceId]; + const targetNode = id2searchNode[targetId]; + link.source = sourceNode; + link.target = targetNode; + })); + const entryNodesLevels = visData.map((levelData) => levelData.entryIds.map((id2) => id2searchNode[id2])); + return { + visData, + id2forcePos, + searchTarget, + entryNodesLevels, + searchNodesLevels, + searchLinksLevels, + searchRecords + }; + }); + + // federjs/FederLayout/visDataHandler/hnsw/index.ts + var searchViewLayoutHandlerMap = { + ["default" /* default */]: searchViewLayoutHandler, + ["hnsw3d" /* hnsw3d */]: searchViewLayoutHandler3d + }; + var defaultHnswLayoutParams = { + padding: [80, 200, 60, 220], + forceTime: 3e3, + layerDotNum: 20, + shortenLineD: 8, + overviewLinkLineWidth: 2, + reachableLineWidth: 3, + shortestPathLineWidth: 4, + ellipseRation: 1.4, + shadowBlur: 4, + mouse2nodeBias: 3, + highlightRadiusExt: 0.5, + targetR: 3, + searchViewNodeBasicR: 1.5, + searchInterLevelTime: 300, + searchIntraLevelTime: 100, + HoveredPanelLine_1_x: 15, + HoveredPanelLine_1_y: -25, + HoveredPanelLine_2_x: 30, + hoveredPanelLineWidth: 2, + forceIterations: 100, + targetOrigin: [0, 0] + }; + var FederLayoutHnsw = class { + constructor() { + } + computeOverviewVisData() { + return {}; + } + computeSearchViewVisData(viewType, searchRecords, layoutParams) { + const searchViewLayoutHandler2 = searchViewLayoutHandlerMap[viewType]; + return searchViewLayoutHandler2(searchRecords, Object.assign({}, defaultHnswLayoutParams, layoutParams)); + } + }; + + // federjs/FederLayout/index.ts + var federLayoutHandlerMap = { + ["hnsw" /* hnsw */]: FederLayoutHnsw + }; + var FederLayout = class { + constructor(federIndex) { + this.federIndex = federIndex; + this.indexType = federIndex.indexType; + this.federLayoutHandler = new federLayoutHandlerMap[federIndex.indexType](); + } + getOverviewVisData(viewType, layoutParams) { + return __async(this, null, function* () { + return {}; + }); + } + getSearchViewVisData(actionData, viewType, layoutParams) { + return __async(this, null, function* () { + const searchRecords = yield this.federIndex.getSearchRecords(actionData.target, actionData.searchParams); + console.log("searchRecords", searchRecords); + return this.federLayoutHandler.computeSearchViewVisData(viewType, searchRecords, layoutParams); + }); + } + getVisData(_0) { + return __async(this, arguments, function* ({ + actionType, + actionData, + viewType = "default" /* default */, + layoutParams = {} + }) { + const visData = actionType === "search" /* search */ ? yield this.getSearchViewVisData(actionData, viewType, layoutParams) : yield this.getOverviewVisData(viewType, layoutParams); + return { + indexType: this.indexType, + actionType, + actionData, + viewType, + visData + }; + }); + } + }; + + // federjs/FederView/InfoPanel/index.ts + var infoPanel = class { + constructor(styles = {}, viewParams = {}) { + } + init() { + } + setContext(context = null) { + } + setPosition(pos = null) { + } + }; + + // node_modules/three/build/three.module.js + var REVISION = "143"; + var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; + var TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; + var CullFaceNone = 0; + var CullFaceBack = 1; + var CullFaceFront = 2; + var PCFShadowMap = 1; + var PCFSoftShadowMap = 2; + var VSMShadowMap = 3; + var FrontSide = 0; + var BackSide = 1; + var DoubleSide = 2; + var FlatShading = 1; + var NoBlending = 0; + var NormalBlending = 1; + var AdditiveBlending = 2; + var SubtractiveBlending = 3; + var MultiplyBlending = 4; + var CustomBlending = 5; + var AddEquation = 100; + var SubtractEquation = 101; + var ReverseSubtractEquation = 102; + var MinEquation = 103; + var MaxEquation = 104; + var ZeroFactor = 200; + var OneFactor = 201; + var SrcColorFactor = 202; + var OneMinusSrcColorFactor = 203; + var SrcAlphaFactor = 204; + var OneMinusSrcAlphaFactor = 205; + var DstAlphaFactor = 206; + var OneMinusDstAlphaFactor = 207; + var DstColorFactor = 208; + var OneMinusDstColorFactor = 209; + var SrcAlphaSaturateFactor = 210; + var NeverDepth = 0; + var AlwaysDepth = 1; + var LessDepth = 2; + var LessEqualDepth = 3; + var EqualDepth = 4; + var GreaterEqualDepth = 5; + var GreaterDepth = 6; + var NotEqualDepth = 7; + var MultiplyOperation = 0; + var MixOperation = 1; + var AddOperation = 2; + var NoToneMapping = 0; + var LinearToneMapping = 1; + var ReinhardToneMapping = 2; + var CineonToneMapping = 3; + var ACESFilmicToneMapping = 4; + var CustomToneMapping = 5; + var UVMapping = 300; + var CubeReflectionMapping = 301; + var CubeRefractionMapping = 302; + var EquirectangularReflectionMapping = 303; + var EquirectangularRefractionMapping = 304; + var CubeUVReflectionMapping = 306; + var RepeatWrapping = 1e3; + var ClampToEdgeWrapping = 1001; + var MirroredRepeatWrapping = 1002; + var NearestFilter = 1003; + var NearestMipmapNearestFilter = 1004; + var NearestMipmapLinearFilter = 1005; + var LinearFilter = 1006; + var LinearMipmapNearestFilter = 1007; + var LinearMipmapLinearFilter = 1008; + var UnsignedByteType = 1009; + var ByteType = 1010; + var ShortType = 1011; + var UnsignedShortType = 1012; + var IntType = 1013; + var UnsignedIntType = 1014; + var FloatType = 1015; + var HalfFloatType = 1016; + var UnsignedShort4444Type = 1017; + var UnsignedShort5551Type = 1018; + var UnsignedInt248Type = 1020; + var AlphaFormat = 1021; + var RGBFormat = 1022; + var RGBAFormat = 1023; + var LuminanceFormat = 1024; + var LuminanceAlphaFormat = 1025; + var DepthFormat = 1026; + var DepthStencilFormat = 1027; + var RedFormat = 1028; + var RedIntegerFormat = 1029; + var RGFormat = 1030; + var RGIntegerFormat = 1031; + var RGBAIntegerFormat = 1033; + var RGB_S3TC_DXT1_Format = 33776; + var RGBA_S3TC_DXT1_Format = 33777; + var RGBA_S3TC_DXT3_Format = 33778; + var RGBA_S3TC_DXT5_Format = 33779; + var RGB_PVRTC_4BPPV1_Format = 35840; + var RGB_PVRTC_2BPPV1_Format = 35841; + var RGBA_PVRTC_4BPPV1_Format = 35842; + var RGBA_PVRTC_2BPPV1_Format = 35843; + var RGB_ETC1_Format = 36196; + var RGB_ETC2_Format = 37492; + var RGBA_ETC2_EAC_Format = 37496; + var RGBA_ASTC_4x4_Format = 37808; + var RGBA_ASTC_5x4_Format = 37809; + var RGBA_ASTC_5x5_Format = 37810; + var RGBA_ASTC_6x5_Format = 37811; + var RGBA_ASTC_6x6_Format = 37812; + var RGBA_ASTC_8x5_Format = 37813; + var RGBA_ASTC_8x6_Format = 37814; + var RGBA_ASTC_8x8_Format = 37815; + var RGBA_ASTC_10x5_Format = 37816; + var RGBA_ASTC_10x6_Format = 37817; + var RGBA_ASTC_10x8_Format = 37818; + var RGBA_ASTC_10x10_Format = 37819; + var RGBA_ASTC_12x10_Format = 37820; + var RGBA_ASTC_12x12_Format = 37821; + var RGBA_BPTC_Format = 36492; + var InterpolateDiscrete = 2300; + var InterpolateLinear = 2301; + var InterpolateSmooth = 2302; + var ZeroCurvatureEnding = 2400; + var ZeroSlopeEnding = 2401; + var WrapAroundEnding = 2402; + var LinearEncoding = 3e3; + var sRGBEncoding = 3001; + var BasicDepthPacking = 3200; + var RGBADepthPacking = 3201; + var TangentSpaceNormalMap = 0; + var ObjectSpaceNormalMap = 1; + var SRGBColorSpace = "srgb"; + var LinearSRGBColorSpace = "srgb-linear"; + var KeepStencilOp = 7680; + var AlwaysStencilFunc = 519; + var StaticDrawUsage = 35044; + var GLSL3 = "300 es"; + var _SRGBAFormat = 1035; + var EventDispatcher = class { + addEventListener(type2, listener) { + if (this._listeners === void 0) + this._listeners = {}; + const listeners = this._listeners; + if (listeners[type2] === void 0) { + listeners[type2] = []; + } + if (listeners[type2].indexOf(listener) === -1) { + listeners[type2].push(listener); + } + } + hasEventListener(type2, listener) { + if (this._listeners === void 0) + return false; + const listeners = this._listeners; + return listeners[type2] !== void 0 && listeners[type2].indexOf(listener) !== -1; + } + removeEventListener(type2, listener) { + if (this._listeners === void 0) + return; + const listeners = this._listeners; + const listenerArray = listeners[type2]; + if (listenerArray !== void 0) { + const index2 = listenerArray.indexOf(listener); + if (index2 !== -1) { + listenerArray.splice(index2, 1); + } + } + } + dispatchEvent(event) { + if (this._listeners === void 0) + return; + const listeners = this._listeners; + const listenerArray = listeners[event.type]; + if (listenerArray !== void 0) { + event.target = this; + const array2 = listenerArray.slice(0); + for (let i = 0, l = array2.length; i < l; i++) { + array2[i].call(this, event); + } + event.target = null; + } + } + }; + var _lut = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"]; + var DEG2RAD = Math.PI / 180; + var RAD2DEG = 180 / Math.PI; + function generateUUID() { + const d0 = Math.random() * 4294967295 | 0; + const d1 = Math.random() * 4294967295 | 0; + const d2 = Math.random() * 4294967295 | 0; + const d3 = Math.random() * 4294967295 | 0; + const uuid = _lut[d0 & 255] + _lut[d0 >> 8 & 255] + _lut[d0 >> 16 & 255] + _lut[d0 >> 24 & 255] + "-" + _lut[d1 & 255] + _lut[d1 >> 8 & 255] + "-" + _lut[d1 >> 16 & 15 | 64] + _lut[d1 >> 24 & 255] + "-" + _lut[d2 & 63 | 128] + _lut[d2 >> 8 & 255] + "-" + _lut[d2 >> 16 & 255] + _lut[d2 >> 24 & 255] + _lut[d3 & 255] + _lut[d3 >> 8 & 255] + _lut[d3 >> 16 & 255] + _lut[d3 >> 24 & 255]; + return uuid.toLowerCase(); + } + function clamp(value, min2, max2) { + return Math.max(min2, Math.min(max2, value)); + } + function euclideanModulo(n, m2) { + return (n % m2 + m2) % m2; + } + function lerp(x2, y2, t) { + return (1 - t) * x2 + t * y2; + } + function isPowerOfTwo(value) { + return (value & value - 1) === 0 && value !== 0; + } + function floorPowerOfTwo(value) { + return Math.pow(2, Math.floor(Math.log(value) / Math.LN2)); + } + var Vector2 = class { + constructor(x2 = 0, y2 = 0) { + Vector2.prototype.isVector2 = true; + this.x = x2; + this.y = y2; + } + get width() { + return this.x; + } + set width(value) { + this.x = value; + } + get height() { + return this.y; + } + set height(value) { + this.y = value; + } + set(x2, y2) { + this.x = x2; + this.y = y2; + return this; + } + setScalar(scalar) { + this.x = scalar; + this.y = scalar; + return this; + } + setX(x2) { + this.x = x2; + return this; + } + setY(y2) { + this.y = y2; + return this; + } + setComponent(index2, value) { + switch (index2) { + case 0: + this.x = value; + break; + case 1: + this.y = value; + break; + default: + throw new Error("index is out of range: " + index2); + } + return this; + } + getComponent(index2) { + switch (index2) { + case 0: + return this.x; + case 1: + return this.y; + default: + throw new Error("index is out of range: " + index2); + } + } + clone() { + return new this.constructor(this.x, this.y); + } + copy(v) { + this.x = v.x; + this.y = v.y; + return this; + } + add(v) { + this.x += v.x; + this.y += v.y; + return this; + } + addScalar(s) { + this.x += s; + this.y += s; + return this; + } + addVectors(a2, b) { + this.x = a2.x + b.x; + this.y = a2.y + b.y; + return this; + } + addScaledVector(v, s) { + this.x += v.x * s; + this.y += v.y * s; + return this; + } + sub(v) { + this.x -= v.x; + this.y -= v.y; + return this; + } + subScalar(s) { + this.x -= s; + this.y -= s; + return this; + } + subVectors(a2, b) { + this.x = a2.x - b.x; + this.y = a2.y - b.y; + return this; + } + multiply(v) { + this.x *= v.x; + this.y *= v.y; + return this; + } + multiplyScalar(scalar) { + this.x *= scalar; + this.y *= scalar; + return this; + } + divide(v) { + this.x /= v.x; + this.y /= v.y; + return this; + } + divideScalar(scalar) { + return this.multiplyScalar(1 / scalar); + } + applyMatrix3(m2) { + const x2 = this.x, y2 = this.y; + const e = m2.elements; + this.x = e[0] * x2 + e[3] * y2 + e[6]; + this.y = e[1] * x2 + e[4] * y2 + e[7]; + return this; + } + min(v) { + this.x = Math.min(this.x, v.x); + this.y = Math.min(this.y, v.y); + return this; + } + max(v) { + this.x = Math.max(this.x, v.x); + this.y = Math.max(this.y, v.y); + return this; + } + clamp(min2, max2) { + this.x = Math.max(min2.x, Math.min(max2.x, this.x)); + this.y = Math.max(min2.y, Math.min(max2.y, this.y)); + return this; + } + clampScalar(minVal, maxVal) { + this.x = Math.max(minVal, Math.min(maxVal, this.x)); + this.y = Math.max(minVal, Math.min(maxVal, this.y)); + return this; + } + clampLength(min2, max2) { + const length = this.length(); + return this.divideScalar(length || 1).multiplyScalar(Math.max(min2, Math.min(max2, length))); + } + floor() { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + return this; + } + ceil() { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + return this; + } + round() { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + return this; + } + roundToZero() { + this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x); + this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y); + return this; + } + negate() { + this.x = -this.x; + this.y = -this.y; + return this; + } + dot(v) { + return this.x * v.x + this.y * v.y; + } + cross(v) { + return this.x * v.y - this.y * v.x; + } + lengthSq() { + return this.x * this.x + this.y * this.y; + } + length() { + return Math.sqrt(this.x * this.x + this.y * this.y); + } + manhattanLength() { + return Math.abs(this.x) + Math.abs(this.y); + } + normalize() { + return this.divideScalar(this.length() || 1); + } + angle() { + const angle = Math.atan2(-this.y, -this.x) + Math.PI; + return angle; + } + distanceTo(v) { + return Math.sqrt(this.distanceToSquared(v)); + } + distanceToSquared(v) { + const dx = this.x - v.x, dy = this.y - v.y; + return dx * dx + dy * dy; + } + manhattanDistanceTo(v) { + return Math.abs(this.x - v.x) + Math.abs(this.y - v.y); + } + setLength(length) { + return this.normalize().multiplyScalar(length); + } + lerp(v, alpha) { + this.x += (v.x - this.x) * alpha; + this.y += (v.y - this.y) * alpha; + return this; + } + lerpVectors(v1, v2, alpha) { + this.x = v1.x + (v2.x - v1.x) * alpha; + this.y = v1.y + (v2.y - v1.y) * alpha; + return this; + } + equals(v) { + return v.x === this.x && v.y === this.y; + } + fromArray(array2, offset = 0) { + this.x = array2[offset]; + this.y = array2[offset + 1]; + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this.x; + array2[offset + 1] = this.y; + return array2; + } + fromBufferAttribute(attribute, index2) { + this.x = attribute.getX(index2); + this.y = attribute.getY(index2); + return this; + } + rotateAround(center, angle) { + const c2 = Math.cos(angle), s = Math.sin(angle); + const x2 = this.x - center.x; + const y2 = this.y - center.y; + this.x = x2 * c2 - y2 * s + center.x; + this.y = x2 * s + y2 * c2 + center.y; + return this; + } + random() { + this.x = Math.random(); + this.y = Math.random(); + return this; + } + *[Symbol.iterator]() { + yield this.x; + yield this.y; + } + }; + var Matrix3 = class { + constructor() { + Matrix3.prototype.isMatrix3 = true; + this.elements = [ + 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 + ]; + } + set(n11, n12, n13, n21, n22, n23, n31, n32, n33) { + const te = this.elements; + te[0] = n11; + te[1] = n21; + te[2] = n31; + te[3] = n12; + te[4] = n22; + te[5] = n32; + te[6] = n13; + te[7] = n23; + te[8] = n33; + return this; + } + identity() { + this.set(1, 0, 0, 0, 1, 0, 0, 0, 1); + return this; + } + copy(m2) { + const te = this.elements; + const me = m2.elements; + te[0] = me[0]; + te[1] = me[1]; + te[2] = me[2]; + te[3] = me[3]; + te[4] = me[4]; + te[5] = me[5]; + te[6] = me[6]; + te[7] = me[7]; + te[8] = me[8]; + return this; + } + extractBasis(xAxis, yAxis, zAxis) { + xAxis.setFromMatrix3Column(this, 0); + yAxis.setFromMatrix3Column(this, 1); + zAxis.setFromMatrix3Column(this, 2); + return this; + } + setFromMatrix4(m2) { + const me = m2.elements; + this.set(me[0], me[4], me[8], me[1], me[5], me[9], me[2], me[6], me[10]); + return this; + } + multiply(m2) { + return this.multiplyMatrices(this, m2); + } + premultiply(m2) { + return this.multiplyMatrices(m2, this); + } + multiplyMatrices(a2, b) { + const ae = a2.elements; + const be = b.elements; + const te = this.elements; + const a11 = ae[0], a12 = ae[3], a13 = ae[6]; + const a21 = ae[1], a22 = ae[4], a23 = ae[7]; + const a31 = ae[2], a32 = ae[5], a33 = ae[8]; + const b11 = be[0], b12 = be[3], b13 = be[6]; + const b21 = be[1], b22 = be[4], b23 = be[7]; + const b31 = be[2], b32 = be[5], b33 = be[8]; + te[0] = a11 * b11 + a12 * b21 + a13 * b31; + te[3] = a11 * b12 + a12 * b22 + a13 * b32; + te[6] = a11 * b13 + a12 * b23 + a13 * b33; + te[1] = a21 * b11 + a22 * b21 + a23 * b31; + te[4] = a21 * b12 + a22 * b22 + a23 * b32; + te[7] = a21 * b13 + a22 * b23 + a23 * b33; + te[2] = a31 * b11 + a32 * b21 + a33 * b31; + te[5] = a31 * b12 + a32 * b22 + a33 * b32; + te[8] = a31 * b13 + a32 * b23 + a33 * b33; + return this; + } + multiplyScalar(s) { + const te = this.elements; + te[0] *= s; + te[3] *= s; + te[6] *= s; + te[1] *= s; + te[4] *= s; + te[7] *= s; + te[2] *= s; + te[5] *= s; + te[8] *= s; + return this; + } + determinant() { + const te = this.elements; + const a2 = te[0], b = te[1], c2 = te[2], d = te[3], e = te[4], f = te[5], g = te[6], h = te[7], i = te[8]; + return a2 * e * i - a2 * f * h - b * d * i + b * f * g + c2 * d * h - c2 * e * g; + } + invert() { + const te = this.elements, n11 = te[0], n21 = te[1], n31 = te[2], n12 = te[3], n22 = te[4], n32 = te[5], n13 = te[6], n23 = te[7], n33 = te[8], t11 = n33 * n22 - n32 * n23, t12 = n32 * n13 - n33 * n12, t13 = n23 * n12 - n22 * n13, det = n11 * t11 + n21 * t12 + n31 * t13; + if (det === 0) + return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0); + const detInv = 1 / det; + te[0] = t11 * detInv; + te[1] = (n31 * n23 - n33 * n21) * detInv; + te[2] = (n32 * n21 - n31 * n22) * detInv; + te[3] = t12 * detInv; + te[4] = (n33 * n11 - n31 * n13) * detInv; + te[5] = (n31 * n12 - n32 * n11) * detInv; + te[6] = t13 * detInv; + te[7] = (n21 * n13 - n23 * n11) * detInv; + te[8] = (n22 * n11 - n21 * n12) * detInv; + return this; + } + transpose() { + let tmp; + const m2 = this.elements; + tmp = m2[1]; + m2[1] = m2[3]; + m2[3] = tmp; + tmp = m2[2]; + m2[2] = m2[6]; + m2[6] = tmp; + tmp = m2[5]; + m2[5] = m2[7]; + m2[7] = tmp; + return this; + } + getNormalMatrix(matrix4) { + return this.setFromMatrix4(matrix4).invert().transpose(); + } + transposeIntoArray(r) { + const m2 = this.elements; + r[0] = m2[0]; + r[1] = m2[3]; + r[2] = m2[6]; + r[3] = m2[1]; + r[4] = m2[4]; + r[5] = m2[7]; + r[6] = m2[2]; + r[7] = m2[5]; + r[8] = m2[8]; + return this; + } + setUvTransform(tx, ty, sx, sy, rotation, cx, cy) { + const c2 = Math.cos(rotation); + const s = Math.sin(rotation); + this.set(sx * c2, sx * s, -sx * (c2 * cx + s * cy) + cx + tx, -sy * s, sy * c2, -sy * (-s * cx + c2 * cy) + cy + ty, 0, 0, 1); + return this; + } + scale(sx, sy) { + const te = this.elements; + te[0] *= sx; + te[3] *= sx; + te[6] *= sx; + te[1] *= sy; + te[4] *= sy; + te[7] *= sy; + return this; + } + rotate(theta) { + const c2 = Math.cos(theta); + const s = Math.sin(theta); + const te = this.elements; + const a11 = te[0], a12 = te[3], a13 = te[6]; + const a21 = te[1], a22 = te[4], a23 = te[7]; + te[0] = c2 * a11 + s * a21; + te[3] = c2 * a12 + s * a22; + te[6] = c2 * a13 + s * a23; + te[1] = -s * a11 + c2 * a21; + te[4] = -s * a12 + c2 * a22; + te[7] = -s * a13 + c2 * a23; + return this; + } + translate(tx, ty) { + const te = this.elements; + te[0] += tx * te[2]; + te[3] += tx * te[5]; + te[6] += tx * te[8]; + te[1] += ty * te[2]; + te[4] += ty * te[5]; + te[7] += ty * te[8]; + return this; + } + equals(matrix) { + const te = this.elements; + const me = matrix.elements; + for (let i = 0; i < 9; i++) { + if (te[i] !== me[i]) + return false; + } + return true; + } + fromArray(array2, offset = 0) { + for (let i = 0; i < 9; i++) { + this.elements[i] = array2[i + offset]; + } + return this; + } + toArray(array2 = [], offset = 0) { + const te = this.elements; + array2[offset] = te[0]; + array2[offset + 1] = te[1]; + array2[offset + 2] = te[2]; + array2[offset + 3] = te[3]; + array2[offset + 4] = te[4]; + array2[offset + 5] = te[5]; + array2[offset + 6] = te[6]; + array2[offset + 7] = te[7]; + array2[offset + 8] = te[8]; + return array2; + } + clone() { + return new this.constructor().fromArray(this.elements); + } + }; + function arrayNeedsUint32(array2) { + for (let i = array2.length - 1; i >= 0; --i) { + if (array2[i] > 65535) + return true; + } + return false; + } + function createElementNS(name) { + return document.createElementNS("http://www.w3.org/1999/xhtml", name); + } + function SRGBToLinear(c2) { + return c2 < 0.04045 ? c2 * 0.0773993808 : Math.pow(c2 * 0.9478672986 + 0.0521327014, 2.4); + } + function LinearToSRGB(c2) { + return c2 < 31308e-7 ? c2 * 12.92 : 1.055 * Math.pow(c2, 0.41666) - 0.055; + } + var FN = { + [SRGBColorSpace]: { [LinearSRGBColorSpace]: SRGBToLinear }, + [LinearSRGBColorSpace]: { [SRGBColorSpace]: LinearToSRGB } + }; + var ColorManagement = { + legacyMode: true, + get workingColorSpace() { + return LinearSRGBColorSpace; + }, + set workingColorSpace(colorSpace) { + console.warn("THREE.ColorManagement: .workingColorSpace is readonly."); + }, + convert: function(color2, sourceColorSpace, targetColorSpace) { + if (this.legacyMode || sourceColorSpace === targetColorSpace || !sourceColorSpace || !targetColorSpace) { + return color2; + } + if (FN[sourceColorSpace] && FN[sourceColorSpace][targetColorSpace] !== void 0) { + const fn = FN[sourceColorSpace][targetColorSpace]; + color2.r = fn(color2.r); + color2.g = fn(color2.g); + color2.b = fn(color2.b); + return color2; + } + throw new Error("Unsupported color space conversion."); + }, + fromWorkingColorSpace: function(color2, targetColorSpace) { + return this.convert(color2, this.workingColorSpace, targetColorSpace); + }, + toWorkingColorSpace: function(color2, sourceColorSpace) { + return this.convert(color2, sourceColorSpace, this.workingColorSpace); + } + }; + var _colorKeywords = { + "aliceblue": 15792383, + "antiquewhite": 16444375, + "aqua": 65535, + "aquamarine": 8388564, + "azure": 15794175, + "beige": 16119260, + "bisque": 16770244, + "black": 0, + "blanchedalmond": 16772045, + "blue": 255, + "blueviolet": 9055202, + "brown": 10824234, + "burlywood": 14596231, + "cadetblue": 6266528, + "chartreuse": 8388352, + "chocolate": 13789470, + "coral": 16744272, + "cornflowerblue": 6591981, + "cornsilk": 16775388, + "crimson": 14423100, + "cyan": 65535, + "darkblue": 139, + "darkcyan": 35723, + "darkgoldenrod": 12092939, + "darkgray": 11119017, + "darkgreen": 25600, + "darkgrey": 11119017, + "darkkhaki": 12433259, + "darkmagenta": 9109643, + "darkolivegreen": 5597999, + "darkorange": 16747520, + "darkorchid": 10040012, + "darkred": 9109504, + "darksalmon": 15308410, + "darkseagreen": 9419919, + "darkslateblue": 4734347, + "darkslategray": 3100495, + "darkslategrey": 3100495, + "darkturquoise": 52945, + "darkviolet": 9699539, + "deeppink": 16716947, + "deepskyblue": 49151, + "dimgray": 6908265, + "dimgrey": 6908265, + "dodgerblue": 2003199, + "firebrick": 11674146, + "floralwhite": 16775920, + "forestgreen": 2263842, + "fuchsia": 16711935, + "gainsboro": 14474460, + "ghostwhite": 16316671, + "gold": 16766720, + "goldenrod": 14329120, + "gray": 8421504, + "green": 32768, + "greenyellow": 11403055, + "grey": 8421504, + "honeydew": 15794160, + "hotpink": 16738740, + "indianred": 13458524, + "indigo": 4915330, + "ivory": 16777200, + "khaki": 15787660, + "lavender": 15132410, + "lavenderblush": 16773365, + "lawngreen": 8190976, + "lemonchiffon": 16775885, + "lightblue": 11393254, + "lightcoral": 15761536, + "lightcyan": 14745599, + "lightgoldenrodyellow": 16448210, + "lightgray": 13882323, + "lightgreen": 9498256, + "lightgrey": 13882323, + "lightpink": 16758465, + "lightsalmon": 16752762, + "lightseagreen": 2142890, + "lightskyblue": 8900346, + "lightslategray": 7833753, + "lightslategrey": 7833753, + "lightsteelblue": 11584734, + "lightyellow": 16777184, + "lime": 65280, + "limegreen": 3329330, + "linen": 16445670, + "magenta": 16711935, + "maroon": 8388608, + "mediumaquamarine": 6737322, + "mediumblue": 205, + "mediumorchid": 12211667, + "mediumpurple": 9662683, + "mediumseagreen": 3978097, + "mediumslateblue": 8087790, + "mediumspringgreen": 64154, + "mediumturquoise": 4772300, + "mediumvioletred": 13047173, + "midnightblue": 1644912, + "mintcream": 16121850, + "mistyrose": 16770273, + "moccasin": 16770229, + "navajowhite": 16768685, + "navy": 128, + "oldlace": 16643558, + "olive": 8421376, + "olivedrab": 7048739, + "orange": 16753920, + "orangered": 16729344, + "orchid": 14315734, + "palegoldenrod": 15657130, + "palegreen": 10025880, + "paleturquoise": 11529966, + "palevioletred": 14381203, + "papayawhip": 16773077, + "peachpuff": 16767673, + "peru": 13468991, + "pink": 16761035, + "plum": 14524637, + "powderblue": 11591910, + "purple": 8388736, + "rebeccapurple": 6697881, + "red": 16711680, + "rosybrown": 12357519, + "royalblue": 4286945, + "saddlebrown": 9127187, + "salmon": 16416882, + "sandybrown": 16032864, + "seagreen": 3050327, + "seashell": 16774638, + "sienna": 10506797, + "silver": 12632256, + "skyblue": 8900331, + "slateblue": 6970061, + "slategray": 7372944, + "slategrey": 7372944, + "snow": 16775930, + "springgreen": 65407, + "steelblue": 4620980, + "tan": 13808780, + "teal": 32896, + "thistle": 14204888, + "tomato": 16737095, + "turquoise": 4251856, + "violet": 15631086, + "wheat": 16113331, + "white": 16777215, + "whitesmoke": 16119285, + "yellow": 16776960, + "yellowgreen": 10145074 + }; + var _rgb = { r: 0, g: 0, b: 0 }; + var _hslA = { h: 0, s: 0, l: 0 }; + var _hslB = { h: 0, s: 0, l: 0 }; + function hue2rgb(p, q, t) { + if (t < 0) + t += 1; + if (t > 1) + t -= 1; + if (t < 1 / 6) + return p + (q - p) * 6 * t; + if (t < 1 / 2) + return q; + if (t < 2 / 3) + return p + (q - p) * 6 * (2 / 3 - t); + return p; + } + function toComponents(source, target) { + target.r = source.r; + target.g = source.g; + target.b = source.b; + return target; + } + var Color2 = class { + constructor(r, g, b) { + this.isColor = true; + this.r = 1; + this.g = 1; + this.b = 1; + if (g === void 0 && b === void 0) { + return this.set(r); + } + return this.setRGB(r, g, b); + } + set(value) { + if (value && value.isColor) { + this.copy(value); + } else if (typeof value === "number") { + this.setHex(value); + } else if (typeof value === "string") { + this.setStyle(value); + } + return this; + } + setScalar(scalar) { + this.r = scalar; + this.g = scalar; + this.b = scalar; + return this; + } + setHex(hex2, colorSpace = SRGBColorSpace) { + hex2 = Math.floor(hex2); + this.r = (hex2 >> 16 & 255) / 255; + this.g = (hex2 >> 8 & 255) / 255; + this.b = (hex2 & 255) / 255; + ColorManagement.toWorkingColorSpace(this, colorSpace); + return this; + } + setRGB(r, g, b, colorSpace = LinearSRGBColorSpace) { + this.r = r; + this.g = g; + this.b = b; + ColorManagement.toWorkingColorSpace(this, colorSpace); + return this; + } + setHSL(h, s, l, colorSpace = LinearSRGBColorSpace) { + h = euclideanModulo(h, 1); + s = clamp(s, 0, 1); + l = clamp(l, 0, 1); + if (s === 0) { + this.r = this.g = this.b = l; + } else { + const p = l <= 0.5 ? l * (1 + s) : l + s - l * s; + const q = 2 * l - p; + this.r = hue2rgb(q, p, h + 1 / 3); + this.g = hue2rgb(q, p, h); + this.b = hue2rgb(q, p, h - 1 / 3); + } + ColorManagement.toWorkingColorSpace(this, colorSpace); + return this; + } + setStyle(style, colorSpace = SRGBColorSpace) { + function handleAlpha(string) { + if (string === void 0) + return; + if (parseFloat(string) < 1) { + console.warn("THREE.Color: Alpha component of " + style + " will be ignored."); + } + } + let m2; + if (m2 = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(style)) { + let color2; + const name = m2[1]; + const components = m2[2]; + switch (name) { + case "rgb": + case "rgba": + if (color2 = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) { + this.r = Math.min(255, parseInt(color2[1], 10)) / 255; + this.g = Math.min(255, parseInt(color2[2], 10)) / 255; + this.b = Math.min(255, parseInt(color2[3], 10)) / 255; + ColorManagement.toWorkingColorSpace(this, colorSpace); + handleAlpha(color2[4]); + return this; + } + if (color2 = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) { + this.r = Math.min(100, parseInt(color2[1], 10)) / 100; + this.g = Math.min(100, parseInt(color2[2], 10)) / 100; + this.b = Math.min(100, parseInt(color2[3], 10)) / 100; + ColorManagement.toWorkingColorSpace(this, colorSpace); + handleAlpha(color2[4]); + return this; + } + break; + case "hsl": + case "hsla": + if (color2 = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) { + const h = parseFloat(color2[1]) / 360; + const s = parseInt(color2[2], 10) / 100; + const l = parseInt(color2[3], 10) / 100; + handleAlpha(color2[4]); + return this.setHSL(h, s, l, colorSpace); + } + break; + } + } else if (m2 = /^\#([A-Fa-f\d]+)$/.exec(style)) { + const hex2 = m2[1]; + const size = hex2.length; + if (size === 3) { + this.r = parseInt(hex2.charAt(0) + hex2.charAt(0), 16) / 255; + this.g = parseInt(hex2.charAt(1) + hex2.charAt(1), 16) / 255; + this.b = parseInt(hex2.charAt(2) + hex2.charAt(2), 16) / 255; + ColorManagement.toWorkingColorSpace(this, colorSpace); + return this; + } else if (size === 6) { + this.r = parseInt(hex2.charAt(0) + hex2.charAt(1), 16) / 255; + this.g = parseInt(hex2.charAt(2) + hex2.charAt(3), 16) / 255; + this.b = parseInt(hex2.charAt(4) + hex2.charAt(5), 16) / 255; + ColorManagement.toWorkingColorSpace(this, colorSpace); + return this; + } + } + if (style && style.length > 0) { + return this.setColorName(style, colorSpace); + } + return this; + } + setColorName(style, colorSpace = SRGBColorSpace) { + const hex2 = _colorKeywords[style.toLowerCase()]; + if (hex2 !== void 0) { + this.setHex(hex2, colorSpace); + } else { + console.warn("THREE.Color: Unknown color " + style); + } + return this; + } + clone() { + return new this.constructor(this.r, this.g, this.b); + } + copy(color2) { + this.r = color2.r; + this.g = color2.g; + this.b = color2.b; + return this; + } + copySRGBToLinear(color2) { + this.r = SRGBToLinear(color2.r); + this.g = SRGBToLinear(color2.g); + this.b = SRGBToLinear(color2.b); + return this; + } + copyLinearToSRGB(color2) { + this.r = LinearToSRGB(color2.r); + this.g = LinearToSRGB(color2.g); + this.b = LinearToSRGB(color2.b); + return this; + } + convertSRGBToLinear() { + this.copySRGBToLinear(this); + return this; + } + convertLinearToSRGB() { + this.copyLinearToSRGB(this); + return this; + } + getHex(colorSpace = SRGBColorSpace) { + ColorManagement.fromWorkingColorSpace(toComponents(this, _rgb), colorSpace); + return clamp(_rgb.r * 255, 0, 255) << 16 ^ clamp(_rgb.g * 255, 0, 255) << 8 ^ clamp(_rgb.b * 255, 0, 255) << 0; + } + getHexString(colorSpace = SRGBColorSpace) { + return ("000000" + this.getHex(colorSpace).toString(16)).slice(-6); + } + getHSL(target, colorSpace = LinearSRGBColorSpace) { + ColorManagement.fromWorkingColorSpace(toComponents(this, _rgb), colorSpace); + const r = _rgb.r, g = _rgb.g, b = _rgb.b; + const max2 = Math.max(r, g, b); + const min2 = Math.min(r, g, b); + let hue, saturation; + const lightness = (min2 + max2) / 2; + if (min2 === max2) { + hue = 0; + saturation = 0; + } else { + const delta = max2 - min2; + saturation = lightness <= 0.5 ? delta / (max2 + min2) : delta / (2 - max2 - min2); + switch (max2) { + case r: + hue = (g - b) / delta + (g < b ? 6 : 0); + break; + case g: + hue = (b - r) / delta + 2; + break; + case b: + hue = (r - g) / delta + 4; + break; + } + hue /= 6; + } + target.h = hue; + target.s = saturation; + target.l = lightness; + return target; + } + getRGB(target, colorSpace = LinearSRGBColorSpace) { + ColorManagement.fromWorkingColorSpace(toComponents(this, _rgb), colorSpace); + target.r = _rgb.r; + target.g = _rgb.g; + target.b = _rgb.b; + return target; + } + getStyle(colorSpace = SRGBColorSpace) { + ColorManagement.fromWorkingColorSpace(toComponents(this, _rgb), colorSpace); + if (colorSpace !== SRGBColorSpace) { + return `color(${colorSpace} ${_rgb.r} ${_rgb.g} ${_rgb.b})`; + } + return `rgb(${_rgb.r * 255 | 0},${_rgb.g * 255 | 0},${_rgb.b * 255 | 0})`; + } + offsetHSL(h, s, l) { + this.getHSL(_hslA); + _hslA.h += h; + _hslA.s += s; + _hslA.l += l; + this.setHSL(_hslA.h, _hslA.s, _hslA.l); + return this; + } + add(color2) { + this.r += color2.r; + this.g += color2.g; + this.b += color2.b; + return this; + } + addColors(color1, color2) { + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; + return this; + } + addScalar(s) { + this.r += s; + this.g += s; + this.b += s; + return this; + } + sub(color2) { + this.r = Math.max(0, this.r - color2.r); + this.g = Math.max(0, this.g - color2.g); + this.b = Math.max(0, this.b - color2.b); + return this; + } + multiply(color2) { + this.r *= color2.r; + this.g *= color2.g; + this.b *= color2.b; + return this; + } + multiplyScalar(s) { + this.r *= s; + this.g *= s; + this.b *= s; + return this; + } + lerp(color2, alpha) { + this.r += (color2.r - this.r) * alpha; + this.g += (color2.g - this.g) * alpha; + this.b += (color2.b - this.b) * alpha; + return this; + } + lerpColors(color1, color2, alpha) { + this.r = color1.r + (color2.r - color1.r) * alpha; + this.g = color1.g + (color2.g - color1.g) * alpha; + this.b = color1.b + (color2.b - color1.b) * alpha; + return this; + } + lerpHSL(color2, alpha) { + this.getHSL(_hslA); + color2.getHSL(_hslB); + const h = lerp(_hslA.h, _hslB.h, alpha); + const s = lerp(_hslA.s, _hslB.s, alpha); + const l = lerp(_hslA.l, _hslB.l, alpha); + this.setHSL(h, s, l); + return this; + } + equals(c2) { + return c2.r === this.r && c2.g === this.g && c2.b === this.b; + } + fromArray(array2, offset = 0) { + this.r = array2[offset]; + this.g = array2[offset + 1]; + this.b = array2[offset + 2]; + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this.r; + array2[offset + 1] = this.g; + array2[offset + 2] = this.b; + return array2; + } + fromBufferAttribute(attribute, index2) { + this.r = attribute.getX(index2); + this.g = attribute.getY(index2); + this.b = attribute.getZ(index2); + if (attribute.normalized === true) { + this.r /= 255; + this.g /= 255; + this.b /= 255; + } + return this; + } + toJSON() { + return this.getHex(); + } + *[Symbol.iterator]() { + yield this.r; + yield this.g; + yield this.b; + } + }; + Color2.NAMES = _colorKeywords; + var _canvas; + var ImageUtils = class { + static getDataURL(image) { + if (/^data:/i.test(image.src)) { + return image.src; + } + if (typeof HTMLCanvasElement == "undefined") { + return image.src; + } + let canvas; + if (image instanceof HTMLCanvasElement) { + canvas = image; + } else { + if (_canvas === void 0) + _canvas = createElementNS("canvas"); + _canvas.width = image.width; + _canvas.height = image.height; + const context = _canvas.getContext("2d"); + if (image instanceof ImageData) { + context.putImageData(image, 0, 0); + } else { + context.drawImage(image, 0, 0, image.width, image.height); + } + canvas = _canvas; + } + if (canvas.width > 2048 || canvas.height > 2048) { + console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons", image); + return canvas.toDataURL("image/jpeg", 0.6); + } else { + return canvas.toDataURL("image/png"); + } + } + static sRGBToLinear(image) { + if (typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && image instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) { + const canvas = createElementNS("canvas"); + canvas.width = image.width; + canvas.height = image.height; + const context = canvas.getContext("2d"); + context.drawImage(image, 0, 0, image.width, image.height); + const imageData = context.getImageData(0, 0, image.width, image.height); + const data = imageData.data; + for (let i = 0; i < data.length; i++) { + data[i] = SRGBToLinear(data[i] / 255) * 255; + } + context.putImageData(imageData, 0, 0); + return canvas; + } else if (image.data) { + const data = image.data.slice(0); + for (let i = 0; i < data.length; i++) { + if (data instanceof Uint8Array || data instanceof Uint8ClampedArray) { + data[i] = Math.floor(SRGBToLinear(data[i] / 255) * 255); + } else { + data[i] = SRGBToLinear(data[i]); + } + } + return { + data, + width: image.width, + height: image.height + }; + } else { + console.warn("THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied."); + return image; + } + } + }; + var Source = class { + constructor(data = null) { + this.isSource = true; + this.uuid = generateUUID(); + this.data = data; + this.version = 0; + } + set needsUpdate(value) { + if (value === true) + this.version++; + } + toJSON(meta) { + const isRootObject = meta === void 0 || typeof meta === "string"; + if (!isRootObject && meta.images[this.uuid] !== void 0) { + return meta.images[this.uuid]; + } + const output = { + uuid: this.uuid, + url: "" + }; + const data = this.data; + if (data !== null) { + let url; + if (Array.isArray(data)) { + url = []; + for (let i = 0, l = data.length; i < l; i++) { + if (data[i].isDataTexture) { + url.push(serializeImage(data[i].image)); + } else { + url.push(serializeImage(data[i])); + } + } + } else { + url = serializeImage(data); + } + output.url = url; + } + if (!isRootObject) { + meta.images[this.uuid] = output; + } + return output; + } + }; + function serializeImage(image) { + if (typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && image instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) { + return ImageUtils.getDataURL(image); + } else { + if (image.data) { + return { + data: Array.from(image.data), + width: image.width, + height: image.height, + type: image.data.constructor.name + }; + } else { + console.warn("THREE.Texture: Unable to serialize Texture."); + return {}; + } + } + } + var textureId = 0; + var Texture = class extends EventDispatcher { + constructor(image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format2 = RGBAFormat, type2 = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding) { + super(); + this.isTexture = true; + Object.defineProperty(this, "id", { value: textureId++ }); + this.uuid = generateUUID(); + this.name = ""; + this.source = new Source(image); + this.mipmaps = []; + this.mapping = mapping; + this.wrapS = wrapS; + this.wrapT = wrapT; + this.magFilter = magFilter; + this.minFilter = minFilter; + this.anisotropy = anisotropy; + this.format = format2; + this.internalFormat = null; + this.type = type2; + this.offset = new Vector2(0, 0); + this.repeat = new Vector2(1, 1); + this.center = new Vector2(0, 0); + this.rotation = 0; + this.matrixAutoUpdate = true; + this.matrix = new Matrix3(); + this.generateMipmaps = true; + this.premultiplyAlpha = false; + this.flipY = true; + this.unpackAlignment = 4; + this.encoding = encoding; + this.userData = {}; + this.version = 0; + this.onUpdate = null; + this.isRenderTargetTexture = false; + this.needsPMREMUpdate = false; + } + get image() { + return this.source.data; + } + set image(value) { + this.source.data = value; + } + updateMatrix() { + this.matrix.setUvTransform(this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y); + } + clone() { + return new this.constructor().copy(this); + } + copy(source) { + this.name = source.name; + this.source = source.source; + this.mipmaps = source.mipmaps.slice(0); + this.mapping = source.mapping; + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; + this.anisotropy = source.anisotropy; + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; + this.offset.copy(source.offset); + this.repeat.copy(source.repeat); + this.center.copy(source.center); + this.rotation = source.rotation; + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrix.copy(source.matrix); + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.encoding = source.encoding; + this.userData = JSON.parse(JSON.stringify(source.userData)); + this.needsUpdate = true; + return this; + } + toJSON(meta) { + const isRootObject = meta === void 0 || typeof meta === "string"; + if (!isRootObject && meta.textures[this.uuid] !== void 0) { + return meta.textures[this.uuid]; + } + const output = { + metadata: { + version: 4.5, + type: "Texture", + generator: "Texture.toJSON" + }, + uuid: this.uuid, + name: this.name, + image: this.source.toJSON(meta).uuid, + mapping: this.mapping, + repeat: [this.repeat.x, this.repeat.y], + offset: [this.offset.x, this.offset.y], + center: [this.center.x, this.center.y], + rotation: this.rotation, + wrap: [this.wrapS, this.wrapT], + format: this.format, + type: this.type, + encoding: this.encoding, + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, + flipY: this.flipY, + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment + }; + if (JSON.stringify(this.userData) !== "{}") + output.userData = this.userData; + if (!isRootObject) { + meta.textures[this.uuid] = output; + } + return output; + } + dispose() { + this.dispatchEvent({ type: "dispose" }); + } + transformUv(uv) { + if (this.mapping !== UVMapping) + return uv; + uv.applyMatrix3(this.matrix); + if (uv.x < 0 || uv.x > 1) { + switch (this.wrapS) { + case RepeatWrapping: + uv.x = uv.x - Math.floor(uv.x); + break; + case ClampToEdgeWrapping: + uv.x = uv.x < 0 ? 0 : 1; + break; + case MirroredRepeatWrapping: + if (Math.abs(Math.floor(uv.x) % 2) === 1) { + uv.x = Math.ceil(uv.x) - uv.x; + } else { + uv.x = uv.x - Math.floor(uv.x); + } + break; + } + } + if (uv.y < 0 || uv.y > 1) { + switch (this.wrapT) { + case RepeatWrapping: + uv.y = uv.y - Math.floor(uv.y); + break; + case ClampToEdgeWrapping: + uv.y = uv.y < 0 ? 0 : 1; + break; + case MirroredRepeatWrapping: + if (Math.abs(Math.floor(uv.y) % 2) === 1) { + uv.y = Math.ceil(uv.y) - uv.y; + } else { + uv.y = uv.y - Math.floor(uv.y); + } + break; + } + } + if (this.flipY) { + uv.y = 1 - uv.y; + } + return uv; + } + set needsUpdate(value) { + if (value === true) { + this.version++; + this.source.needsUpdate = true; + } + } + }; + Texture.DEFAULT_IMAGE = null; + Texture.DEFAULT_MAPPING = UVMapping; + var Vector4 = class { + constructor(x2 = 0, y2 = 0, z = 0, w = 1) { + Vector4.prototype.isVector4 = true; + this.x = x2; + this.y = y2; + this.z = z; + this.w = w; + } + get width() { + return this.z; + } + set width(value) { + this.z = value; + } + get height() { + return this.w; + } + set height(value) { + this.w = value; + } + set(x2, y2, z, w) { + this.x = x2; + this.y = y2; + this.z = z; + this.w = w; + return this; + } + setScalar(scalar) { + this.x = scalar; + this.y = scalar; + this.z = scalar; + this.w = scalar; + return this; + } + setX(x2) { + this.x = x2; + return this; + } + setY(y2) { + this.y = y2; + return this; + } + setZ(z) { + this.z = z; + return this; + } + setW(w) { + this.w = w; + return this; + } + setComponent(index2, value) { + switch (index2) { + case 0: + this.x = value; + break; + case 1: + this.y = value; + break; + case 2: + this.z = value; + break; + case 3: + this.w = value; + break; + default: + throw new Error("index is out of range: " + index2); + } + return this; + } + getComponent(index2) { + switch (index2) { + case 0: + return this.x; + case 1: + return this.y; + case 2: + return this.z; + case 3: + return this.w; + default: + throw new Error("index is out of range: " + index2); + } + } + clone() { + return new this.constructor(this.x, this.y, this.z, this.w); + } + copy(v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + this.w = v.w !== void 0 ? v.w : 1; + return this; + } + add(v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + this.w += v.w; + return this; + } + addScalar(s) { + this.x += s; + this.y += s; + this.z += s; + this.w += s; + return this; + } + addVectors(a2, b) { + this.x = a2.x + b.x; + this.y = a2.y + b.y; + this.z = a2.z + b.z; + this.w = a2.w + b.w; + return this; + } + addScaledVector(v, s) { + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + this.w += v.w * s; + return this; + } + sub(v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; + return this; + } + subScalar(s) { + this.x -= s; + this.y -= s; + this.z -= s; + this.w -= s; + return this; + } + subVectors(a2, b) { + this.x = a2.x - b.x; + this.y = a2.y - b.y; + this.z = a2.z - b.z; + this.w = a2.w - b.w; + return this; + } + multiply(v) { + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + this.w *= v.w; + return this; + } + multiplyScalar(scalar) { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + this.w *= scalar; + return this; + } + applyMatrix4(m2) { + const x2 = this.x, y2 = this.y, z = this.z, w = this.w; + const e = m2.elements; + this.x = e[0] * x2 + e[4] * y2 + e[8] * z + e[12] * w; + this.y = e[1] * x2 + e[5] * y2 + e[9] * z + e[13] * w; + this.z = e[2] * x2 + e[6] * y2 + e[10] * z + e[14] * w; + this.w = e[3] * x2 + e[7] * y2 + e[11] * z + e[15] * w; + return this; + } + divideScalar(scalar) { + return this.multiplyScalar(1 / scalar); + } + setAxisAngleFromQuaternion(q) { + this.w = 2 * Math.acos(q.w); + const s = Math.sqrt(1 - q.w * q.w); + if (s < 1e-4) { + this.x = 1; + this.y = 0; + this.z = 0; + } else { + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; + } + return this; + } + setAxisAngleFromRotationMatrix(m2) { + let angle, x2, y2, z; + const epsilon = 0.01, epsilon2 = 0.1, te = m2.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10]; + if (Math.abs(m12 - m21) < epsilon && Math.abs(m13 - m31) < epsilon && Math.abs(m23 - m32) < epsilon) { + if (Math.abs(m12 + m21) < epsilon2 && Math.abs(m13 + m31) < epsilon2 && Math.abs(m23 + m32) < epsilon2 && Math.abs(m11 + m22 + m33 - 3) < epsilon2) { + this.set(1, 0, 0, 0); + return this; + } + angle = Math.PI; + const xx = (m11 + 1) / 2; + const yy = (m22 + 1) / 2; + const zz = (m33 + 1) / 2; + const xy = (m12 + m21) / 4; + const xz = (m13 + m31) / 4; + const yz = (m23 + m32) / 4; + if (xx > yy && xx > zz) { + if (xx < epsilon) { + x2 = 0; + y2 = 0.707106781; + z = 0.707106781; + } else { + x2 = Math.sqrt(xx); + y2 = xy / x2; + z = xz / x2; + } + } else if (yy > zz) { + if (yy < epsilon) { + x2 = 0.707106781; + y2 = 0; + z = 0.707106781; + } else { + y2 = Math.sqrt(yy); + x2 = xy / y2; + z = yz / y2; + } + } else { + if (zz < epsilon) { + x2 = 0.707106781; + y2 = 0.707106781; + z = 0; + } else { + z = Math.sqrt(zz); + x2 = xz / z; + y2 = yz / z; + } + } + this.set(x2, y2, z, angle); + return this; + } + let s = Math.sqrt((m32 - m23) * (m32 - m23) + (m13 - m31) * (m13 - m31) + (m21 - m12) * (m21 - m12)); + if (Math.abs(s) < 1e-3) + s = 1; + this.x = (m32 - m23) / s; + this.y = (m13 - m31) / s; + this.z = (m21 - m12) / s; + this.w = Math.acos((m11 + m22 + m33 - 1) / 2); + return this; + } + min(v) { + this.x = Math.min(this.x, v.x); + this.y = Math.min(this.y, v.y); + this.z = Math.min(this.z, v.z); + this.w = Math.min(this.w, v.w); + return this; + } + max(v) { + this.x = Math.max(this.x, v.x); + this.y = Math.max(this.y, v.y); + this.z = Math.max(this.z, v.z); + this.w = Math.max(this.w, v.w); + return this; + } + clamp(min2, max2) { + this.x = Math.max(min2.x, Math.min(max2.x, this.x)); + this.y = Math.max(min2.y, Math.min(max2.y, this.y)); + this.z = Math.max(min2.z, Math.min(max2.z, this.z)); + this.w = Math.max(min2.w, Math.min(max2.w, this.w)); + return this; + } + clampScalar(minVal, maxVal) { + this.x = Math.max(minVal, Math.min(maxVal, this.x)); + this.y = Math.max(minVal, Math.min(maxVal, this.y)); + this.z = Math.max(minVal, Math.min(maxVal, this.z)); + this.w = Math.max(minVal, Math.min(maxVal, this.w)); + return this; + } + clampLength(min2, max2) { + const length = this.length(); + return this.divideScalar(length || 1).multiplyScalar(Math.max(min2, Math.min(max2, length))); + } + floor() { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + this.w = Math.floor(this.w); + return this; + } + ceil() { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + this.z = Math.ceil(this.z); + this.w = Math.ceil(this.w); + return this; + } + round() { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + this.z = Math.round(this.z); + this.w = Math.round(this.w); + return this; + } + roundToZero() { + this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x); + this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y); + this.z = this.z < 0 ? Math.ceil(this.z) : Math.floor(this.z); + this.w = this.w < 0 ? Math.ceil(this.w) : Math.floor(this.w); + return this; + } + negate() { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + this.w = -this.w; + return this; + } + dot(v) { + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + } + lengthSq() { + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + } + length() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w); + } + manhattanLength() { + return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) + Math.abs(this.w); + } + normalize() { + return this.divideScalar(this.length() || 1); + } + setLength(length) { + return this.normalize().multiplyScalar(length); + } + lerp(v, alpha) { + this.x += (v.x - this.x) * alpha; + this.y += (v.y - this.y) * alpha; + this.z += (v.z - this.z) * alpha; + this.w += (v.w - this.w) * alpha; + return this; + } + lerpVectors(v1, v2, alpha) { + this.x = v1.x + (v2.x - v1.x) * alpha; + this.y = v1.y + (v2.y - v1.y) * alpha; + this.z = v1.z + (v2.z - v1.z) * alpha; + this.w = v1.w + (v2.w - v1.w) * alpha; + return this; + } + equals(v) { + return v.x === this.x && v.y === this.y && v.z === this.z && v.w === this.w; + } + fromArray(array2, offset = 0) { + this.x = array2[offset]; + this.y = array2[offset + 1]; + this.z = array2[offset + 2]; + this.w = array2[offset + 3]; + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this.x; + array2[offset + 1] = this.y; + array2[offset + 2] = this.z; + array2[offset + 3] = this.w; + return array2; + } + fromBufferAttribute(attribute, index2) { + this.x = attribute.getX(index2); + this.y = attribute.getY(index2); + this.z = attribute.getZ(index2); + this.w = attribute.getW(index2); + return this; + } + random() { + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + this.w = Math.random(); + return this; + } + *[Symbol.iterator]() { + yield this.x; + yield this.y; + yield this.z; + yield this.w; + } + }; + var WebGLRenderTarget = class extends EventDispatcher { + constructor(width, height, options = {}) { + super(); + this.isWebGLRenderTarget = true; + this.width = width; + this.height = height; + this.depth = 1; + this.scissor = new Vector4(0, 0, width, height); + this.scissorTest = false; + this.viewport = new Vector4(0, 0, width, height); + const image = { width, height, depth: 1 }; + this.texture = new Texture(image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding); + this.texture.isRenderTargetTexture = true; + this.texture.flipY = false; + this.texture.generateMipmaps = options.generateMipmaps !== void 0 ? options.generateMipmaps : false; + this.texture.internalFormat = options.internalFormat !== void 0 ? options.internalFormat : null; + this.texture.minFilter = options.minFilter !== void 0 ? options.minFilter : LinearFilter; + this.depthBuffer = options.depthBuffer !== void 0 ? options.depthBuffer : true; + this.stencilBuffer = options.stencilBuffer !== void 0 ? options.stencilBuffer : false; + this.depthTexture = options.depthTexture !== void 0 ? options.depthTexture : null; + this.samples = options.samples !== void 0 ? options.samples : 0; + } + setSize(width, height, depth = 1) { + if (this.width !== width || this.height !== height || this.depth !== depth) { + this.width = width; + this.height = height; + this.depth = depth; + this.texture.image.width = width; + this.texture.image.height = height; + this.texture.image.depth = depth; + this.dispose(); + } + this.viewport.set(0, 0, width, height); + this.scissor.set(0, 0, width, height); + } + clone() { + return new this.constructor().copy(this); + } + copy(source) { + this.width = source.width; + this.height = source.height; + this.depth = source.depth; + this.viewport.copy(source.viewport); + this.texture = source.texture.clone(); + this.texture.isRenderTargetTexture = true; + const image = Object.assign({}, source.texture.image); + this.texture.source = new Source(image); + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; + if (source.depthTexture !== null) + this.depthTexture = source.depthTexture.clone(); + this.samples = source.samples; + return this; + } + dispose() { + this.dispatchEvent({ type: "dispose" }); + } + }; + var DataArrayTexture = class extends Texture { + constructor(data = null, width = 1, height = 1, depth = 1) { + super(null); + this.isDataArrayTexture = true; + this.image = { data, width, height, depth }; + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; + this.wrapR = ClampToEdgeWrapping; + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; + } + }; + var Data3DTexture = class extends Texture { + constructor(data = null, width = 1, height = 1, depth = 1) { + super(null); + this.isData3DTexture = true; + this.image = { data, width, height, depth }; + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; + this.wrapR = ClampToEdgeWrapping; + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; + } + }; + var Quaternion = class { + constructor(x2 = 0, y2 = 0, z = 0, w = 1) { + this.isQuaternion = true; + this._x = x2; + this._y = y2; + this._z = z; + this._w = w; + } + static slerpFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t) { + let x0 = src0[srcOffset0 + 0], y0 = src0[srcOffset0 + 1], z0 = src0[srcOffset0 + 2], w0 = src0[srcOffset0 + 3]; + const x1 = src1[srcOffset1 + 0], y1 = src1[srcOffset1 + 1], z1 = src1[srcOffset1 + 2], w1 = src1[srcOffset1 + 3]; + if (t === 0) { + dst[dstOffset + 0] = x0; + dst[dstOffset + 1] = y0; + dst[dstOffset + 2] = z0; + dst[dstOffset + 3] = w0; + return; + } + if (t === 1) { + dst[dstOffset + 0] = x1; + dst[dstOffset + 1] = y1; + dst[dstOffset + 2] = z1; + dst[dstOffset + 3] = w1; + return; + } + if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) { + let s = 1 - t; + const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, dir = cos >= 0 ? 1 : -1, sqrSin = 1 - cos * cos; + if (sqrSin > Number.EPSILON) { + const sin = Math.sqrt(sqrSin), len = Math.atan2(sin, cos * dir); + s = Math.sin(s * len) / sin; + t = Math.sin(t * len) / sin; + } + const tDir = t * dir; + x0 = x0 * s + x1 * tDir; + y0 = y0 * s + y1 * tDir; + z0 = z0 * s + z1 * tDir; + w0 = w0 * s + w1 * tDir; + if (s === 1 - t) { + const f = 1 / Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0); + x0 *= f; + y0 *= f; + z0 *= f; + w0 *= f; + } + } + dst[dstOffset] = x0; + dst[dstOffset + 1] = y0; + dst[dstOffset + 2] = z0; + dst[dstOffset + 3] = w0; + } + static multiplyQuaternionsFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1) { + const x0 = src0[srcOffset0]; + const y0 = src0[srcOffset0 + 1]; + const z0 = src0[srcOffset0 + 2]; + const w0 = src0[srcOffset0 + 3]; + const x1 = src1[srcOffset1]; + const y1 = src1[srcOffset1 + 1]; + const z1 = src1[srcOffset1 + 2]; + const w1 = src1[srcOffset1 + 3]; + dst[dstOffset] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; + dst[dstOffset + 1] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; + dst[dstOffset + 2] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; + dst[dstOffset + 3] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; + return dst; + } + get x() { + return this._x; + } + set x(value) { + this._x = value; + this._onChangeCallback(); + } + get y() { + return this._y; + } + set y(value) { + this._y = value; + this._onChangeCallback(); + } + get z() { + return this._z; + } + set z(value) { + this._z = value; + this._onChangeCallback(); + } + get w() { + return this._w; + } + set w(value) { + this._w = value; + this._onChangeCallback(); + } + set(x2, y2, z, w) { + this._x = x2; + this._y = y2; + this._z = z; + this._w = w; + this._onChangeCallback(); + return this; + } + clone() { + return new this.constructor(this._x, this._y, this._z, this._w); + } + copy(quaternion) { + this._x = quaternion.x; + this._y = quaternion.y; + this._z = quaternion.z; + this._w = quaternion.w; + this._onChangeCallback(); + return this; + } + setFromEuler(euler, update) { + if (!(euler && euler.isEuler)) { + throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order."); + } + const x2 = euler._x, y2 = euler._y, z = euler._z, order = euler._order; + const cos = Math.cos; + const sin = Math.sin; + const c1 = cos(x2 / 2); + const c2 = cos(y2 / 2); + const c3 = cos(z / 2); + const s1 = sin(x2 / 2); + const s2 = sin(y2 / 2); + const s3 = sin(z / 2); + switch (order) { + case "XYZ": + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; + case "YXZ": + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; + case "ZXY": + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; + case "ZYX": + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; + case "YZX": + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; + case "XZY": + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; + default: + console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: " + order); + } + if (update !== false) + this._onChangeCallback(); + return this; + } + setFromAxisAngle(axis, angle) { + const halfAngle = angle / 2, s = Math.sin(halfAngle); + this._x = axis.x * s; + this._y = axis.y * s; + this._z = axis.z * s; + this._w = Math.cos(halfAngle); + this._onChangeCallback(); + return this; + } + setFromRotationMatrix(m2) { + const te = m2.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10], trace = m11 + m22 + m33; + if (trace > 0) { + const s = 0.5 / Math.sqrt(trace + 1); + this._w = 0.25 / s; + this._x = (m32 - m23) * s; + this._y = (m13 - m31) * s; + this._z = (m21 - m12) * s; + } else if (m11 > m22 && m11 > m33) { + const s = 2 * Math.sqrt(1 + m11 - m22 - m33); + this._w = (m32 - m23) / s; + this._x = 0.25 * s; + this._y = (m12 + m21) / s; + this._z = (m13 + m31) / s; + } else if (m22 > m33) { + const s = 2 * Math.sqrt(1 + m22 - m11 - m33); + this._w = (m13 - m31) / s; + this._x = (m12 + m21) / s; + this._y = 0.25 * s; + this._z = (m23 + m32) / s; + } else { + const s = 2 * Math.sqrt(1 + m33 - m11 - m22); + this._w = (m21 - m12) / s; + this._x = (m13 + m31) / s; + this._y = (m23 + m32) / s; + this._z = 0.25 * s; + } + this._onChangeCallback(); + return this; + } + setFromUnitVectors(vFrom, vTo) { + let r = vFrom.dot(vTo) + 1; + if (r < Number.EPSILON) { + r = 0; + if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) { + this._x = -vFrom.y; + this._y = vFrom.x; + this._z = 0; + this._w = r; + } else { + this._x = 0; + this._y = -vFrom.z; + this._z = vFrom.y; + this._w = r; + } + } else { + this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; + this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; + this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; + this._w = r; + } + return this.normalize(); + } + angleTo(q) { + return 2 * Math.acos(Math.abs(clamp(this.dot(q), -1, 1))); + } + rotateTowards(q, step) { + const angle = this.angleTo(q); + if (angle === 0) + return this; + const t = Math.min(1, step / angle); + this.slerp(q, t); + return this; + } + identity() { + return this.set(0, 0, 0, 1); + } + invert() { + return this.conjugate(); + } + conjugate() { + this._x *= -1; + this._y *= -1; + this._z *= -1; + this._onChangeCallback(); + return this; + } + dot(v) { + return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; + } + lengthSq() { + return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; + } + length() { + return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w); + } + normalize() { + let l = this.length(); + if (l === 0) { + this._x = 0; + this._y = 0; + this._z = 0; + this._w = 1; + } else { + l = 1 / l; + this._x = this._x * l; + this._y = this._y * l; + this._z = this._z * l; + this._w = this._w * l; + } + this._onChangeCallback(); + return this; + } + multiply(q) { + return this.multiplyQuaternions(this, q); + } + premultiply(q) { + return this.multiplyQuaternions(q, this); + } + multiplyQuaternions(a2, b) { + const qax = a2._x, qay = a2._y, qaz = a2._z, qaw = a2._w; + const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; + this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; + this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; + this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; + this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; + this._onChangeCallback(); + return this; + } + slerp(qb, t) { + if (t === 0) + return this; + if (t === 1) + return this.copy(qb); + const x2 = this._x, y2 = this._y, z = this._z, w = this._w; + let cosHalfTheta = w * qb._w + x2 * qb._x + y2 * qb._y + z * qb._z; + if (cosHalfTheta < 0) { + this._w = -qb._w; + this._x = -qb._x; + this._y = -qb._y; + this._z = -qb._z; + cosHalfTheta = -cosHalfTheta; + } else { + this.copy(qb); + } + if (cosHalfTheta >= 1) { + this._w = w; + this._x = x2; + this._y = y2; + this._z = z; + return this; + } + const sqrSinHalfTheta = 1 - cosHalfTheta * cosHalfTheta; + if (sqrSinHalfTheta <= Number.EPSILON) { + const s = 1 - t; + this._w = s * w + t * this._w; + this._x = s * x2 + t * this._x; + this._y = s * y2 + t * this._y; + this._z = s * z + t * this._z; + this.normalize(); + this._onChangeCallback(); + return this; + } + const sinHalfTheta = Math.sqrt(sqrSinHalfTheta); + const halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta); + const ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta, ratioB = Math.sin(t * halfTheta) / sinHalfTheta; + this._w = w * ratioA + this._w * ratioB; + this._x = x2 * ratioA + this._x * ratioB; + this._y = y2 * ratioA + this._y * ratioB; + this._z = z * ratioA + this._z * ratioB; + this._onChangeCallback(); + return this; + } + slerpQuaternions(qa, qb, t) { + return this.copy(qa).slerp(qb, t); + } + random() { + const u1 = Math.random(); + const sqrt1u1 = Math.sqrt(1 - u1); + const sqrtu1 = Math.sqrt(u1); + const u2 = 2 * Math.PI * Math.random(); + const u3 = 2 * Math.PI * Math.random(); + return this.set(sqrt1u1 * Math.cos(u2), sqrtu1 * Math.sin(u3), sqrtu1 * Math.cos(u3), sqrt1u1 * Math.sin(u2)); + } + equals(quaternion) { + return quaternion._x === this._x && quaternion._y === this._y && quaternion._z === this._z && quaternion._w === this._w; + } + fromArray(array2, offset = 0) { + this._x = array2[offset]; + this._y = array2[offset + 1]; + this._z = array2[offset + 2]; + this._w = array2[offset + 3]; + this._onChangeCallback(); + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this._x; + array2[offset + 1] = this._y; + array2[offset + 2] = this._z; + array2[offset + 3] = this._w; + return array2; + } + fromBufferAttribute(attribute, index2) { + this._x = attribute.getX(index2); + this._y = attribute.getY(index2); + this._z = attribute.getZ(index2); + this._w = attribute.getW(index2); + return this; + } + _onChange(callback) { + this._onChangeCallback = callback; + return this; + } + _onChangeCallback() { + } + *[Symbol.iterator]() { + yield this._x; + yield this._y; + yield this._z; + yield this._w; + } + }; + var Vector3 = class { + constructor(x2 = 0, y2 = 0, z = 0) { + Vector3.prototype.isVector3 = true; + this.x = x2; + this.y = y2; + this.z = z; + } + set(x2, y2, z) { + if (z === void 0) + z = this.z; + this.x = x2; + this.y = y2; + this.z = z; + return this; + } + setScalar(scalar) { + this.x = scalar; + this.y = scalar; + this.z = scalar; + return this; + } + setX(x2) { + this.x = x2; + return this; + } + setY(y2) { + this.y = y2; + return this; + } + setZ(z) { + this.z = z; + return this; + } + setComponent(index2, value) { + switch (index2) { + case 0: + this.x = value; + break; + case 1: + this.y = value; + break; + case 2: + this.z = value; + break; + default: + throw new Error("index is out of range: " + index2); + } + return this; + } + getComponent(index2) { + switch (index2) { + case 0: + return this.x; + case 1: + return this.y; + case 2: + return this.z; + default: + throw new Error("index is out of range: " + index2); + } + } + clone() { + return new this.constructor(this.x, this.y, this.z); + } + copy(v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + return this; + } + add(v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; + } + addScalar(s) { + this.x += s; + this.y += s; + this.z += s; + return this; + } + addVectors(a2, b) { + this.x = a2.x + b.x; + this.y = a2.y + b.y; + this.z = a2.z + b.z; + return this; + } + addScaledVector(v, s) { + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + return this; + } + sub(v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + return this; + } + subScalar(s) { + this.x -= s; + this.y -= s; + this.z -= s; + return this; + } + subVectors(a2, b) { + this.x = a2.x - b.x; + this.y = a2.y - b.y; + this.z = a2.z - b.z; + return this; + } + multiply(v) { + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + return this; + } + multiplyScalar(scalar) { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + return this; + } + multiplyVectors(a2, b) { + this.x = a2.x * b.x; + this.y = a2.y * b.y; + this.z = a2.z * b.z; + return this; + } + applyEuler(euler) { + return this.applyQuaternion(_quaternion$4.setFromEuler(euler)); + } + applyAxisAngle(axis, angle) { + return this.applyQuaternion(_quaternion$4.setFromAxisAngle(axis, angle)); + } + applyMatrix3(m2) { + const x2 = this.x, y2 = this.y, z = this.z; + const e = m2.elements; + this.x = e[0] * x2 + e[3] * y2 + e[6] * z; + this.y = e[1] * x2 + e[4] * y2 + e[7] * z; + this.z = e[2] * x2 + e[5] * y2 + e[8] * z; + return this; + } + applyNormalMatrix(m2) { + return this.applyMatrix3(m2).normalize(); + } + applyMatrix4(m2) { + const x2 = this.x, y2 = this.y, z = this.z; + const e = m2.elements; + const w = 1 / (e[3] * x2 + e[7] * y2 + e[11] * z + e[15]); + this.x = (e[0] * x2 + e[4] * y2 + e[8] * z + e[12]) * w; + this.y = (e[1] * x2 + e[5] * y2 + e[9] * z + e[13]) * w; + this.z = (e[2] * x2 + e[6] * y2 + e[10] * z + e[14]) * w; + return this; + } + applyQuaternion(q) { + const x2 = this.x, y2 = this.y, z = this.z; + const qx = q.x, qy = q.y, qz = q.z, qw = q.w; + const ix = qw * x2 + qy * z - qz * y2; + const iy = qw * y2 + qz * x2 - qx * z; + const iz = qw * z + qx * y2 - qy * x2; + const iw = -qx * x2 - qy * y2 - qz * z; + this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; + this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; + this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; + return this; + } + project(camera) { + return this.applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix); + } + unproject(camera) { + return this.applyMatrix4(camera.projectionMatrixInverse).applyMatrix4(camera.matrixWorld); + } + transformDirection(m2) { + const x2 = this.x, y2 = this.y, z = this.z; + const e = m2.elements; + this.x = e[0] * x2 + e[4] * y2 + e[8] * z; + this.y = e[1] * x2 + e[5] * y2 + e[9] * z; + this.z = e[2] * x2 + e[6] * y2 + e[10] * z; + return this.normalize(); + } + divide(v) { + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; + return this; + } + divideScalar(scalar) { + return this.multiplyScalar(1 / scalar); + } + min(v) { + this.x = Math.min(this.x, v.x); + this.y = Math.min(this.y, v.y); + this.z = Math.min(this.z, v.z); + return this; + } + max(v) { + this.x = Math.max(this.x, v.x); + this.y = Math.max(this.y, v.y); + this.z = Math.max(this.z, v.z); + return this; + } + clamp(min2, max2) { + this.x = Math.max(min2.x, Math.min(max2.x, this.x)); + this.y = Math.max(min2.y, Math.min(max2.y, this.y)); + this.z = Math.max(min2.z, Math.min(max2.z, this.z)); + return this; + } + clampScalar(minVal, maxVal) { + this.x = Math.max(minVal, Math.min(maxVal, this.x)); + this.y = Math.max(minVal, Math.min(maxVal, this.y)); + this.z = Math.max(minVal, Math.min(maxVal, this.z)); + return this; + } + clampLength(min2, max2) { + const length = this.length(); + return this.divideScalar(length || 1).multiplyScalar(Math.max(min2, Math.min(max2, length))); + } + floor() { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + return this; + } + ceil() { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + this.z = Math.ceil(this.z); + return this; + } + round() { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + this.z = Math.round(this.z); + return this; + } + roundToZero() { + this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x); + this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y); + this.z = this.z < 0 ? Math.ceil(this.z) : Math.floor(this.z); + return this; + } + negate() { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + return this; + } + dot(v) { + return this.x * v.x + this.y * v.y + this.z * v.z; + } + lengthSq() { + return this.x * this.x + this.y * this.y + this.z * this.z; + } + length() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + } + manhattanLength() { + return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z); + } + normalize() { + return this.divideScalar(this.length() || 1); + } + setLength(length) { + return this.normalize().multiplyScalar(length); + } + lerp(v, alpha) { + this.x += (v.x - this.x) * alpha; + this.y += (v.y - this.y) * alpha; + this.z += (v.z - this.z) * alpha; + return this; + } + lerpVectors(v1, v2, alpha) { + this.x = v1.x + (v2.x - v1.x) * alpha; + this.y = v1.y + (v2.y - v1.y) * alpha; + this.z = v1.z + (v2.z - v1.z) * alpha; + return this; + } + cross(v) { + return this.crossVectors(this, v); + } + crossVectors(a2, b) { + const ax = a2.x, ay = a2.y, az = a2.z; + const bx = b.x, by = b.y, bz = b.z; + this.x = ay * bz - az * by; + this.y = az * bx - ax * bz; + this.z = ax * by - ay * bx; + return this; + } + projectOnVector(v) { + const denominator = v.lengthSq(); + if (denominator === 0) + return this.set(0, 0, 0); + const scalar = v.dot(this) / denominator; + return this.copy(v).multiplyScalar(scalar); + } + projectOnPlane(planeNormal) { + _vector$c.copy(this).projectOnVector(planeNormal); + return this.sub(_vector$c); + } + reflect(normal) { + return this.sub(_vector$c.copy(normal).multiplyScalar(2 * this.dot(normal))); + } + angleTo(v) { + const denominator = Math.sqrt(this.lengthSq() * v.lengthSq()); + if (denominator === 0) + return Math.PI / 2; + const theta = this.dot(v) / denominator; + return Math.acos(clamp(theta, -1, 1)); + } + distanceTo(v) { + return Math.sqrt(this.distanceToSquared(v)); + } + distanceToSquared(v) { + const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; + return dx * dx + dy * dy + dz * dz; + } + manhattanDistanceTo(v) { + return Math.abs(this.x - v.x) + Math.abs(this.y - v.y) + Math.abs(this.z - v.z); + } + setFromSpherical(s) { + return this.setFromSphericalCoords(s.radius, s.phi, s.theta); + } + setFromSphericalCoords(radius, phi, theta) { + const sinPhiRadius = Math.sin(phi) * radius; + this.x = sinPhiRadius * Math.sin(theta); + this.y = Math.cos(phi) * radius; + this.z = sinPhiRadius * Math.cos(theta); + return this; + } + setFromCylindrical(c2) { + return this.setFromCylindricalCoords(c2.radius, c2.theta, c2.y); + } + setFromCylindricalCoords(radius, theta, y2) { + this.x = radius * Math.sin(theta); + this.y = y2; + this.z = radius * Math.cos(theta); + return this; + } + setFromMatrixPosition(m2) { + const e = m2.elements; + this.x = e[12]; + this.y = e[13]; + this.z = e[14]; + return this; + } + setFromMatrixScale(m2) { + const sx = this.setFromMatrixColumn(m2, 0).length(); + const sy = this.setFromMatrixColumn(m2, 1).length(); + const sz = this.setFromMatrixColumn(m2, 2).length(); + this.x = sx; + this.y = sy; + this.z = sz; + return this; + } + setFromMatrixColumn(m2, index2) { + return this.fromArray(m2.elements, index2 * 4); + } + setFromMatrix3Column(m2, index2) { + return this.fromArray(m2.elements, index2 * 3); + } + setFromEuler(e) { + this.x = e._x; + this.y = e._y; + this.z = e._z; + return this; + } + equals(v) { + return v.x === this.x && v.y === this.y && v.z === this.z; + } + fromArray(array2, offset = 0) { + this.x = array2[offset]; + this.y = array2[offset + 1]; + this.z = array2[offset + 2]; + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this.x; + array2[offset + 1] = this.y; + array2[offset + 2] = this.z; + return array2; + } + fromBufferAttribute(attribute, index2) { + this.x = attribute.getX(index2); + this.y = attribute.getY(index2); + this.z = attribute.getZ(index2); + return this; + } + random() { + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + return this; + } + randomDirection() { + const u = (Math.random() - 0.5) * 2; + const t = Math.random() * Math.PI * 2; + const f = Math.sqrt(1 - u ** 2); + this.x = f * Math.cos(t); + this.y = f * Math.sin(t); + this.z = u; + return this; + } + *[Symbol.iterator]() { + yield this.x; + yield this.y; + yield this.z; + } + }; + var _vector$c = /* @__PURE__ */ new Vector3(); + var _quaternion$4 = /* @__PURE__ */ new Quaternion(); + var Box3 = class { + constructor(min2 = new Vector3(Infinity, Infinity, Infinity), max2 = new Vector3(-Infinity, -Infinity, -Infinity)) { + this.isBox3 = true; + this.min = min2; + this.max = max2; + } + set(min2, max2) { + this.min.copy(min2); + this.max.copy(max2); + return this; + } + setFromArray(array2) { + let minX = Infinity; + let minY = Infinity; + let minZ = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + let maxZ = -Infinity; + for (let i = 0, l = array2.length; i < l; i += 3) { + const x2 = array2[i]; + const y2 = array2[i + 1]; + const z = array2[i + 2]; + if (x2 < minX) + minX = x2; + if (y2 < minY) + minY = y2; + if (z < minZ) + minZ = z; + if (x2 > maxX) + maxX = x2; + if (y2 > maxY) + maxY = y2; + if (z > maxZ) + maxZ = z; + } + this.min.set(minX, minY, minZ); + this.max.set(maxX, maxY, maxZ); + return this; + } + setFromBufferAttribute(attribute) { + let minX = Infinity; + let minY = Infinity; + let minZ = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + let maxZ = -Infinity; + for (let i = 0, l = attribute.count; i < l; i++) { + const x2 = attribute.getX(i); + const y2 = attribute.getY(i); + const z = attribute.getZ(i); + if (x2 < minX) + minX = x2; + if (y2 < minY) + minY = y2; + if (z < minZ) + minZ = z; + if (x2 > maxX) + maxX = x2; + if (y2 > maxY) + maxY = y2; + if (z > maxZ) + maxZ = z; + } + this.min.set(minX, minY, minZ); + this.max.set(maxX, maxY, maxZ); + return this; + } + setFromPoints(points) { + this.makeEmpty(); + for (let i = 0, il = points.length; i < il; i++) { + this.expandByPoint(points[i]); + } + return this; + } + setFromCenterAndSize(center, size) { + const halfSize = _vector$b.copy(size).multiplyScalar(0.5); + this.min.copy(center).sub(halfSize); + this.max.copy(center).add(halfSize); + return this; + } + setFromObject(object, precise = false) { + this.makeEmpty(); + return this.expandByObject(object, precise); + } + clone() { + return new this.constructor().copy(this); + } + copy(box) { + this.min.copy(box.min); + this.max.copy(box.max); + return this; + } + makeEmpty() { + this.min.x = this.min.y = this.min.z = Infinity; + this.max.x = this.max.y = this.max.z = -Infinity; + return this; + } + isEmpty() { + return this.max.x < this.min.x || this.max.y < this.min.y || this.max.z < this.min.z; + } + getCenter(target) { + return this.isEmpty() ? target.set(0, 0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5); + } + getSize(target) { + return this.isEmpty() ? target.set(0, 0, 0) : target.subVectors(this.max, this.min); + } + expandByPoint(point) { + this.min.min(point); + this.max.max(point); + return this; + } + expandByVector(vector) { + this.min.sub(vector); + this.max.add(vector); + return this; + } + expandByScalar(scalar) { + this.min.addScalar(-scalar); + this.max.addScalar(scalar); + return this; + } + expandByObject(object, precise = false) { + object.updateWorldMatrix(false, false); + const geometry = object.geometry; + if (geometry !== void 0) { + if (precise && geometry.attributes != void 0 && geometry.attributes.position !== void 0) { + const position = geometry.attributes.position; + for (let i = 0, l = position.count; i < l; i++) { + _vector$b.fromBufferAttribute(position, i).applyMatrix4(object.matrixWorld); + this.expandByPoint(_vector$b); + } + } else { + if (geometry.boundingBox === null) { + geometry.computeBoundingBox(); + } + _box$3.copy(geometry.boundingBox); + _box$3.applyMatrix4(object.matrixWorld); + this.union(_box$3); + } + } + const children2 = object.children; + for (let i = 0, l = children2.length; i < l; i++) { + this.expandByObject(children2[i], precise); + } + return this; + } + containsPoint(point) { + return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y || point.z < this.min.z || point.z > this.max.z ? false : true; + } + containsBox(box) { + return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y && this.min.z <= box.min.z && box.max.z <= this.max.z; + } + getParameter(point, target) { + return target.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y), (point.z - this.min.z) / (this.max.z - this.min.z)); + } + intersectsBox(box) { + return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y || box.max.z < this.min.z || box.min.z > this.max.z ? false : true; + } + intersectsSphere(sphere) { + this.clampPoint(sphere.center, _vector$b); + return _vector$b.distanceToSquared(sphere.center) <= sphere.radius * sphere.radius; + } + intersectsPlane(plane) { + let min2, max2; + if (plane.normal.x > 0) { + min2 = plane.normal.x * this.min.x; + max2 = plane.normal.x * this.max.x; + } else { + min2 = plane.normal.x * this.max.x; + max2 = plane.normal.x * this.min.x; + } + if (plane.normal.y > 0) { + min2 += plane.normal.y * this.min.y; + max2 += plane.normal.y * this.max.y; + } else { + min2 += plane.normal.y * this.max.y; + max2 += plane.normal.y * this.min.y; + } + if (plane.normal.z > 0) { + min2 += plane.normal.z * this.min.z; + max2 += plane.normal.z * this.max.z; + } else { + min2 += plane.normal.z * this.max.z; + max2 += plane.normal.z * this.min.z; + } + return min2 <= -plane.constant && max2 >= -plane.constant; + } + intersectsTriangle(triangle) { + if (this.isEmpty()) { + return false; + } + this.getCenter(_center); + _extents.subVectors(this.max, _center); + _v0$2.subVectors(triangle.a, _center); + _v1$7.subVectors(triangle.b, _center); + _v2$3.subVectors(triangle.c, _center); + _f0.subVectors(_v1$7, _v0$2); + _f1.subVectors(_v2$3, _v1$7); + _f2.subVectors(_v0$2, _v2$3); + let axes = [ + 0, + -_f0.z, + _f0.y, + 0, + -_f1.z, + _f1.y, + 0, + -_f2.z, + _f2.y, + _f0.z, + 0, + -_f0.x, + _f1.z, + 0, + -_f1.x, + _f2.z, + 0, + -_f2.x, + -_f0.y, + _f0.x, + 0, + -_f1.y, + _f1.x, + 0, + -_f2.y, + _f2.x, + 0 + ]; + if (!satForAxes(axes, _v0$2, _v1$7, _v2$3, _extents)) { + return false; + } + axes = [1, 0, 0, 0, 1, 0, 0, 0, 1]; + if (!satForAxes(axes, _v0$2, _v1$7, _v2$3, _extents)) { + return false; + } + _triangleNormal.crossVectors(_f0, _f1); + axes = [_triangleNormal.x, _triangleNormal.y, _triangleNormal.z]; + return satForAxes(axes, _v0$2, _v1$7, _v2$3, _extents); + } + clampPoint(point, target) { + return target.copy(point).clamp(this.min, this.max); + } + distanceToPoint(point) { + const clampedPoint = _vector$b.copy(point).clamp(this.min, this.max); + return clampedPoint.sub(point).length(); + } + getBoundingSphere(target) { + this.getCenter(target.center); + target.radius = this.getSize(_vector$b).length() * 0.5; + return target; + } + intersect(box) { + this.min.max(box.min); + this.max.min(box.max); + if (this.isEmpty()) + this.makeEmpty(); + return this; + } + union(box) { + this.min.min(box.min); + this.max.max(box.max); + return this; + } + applyMatrix4(matrix) { + if (this.isEmpty()) + return this; + _points[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix); + _points[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix); + _points[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix); + _points[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix); + _points[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix); + _points[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix); + _points[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix); + _points[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix); + this.setFromPoints(_points); + return this; + } + translate(offset) { + this.min.add(offset); + this.max.add(offset); + return this; + } + equals(box) { + return box.min.equals(this.min) && box.max.equals(this.max); + } + }; + var _points = [ + /* @__PURE__ */ new Vector3(), + /* @__PURE__ */ new Vector3(), + /* @__PURE__ */ new Vector3(), + /* @__PURE__ */ new Vector3(), + /* @__PURE__ */ new Vector3(), + /* @__PURE__ */ new Vector3(), + /* @__PURE__ */ new Vector3(), + /* @__PURE__ */ new Vector3() + ]; + var _vector$b = /* @__PURE__ */ new Vector3(); + var _box$3 = /* @__PURE__ */ new Box3(); + var _v0$2 = /* @__PURE__ */ new Vector3(); + var _v1$7 = /* @__PURE__ */ new Vector3(); + var _v2$3 = /* @__PURE__ */ new Vector3(); + var _f0 = /* @__PURE__ */ new Vector3(); + var _f1 = /* @__PURE__ */ new Vector3(); + var _f2 = /* @__PURE__ */ new Vector3(); + var _center = /* @__PURE__ */ new Vector3(); + var _extents = /* @__PURE__ */ new Vector3(); + var _triangleNormal = /* @__PURE__ */ new Vector3(); + var _testAxis = /* @__PURE__ */ new Vector3(); + function satForAxes(axes, v0, v1, v2, extents) { + for (let i = 0, j = axes.length - 3; i <= j; i += 3) { + _testAxis.fromArray(axes, i); + const r = extents.x * Math.abs(_testAxis.x) + extents.y * Math.abs(_testAxis.y) + extents.z * Math.abs(_testAxis.z); + const p0 = v0.dot(_testAxis); + const p1 = v1.dot(_testAxis); + const p2 = v2.dot(_testAxis); + if (Math.max(-Math.max(p0, p1, p2), Math.min(p0, p1, p2)) > r) { + return false; + } + } + return true; + } + var _box$2 = /* @__PURE__ */ new Box3(); + var _v1$6 = /* @__PURE__ */ new Vector3(); + var _toFarthestPoint = /* @__PURE__ */ new Vector3(); + var _toPoint = /* @__PURE__ */ new Vector3(); + var Sphere = class { + constructor(center = new Vector3(), radius = -1) { + this.center = center; + this.radius = radius; + } + set(center, radius) { + this.center.copy(center); + this.radius = radius; + return this; + } + setFromPoints(points, optionalCenter) { + const center = this.center; + if (optionalCenter !== void 0) { + center.copy(optionalCenter); + } else { + _box$2.setFromPoints(points).getCenter(center); + } + let maxRadiusSq = 0; + for (let i = 0, il = points.length; i < il; i++) { + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(points[i])); + } + this.radius = Math.sqrt(maxRadiusSq); + return this; + } + copy(sphere) { + this.center.copy(sphere.center); + this.radius = sphere.radius; + return this; + } + isEmpty() { + return this.radius < 0; + } + makeEmpty() { + this.center.set(0, 0, 0); + this.radius = -1; + return this; + } + containsPoint(point) { + return point.distanceToSquared(this.center) <= this.radius * this.radius; + } + distanceToPoint(point) { + return point.distanceTo(this.center) - this.radius; + } + intersectsSphere(sphere) { + const radiusSum = this.radius + sphere.radius; + return sphere.center.distanceToSquared(this.center) <= radiusSum * radiusSum; + } + intersectsBox(box) { + return box.intersectsSphere(this); + } + intersectsPlane(plane) { + return Math.abs(plane.distanceToPoint(this.center)) <= this.radius; + } + clampPoint(point, target) { + const deltaLengthSq = this.center.distanceToSquared(point); + target.copy(point); + if (deltaLengthSq > this.radius * this.radius) { + target.sub(this.center).normalize(); + target.multiplyScalar(this.radius).add(this.center); + } + return target; + } + getBoundingBox(target) { + if (this.isEmpty()) { + target.makeEmpty(); + return target; + } + target.set(this.center, this.center); + target.expandByScalar(this.radius); + return target; + } + applyMatrix4(matrix) { + this.center.applyMatrix4(matrix); + this.radius = this.radius * matrix.getMaxScaleOnAxis(); + return this; + } + translate(offset) { + this.center.add(offset); + return this; + } + expandByPoint(point) { + _toPoint.subVectors(point, this.center); + const lengthSq = _toPoint.lengthSq(); + if (lengthSq > this.radius * this.radius) { + const length = Math.sqrt(lengthSq); + const missingRadiusHalf = (length - this.radius) * 0.5; + this.center.add(_toPoint.multiplyScalar(missingRadiusHalf / length)); + this.radius += missingRadiusHalf; + } + return this; + } + union(sphere) { + if (this.center.equals(sphere.center) === true) { + _toFarthestPoint.set(0, 0, 1).multiplyScalar(sphere.radius); + } else { + _toFarthestPoint.subVectors(sphere.center, this.center).normalize().multiplyScalar(sphere.radius); + } + this.expandByPoint(_v1$6.copy(sphere.center).add(_toFarthestPoint)); + this.expandByPoint(_v1$6.copy(sphere.center).sub(_toFarthestPoint)); + return this; + } + equals(sphere) { + return sphere.center.equals(this.center) && sphere.radius === this.radius; + } + clone() { + return new this.constructor().copy(this); + } + }; + var _vector$a = /* @__PURE__ */ new Vector3(); + var _segCenter = /* @__PURE__ */ new Vector3(); + var _segDir = /* @__PURE__ */ new Vector3(); + var _diff = /* @__PURE__ */ new Vector3(); + var _edge1 = /* @__PURE__ */ new Vector3(); + var _edge2 = /* @__PURE__ */ new Vector3(); + var _normal$1 = /* @__PURE__ */ new Vector3(); + var Ray = class { + constructor(origin = new Vector3(), direction = new Vector3(0, 0, -1)) { + this.origin = origin; + this.direction = direction; + } + set(origin, direction) { + this.origin.copy(origin); + this.direction.copy(direction); + return this; + } + copy(ray) { + this.origin.copy(ray.origin); + this.direction.copy(ray.direction); + return this; + } + at(t, target) { + return target.copy(this.direction).multiplyScalar(t).add(this.origin); + } + lookAt(v) { + this.direction.copy(v).sub(this.origin).normalize(); + return this; + } + recast(t) { + this.origin.copy(this.at(t, _vector$a)); + return this; + } + closestPointToPoint(point, target) { + target.subVectors(point, this.origin); + const directionDistance = target.dot(this.direction); + if (directionDistance < 0) { + return target.copy(this.origin); + } + return target.copy(this.direction).multiplyScalar(directionDistance).add(this.origin); + } + distanceToPoint(point) { + return Math.sqrt(this.distanceSqToPoint(point)); + } + distanceSqToPoint(point) { + const directionDistance = _vector$a.subVectors(point, this.origin).dot(this.direction); + if (directionDistance < 0) { + return this.origin.distanceToSquared(point); + } + _vector$a.copy(this.direction).multiplyScalar(directionDistance).add(this.origin); + return _vector$a.distanceToSquared(point); + } + distanceSqToSegment(v0, v1, optionalPointOnRay, optionalPointOnSegment) { + _segCenter.copy(v0).add(v1).multiplyScalar(0.5); + _segDir.copy(v1).sub(v0).normalize(); + _diff.copy(this.origin).sub(_segCenter); + const segExtent = v0.distanceTo(v1) * 0.5; + const a01 = -this.direction.dot(_segDir); + const b0 = _diff.dot(this.direction); + const b1 = -_diff.dot(_segDir); + const c2 = _diff.lengthSq(); + const det = Math.abs(1 - a01 * a01); + let s0, s1, sqrDist, extDet; + if (det > 0) { + s0 = a01 * b1 - b0; + s1 = a01 * b0 - b1; + extDet = segExtent * det; + if (s0 >= 0) { + if (s1 >= -extDet) { + if (s1 <= extDet) { + const invDet = 1 / det; + s0 *= invDet; + s1 *= invDet; + sqrDist = s0 * (s0 + a01 * s1 + 2 * b0) + s1 * (a01 * s0 + s1 + 2 * b1) + c2; + } else { + s1 = segExtent; + s0 = Math.max(0, -(a01 * s1 + b0)); + sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2; + } + } else { + s1 = -segExtent; + s0 = Math.max(0, -(a01 * s1 + b0)); + sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2; + } + } else { + if (s1 <= -extDet) { + s0 = Math.max(0, -(-a01 * segExtent + b0)); + s1 = s0 > 0 ? -segExtent : Math.min(Math.max(-segExtent, -b1), segExtent); + sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2; + } else if (s1 <= extDet) { + s0 = 0; + s1 = Math.min(Math.max(-segExtent, -b1), segExtent); + sqrDist = s1 * (s1 + 2 * b1) + c2; + } else { + s0 = Math.max(0, -(a01 * segExtent + b0)); + s1 = s0 > 0 ? segExtent : Math.min(Math.max(-segExtent, -b1), segExtent); + sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2; + } + } + } else { + s1 = a01 > 0 ? -segExtent : segExtent; + s0 = Math.max(0, -(a01 * s1 + b0)); + sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c2; + } + if (optionalPointOnRay) { + optionalPointOnRay.copy(this.direction).multiplyScalar(s0).add(this.origin); + } + if (optionalPointOnSegment) { + optionalPointOnSegment.copy(_segDir).multiplyScalar(s1).add(_segCenter); + } + return sqrDist; + } + intersectSphere(sphere, target) { + _vector$a.subVectors(sphere.center, this.origin); + const tca = _vector$a.dot(this.direction); + const d2 = _vector$a.dot(_vector$a) - tca * tca; + const radius2 = sphere.radius * sphere.radius; + if (d2 > radius2) + return null; + const thc = Math.sqrt(radius2 - d2); + const t0 = tca - thc; + const t1 = tca + thc; + if (t0 < 0 && t1 < 0) + return null; + if (t0 < 0) + return this.at(t1, target); + return this.at(t0, target); + } + intersectsSphere(sphere) { + return this.distanceSqToPoint(sphere.center) <= sphere.radius * sphere.radius; + } + distanceToPlane(plane) { + const denominator = plane.normal.dot(this.direction); + if (denominator === 0) { + if (plane.distanceToPoint(this.origin) === 0) { + return 0; + } + return null; + } + const t = -(this.origin.dot(plane.normal) + plane.constant) / denominator; + return t >= 0 ? t : null; + } + intersectPlane(plane, target) { + const t = this.distanceToPlane(plane); + if (t === null) { + return null; + } + return this.at(t, target); + } + intersectsPlane(plane) { + const distToPoint = plane.distanceToPoint(this.origin); + if (distToPoint === 0) { + return true; + } + const denominator = plane.normal.dot(this.direction); + if (denominator * distToPoint < 0) { + return true; + } + return false; + } + intersectBox(box, target) { + let tmin, tmax, tymin, tymax, tzmin, tzmax; + const invdirx = 1 / this.direction.x, invdiry = 1 / this.direction.y, invdirz = 1 / this.direction.z; + const origin = this.origin; + if (invdirx >= 0) { + tmin = (box.min.x - origin.x) * invdirx; + tmax = (box.max.x - origin.x) * invdirx; + } else { + tmin = (box.max.x - origin.x) * invdirx; + tmax = (box.min.x - origin.x) * invdirx; + } + if (invdiry >= 0) { + tymin = (box.min.y - origin.y) * invdiry; + tymax = (box.max.y - origin.y) * invdiry; + } else { + tymin = (box.max.y - origin.y) * invdiry; + tymax = (box.min.y - origin.y) * invdiry; + } + if (tmin > tymax || tymin > tmax) + return null; + if (tymin > tmin || tmin !== tmin) + tmin = tymin; + if (tymax < tmax || tmax !== tmax) + tmax = tymax; + if (invdirz >= 0) { + tzmin = (box.min.z - origin.z) * invdirz; + tzmax = (box.max.z - origin.z) * invdirz; + } else { + tzmin = (box.max.z - origin.z) * invdirz; + tzmax = (box.min.z - origin.z) * invdirz; + } + if (tmin > tzmax || tzmin > tmax) + return null; + if (tzmin > tmin || tmin !== tmin) + tmin = tzmin; + if (tzmax < tmax || tmax !== tmax) + tmax = tzmax; + if (tmax < 0) + return null; + return this.at(tmin >= 0 ? tmin : tmax, target); + } + intersectsBox(box) { + return this.intersectBox(box, _vector$a) !== null; + } + intersectTriangle(a2, b, c2, backfaceCulling, target) { + _edge1.subVectors(b, a2); + _edge2.subVectors(c2, a2); + _normal$1.crossVectors(_edge1, _edge2); + let DdN = this.direction.dot(_normal$1); + let sign; + if (DdN > 0) { + if (backfaceCulling) + return null; + sign = 1; + } else if (DdN < 0) { + sign = -1; + DdN = -DdN; + } else { + return null; + } + _diff.subVectors(this.origin, a2); + const DdQxE2 = sign * this.direction.dot(_edge2.crossVectors(_diff, _edge2)); + if (DdQxE2 < 0) { + return null; + } + const DdE1xQ = sign * this.direction.dot(_edge1.cross(_diff)); + if (DdE1xQ < 0) { + return null; + } + if (DdQxE2 + DdE1xQ > DdN) { + return null; + } + const QdN = -sign * _diff.dot(_normal$1); + if (QdN < 0) { + return null; + } + return this.at(QdN / DdN, target); + } + applyMatrix4(matrix4) { + this.origin.applyMatrix4(matrix4); + this.direction.transformDirection(matrix4); + return this; + } + equals(ray) { + return ray.origin.equals(this.origin) && ray.direction.equals(this.direction); + } + clone() { + return new this.constructor().copy(this); + } + }; + var Matrix4 = class { + constructor() { + Matrix4.prototype.isMatrix4 = true; + this.elements = [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ]; + } + set(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) { + const te = this.elements; + te[0] = n11; + te[4] = n12; + te[8] = n13; + te[12] = n14; + te[1] = n21; + te[5] = n22; + te[9] = n23; + te[13] = n24; + te[2] = n31; + te[6] = n32; + te[10] = n33; + te[14] = n34; + te[3] = n41; + te[7] = n42; + te[11] = n43; + te[15] = n44; + return this; + } + identity() { + this.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + return this; + } + clone() { + return new Matrix4().fromArray(this.elements); + } + copy(m2) { + const te = this.elements; + const me = m2.elements; + te[0] = me[0]; + te[1] = me[1]; + te[2] = me[2]; + te[3] = me[3]; + te[4] = me[4]; + te[5] = me[5]; + te[6] = me[6]; + te[7] = me[7]; + te[8] = me[8]; + te[9] = me[9]; + te[10] = me[10]; + te[11] = me[11]; + te[12] = me[12]; + te[13] = me[13]; + te[14] = me[14]; + te[15] = me[15]; + return this; + } + copyPosition(m2) { + const te = this.elements, me = m2.elements; + te[12] = me[12]; + te[13] = me[13]; + te[14] = me[14]; + return this; + } + setFromMatrix3(m2) { + const me = m2.elements; + this.set(me[0], me[3], me[6], 0, me[1], me[4], me[7], 0, me[2], me[5], me[8], 0, 0, 0, 0, 1); + return this; + } + extractBasis(xAxis, yAxis, zAxis) { + xAxis.setFromMatrixColumn(this, 0); + yAxis.setFromMatrixColumn(this, 1); + zAxis.setFromMatrixColumn(this, 2); + return this; + } + makeBasis(xAxis, yAxis, zAxis) { + this.set(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, 0, 0, 0, 1); + return this; + } + extractRotation(m2) { + const te = this.elements; + const me = m2.elements; + const scaleX = 1 / _v1$5.setFromMatrixColumn(m2, 0).length(); + const scaleY = 1 / _v1$5.setFromMatrixColumn(m2, 1).length(); + const scaleZ = 1 / _v1$5.setFromMatrixColumn(m2, 2).length(); + te[0] = me[0] * scaleX; + te[1] = me[1] * scaleX; + te[2] = me[2] * scaleX; + te[3] = 0; + te[4] = me[4] * scaleY; + te[5] = me[5] * scaleY; + te[6] = me[6] * scaleY; + te[7] = 0; + te[8] = me[8] * scaleZ; + te[9] = me[9] * scaleZ; + te[10] = me[10] * scaleZ; + te[11] = 0; + te[12] = 0; + te[13] = 0; + te[14] = 0; + te[15] = 1; + return this; + } + makeRotationFromEuler(euler) { + const te = this.elements; + const x2 = euler.x, y2 = euler.y, z = euler.z; + const a2 = Math.cos(x2), b = Math.sin(x2); + const c2 = Math.cos(y2), d = Math.sin(y2); + const e = Math.cos(z), f = Math.sin(z); + if (euler.order === "XYZ") { + const ae = a2 * e, af = a2 * f, be = b * e, bf = b * f; + te[0] = c2 * e; + te[4] = -c2 * f; + te[8] = d; + te[1] = af + be * d; + te[5] = ae - bf * d; + te[9] = -b * c2; + te[2] = bf - ae * d; + te[6] = be + af * d; + te[10] = a2 * c2; + } else if (euler.order === "YXZ") { + const ce = c2 * e, cf = c2 * f, de = d * e, df = d * f; + te[0] = ce + df * b; + te[4] = de * b - cf; + te[8] = a2 * d; + te[1] = a2 * f; + te[5] = a2 * e; + te[9] = -b; + te[2] = cf * b - de; + te[6] = df + ce * b; + te[10] = a2 * c2; + } else if (euler.order === "ZXY") { + const ce = c2 * e, cf = c2 * f, de = d * e, df = d * f; + te[0] = ce - df * b; + te[4] = -a2 * f; + te[8] = de + cf * b; + te[1] = cf + de * b; + te[5] = a2 * e; + te[9] = df - ce * b; + te[2] = -a2 * d; + te[6] = b; + te[10] = a2 * c2; + } else if (euler.order === "ZYX") { + const ae = a2 * e, af = a2 * f, be = b * e, bf = b * f; + te[0] = c2 * e; + te[4] = be * d - af; + te[8] = ae * d + bf; + te[1] = c2 * f; + te[5] = bf * d + ae; + te[9] = af * d - be; + te[2] = -d; + te[6] = b * c2; + te[10] = a2 * c2; + } else if (euler.order === "YZX") { + const ac = a2 * c2, ad = a2 * d, bc = b * c2, bd = b * d; + te[0] = c2 * e; + te[4] = bd - ac * f; + te[8] = bc * f + ad; + te[1] = f; + te[5] = a2 * e; + te[9] = -b * e; + te[2] = -d * e; + te[6] = ad * f + bc; + te[10] = ac - bd * f; + } else if (euler.order === "XZY") { + const ac = a2 * c2, ad = a2 * d, bc = b * c2, bd = b * d; + te[0] = c2 * e; + te[4] = -f; + te[8] = d * e; + te[1] = ac * f + bd; + te[5] = a2 * e; + te[9] = ad * f - bc; + te[2] = bc * f - ad; + te[6] = b * e; + te[10] = bd * f + ac; + } + te[3] = 0; + te[7] = 0; + te[11] = 0; + te[12] = 0; + te[13] = 0; + te[14] = 0; + te[15] = 1; + return this; + } + makeRotationFromQuaternion(q) { + return this.compose(_zero, q, _one); + } + lookAt(eye, target, up) { + const te = this.elements; + _z.subVectors(eye, target); + if (_z.lengthSq() === 0) { + _z.z = 1; + } + _z.normalize(); + _x.crossVectors(up, _z); + if (_x.lengthSq() === 0) { + if (Math.abs(up.z) === 1) { + _z.x += 1e-4; + } else { + _z.z += 1e-4; + } + _z.normalize(); + _x.crossVectors(up, _z); + } + _x.normalize(); + _y.crossVectors(_z, _x); + te[0] = _x.x; + te[4] = _y.x; + te[8] = _z.x; + te[1] = _x.y; + te[5] = _y.y; + te[9] = _z.y; + te[2] = _x.z; + te[6] = _y.z; + te[10] = _z.z; + return this; + } + multiply(m2) { + return this.multiplyMatrices(this, m2); + } + premultiply(m2) { + return this.multiplyMatrices(m2, this); + } + multiplyMatrices(a2, b) { + const ae = a2.elements; + const be = b.elements; + const te = this.elements; + const a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12]; + const a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13]; + const a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14]; + const a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15]; + const b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12]; + const b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13]; + const b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14]; + const b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15]; + te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; + te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; + te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; + te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; + te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; + te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; + te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; + te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; + te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; + te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; + te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; + te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; + te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; + te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; + te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; + te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; + return this; + } + multiplyScalar(s) { + const te = this.elements; + te[0] *= s; + te[4] *= s; + te[8] *= s; + te[12] *= s; + te[1] *= s; + te[5] *= s; + te[9] *= s; + te[13] *= s; + te[2] *= s; + te[6] *= s; + te[10] *= s; + te[14] *= s; + te[3] *= s; + te[7] *= s; + te[11] *= s; + te[15] *= s; + return this; + } + determinant() { + const te = this.elements; + const n11 = te[0], n12 = te[4], n13 = te[8], n14 = te[12]; + const n21 = te[1], n22 = te[5], n23 = te[9], n24 = te[13]; + const n31 = te[2], n32 = te[6], n33 = te[10], n34 = te[14]; + const n41 = te[3], n42 = te[7], n43 = te[11], n44 = te[15]; + return n41 * (+n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34) + n42 * (+n11 * n23 * n34 - n11 * n24 * n33 + n14 * n21 * n33 - n13 * n21 * n34 + n13 * n24 * n31 - n14 * n23 * n31) + n43 * (+n11 * n24 * n32 - n11 * n22 * n34 - n14 * n21 * n32 + n12 * n21 * n34 + n14 * n22 * n31 - n12 * n24 * n31) + n44 * (-n13 * n22 * n31 - n11 * n23 * n32 + n11 * n22 * n33 + n13 * n21 * n32 - n12 * n21 * n33 + n12 * n23 * n31); + } + transpose() { + const te = this.elements; + let tmp; + tmp = te[1]; + te[1] = te[4]; + te[4] = tmp; + tmp = te[2]; + te[2] = te[8]; + te[8] = tmp; + tmp = te[6]; + te[6] = te[9]; + te[9] = tmp; + tmp = te[3]; + te[3] = te[12]; + te[12] = tmp; + tmp = te[7]; + te[7] = te[13]; + te[13] = tmp; + tmp = te[11]; + te[11] = te[14]; + te[14] = tmp; + return this; + } + setPosition(x2, y2, z) { + const te = this.elements; + if (x2.isVector3) { + te[12] = x2.x; + te[13] = x2.y; + te[14] = x2.z; + } else { + te[12] = x2; + te[13] = y2; + te[14] = z; + } + return this; + } + invert() { + const te = this.elements, n11 = te[0], n21 = te[1], n31 = te[2], n41 = te[3], n12 = te[4], n22 = te[5], n32 = te[6], n42 = te[7], n13 = te[8], n23 = te[9], n33 = te[10], n43 = te[11], n14 = te[12], n24 = te[13], n34 = te[14], n44 = te[15], t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; + const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; + if (det === 0) + return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + const detInv = 1 / det; + te[0] = t11 * detInv; + te[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv; + te[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv; + te[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv; + te[4] = t12 * detInv; + te[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv; + te[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv; + te[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv; + te[8] = t13 * detInv; + te[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv; + te[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv; + te[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv; + te[12] = t14 * detInv; + te[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv; + te[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv; + te[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv; + return this; + } + scale(v) { + const te = this.elements; + const x2 = v.x, y2 = v.y, z = v.z; + te[0] *= x2; + te[4] *= y2; + te[8] *= z; + te[1] *= x2; + te[5] *= y2; + te[9] *= z; + te[2] *= x2; + te[6] *= y2; + te[10] *= z; + te[3] *= x2; + te[7] *= y2; + te[11] *= z; + return this; + } + getMaxScaleOnAxis() { + const te = this.elements; + const scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2]; + const scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6]; + const scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10]; + return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq)); + } + makeTranslation(x2, y2, z) { + this.set(1, 0, 0, x2, 0, 1, 0, y2, 0, 0, 1, z, 0, 0, 0, 1); + return this; + } + makeRotationX(theta) { + const c2 = Math.cos(theta), s = Math.sin(theta); + this.set(1, 0, 0, 0, 0, c2, -s, 0, 0, s, c2, 0, 0, 0, 0, 1); + return this; + } + makeRotationY(theta) { + const c2 = Math.cos(theta), s = Math.sin(theta); + this.set(c2, 0, s, 0, 0, 1, 0, 0, -s, 0, c2, 0, 0, 0, 0, 1); + return this; + } + makeRotationZ(theta) { + const c2 = Math.cos(theta), s = Math.sin(theta); + this.set(c2, -s, 0, 0, s, c2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + return this; + } + makeRotationAxis(axis, angle) { + const c2 = Math.cos(angle); + const s = Math.sin(angle); + const t = 1 - c2; + const x2 = axis.x, y2 = axis.y, z = axis.z; + const tx = t * x2, ty = t * y2; + this.set(tx * x2 + c2, tx * y2 - s * z, tx * z + s * y2, 0, tx * y2 + s * z, ty * y2 + c2, ty * z - s * x2, 0, tx * z - s * y2, ty * z + s * x2, t * z * z + c2, 0, 0, 0, 0, 1); + return this; + } + makeScale(x2, y2, z) { + this.set(x2, 0, 0, 0, 0, y2, 0, 0, 0, 0, z, 0, 0, 0, 0, 1); + return this; + } + makeShear(xy, xz, yx, yz, zx, zy) { + this.set(1, yx, zx, 0, xy, 1, zy, 0, xz, yz, 1, 0, 0, 0, 0, 1); + return this; + } + compose(position, quaternion, scale) { + const te = this.elements; + const x2 = quaternion._x, y2 = quaternion._y, z = quaternion._z, w = quaternion._w; + const x22 = x2 + x2, y22 = y2 + y2, z2 = z + z; + const xx = x2 * x22, xy = x2 * y22, xz = x2 * z2; + const yy = y2 * y22, yz = y2 * z2, zz = z * z2; + const wx = w * x22, wy = w * y22, wz = w * z2; + const sx = scale.x, sy = scale.y, sz = scale.z; + te[0] = (1 - (yy + zz)) * sx; + te[1] = (xy + wz) * sx; + te[2] = (xz - wy) * sx; + te[3] = 0; + te[4] = (xy - wz) * sy; + te[5] = (1 - (xx + zz)) * sy; + te[6] = (yz + wx) * sy; + te[7] = 0; + te[8] = (xz + wy) * sz; + te[9] = (yz - wx) * sz; + te[10] = (1 - (xx + yy)) * sz; + te[11] = 0; + te[12] = position.x; + te[13] = position.y; + te[14] = position.z; + te[15] = 1; + return this; + } + decompose(position, quaternion, scale) { + const te = this.elements; + let sx = _v1$5.set(te[0], te[1], te[2]).length(); + const sy = _v1$5.set(te[4], te[5], te[6]).length(); + const sz = _v1$5.set(te[8], te[9], te[10]).length(); + const det = this.determinant(); + if (det < 0) + sx = -sx; + position.x = te[12]; + position.y = te[13]; + position.z = te[14]; + _m1$2.copy(this); + const invSX = 1 / sx; + const invSY = 1 / sy; + const invSZ = 1 / sz; + _m1$2.elements[0] *= invSX; + _m1$2.elements[1] *= invSX; + _m1$2.elements[2] *= invSX; + _m1$2.elements[4] *= invSY; + _m1$2.elements[5] *= invSY; + _m1$2.elements[6] *= invSY; + _m1$2.elements[8] *= invSZ; + _m1$2.elements[9] *= invSZ; + _m1$2.elements[10] *= invSZ; + quaternion.setFromRotationMatrix(_m1$2); + scale.x = sx; + scale.y = sy; + scale.z = sz; + return this; + } + makePerspective(left, right, top, bottom, near, far) { + const te = this.elements; + const x2 = 2 * near / (right - left); + const y2 = 2 * near / (top - bottom); + const a2 = (right + left) / (right - left); + const b = (top + bottom) / (top - bottom); + const c2 = -(far + near) / (far - near); + const d = -2 * far * near / (far - near); + te[0] = x2; + te[4] = 0; + te[8] = a2; + te[12] = 0; + te[1] = 0; + te[5] = y2; + te[9] = b; + te[13] = 0; + te[2] = 0; + te[6] = 0; + te[10] = c2; + te[14] = d; + te[3] = 0; + te[7] = 0; + te[11] = -1; + te[15] = 0; + return this; + } + makeOrthographic(left, right, top, bottom, near, far) { + const te = this.elements; + const w = 1 / (right - left); + const h = 1 / (top - bottom); + const p = 1 / (far - near); + const x2 = (right + left) * w; + const y2 = (top + bottom) * h; + const z = (far + near) * p; + te[0] = 2 * w; + te[4] = 0; + te[8] = 0; + te[12] = -x2; + te[1] = 0; + te[5] = 2 * h; + te[9] = 0; + te[13] = -y2; + te[2] = 0; + te[6] = 0; + te[10] = -2 * p; + te[14] = -z; + te[3] = 0; + te[7] = 0; + te[11] = 0; + te[15] = 1; + return this; + } + equals(matrix) { + const te = this.elements; + const me = matrix.elements; + for (let i = 0; i < 16; i++) { + if (te[i] !== me[i]) + return false; + } + return true; + } + fromArray(array2, offset = 0) { + for (let i = 0; i < 16; i++) { + this.elements[i] = array2[i + offset]; + } + return this; + } + toArray(array2 = [], offset = 0) { + const te = this.elements; + array2[offset] = te[0]; + array2[offset + 1] = te[1]; + array2[offset + 2] = te[2]; + array2[offset + 3] = te[3]; + array2[offset + 4] = te[4]; + array2[offset + 5] = te[5]; + array2[offset + 6] = te[6]; + array2[offset + 7] = te[7]; + array2[offset + 8] = te[8]; + array2[offset + 9] = te[9]; + array2[offset + 10] = te[10]; + array2[offset + 11] = te[11]; + array2[offset + 12] = te[12]; + array2[offset + 13] = te[13]; + array2[offset + 14] = te[14]; + array2[offset + 15] = te[15]; + return array2; + } + }; + var _v1$5 = /* @__PURE__ */ new Vector3(); + var _m1$2 = /* @__PURE__ */ new Matrix4(); + var _zero = /* @__PURE__ */ new Vector3(0, 0, 0); + var _one = /* @__PURE__ */ new Vector3(1, 1, 1); + var _x = /* @__PURE__ */ new Vector3(); + var _y = /* @__PURE__ */ new Vector3(); + var _z = /* @__PURE__ */ new Vector3(); + var _matrix$1 = /* @__PURE__ */ new Matrix4(); + var _quaternion$3 = /* @__PURE__ */ new Quaternion(); + var Euler = class { + constructor(x2 = 0, y2 = 0, z = 0, order = Euler.DefaultOrder) { + this.isEuler = true; + this._x = x2; + this._y = y2; + this._z = z; + this._order = order; + } + get x() { + return this._x; + } + set x(value) { + this._x = value; + this._onChangeCallback(); + } + get y() { + return this._y; + } + set y(value) { + this._y = value; + this._onChangeCallback(); + } + get z() { + return this._z; + } + set z(value) { + this._z = value; + this._onChangeCallback(); + } + get order() { + return this._order; + } + set order(value) { + this._order = value; + this._onChangeCallback(); + } + set(x2, y2, z, order = this._order) { + this._x = x2; + this._y = y2; + this._z = z; + this._order = order; + this._onChangeCallback(); + return this; + } + clone() { + return new this.constructor(this._x, this._y, this._z, this._order); + } + copy(euler) { + this._x = euler._x; + this._y = euler._y; + this._z = euler._z; + this._order = euler._order; + this._onChangeCallback(); + return this; + } + setFromRotationMatrix(m2, order = this._order, update = true) { + const te = m2.elements; + const m11 = te[0], m12 = te[4], m13 = te[8]; + const m21 = te[1], m22 = te[5], m23 = te[9]; + const m31 = te[2], m32 = te[6], m33 = te[10]; + switch (order) { + case "XYZ": + this._y = Math.asin(clamp(m13, -1, 1)); + if (Math.abs(m13) < 0.9999999) { + this._x = Math.atan2(-m23, m33); + this._z = Math.atan2(-m12, m11); + } else { + this._x = Math.atan2(m32, m22); + this._z = 0; + } + break; + case "YXZ": + this._x = Math.asin(-clamp(m23, -1, 1)); + if (Math.abs(m23) < 0.9999999) { + this._y = Math.atan2(m13, m33); + this._z = Math.atan2(m21, m22); + } else { + this._y = Math.atan2(-m31, m11); + this._z = 0; + } + break; + case "ZXY": + this._x = Math.asin(clamp(m32, -1, 1)); + if (Math.abs(m32) < 0.9999999) { + this._y = Math.atan2(-m31, m33); + this._z = Math.atan2(-m12, m22); + } else { + this._y = 0; + this._z = Math.atan2(m21, m11); + } + break; + case "ZYX": + this._y = Math.asin(-clamp(m31, -1, 1)); + if (Math.abs(m31) < 0.9999999) { + this._x = Math.atan2(m32, m33); + this._z = Math.atan2(m21, m11); + } else { + this._x = 0; + this._z = Math.atan2(-m12, m22); + } + break; + case "YZX": + this._z = Math.asin(clamp(m21, -1, 1)); + if (Math.abs(m21) < 0.9999999) { + this._x = Math.atan2(-m23, m22); + this._y = Math.atan2(-m31, m11); + } else { + this._x = 0; + this._y = Math.atan2(m13, m33); + } + break; + case "XZY": + this._z = Math.asin(-clamp(m12, -1, 1)); + if (Math.abs(m12) < 0.9999999) { + this._x = Math.atan2(m32, m22); + this._y = Math.atan2(m13, m11); + } else { + this._x = Math.atan2(-m23, m33); + this._y = 0; + } + break; + default: + console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: " + order); + } + this._order = order; + if (update === true) + this._onChangeCallback(); + return this; + } + setFromQuaternion(q, order, update) { + _matrix$1.makeRotationFromQuaternion(q); + return this.setFromRotationMatrix(_matrix$1, order, update); + } + setFromVector3(v, order = this._order) { + return this.set(v.x, v.y, v.z, order); + } + reorder(newOrder) { + _quaternion$3.setFromEuler(this); + return this.setFromQuaternion(_quaternion$3, newOrder); + } + equals(euler) { + return euler._x === this._x && euler._y === this._y && euler._z === this._z && euler._order === this._order; + } + fromArray(array2) { + this._x = array2[0]; + this._y = array2[1]; + this._z = array2[2]; + if (array2[3] !== void 0) + this._order = array2[3]; + this._onChangeCallback(); + return this; + } + toArray(array2 = [], offset = 0) { + array2[offset] = this._x; + array2[offset + 1] = this._y; + array2[offset + 2] = this._z; + array2[offset + 3] = this._order; + return array2; + } + _onChange(callback) { + this._onChangeCallback = callback; + return this; + } + _onChangeCallback() { + } + *[Symbol.iterator]() { + yield this._x; + yield this._y; + yield this._z; + yield this._order; + } + toVector3() { + console.error("THREE.Euler: .toVector3() has been removed. Use Vector3.setFromEuler() instead"); + } + }; + Euler.DefaultOrder = "XYZ"; + Euler.RotationOrders = ["XYZ", "YZX", "ZXY", "XZY", "YXZ", "ZYX"]; + var Layers = class { + constructor() { + this.mask = 1 | 0; + } + set(channel) { + this.mask = (1 << channel | 0) >>> 0; + } + enable(channel) { + this.mask |= 1 << channel | 0; + } + enableAll() { + this.mask = 4294967295 | 0; + } + toggle(channel) { + this.mask ^= 1 << channel | 0; + } + disable(channel) { + this.mask &= ~(1 << channel | 0); + } + disableAll() { + this.mask = 0; + } + test(layers) { + return (this.mask & layers.mask) !== 0; + } + isEnabled(channel) { + return (this.mask & (1 << channel | 0)) !== 0; + } + }; + var _object3DId = 0; + var _v1$4 = /* @__PURE__ */ new Vector3(); + var _q1 = /* @__PURE__ */ new Quaternion(); + var _m1$1 = /* @__PURE__ */ new Matrix4(); + var _target = /* @__PURE__ */ new Vector3(); + var _position$3 = /* @__PURE__ */ new Vector3(); + var _scale$2 = /* @__PURE__ */ new Vector3(); + var _quaternion$2 = /* @__PURE__ */ new Quaternion(); + var _xAxis = /* @__PURE__ */ new Vector3(1, 0, 0); + var _yAxis = /* @__PURE__ */ new Vector3(0, 1, 0); + var _zAxis = /* @__PURE__ */ new Vector3(0, 0, 1); + var _addedEvent = { type: "added" }; + var _removedEvent = { type: "removed" }; + var Object3D = class extends EventDispatcher { + constructor() { + super(); + this.isObject3D = true; + Object.defineProperty(this, "id", { value: _object3DId++ }); + this.uuid = generateUUID(); + this.name = ""; + this.type = "Object3D"; + this.parent = null; + this.children = []; + this.up = Object3D.DefaultUp.clone(); + const position = new Vector3(); + const rotation = new Euler(); + const quaternion = new Quaternion(); + const scale = new Vector3(1, 1, 1); + function onRotationChange() { + quaternion.setFromEuler(rotation, false); + } + function onQuaternionChange() { + rotation.setFromQuaternion(quaternion, void 0, false); + } + rotation._onChange(onRotationChange); + quaternion._onChange(onQuaternionChange); + Object.defineProperties(this, { + position: { + configurable: true, + enumerable: true, + value: position + }, + rotation: { + configurable: true, + enumerable: true, + value: rotation + }, + quaternion: { + configurable: true, + enumerable: true, + value: quaternion + }, + scale: { + configurable: true, + enumerable: true, + value: scale + }, + modelViewMatrix: { + value: new Matrix4() + }, + normalMatrix: { + value: new Matrix3() + } + }); + this.matrix = new Matrix4(); + this.matrixWorld = new Matrix4(); + this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate; + this.matrixWorldNeedsUpdate = false; + this.layers = new Layers(); + this.visible = true; + this.castShadow = false; + this.receiveShadow = false; + this.frustumCulled = true; + this.renderOrder = 0; + this.animations = []; + this.userData = {}; + } + onBeforeRender() { + } + onAfterRender() { + } + applyMatrix4(matrix) { + if (this.matrixAutoUpdate) + this.updateMatrix(); + this.matrix.premultiply(matrix); + this.matrix.decompose(this.position, this.quaternion, this.scale); + } + applyQuaternion(q) { + this.quaternion.premultiply(q); + return this; + } + setRotationFromAxisAngle(axis, angle) { + this.quaternion.setFromAxisAngle(axis, angle); + } + setRotationFromEuler(euler) { + this.quaternion.setFromEuler(euler, true); + } + setRotationFromMatrix(m2) { + this.quaternion.setFromRotationMatrix(m2); + } + setRotationFromQuaternion(q) { + this.quaternion.copy(q); + } + rotateOnAxis(axis, angle) { + _q1.setFromAxisAngle(axis, angle); + this.quaternion.multiply(_q1); + return this; + } + rotateOnWorldAxis(axis, angle) { + _q1.setFromAxisAngle(axis, angle); + this.quaternion.premultiply(_q1); + return this; + } + rotateX(angle) { + return this.rotateOnAxis(_xAxis, angle); + } + rotateY(angle) { + return this.rotateOnAxis(_yAxis, angle); + } + rotateZ(angle) { + return this.rotateOnAxis(_zAxis, angle); + } + translateOnAxis(axis, distance) { + _v1$4.copy(axis).applyQuaternion(this.quaternion); + this.position.add(_v1$4.multiplyScalar(distance)); + return this; + } + translateX(distance) { + return this.translateOnAxis(_xAxis, distance); + } + translateY(distance) { + return this.translateOnAxis(_yAxis, distance); + } + translateZ(distance) { + return this.translateOnAxis(_zAxis, distance); + } + localToWorld(vector) { + return vector.applyMatrix4(this.matrixWorld); + } + worldToLocal(vector) { + return vector.applyMatrix4(_m1$1.copy(this.matrixWorld).invert()); + } + lookAt(x2, y2, z) { + if (x2.isVector3) { + _target.copy(x2); + } else { + _target.set(x2, y2, z); + } + const parent = this.parent; + this.updateWorldMatrix(true, false); + _position$3.setFromMatrixPosition(this.matrixWorld); + if (this.isCamera || this.isLight) { + _m1$1.lookAt(_position$3, _target, this.up); + } else { + _m1$1.lookAt(_target, _position$3, this.up); + } + this.quaternion.setFromRotationMatrix(_m1$1); + if (parent) { + _m1$1.extractRotation(parent.matrixWorld); + _q1.setFromRotationMatrix(_m1$1); + this.quaternion.premultiply(_q1.invert()); + } + } + add(object) { + if (arguments.length > 1) { + for (let i = 0; i < arguments.length; i++) { + this.add(arguments[i]); + } + return this; + } + if (object === this) { + console.error("THREE.Object3D.add: object can't be added as a child of itself.", object); + return this; + } + if (object && object.isObject3D) { + if (object.parent !== null) { + object.parent.remove(object); + } + object.parent = this; + this.children.push(object); + object.dispatchEvent(_addedEvent); + } else { + console.error("THREE.Object3D.add: object not an instance of THREE.Object3D.", object); + } + return this; + } + remove(object) { + if (arguments.length > 1) { + for (let i = 0; i < arguments.length; i++) { + this.remove(arguments[i]); + } + return this; + } + const index2 = this.children.indexOf(object); + if (index2 !== -1) { + object.parent = null; + this.children.splice(index2, 1); + object.dispatchEvent(_removedEvent); + } + return this; + } + removeFromParent() { + const parent = this.parent; + if (parent !== null) { + parent.remove(this); + } + return this; + } + clear() { + for (let i = 0; i < this.children.length; i++) { + const object = this.children[i]; + object.parent = null; + object.dispatchEvent(_removedEvent); + } + this.children.length = 0; + return this; + } + attach(object) { + this.updateWorldMatrix(true, false); + _m1$1.copy(this.matrixWorld).invert(); + if (object.parent !== null) { + object.parent.updateWorldMatrix(true, false); + _m1$1.multiply(object.parent.matrixWorld); + } + object.applyMatrix4(_m1$1); + this.add(object); + object.updateWorldMatrix(false, true); + return this; + } + getObjectById(id2) { + return this.getObjectByProperty("id", id2); + } + getObjectByName(name) { + return this.getObjectByProperty("name", name); + } + getObjectByProperty(name, value) { + if (this[name] === value) + return this; + for (let i = 0, l = this.children.length; i < l; i++) { + const child = this.children[i]; + const object = child.getObjectByProperty(name, value); + if (object !== void 0) { + return object; + } + } + return void 0; + } + getWorldPosition(target) { + this.updateWorldMatrix(true, false); + return target.setFromMatrixPosition(this.matrixWorld); + } + getWorldQuaternion(target) { + this.updateWorldMatrix(true, false); + this.matrixWorld.decompose(_position$3, target, _scale$2); + return target; + } + getWorldScale(target) { + this.updateWorldMatrix(true, false); + this.matrixWorld.decompose(_position$3, _quaternion$2, target); + return target; + } + getWorldDirection(target) { + this.updateWorldMatrix(true, false); + const e = this.matrixWorld.elements; + return target.set(e[8], e[9], e[10]).normalize(); + } + raycast() { + } + traverse(callback) { + callback(this); + const children2 = this.children; + for (let i = 0, l = children2.length; i < l; i++) { + children2[i].traverse(callback); + } + } + traverseVisible(callback) { + if (this.visible === false) + return; + callback(this); + const children2 = this.children; + for (let i = 0, l = children2.length; i < l; i++) { + children2[i].traverseVisible(callback); + } + } + traverseAncestors(callback) { + const parent = this.parent; + if (parent !== null) { + callback(parent); + parent.traverseAncestors(callback); + } + } + updateMatrix() { + this.matrix.compose(this.position, this.quaternion, this.scale); + this.matrixWorldNeedsUpdate = true; + } + updateMatrixWorld(force) { + if (this.matrixAutoUpdate) + this.updateMatrix(); + if (this.matrixWorldNeedsUpdate || force) { + if (this.parent === null) { + this.matrixWorld.copy(this.matrix); + } else { + this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix); + } + this.matrixWorldNeedsUpdate = false; + force = true; + } + const children2 = this.children; + for (let i = 0, l = children2.length; i < l; i++) { + children2[i].updateMatrixWorld(force); + } + } + updateWorldMatrix(updateParents, updateChildren) { + const parent = this.parent; + if (updateParents === true && parent !== null) { + parent.updateWorldMatrix(true, false); + } + if (this.matrixAutoUpdate) + this.updateMatrix(); + if (this.parent === null) { + this.matrixWorld.copy(this.matrix); + } else { + this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix); + } + if (updateChildren === true) { + const children2 = this.children; + for (let i = 0, l = children2.length; i < l; i++) { + children2[i].updateWorldMatrix(false, true); + } + } + } + toJSON(meta) { + const isRootObject = meta === void 0 || typeof meta === "string"; + const output = {}; + if (isRootObject) { + meta = { + geometries: {}, + materials: {}, + textures: {}, + images: {}, + shapes: {}, + skeletons: {}, + animations: {}, + nodes: {} + }; + output.metadata = { + version: 4.5, + type: "Object", + generator: "Object3D.toJSON" + }; + } + const object = {}; + object.uuid = this.uuid; + object.type = this.type; + if (this.name !== "") + object.name = this.name; + if (this.castShadow === true) + object.castShadow = true; + if (this.receiveShadow === true) + object.receiveShadow = true; + if (this.visible === false) + object.visible = false; + if (this.frustumCulled === false) + object.frustumCulled = false; + if (this.renderOrder !== 0) + object.renderOrder = this.renderOrder; + if (JSON.stringify(this.userData) !== "{}") + object.userData = this.userData; + object.layers = this.layers.mask; + object.matrix = this.matrix.toArray(); + if (this.matrixAutoUpdate === false) + object.matrixAutoUpdate = false; + if (this.isInstancedMesh) { + object.type = "InstancedMesh"; + object.count = this.count; + object.instanceMatrix = this.instanceMatrix.toJSON(); + if (this.instanceColor !== null) + object.instanceColor = this.instanceColor.toJSON(); + } + function serialize(library, element) { + if (library[element.uuid] === void 0) { + library[element.uuid] = element.toJSON(meta); + } + return element.uuid; + } + if (this.isScene) { + if (this.background) { + if (this.background.isColor) { + object.background = this.background.toJSON(); + } else if (this.background.isTexture) { + object.background = this.background.toJSON(meta).uuid; + } + } + if (this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true) { + object.environment = this.environment.toJSON(meta).uuid; + } + } else if (this.isMesh || this.isLine || this.isPoints) { + object.geometry = serialize(meta.geometries, this.geometry); + const parameters = this.geometry.parameters; + if (parameters !== void 0 && parameters.shapes !== void 0) { + const shapes = parameters.shapes; + if (Array.isArray(shapes)) { + for (let i = 0, l = shapes.length; i < l; i++) { + const shape = shapes[i]; + serialize(meta.shapes, shape); + } + } else { + serialize(meta.shapes, shapes); + } + } + } + if (this.isSkinnedMesh) { + object.bindMode = this.bindMode; + object.bindMatrix = this.bindMatrix.toArray(); + if (this.skeleton !== void 0) { + serialize(meta.skeletons, this.skeleton); + object.skeleton = this.skeleton.uuid; + } + } + if (this.material !== void 0) { + if (Array.isArray(this.material)) { + const uuids = []; + for (let i = 0, l = this.material.length; i < l; i++) { + uuids.push(serialize(meta.materials, this.material[i])); + } + object.material = uuids; + } else { + object.material = serialize(meta.materials, this.material); + } + } + if (this.children.length > 0) { + object.children = []; + for (let i = 0; i < this.children.length; i++) { + object.children.push(this.children[i].toJSON(meta).object); + } + } + if (this.animations.length > 0) { + object.animations = []; + for (let i = 0; i < this.animations.length; i++) { + const animation = this.animations[i]; + object.animations.push(serialize(meta.animations, animation)); + } + } + if (isRootObject) { + const geometries = extractFromCache(meta.geometries); + const materials = extractFromCache(meta.materials); + const textures = extractFromCache(meta.textures); + const images = extractFromCache(meta.images); + const shapes = extractFromCache(meta.shapes); + const skeletons = extractFromCache(meta.skeletons); + const animations = extractFromCache(meta.animations); + const nodes = extractFromCache(meta.nodes); + if (geometries.length > 0) + output.geometries = geometries; + if (materials.length > 0) + output.materials = materials; + if (textures.length > 0) + output.textures = textures; + if (images.length > 0) + output.images = images; + if (shapes.length > 0) + output.shapes = shapes; + if (skeletons.length > 0) + output.skeletons = skeletons; + if (animations.length > 0) + output.animations = animations; + if (nodes.length > 0) + output.nodes = nodes; + } + output.object = object; + return output; + function extractFromCache(cache2) { + const values = []; + for (const key in cache2) { + const data = cache2[key]; + delete data.metadata; + values.push(data); + } + return values; + } + } + clone(recursive) { + return new this.constructor().copy(this, recursive); + } + copy(source, recursive = true) { + this.name = source.name; + this.up.copy(source.up); + this.position.copy(source.position); + this.rotation.order = source.rotation.order; + this.quaternion.copy(source.quaternion); + this.scale.copy(source.scale); + this.matrix.copy(source.matrix); + this.matrixWorld.copy(source.matrixWorld); + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; + this.layers.mask = source.layers.mask; + this.visible = source.visible; + this.castShadow = source.castShadow; + this.receiveShadow = source.receiveShadow; + this.frustumCulled = source.frustumCulled; + this.renderOrder = source.renderOrder; + this.userData = JSON.parse(JSON.stringify(source.userData)); + if (recursive === true) { + for (let i = 0; i < source.children.length; i++) { + const child = source.children[i]; + this.add(child.clone()); + } + } + return this; + } + }; + Object3D.DefaultUp = /* @__PURE__ */ new Vector3(0, 1, 0); + Object3D.DefaultMatrixAutoUpdate = true; + var _v0$1 = /* @__PURE__ */ new Vector3(); + var _v1$3 = /* @__PURE__ */ new Vector3(); + var _v2$2 = /* @__PURE__ */ new Vector3(); + var _v3$1 = /* @__PURE__ */ new Vector3(); + var _vab = /* @__PURE__ */ new Vector3(); + var _vac = /* @__PURE__ */ new Vector3(); + var _vbc = /* @__PURE__ */ new Vector3(); + var _vap = /* @__PURE__ */ new Vector3(); + var _vbp = /* @__PURE__ */ new Vector3(); + var _vcp = /* @__PURE__ */ new Vector3(); + var Triangle = class { + constructor(a2 = new Vector3(), b = new Vector3(), c2 = new Vector3()) { + this.a = a2; + this.b = b; + this.c = c2; + } + static getNormal(a2, b, c2, target) { + target.subVectors(c2, b); + _v0$1.subVectors(a2, b); + target.cross(_v0$1); + const targetLengthSq = target.lengthSq(); + if (targetLengthSq > 0) { + return target.multiplyScalar(1 / Math.sqrt(targetLengthSq)); + } + return target.set(0, 0, 0); + } + static getBarycoord(point, a2, b, c2, target) { + _v0$1.subVectors(c2, a2); + _v1$3.subVectors(b, a2); + _v2$2.subVectors(point, a2); + const dot00 = _v0$1.dot(_v0$1); + const dot01 = _v0$1.dot(_v1$3); + const dot02 = _v0$1.dot(_v2$2); + const dot11 = _v1$3.dot(_v1$3); + const dot12 = _v1$3.dot(_v2$2); + const denom = dot00 * dot11 - dot01 * dot01; + if (denom === 0) { + return target.set(-2, -1, -1); + } + const invDenom = 1 / denom; + const u = (dot11 * dot02 - dot01 * dot12) * invDenom; + const v = (dot00 * dot12 - dot01 * dot02) * invDenom; + return target.set(1 - u - v, v, u); + } + static containsPoint(point, a2, b, c2) { + this.getBarycoord(point, a2, b, c2, _v3$1); + return _v3$1.x >= 0 && _v3$1.y >= 0 && _v3$1.x + _v3$1.y <= 1; + } + static getUV(point, p1, p2, p3, uv1, uv2, uv3, target) { + this.getBarycoord(point, p1, p2, p3, _v3$1); + target.set(0, 0); + target.addScaledVector(uv1, _v3$1.x); + target.addScaledVector(uv2, _v3$1.y); + target.addScaledVector(uv3, _v3$1.z); + return target; + } + static isFrontFacing(a2, b, c2, direction) { + _v0$1.subVectors(c2, b); + _v1$3.subVectors(a2, b); + return _v0$1.cross(_v1$3).dot(direction) < 0 ? true : false; + } + set(a2, b, c2) { + this.a.copy(a2); + this.b.copy(b); + this.c.copy(c2); + return this; + } + setFromPointsAndIndices(points, i0, i1, i2) { + this.a.copy(points[i0]); + this.b.copy(points[i1]); + this.c.copy(points[i2]); + return this; + } + setFromAttributeAndIndices(attribute, i0, i1, i2) { + this.a.fromBufferAttribute(attribute, i0); + this.b.fromBufferAttribute(attribute, i1); + this.c.fromBufferAttribute(attribute, i2); + return this; + } + clone() { + return new this.constructor().copy(this); + } + copy(triangle) { + this.a.copy(triangle.a); + this.b.copy(triangle.b); + this.c.copy(triangle.c); + return this; + } + getArea() { + _v0$1.subVectors(this.c, this.b); + _v1$3.subVectors(this.a, this.b); + return _v0$1.cross(_v1$3).length() * 0.5; + } + getMidpoint(target) { + return target.addVectors(this.a, this.b).add(this.c).multiplyScalar(1 / 3); + } + getNormal(target) { + return Triangle.getNormal(this.a, this.b, this.c, target); + } + getPlane(target) { + return target.setFromCoplanarPoints(this.a, this.b, this.c); + } + getBarycoord(point, target) { + return Triangle.getBarycoord(point, this.a, this.b, this.c, target); + } + getUV(point, uv1, uv2, uv3, target) { + return Triangle.getUV(point, this.a, this.b, this.c, uv1, uv2, uv3, target); + } + containsPoint(point) { + return Triangle.containsPoint(point, this.a, this.b, this.c); + } + isFrontFacing(direction) { + return Triangle.isFrontFacing(this.a, this.b, this.c, direction); + } + intersectsBox(box) { + return box.intersectsTriangle(this); + } + closestPointToPoint(p, target) { + const a2 = this.a, b = this.b, c2 = this.c; + let v, w; + _vab.subVectors(b, a2); + _vac.subVectors(c2, a2); + _vap.subVectors(p, a2); + const d1 = _vab.dot(_vap); + const d2 = _vac.dot(_vap); + if (d1 <= 0 && d2 <= 0) { + return target.copy(a2); + } + _vbp.subVectors(p, b); + const d3 = _vab.dot(_vbp); + const d4 = _vac.dot(_vbp); + if (d3 >= 0 && d4 <= d3) { + return target.copy(b); + } + const vc = d1 * d4 - d3 * d2; + if (vc <= 0 && d1 >= 0 && d3 <= 0) { + v = d1 / (d1 - d3); + return target.copy(a2).addScaledVector(_vab, v); + } + _vcp.subVectors(p, c2); + const d5 = _vab.dot(_vcp); + const d6 = _vac.dot(_vcp); + if (d6 >= 0 && d5 <= d6) { + return target.copy(c2); + } + const vb = d5 * d2 - d1 * d6; + if (vb <= 0 && d2 >= 0 && d6 <= 0) { + w = d2 / (d2 - d6); + return target.copy(a2).addScaledVector(_vac, w); + } + const va = d3 * d6 - d5 * d4; + if (va <= 0 && d4 - d3 >= 0 && d5 - d6 >= 0) { + _vbc.subVectors(c2, b); + w = (d4 - d3) / (d4 - d3 + (d5 - d6)); + return target.copy(b).addScaledVector(_vbc, w); + } + const denom = 1 / (va + vb + vc); + v = vb * denom; + w = vc * denom; + return target.copy(a2).addScaledVector(_vab, v).addScaledVector(_vac, w); + } + equals(triangle) { + return triangle.a.equals(this.a) && triangle.b.equals(this.b) && triangle.c.equals(this.c); + } + }; + var materialId = 0; + var Material = class extends EventDispatcher { + constructor() { + super(); + this.isMaterial = true; + Object.defineProperty(this, "id", { value: materialId++ }); + this.uuid = generateUUID(); + this.name = ""; + this.type = "Material"; + this.blending = NormalBlending; + this.side = FrontSide; + this.vertexColors = false; + this.opacity = 1; + this.transparent = false; + this.blendSrc = SrcAlphaFactor; + this.blendDst = OneMinusSrcAlphaFactor; + this.blendEquation = AddEquation; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; + this.depthFunc = LessEqualDepth; + this.depthTest = true; + this.depthWrite = true; + this.stencilWriteMask = 255; + this.stencilFunc = AlwaysStencilFunc; + this.stencilRef = 0; + this.stencilFuncMask = 255; + this.stencilFail = KeepStencilOp; + this.stencilZFail = KeepStencilOp; + this.stencilZPass = KeepStencilOp; + this.stencilWrite = false; + this.clippingPlanes = null; + this.clipIntersection = false; + this.clipShadows = false; + this.shadowSide = null; + this.colorWrite = true; + this.precision = null; + this.polygonOffset = false; + this.polygonOffsetFactor = 0; + this.polygonOffsetUnits = 0; + this.dithering = false; + this.alphaToCoverage = false; + this.premultipliedAlpha = false; + this.visible = true; + this.toneMapped = true; + this.userData = {}; + this.version = 0; + this._alphaTest = 0; + } + get alphaTest() { + return this._alphaTest; + } + set alphaTest(value) { + if (this._alphaTest > 0 !== value > 0) { + this.version++; + } + this._alphaTest = value; + } + onBuild() { + } + onBeforeRender() { + } + onBeforeCompile() { + } + customProgramCacheKey() { + return this.onBeforeCompile.toString(); + } + setValues(values) { + if (values === void 0) + return; + for (const key in values) { + const newValue = values[key]; + if (newValue === void 0) { + console.warn("THREE.Material: '" + key + "' parameter is undefined."); + continue; + } + if (key === "shading") { + console.warn("THREE." + this.type + ": .shading has been removed. Use the boolean .flatShading instead."); + this.flatShading = newValue === FlatShading ? true : false; + continue; + } + const currentValue = this[key]; + if (currentValue === void 0) { + console.warn("THREE." + this.type + ": '" + key + "' is not a property of this material."); + continue; + } + if (currentValue && currentValue.isColor) { + currentValue.set(newValue); + } else if (currentValue && currentValue.isVector3 && (newValue && newValue.isVector3)) { + currentValue.copy(newValue); + } else { + this[key] = newValue; + } + } + } + toJSON(meta) { + const isRootObject = meta === void 0 || typeof meta === "string"; + if (isRootObject) { + meta = { + textures: {}, + images: {} + }; + } + const data = { + metadata: { + version: 4.5, + type: "Material", + generator: "Material.toJSON" + } + }; + data.uuid = this.uuid; + data.type = this.type; + if (this.name !== "") + data.name = this.name; + if (this.color && this.color.isColor) + data.color = this.color.getHex(); + if (this.roughness !== void 0) + data.roughness = this.roughness; + if (this.metalness !== void 0) + data.metalness = this.metalness; + if (this.sheen !== void 0) + data.sheen = this.sheen; + if (this.sheenColor && this.sheenColor.isColor) + data.sheenColor = this.sheenColor.getHex(); + if (this.sheenRoughness !== void 0) + data.sheenRoughness = this.sheenRoughness; + if (this.emissive && this.emissive.isColor) + data.emissive = this.emissive.getHex(); + if (this.emissiveIntensity && this.emissiveIntensity !== 1) + data.emissiveIntensity = this.emissiveIntensity; + if (this.specular && this.specular.isColor) + data.specular = this.specular.getHex(); + if (this.specularIntensity !== void 0) + data.specularIntensity = this.specularIntensity; + if (this.specularColor && this.specularColor.isColor) + data.specularColor = this.specularColor.getHex(); + if (this.shininess !== void 0) + data.shininess = this.shininess; + if (this.clearcoat !== void 0) + data.clearcoat = this.clearcoat; + if (this.clearcoatRoughness !== void 0) + data.clearcoatRoughness = this.clearcoatRoughness; + if (this.clearcoatMap && this.clearcoatMap.isTexture) { + data.clearcoatMap = this.clearcoatMap.toJSON(meta).uuid; + } + if (this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture) { + data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON(meta).uuid; + } + if (this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture) { + data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON(meta).uuid; + data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); + } + if (this.iridescence !== void 0) + data.iridescence = this.iridescence; + if (this.iridescenceIOR !== void 0) + data.iridescenceIOR = this.iridescenceIOR; + if (this.iridescenceThicknessRange !== void 0) + data.iridescenceThicknessRange = this.iridescenceThicknessRange; + if (this.iridescenceMap && this.iridescenceMap.isTexture) { + data.iridescenceMap = this.iridescenceMap.toJSON(meta).uuid; + } + if (this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture) { + data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON(meta).uuid; + } + if (this.map && this.map.isTexture) + data.map = this.map.toJSON(meta).uuid; + if (this.matcap && this.matcap.isTexture) + data.matcap = this.matcap.toJSON(meta).uuid; + if (this.alphaMap && this.alphaMap.isTexture) + data.alphaMap = this.alphaMap.toJSON(meta).uuid; + if (this.lightMap && this.lightMap.isTexture) { + data.lightMap = this.lightMap.toJSON(meta).uuid; + data.lightMapIntensity = this.lightMapIntensity; + } + if (this.aoMap && this.aoMap.isTexture) { + data.aoMap = this.aoMap.toJSON(meta).uuid; + data.aoMapIntensity = this.aoMapIntensity; + } + if (this.bumpMap && this.bumpMap.isTexture) { + data.bumpMap = this.bumpMap.toJSON(meta).uuid; + data.bumpScale = this.bumpScale; + } + if (this.normalMap && this.normalMap.isTexture) { + data.normalMap = this.normalMap.toJSON(meta).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); + } + if (this.displacementMap && this.displacementMap.isTexture) { + data.displacementMap = this.displacementMap.toJSON(meta).uuid; + data.displacementScale = this.displacementScale; + data.displacementBias = this.displacementBias; + } + if (this.roughnessMap && this.roughnessMap.isTexture) + data.roughnessMap = this.roughnessMap.toJSON(meta).uuid; + if (this.metalnessMap && this.metalnessMap.isTexture) + data.metalnessMap = this.metalnessMap.toJSON(meta).uuid; + if (this.emissiveMap && this.emissiveMap.isTexture) + data.emissiveMap = this.emissiveMap.toJSON(meta).uuid; + if (this.specularMap && this.specularMap.isTexture) + data.specularMap = this.specularMap.toJSON(meta).uuid; + if (this.specularIntensityMap && this.specularIntensityMap.isTexture) + data.specularIntensityMap = this.specularIntensityMap.toJSON(meta).uuid; + if (this.specularColorMap && this.specularColorMap.isTexture) + data.specularColorMap = this.specularColorMap.toJSON(meta).uuid; + if (this.envMap && this.envMap.isTexture) { + data.envMap = this.envMap.toJSON(meta).uuid; + if (this.combine !== void 0) + data.combine = this.combine; + } + if (this.envMapIntensity !== void 0) + data.envMapIntensity = this.envMapIntensity; + if (this.reflectivity !== void 0) + data.reflectivity = this.reflectivity; + if (this.refractionRatio !== void 0) + data.refractionRatio = this.refractionRatio; + if (this.gradientMap && this.gradientMap.isTexture) { + data.gradientMap = this.gradientMap.toJSON(meta).uuid; + } + if (this.transmission !== void 0) + data.transmission = this.transmission; + if (this.transmissionMap && this.transmissionMap.isTexture) + data.transmissionMap = this.transmissionMap.toJSON(meta).uuid; + if (this.thickness !== void 0) + data.thickness = this.thickness; + if (this.thicknessMap && this.thicknessMap.isTexture) + data.thicknessMap = this.thicknessMap.toJSON(meta).uuid; + if (this.attenuationDistance !== void 0) + data.attenuationDistance = this.attenuationDistance; + if (this.attenuationColor !== void 0) + data.attenuationColor = this.attenuationColor.getHex(); + if (this.size !== void 0) + data.size = this.size; + if (this.shadowSide !== null) + data.shadowSide = this.shadowSide; + if (this.sizeAttenuation !== void 0) + data.sizeAttenuation = this.sizeAttenuation; + if (this.blending !== NormalBlending) + data.blending = this.blending; + if (this.side !== FrontSide) + data.side = this.side; + if (this.vertexColors) + data.vertexColors = true; + if (this.opacity < 1) + data.opacity = this.opacity; + if (this.transparent === true) + data.transparent = this.transparent; + data.depthFunc = this.depthFunc; + data.depthTest = this.depthTest; + data.depthWrite = this.depthWrite; + data.colorWrite = this.colorWrite; + data.stencilWrite = this.stencilWrite; + data.stencilWriteMask = this.stencilWriteMask; + data.stencilFunc = this.stencilFunc; + data.stencilRef = this.stencilRef; + data.stencilFuncMask = this.stencilFuncMask; + data.stencilFail = this.stencilFail; + data.stencilZFail = this.stencilZFail; + data.stencilZPass = this.stencilZPass; + if (this.rotation !== void 0 && this.rotation !== 0) + data.rotation = this.rotation; + if (this.polygonOffset === true) + data.polygonOffset = true; + if (this.polygonOffsetFactor !== 0) + data.polygonOffsetFactor = this.polygonOffsetFactor; + if (this.polygonOffsetUnits !== 0) + data.polygonOffsetUnits = this.polygonOffsetUnits; + if (this.linewidth !== void 0 && this.linewidth !== 1) + data.linewidth = this.linewidth; + if (this.dashSize !== void 0) + data.dashSize = this.dashSize; + if (this.gapSize !== void 0) + data.gapSize = this.gapSize; + if (this.scale !== void 0) + data.scale = this.scale; + if (this.dithering === true) + data.dithering = true; + if (this.alphaTest > 0) + data.alphaTest = this.alphaTest; + if (this.alphaToCoverage === true) + data.alphaToCoverage = this.alphaToCoverage; + if (this.premultipliedAlpha === true) + data.premultipliedAlpha = this.premultipliedAlpha; + if (this.wireframe === true) + data.wireframe = this.wireframe; + if (this.wireframeLinewidth > 1) + data.wireframeLinewidth = this.wireframeLinewidth; + if (this.wireframeLinecap !== "round") + data.wireframeLinecap = this.wireframeLinecap; + if (this.wireframeLinejoin !== "round") + data.wireframeLinejoin = this.wireframeLinejoin; + if (this.flatShading === true) + data.flatShading = this.flatShading; + if (this.visible === false) + data.visible = false; + if (this.toneMapped === false) + data.toneMapped = false; + if (this.fog === false) + data.fog = false; + if (JSON.stringify(this.userData) !== "{}") + data.userData = this.userData; + function extractFromCache(cache2) { + const values = []; + for (const key in cache2) { + const data2 = cache2[key]; + delete data2.metadata; + values.push(data2); + } + return values; + } + if (isRootObject) { + const textures = extractFromCache(meta.textures); + const images = extractFromCache(meta.images); + if (textures.length > 0) + data.textures = textures; + if (images.length > 0) + data.images = images; + } + return data; + } + clone() { + return new this.constructor().copy(this); + } + copy(source) { + this.name = source.name; + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; + this.opacity = source.opacity; + this.transparent = source.transparent; + this.blendSrc = source.blendSrc; + this.blendDst = source.blendDst; + this.blendEquation = source.blendEquation; + this.blendSrcAlpha = source.blendSrcAlpha; + this.blendDstAlpha = source.blendDstAlpha; + this.blendEquationAlpha = source.blendEquationAlpha; + this.depthFunc = source.depthFunc; + this.depthTest = source.depthTest; + this.depthWrite = source.depthWrite; + this.stencilWriteMask = source.stencilWriteMask; + this.stencilFunc = source.stencilFunc; + this.stencilRef = source.stencilRef; + this.stencilFuncMask = source.stencilFuncMask; + this.stencilFail = source.stencilFail; + this.stencilZFail = source.stencilZFail; + this.stencilZPass = source.stencilZPass; + this.stencilWrite = source.stencilWrite; + const srcPlanes = source.clippingPlanes; + let dstPlanes = null; + if (srcPlanes !== null) { + const n = srcPlanes.length; + dstPlanes = new Array(n); + for (let i = 0; i !== n; ++i) { + dstPlanes[i] = srcPlanes[i].clone(); + } + } + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; + this.shadowSide = source.shadowSide; + this.colorWrite = source.colorWrite; + this.precision = source.precision; + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; + this.dithering = source.dithering; + this.alphaTest = source.alphaTest; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; + this.visible = source.visible; + this.toneMapped = source.toneMapped; + this.userData = JSON.parse(JSON.stringify(source.userData)); + return this; + } + dispose() { + this.dispatchEvent({ type: "dispose" }); + } + set needsUpdate(value) { + if (value === true) + this.version++; + } + }; + var MeshBasicMaterial = class extends Material { + constructor(parameters) { + super(); + this.isMeshBasicMaterial = true; + this.type = "MeshBasicMaterial"; + this.color = new Color2(16777215); + this.map = null; + this.lightMap = null; + this.lightMapIntensity = 1; + this.aoMap = null; + this.aoMapIntensity = 1; + this.specularMap = null; + this.alphaMap = null; + this.envMap = null; + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = "round"; + this.wireframeLinejoin = "round"; + this.fog = true; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.color.copy(source.color); + this.map = source.map; + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + this.specularMap = source.specularMap; + this.alphaMap = source.alphaMap; + this.envMap = source.envMap; + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + this.fog = source.fog; + return this; + } + }; + var _vector$9 = /* @__PURE__ */ new Vector3(); + var _vector2$1 = /* @__PURE__ */ new Vector2(); + var BufferAttribute = class { + constructor(array2, itemSize, normalized) { + if (Array.isArray(array2)) { + throw new TypeError("THREE.BufferAttribute: array should be a Typed Array."); + } + this.isBufferAttribute = true; + this.name = ""; + this.array = array2; + this.itemSize = itemSize; + this.count = array2 !== void 0 ? array2.length / itemSize : 0; + this.normalized = normalized === true; + this.usage = StaticDrawUsage; + this.updateRange = { offset: 0, count: -1 }; + this.version = 0; + } + onUploadCallback() { + } + set needsUpdate(value) { + if (value === true) + this.version++; + } + setUsage(value) { + this.usage = value; + return this; + } + copy(source) { + this.name = source.name; + this.array = new source.array.constructor(source.array); + this.itemSize = source.itemSize; + this.count = source.count; + this.normalized = source.normalized; + this.usage = source.usage; + return this; + } + copyAt(index1, attribute, index2) { + index1 *= this.itemSize; + index2 *= attribute.itemSize; + for (let i = 0, l = this.itemSize; i < l; i++) { + this.array[index1 + i] = attribute.array[index2 + i]; + } + return this; + } + copyArray(array2) { + this.array.set(array2); + return this; + } + copyColorsArray(colors) { + const array2 = this.array; + let offset = 0; + for (let i = 0, l = colors.length; i < l; i++) { + let color2 = colors[i]; + if (color2 === void 0) { + console.warn("THREE.BufferAttribute.copyColorsArray(): color is undefined", i); + color2 = new Color2(); + } + array2[offset++] = color2.r; + array2[offset++] = color2.g; + array2[offset++] = color2.b; + } + return this; + } + copyVector2sArray(vectors) { + const array2 = this.array; + let offset = 0; + for (let i = 0, l = vectors.length; i < l; i++) { + let vector = vectors[i]; + if (vector === void 0) { + console.warn("THREE.BufferAttribute.copyVector2sArray(): vector is undefined", i); + vector = new Vector2(); + } + array2[offset++] = vector.x; + array2[offset++] = vector.y; + } + return this; + } + copyVector3sArray(vectors) { + const array2 = this.array; + let offset = 0; + for (let i = 0, l = vectors.length; i < l; i++) { + let vector = vectors[i]; + if (vector === void 0) { + console.warn("THREE.BufferAttribute.copyVector3sArray(): vector is undefined", i); + vector = new Vector3(); + } + array2[offset++] = vector.x; + array2[offset++] = vector.y; + array2[offset++] = vector.z; + } + return this; + } + copyVector4sArray(vectors) { + const array2 = this.array; + let offset = 0; + for (let i = 0, l = vectors.length; i < l; i++) { + let vector = vectors[i]; + if (vector === void 0) { + console.warn("THREE.BufferAttribute.copyVector4sArray(): vector is undefined", i); + vector = new Vector4(); + } + array2[offset++] = vector.x; + array2[offset++] = vector.y; + array2[offset++] = vector.z; + array2[offset++] = vector.w; + } + return this; + } + applyMatrix3(m2) { + if (this.itemSize === 2) { + for (let i = 0, l = this.count; i < l; i++) { + _vector2$1.fromBufferAttribute(this, i); + _vector2$1.applyMatrix3(m2); + this.setXY(i, _vector2$1.x, _vector2$1.y); + } + } else if (this.itemSize === 3) { + for (let i = 0, l = this.count; i < l; i++) { + _vector$9.fromBufferAttribute(this, i); + _vector$9.applyMatrix3(m2); + this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z); + } + } + return this; + } + applyMatrix4(m2) { + for (let i = 0, l = this.count; i < l; i++) { + _vector$9.fromBufferAttribute(this, i); + _vector$9.applyMatrix4(m2); + this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z); + } + return this; + } + applyNormalMatrix(m2) { + for (let i = 0, l = this.count; i < l; i++) { + _vector$9.fromBufferAttribute(this, i); + _vector$9.applyNormalMatrix(m2); + this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z); + } + return this; + } + transformDirection(m2) { + for (let i = 0, l = this.count; i < l; i++) { + _vector$9.fromBufferAttribute(this, i); + _vector$9.transformDirection(m2); + this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z); + } + return this; + } + set(value, offset = 0) { + this.array.set(value, offset); + return this; + } + getX(index2) { + return this.array[index2 * this.itemSize]; + } + setX(index2, x2) { + this.array[index2 * this.itemSize] = x2; + return this; + } + getY(index2) { + return this.array[index2 * this.itemSize + 1]; + } + setY(index2, y2) { + this.array[index2 * this.itemSize + 1] = y2; + return this; + } + getZ(index2) { + return this.array[index2 * this.itemSize + 2]; + } + setZ(index2, z) { + this.array[index2 * this.itemSize + 2] = z; + return this; + } + getW(index2) { + return this.array[index2 * this.itemSize + 3]; + } + setW(index2, w) { + this.array[index2 * this.itemSize + 3] = w; + return this; + } + setXY(index2, x2, y2) { + index2 *= this.itemSize; + this.array[index2 + 0] = x2; + this.array[index2 + 1] = y2; + return this; + } + setXYZ(index2, x2, y2, z) { + index2 *= this.itemSize; + this.array[index2 + 0] = x2; + this.array[index2 + 1] = y2; + this.array[index2 + 2] = z; + return this; + } + setXYZW(index2, x2, y2, z, w) { + index2 *= this.itemSize; + this.array[index2 + 0] = x2; + this.array[index2 + 1] = y2; + this.array[index2 + 2] = z; + this.array[index2 + 3] = w; + return this; + } + onUpload(callback) { + this.onUploadCallback = callback; + return this; + } + clone() { + return new this.constructor(this.array, this.itemSize).copy(this); + } + toJSON() { + const data = { + itemSize: this.itemSize, + type: this.array.constructor.name, + array: Array.from(this.array), + normalized: this.normalized + }; + if (this.name !== "") + data.name = this.name; + if (this.usage !== StaticDrawUsage) + data.usage = this.usage; + if (this.updateRange.offset !== 0 || this.updateRange.count !== -1) + data.updateRange = this.updateRange; + return data; + } + }; + var Uint16BufferAttribute = class extends BufferAttribute { + constructor(array2, itemSize, normalized) { + super(new Uint16Array(array2), itemSize, normalized); + } + }; + var Uint32BufferAttribute = class extends BufferAttribute { + constructor(array2, itemSize, normalized) { + super(new Uint32Array(array2), itemSize, normalized); + } + }; + var Float32BufferAttribute = class extends BufferAttribute { + constructor(array2, itemSize, normalized) { + super(new Float32Array(array2), itemSize, normalized); + } + }; + var _id$1 = 0; + var _m1 = /* @__PURE__ */ new Matrix4(); + var _obj = /* @__PURE__ */ new Object3D(); + var _offset = /* @__PURE__ */ new Vector3(); + var _box$1 = /* @__PURE__ */ new Box3(); + var _boxMorphTargets = /* @__PURE__ */ new Box3(); + var _vector$8 = /* @__PURE__ */ new Vector3(); + var BufferGeometry = class extends EventDispatcher { + constructor() { + super(); + this.isBufferGeometry = true; + Object.defineProperty(this, "id", { value: _id$1++ }); + this.uuid = generateUUID(); + this.name = ""; + this.type = "BufferGeometry"; + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.morphTargetsRelative = false; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; + this.drawRange = { start: 0, count: Infinity }; + this.userData = {}; + } + getIndex() { + return this.index; + } + setIndex(index2) { + if (Array.isArray(index2)) { + this.index = new (arrayNeedsUint32(index2) ? Uint32BufferAttribute : Uint16BufferAttribute)(index2, 1); + } else { + this.index = index2; + } + return this; + } + getAttribute(name) { + return this.attributes[name]; + } + setAttribute(name, attribute) { + this.attributes[name] = attribute; + return this; + } + deleteAttribute(name) { + delete this.attributes[name]; + return this; + } + hasAttribute(name) { + return this.attributes[name] !== void 0; + } + addGroup(start2, count, materialIndex = 0) { + this.groups.push({ + start: start2, + count, + materialIndex + }); + } + clearGroups() { + this.groups = []; + } + setDrawRange(start2, count) { + this.drawRange.start = start2; + this.drawRange.count = count; + } + applyMatrix4(matrix) { + const position = this.attributes.position; + if (position !== void 0) { + position.applyMatrix4(matrix); + position.needsUpdate = true; + } + const normal = this.attributes.normal; + if (normal !== void 0) { + const normalMatrix = new Matrix3().getNormalMatrix(matrix); + normal.applyNormalMatrix(normalMatrix); + normal.needsUpdate = true; + } + const tangent = this.attributes.tangent; + if (tangent !== void 0) { + tangent.transformDirection(matrix); + tangent.needsUpdate = true; + } + if (this.boundingBox !== null) { + this.computeBoundingBox(); + } + if (this.boundingSphere !== null) { + this.computeBoundingSphere(); + } + return this; + } + applyQuaternion(q) { + _m1.makeRotationFromQuaternion(q); + this.applyMatrix4(_m1); + return this; + } + rotateX(angle) { + _m1.makeRotationX(angle); + this.applyMatrix4(_m1); + return this; + } + rotateY(angle) { + _m1.makeRotationY(angle); + this.applyMatrix4(_m1); + return this; + } + rotateZ(angle) { + _m1.makeRotationZ(angle); + this.applyMatrix4(_m1); + return this; + } + translate(x2, y2, z) { + _m1.makeTranslation(x2, y2, z); + this.applyMatrix4(_m1); + return this; + } + scale(x2, y2, z) { + _m1.makeScale(x2, y2, z); + this.applyMatrix4(_m1); + return this; + } + lookAt(vector) { + _obj.lookAt(vector); + _obj.updateMatrix(); + this.applyMatrix4(_obj.matrix); + return this; + } + center() { + this.computeBoundingBox(); + this.boundingBox.getCenter(_offset).negate(); + this.translate(_offset.x, _offset.y, _offset.z); + return this; + } + setFromPoints(points) { + const position = []; + for (let i = 0, l = points.length; i < l; i++) { + const point = points[i]; + position.push(point.x, point.y, point.z || 0); + } + this.setAttribute("position", new Float32BufferAttribute(position, 3)); + return this; + } + computeBoundingBox() { + if (this.boundingBox === null) { + this.boundingBox = new Box3(); + } + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; + if (position && position.isGLBufferAttribute) { + console.error('THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this); + this.boundingBox.set(new Vector3(-Infinity, -Infinity, -Infinity), new Vector3(Infinity, Infinity, Infinity)); + return; + } + if (position !== void 0) { + this.boundingBox.setFromBufferAttribute(position); + if (morphAttributesPosition) { + for (let i = 0, il = morphAttributesPosition.length; i < il; i++) { + const morphAttribute = morphAttributesPosition[i]; + _box$1.setFromBufferAttribute(morphAttribute); + if (this.morphTargetsRelative) { + _vector$8.addVectors(this.boundingBox.min, _box$1.min); + this.boundingBox.expandByPoint(_vector$8); + _vector$8.addVectors(this.boundingBox.max, _box$1.max); + this.boundingBox.expandByPoint(_vector$8); + } else { + this.boundingBox.expandByPoint(_box$1.min); + this.boundingBox.expandByPoint(_box$1.max); + } + } + } + } else { + this.boundingBox.makeEmpty(); + } + if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) { + console.error('THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this); + } + } + computeBoundingSphere() { + if (this.boundingSphere === null) { + this.boundingSphere = new Sphere(); + } + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; + if (position && position.isGLBufferAttribute) { + console.error('THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this); + this.boundingSphere.set(new Vector3(), Infinity); + return; + } + if (position) { + const center = this.boundingSphere.center; + _box$1.setFromBufferAttribute(position); + if (morphAttributesPosition) { + for (let i = 0, il = morphAttributesPosition.length; i < il; i++) { + const morphAttribute = morphAttributesPosition[i]; + _boxMorphTargets.setFromBufferAttribute(morphAttribute); + if (this.morphTargetsRelative) { + _vector$8.addVectors(_box$1.min, _boxMorphTargets.min); + _box$1.expandByPoint(_vector$8); + _vector$8.addVectors(_box$1.max, _boxMorphTargets.max); + _box$1.expandByPoint(_vector$8); + } else { + _box$1.expandByPoint(_boxMorphTargets.min); + _box$1.expandByPoint(_boxMorphTargets.max); + } + } + } + _box$1.getCenter(center); + let maxRadiusSq = 0; + for (let i = 0, il = position.count; i < il; i++) { + _vector$8.fromBufferAttribute(position, i); + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$8)); + } + if (morphAttributesPosition) { + for (let i = 0, il = morphAttributesPosition.length; i < il; i++) { + const morphAttribute = morphAttributesPosition[i]; + const morphTargetsRelative = this.morphTargetsRelative; + for (let j = 0, jl = morphAttribute.count; j < jl; j++) { + _vector$8.fromBufferAttribute(morphAttribute, j); + if (morphTargetsRelative) { + _offset.fromBufferAttribute(position, j); + _vector$8.add(_offset); + } + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$8)); + } + } + } + this.boundingSphere.radius = Math.sqrt(maxRadiusSq); + if (isNaN(this.boundingSphere.radius)) { + console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this); + } + } + } + computeTangents() { + const index2 = this.index; + const attributes = this.attributes; + if (index2 === null || attributes.position === void 0 || attributes.normal === void 0 || attributes.uv === void 0) { + console.error("THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)"); + return; + } + const indices = index2.array; + const positions = attributes.position.array; + const normals = attributes.normal.array; + const uvs = attributes.uv.array; + const nVertices = positions.length / 3; + if (this.hasAttribute("tangent") === false) { + this.setAttribute("tangent", new BufferAttribute(new Float32Array(4 * nVertices), 4)); + } + const tangents = this.getAttribute("tangent").array; + const tan1 = [], tan2 = []; + for (let i = 0; i < nVertices; i++) { + tan1[i] = new Vector3(); + tan2[i] = new Vector3(); + } + const vA = new Vector3(), vB = new Vector3(), vC = new Vector3(), uvA = new Vector2(), uvB = new Vector2(), uvC = new Vector2(), sdir = new Vector3(), tdir = new Vector3(); + function handleTriangle(a2, b, c2) { + vA.fromArray(positions, a2 * 3); + vB.fromArray(positions, b * 3); + vC.fromArray(positions, c2 * 3); + uvA.fromArray(uvs, a2 * 2); + uvB.fromArray(uvs, b * 2); + uvC.fromArray(uvs, c2 * 2); + vB.sub(vA); + vC.sub(vA); + uvB.sub(uvA); + uvC.sub(uvA); + const r = 1 / (uvB.x * uvC.y - uvC.x * uvB.y); + if (!isFinite(r)) + return; + sdir.copy(vB).multiplyScalar(uvC.y).addScaledVector(vC, -uvB.y).multiplyScalar(r); + tdir.copy(vC).multiplyScalar(uvB.x).addScaledVector(vB, -uvC.x).multiplyScalar(r); + tan1[a2].add(sdir); + tan1[b].add(sdir); + tan1[c2].add(sdir); + tan2[a2].add(tdir); + tan2[b].add(tdir); + tan2[c2].add(tdir); + } + let groups = this.groups; + if (groups.length === 0) { + groups = [{ + start: 0, + count: indices.length + }]; + } + for (let i = 0, il = groups.length; i < il; ++i) { + const group = groups[i]; + const start2 = group.start; + const count = group.count; + for (let j = start2, jl = start2 + count; j < jl; j += 3) { + handleTriangle(indices[j + 0], indices[j + 1], indices[j + 2]); + } + } + const tmp = new Vector3(), tmp2 = new Vector3(); + const n = new Vector3(), n2 = new Vector3(); + function handleVertex(v) { + n.fromArray(normals, v * 3); + n2.copy(n); + const t = tan1[v]; + tmp.copy(t); + tmp.sub(n.multiplyScalar(n.dot(t))).normalize(); + tmp2.crossVectors(n2, t); + const test = tmp2.dot(tan2[v]); + const w = test < 0 ? -1 : 1; + tangents[v * 4] = tmp.x; + tangents[v * 4 + 1] = tmp.y; + tangents[v * 4 + 2] = tmp.z; + tangents[v * 4 + 3] = w; + } + for (let i = 0, il = groups.length; i < il; ++i) { + const group = groups[i]; + const start2 = group.start; + const count = group.count; + for (let j = start2, jl = start2 + count; j < jl; j += 3) { + handleVertex(indices[j + 0]); + handleVertex(indices[j + 1]); + handleVertex(indices[j + 2]); + } + } + } + computeVertexNormals() { + const index2 = this.index; + const positionAttribute = this.getAttribute("position"); + if (positionAttribute !== void 0) { + let normalAttribute = this.getAttribute("normal"); + if (normalAttribute === void 0) { + normalAttribute = new BufferAttribute(new Float32Array(positionAttribute.count * 3), 3); + this.setAttribute("normal", normalAttribute); + } else { + for (let i = 0, il = normalAttribute.count; i < il; i++) { + normalAttribute.setXYZ(i, 0, 0, 0); + } + } + const pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); + const nA = new Vector3(), nB = new Vector3(), nC = new Vector3(); + const cb = new Vector3(), ab = new Vector3(); + if (index2) { + for (let i = 0, il = index2.count; i < il; i += 3) { + const vA = index2.getX(i + 0); + const vB = index2.getX(i + 1); + const vC = index2.getX(i + 2); + pA.fromBufferAttribute(positionAttribute, vA); + pB.fromBufferAttribute(positionAttribute, vB); + pC.fromBufferAttribute(positionAttribute, vC); + cb.subVectors(pC, pB); + ab.subVectors(pA, pB); + cb.cross(ab); + nA.fromBufferAttribute(normalAttribute, vA); + nB.fromBufferAttribute(normalAttribute, vB); + nC.fromBufferAttribute(normalAttribute, vC); + nA.add(cb); + nB.add(cb); + nC.add(cb); + normalAttribute.setXYZ(vA, nA.x, nA.y, nA.z); + normalAttribute.setXYZ(vB, nB.x, nB.y, nB.z); + normalAttribute.setXYZ(vC, nC.x, nC.y, nC.z); + } + } else { + for (let i = 0, il = positionAttribute.count; i < il; i += 3) { + pA.fromBufferAttribute(positionAttribute, i + 0); + pB.fromBufferAttribute(positionAttribute, i + 1); + pC.fromBufferAttribute(positionAttribute, i + 2); + cb.subVectors(pC, pB); + ab.subVectors(pA, pB); + cb.cross(ab); + normalAttribute.setXYZ(i + 0, cb.x, cb.y, cb.z); + normalAttribute.setXYZ(i + 1, cb.x, cb.y, cb.z); + normalAttribute.setXYZ(i + 2, cb.x, cb.y, cb.z); + } + } + this.normalizeNormals(); + normalAttribute.needsUpdate = true; + } + } + merge(geometry, offset) { + if (!(geometry && geometry.isBufferGeometry)) { + console.error("THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.", geometry); + return; + } + if (offset === void 0) { + offset = 0; + console.warn("THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge."); + } + const attributes = this.attributes; + for (const key in attributes) { + if (geometry.attributes[key] === void 0) + continue; + const attribute1 = attributes[key]; + const attributeArray1 = attribute1.array; + const attribute2 = geometry.attributes[key]; + const attributeArray2 = attribute2.array; + const attributeOffset = attribute2.itemSize * offset; + const length = Math.min(attributeArray2.length, attributeArray1.length - attributeOffset); + for (let i = 0, j = attributeOffset; i < length; i++, j++) { + attributeArray1[j] = attributeArray2[i]; + } + } + return this; + } + normalizeNormals() { + const normals = this.attributes.normal; + for (let i = 0, il = normals.count; i < il; i++) { + _vector$8.fromBufferAttribute(normals, i); + _vector$8.normalize(); + normals.setXYZ(i, _vector$8.x, _vector$8.y, _vector$8.z); + } + } + toNonIndexed() { + function convertBufferAttribute(attribute, indices2) { + const array2 = attribute.array; + const itemSize = attribute.itemSize; + const normalized = attribute.normalized; + const array22 = new array2.constructor(indices2.length * itemSize); + let index2 = 0, index22 = 0; + for (let i = 0, l = indices2.length; i < l; i++) { + if (attribute.isInterleavedBufferAttribute) { + index2 = indices2[i] * attribute.data.stride + attribute.offset; + } else { + index2 = indices2[i] * itemSize; + } + for (let j = 0; j < itemSize; j++) { + array22[index22++] = array2[index2++]; + } + } + return new BufferAttribute(array22, itemSize, normalized); + } + if (this.index === null) { + console.warn("THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed."); + return this; + } + const geometry2 = new BufferGeometry(); + const indices = this.index.array; + const attributes = this.attributes; + for (const name in attributes) { + const attribute = attributes[name]; + const newAttribute = convertBufferAttribute(attribute, indices); + geometry2.setAttribute(name, newAttribute); + } + const morphAttributes = this.morphAttributes; + for (const name in morphAttributes) { + const morphArray = []; + const morphAttribute = morphAttributes[name]; + for (let i = 0, il = morphAttribute.length; i < il; i++) { + const attribute = morphAttribute[i]; + const newAttribute = convertBufferAttribute(attribute, indices); + morphArray.push(newAttribute); + } + geometry2.morphAttributes[name] = morphArray; + } + geometry2.morphTargetsRelative = this.morphTargetsRelative; + const groups = this.groups; + for (let i = 0, l = groups.length; i < l; i++) { + const group = groups[i]; + geometry2.addGroup(group.start, group.count, group.materialIndex); + } + return geometry2; + } + toJSON() { + const data = { + metadata: { + version: 4.5, + type: "BufferGeometry", + generator: "BufferGeometry.toJSON" + } + }; + data.uuid = this.uuid; + data.type = this.type; + if (this.name !== "") + data.name = this.name; + if (Object.keys(this.userData).length > 0) + data.userData = this.userData; + if (this.parameters !== void 0) { + const parameters = this.parameters; + for (const key in parameters) { + if (parameters[key] !== void 0) + data[key] = parameters[key]; + } + return data; + } + data.data = { attributes: {} }; + const index2 = this.index; + if (index2 !== null) { + data.data.index = { + type: index2.array.constructor.name, + array: Array.prototype.slice.call(index2.array) + }; + } + const attributes = this.attributes; + for (const key in attributes) { + const attribute = attributes[key]; + data.data.attributes[key] = attribute.toJSON(data.data); + } + const morphAttributes = {}; + let hasMorphAttributes = false; + for (const key in this.morphAttributes) { + const attributeArray = this.morphAttributes[key]; + const array2 = []; + for (let i = 0, il = attributeArray.length; i < il; i++) { + const attribute = attributeArray[i]; + array2.push(attribute.toJSON(data.data)); + } + if (array2.length > 0) { + morphAttributes[key] = array2; + hasMorphAttributes = true; + } + } + if (hasMorphAttributes) { + data.data.morphAttributes = morphAttributes; + data.data.morphTargetsRelative = this.morphTargetsRelative; + } + const groups = this.groups; + if (groups.length > 0) { + data.data.groups = JSON.parse(JSON.stringify(groups)); + } + const boundingSphere = this.boundingSphere; + if (boundingSphere !== null) { + data.data.boundingSphere = { + center: boundingSphere.center.toArray(), + radius: boundingSphere.radius + }; + } + return data; + } + clone() { + return new this.constructor().copy(this); + } + copy(source) { + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; + const data = {}; + this.name = source.name; + const index2 = source.index; + if (index2 !== null) { + this.setIndex(index2.clone(data)); + } + const attributes = source.attributes; + for (const name in attributes) { + const attribute = attributes[name]; + this.setAttribute(name, attribute.clone(data)); + } + const morphAttributes = source.morphAttributes; + for (const name in morphAttributes) { + const array2 = []; + const morphAttribute = morphAttributes[name]; + for (let i = 0, l = morphAttribute.length; i < l; i++) { + array2.push(morphAttribute[i].clone(data)); + } + this.morphAttributes[name] = array2; + } + this.morphTargetsRelative = source.morphTargetsRelative; + const groups = source.groups; + for (let i = 0, l = groups.length; i < l; i++) { + const group = groups[i]; + this.addGroup(group.start, group.count, group.materialIndex); + } + const boundingBox = source.boundingBox; + if (boundingBox !== null) { + this.boundingBox = boundingBox.clone(); + } + const boundingSphere = source.boundingSphere; + if (boundingSphere !== null) { + this.boundingSphere = boundingSphere.clone(); + } + this.drawRange.start = source.drawRange.start; + this.drawRange.count = source.drawRange.count; + this.userData = source.userData; + if (source.parameters !== void 0) + this.parameters = Object.assign({}, source.parameters); + return this; + } + dispose() { + this.dispatchEvent({ type: "dispose" }); + } + }; + var _inverseMatrix$2 = /* @__PURE__ */ new Matrix4(); + var _ray$2 = /* @__PURE__ */ new Ray(); + var _sphere$3 = /* @__PURE__ */ new Sphere(); + var _vA$1 = /* @__PURE__ */ new Vector3(); + var _vB$1 = /* @__PURE__ */ new Vector3(); + var _vC$1 = /* @__PURE__ */ new Vector3(); + var _tempA = /* @__PURE__ */ new Vector3(); + var _tempB = /* @__PURE__ */ new Vector3(); + var _tempC = /* @__PURE__ */ new Vector3(); + var _morphA = /* @__PURE__ */ new Vector3(); + var _morphB = /* @__PURE__ */ new Vector3(); + var _morphC = /* @__PURE__ */ new Vector3(); + var _uvA$1 = /* @__PURE__ */ new Vector2(); + var _uvB$1 = /* @__PURE__ */ new Vector2(); + var _uvC$1 = /* @__PURE__ */ new Vector2(); + var _intersectionPoint = /* @__PURE__ */ new Vector3(); + var _intersectionPointWorld = /* @__PURE__ */ new Vector3(); + var Mesh = class extends Object3D { + constructor(geometry = new BufferGeometry(), material = new MeshBasicMaterial()) { + super(); + this.isMesh = true; + this.type = "Mesh"; + this.geometry = geometry; + this.material = material; + this.updateMorphTargets(); + } + copy(source, recursive) { + super.copy(source, recursive); + if (source.morphTargetInfluences !== void 0) { + this.morphTargetInfluences = source.morphTargetInfluences.slice(); + } + if (source.morphTargetDictionary !== void 0) { + this.morphTargetDictionary = Object.assign({}, source.morphTargetDictionary); + } + this.material = source.material; + this.geometry = source.geometry; + return this; + } + updateMorphTargets() { + const geometry = this.geometry; + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys(morphAttributes); + if (keys.length > 0) { + const morphAttribute = morphAttributes[keys[0]]; + if (morphAttribute !== void 0) { + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; + for (let m2 = 0, ml = morphAttribute.length; m2 < ml; m2++) { + const name = morphAttribute[m2].name || String(m2); + this.morphTargetInfluences.push(0); + this.morphTargetDictionary[name] = m2; + } + } + } + } + raycast(raycaster, intersects) { + const geometry = this.geometry; + const material = this.material; + const matrixWorld = this.matrixWorld; + if (material === void 0) + return; + if (geometry.boundingSphere === null) + geometry.computeBoundingSphere(); + _sphere$3.copy(geometry.boundingSphere); + _sphere$3.applyMatrix4(matrixWorld); + if (raycaster.ray.intersectsSphere(_sphere$3) === false) + return; + _inverseMatrix$2.copy(matrixWorld).invert(); + _ray$2.copy(raycaster.ray).applyMatrix4(_inverseMatrix$2); + if (geometry.boundingBox !== null) { + if (_ray$2.intersectsBox(geometry.boundingBox) === false) + return; + } + let intersection; + const index2 = geometry.index; + const position = geometry.attributes.position; + const morphPosition = geometry.morphAttributes.position; + const morphTargetsRelative = geometry.morphTargetsRelative; + const uv = geometry.attributes.uv; + const uv2 = geometry.attributes.uv2; + const groups = geometry.groups; + const drawRange = geometry.drawRange; + if (index2 !== null) { + if (Array.isArray(material)) { + for (let i = 0, il = groups.length; i < il; i++) { + const group = groups[i]; + const groupMaterial = material[group.materialIndex]; + const start2 = Math.max(group.start, drawRange.start); + const end = Math.min(index2.count, Math.min(group.start + group.count, drawRange.start + drawRange.count)); + for (let j = start2, jl = end; j < jl; j += 3) { + const a2 = index2.getX(j); + const b = index2.getX(j + 1); + const c2 = index2.getX(j + 2); + intersection = checkBufferGeometryIntersection(this, groupMaterial, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b, c2); + if (intersection) { + intersection.faceIndex = Math.floor(j / 3); + intersection.face.materialIndex = group.materialIndex; + intersects.push(intersection); + } + } + } + } else { + const start2 = Math.max(0, drawRange.start); + const end = Math.min(index2.count, drawRange.start + drawRange.count); + for (let i = start2, il = end; i < il; i += 3) { + const a2 = index2.getX(i); + const b = index2.getX(i + 1); + const c2 = index2.getX(i + 2); + intersection = checkBufferGeometryIntersection(this, material, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b, c2); + if (intersection) { + intersection.faceIndex = Math.floor(i / 3); + intersects.push(intersection); + } + } + } + } else if (position !== void 0) { + if (Array.isArray(material)) { + for (let i = 0, il = groups.length; i < il; i++) { + const group = groups[i]; + const groupMaterial = material[group.materialIndex]; + const start2 = Math.max(group.start, drawRange.start); + const end = Math.min(position.count, Math.min(group.start + group.count, drawRange.start + drawRange.count)); + for (let j = start2, jl = end; j < jl; j += 3) { + const a2 = j; + const b = j + 1; + const c2 = j + 2; + intersection = checkBufferGeometryIntersection(this, groupMaterial, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b, c2); + if (intersection) { + intersection.faceIndex = Math.floor(j / 3); + intersection.face.materialIndex = group.materialIndex; + intersects.push(intersection); + } + } + } + } else { + const start2 = Math.max(0, drawRange.start); + const end = Math.min(position.count, drawRange.start + drawRange.count); + for (let i = start2, il = end; i < il; i += 3) { + const a2 = i; + const b = i + 1; + const c2 = i + 2; + intersection = checkBufferGeometryIntersection(this, material, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b, c2); + if (intersection) { + intersection.faceIndex = Math.floor(i / 3); + intersects.push(intersection); + } + } + } + } + } + }; + function checkIntersection(object, material, raycaster, ray, pA, pB, pC, point) { + let intersect; + if (material.side === BackSide) { + intersect = ray.intersectTriangle(pC, pB, pA, true, point); + } else { + intersect = ray.intersectTriangle(pA, pB, pC, material.side !== DoubleSide, point); + } + if (intersect === null) + return null; + _intersectionPointWorld.copy(point); + _intersectionPointWorld.applyMatrix4(object.matrixWorld); + const distance = raycaster.ray.origin.distanceTo(_intersectionPointWorld); + if (distance < raycaster.near || distance > raycaster.far) + return null; + return { + distance, + point: _intersectionPointWorld.clone(), + object + }; + } + function checkBufferGeometryIntersection(object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a2, b, c2) { + _vA$1.fromBufferAttribute(position, a2); + _vB$1.fromBufferAttribute(position, b); + _vC$1.fromBufferAttribute(position, c2); + const morphInfluences = object.morphTargetInfluences; + if (morphPosition && morphInfluences) { + _morphA.set(0, 0, 0); + _morphB.set(0, 0, 0); + _morphC.set(0, 0, 0); + for (let i = 0, il = morphPosition.length; i < il; i++) { + const influence = morphInfluences[i]; + const morphAttribute = morphPosition[i]; + if (influence === 0) + continue; + _tempA.fromBufferAttribute(morphAttribute, a2); + _tempB.fromBufferAttribute(morphAttribute, b); + _tempC.fromBufferAttribute(morphAttribute, c2); + if (morphTargetsRelative) { + _morphA.addScaledVector(_tempA, influence); + _morphB.addScaledVector(_tempB, influence); + _morphC.addScaledVector(_tempC, influence); + } else { + _morphA.addScaledVector(_tempA.sub(_vA$1), influence); + _morphB.addScaledVector(_tempB.sub(_vB$1), influence); + _morphC.addScaledVector(_tempC.sub(_vC$1), influence); + } + } + _vA$1.add(_morphA); + _vB$1.add(_morphB); + _vC$1.add(_morphC); + } + if (object.isSkinnedMesh) { + object.boneTransform(a2, _vA$1); + object.boneTransform(b, _vB$1); + object.boneTransform(c2, _vC$1); + } + const intersection = checkIntersection(object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint); + if (intersection) { + if (uv) { + _uvA$1.fromBufferAttribute(uv, a2); + _uvB$1.fromBufferAttribute(uv, b); + _uvC$1.fromBufferAttribute(uv, c2); + intersection.uv = Triangle.getUV(_intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2()); + } + if (uv2) { + _uvA$1.fromBufferAttribute(uv2, a2); + _uvB$1.fromBufferAttribute(uv2, b); + _uvC$1.fromBufferAttribute(uv2, c2); + intersection.uv2 = Triangle.getUV(_intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2()); + } + const face = { + a: a2, + b, + c: c2, + normal: new Vector3(), + materialIndex: 0 + }; + Triangle.getNormal(_vA$1, _vB$1, _vC$1, face.normal); + intersection.face = face; + } + return intersection; + } + var BoxGeometry = class extends BufferGeometry { + constructor(width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1) { + super(); + this.type = "BoxGeometry"; + this.parameters = { + width, + height, + depth, + widthSegments, + heightSegments, + depthSegments + }; + const scope = this; + widthSegments = Math.floor(widthSegments); + heightSegments = Math.floor(heightSegments); + depthSegments = Math.floor(depthSegments); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + let numberOfVertices = 0; + let groupStart = 0; + buildPlane("z", "y", "x", -1, -1, depth, height, width, depthSegments, heightSegments, 0); + buildPlane("z", "y", "x", 1, -1, depth, height, -width, depthSegments, heightSegments, 1); + buildPlane("x", "z", "y", 1, 1, width, depth, height, widthSegments, depthSegments, 2); + buildPlane("x", "z", "y", 1, -1, width, depth, -height, widthSegments, depthSegments, 3); + buildPlane("x", "y", "z", 1, -1, width, height, depth, widthSegments, heightSegments, 4); + buildPlane("x", "y", "z", -1, -1, width, height, -depth, widthSegments, heightSegments, 5); + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute(uvs, 2)); + function buildPlane(u, v, w, udir, vdir, width2, height2, depth2, gridX, gridY, materialIndex) { + const segmentWidth = width2 / gridX; + const segmentHeight = height2 / gridY; + const widthHalf = width2 / 2; + const heightHalf = height2 / 2; + const depthHalf = depth2 / 2; + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; + let vertexCounter = 0; + let groupCount = 0; + const vector = new Vector3(); + for (let iy = 0; iy < gridY1; iy++) { + const y2 = iy * segmentHeight - heightHalf; + for (let ix = 0; ix < gridX1; ix++) { + const x2 = ix * segmentWidth - widthHalf; + vector[u] = x2 * udir; + vector[v] = y2 * vdir; + vector[w] = depthHalf; + vertices.push(vector.x, vector.y, vector.z); + vector[u] = 0; + vector[v] = 0; + vector[w] = depth2 > 0 ? 1 : -1; + normals.push(vector.x, vector.y, vector.z); + uvs.push(ix / gridX); + uvs.push(1 - iy / gridY); + vertexCounter += 1; + } + } + for (let iy = 0; iy < gridY; iy++) { + for (let ix = 0; ix < gridX; ix++) { + const a2 = numberOfVertices + ix + gridX1 * iy; + const b = numberOfVertices + ix + gridX1 * (iy + 1); + const c2 = numberOfVertices + (ix + 1) + gridX1 * (iy + 1); + const d = numberOfVertices + (ix + 1) + gridX1 * iy; + indices.push(a2, b, d); + indices.push(b, c2, d); + groupCount += 6; + } + } + scope.addGroup(groupStart, groupCount, materialIndex); + groupStart += groupCount; + numberOfVertices += vertexCounter; + } + } + static fromJSON(data) { + return new BoxGeometry(data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments); + } + }; + function cloneUniforms(src) { + const dst = {}; + for (const u in src) { + dst[u] = {}; + for (const p in src[u]) { + const property = src[u][p]; + if (property && (property.isColor || property.isMatrix3 || property.isMatrix4 || property.isVector2 || property.isVector3 || property.isVector4 || property.isTexture || property.isQuaternion)) { + dst[u][p] = property.clone(); + } else if (Array.isArray(property)) { + dst[u][p] = property.slice(); + } else { + dst[u][p] = property; + } + } + } + return dst; + } + function mergeUniforms(uniforms) { + const merged = {}; + for (let u = 0; u < uniforms.length; u++) { + const tmp = cloneUniforms(uniforms[u]); + for (const p in tmp) { + merged[p] = tmp[p]; + } + } + return merged; + } + function cloneUniformsGroups(src) { + const dst = []; + for (let u = 0; u < src.length; u++) { + dst.push(src[u].clone()); + } + return dst; + } + var UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms }; + var default_vertex = "void main() {\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"; + var default_fragment = "void main() {\n gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}"; + var ShaderMaterial = class extends Material { + constructor(parameters) { + super(); + this.isShaderMaterial = true; + this.type = "ShaderMaterial"; + this.defines = {}; + this.uniforms = {}; + this.uniformsGroups = []; + this.vertexShader = default_vertex; + this.fragmentShader = default_fragment; + this.linewidth = 1; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.fog = false; + this.lights = false; + this.clipping = false; + this.extensions = { + derivatives: false, + fragDepth: false, + drawBuffers: false, + shaderTextureLOD: false + }; + this.defaultAttributeValues = { + "color": [1, 1, 1], + "uv": [0, 0], + "uv2": [0, 0] + }; + this.index0AttributeName = void 0; + this.uniformsNeedUpdate = false; + this.glslVersion = null; + if (parameters !== void 0) { + if (parameters.attributes !== void 0) { + console.error("THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead."); + } + this.setValues(parameters); + } + } + copy(source) { + super.copy(source); + this.fragmentShader = source.fragmentShader; + this.vertexShader = source.vertexShader; + this.uniforms = cloneUniforms(source.uniforms); + this.uniformsGroups = cloneUniformsGroups(source.uniformsGroups); + this.defines = Object.assign({}, source.defines); + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.fog = source.fog; + this.lights = source.lights; + this.clipping = source.clipping; + this.extensions = Object.assign({}, source.extensions); + this.glslVersion = source.glslVersion; + return this; + } + toJSON(meta) { + const data = super.toJSON(meta); + data.glslVersion = this.glslVersion; + data.uniforms = {}; + for (const name in this.uniforms) { + const uniform = this.uniforms[name]; + const value = uniform.value; + if (value && value.isTexture) { + data.uniforms[name] = { + type: "t", + value: value.toJSON(meta).uuid + }; + } else if (value && value.isColor) { + data.uniforms[name] = { + type: "c", + value: value.getHex() + }; + } else if (value && value.isVector2) { + data.uniforms[name] = { + type: "v2", + value: value.toArray() + }; + } else if (value && value.isVector3) { + data.uniforms[name] = { + type: "v3", + value: value.toArray() + }; + } else if (value && value.isVector4) { + data.uniforms[name] = { + type: "v4", + value: value.toArray() + }; + } else if (value && value.isMatrix3) { + data.uniforms[name] = { + type: "m3", + value: value.toArray() + }; + } else if (value && value.isMatrix4) { + data.uniforms[name] = { + type: "m4", + value: value.toArray() + }; + } else { + data.uniforms[name] = { + value + }; + } + } + if (Object.keys(this.defines).length > 0) + data.defines = this.defines; + data.vertexShader = this.vertexShader; + data.fragmentShader = this.fragmentShader; + const extensions = {}; + for (const key in this.extensions) { + if (this.extensions[key] === true) + extensions[key] = true; + } + if (Object.keys(extensions).length > 0) + data.extensions = extensions; + return data; + } + }; + var Camera = class extends Object3D { + constructor() { + super(); + this.isCamera = true; + this.type = "Camera"; + this.matrixWorldInverse = new Matrix4(); + this.projectionMatrix = new Matrix4(); + this.projectionMatrixInverse = new Matrix4(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.matrixWorldInverse.copy(source.matrixWorldInverse); + this.projectionMatrix.copy(source.projectionMatrix); + this.projectionMatrixInverse.copy(source.projectionMatrixInverse); + return this; + } + getWorldDirection(target) { + this.updateWorldMatrix(true, false); + const e = this.matrixWorld.elements; + return target.set(-e[8], -e[9], -e[10]).normalize(); + } + updateMatrixWorld(force) { + super.updateMatrixWorld(force); + this.matrixWorldInverse.copy(this.matrixWorld).invert(); + } + updateWorldMatrix(updateParents, updateChildren) { + super.updateWorldMatrix(updateParents, updateChildren); + this.matrixWorldInverse.copy(this.matrixWorld).invert(); + } + clone() { + return new this.constructor().copy(this); + } + }; + var PerspectiveCamera = class extends Camera { + constructor(fov2 = 50, aspect2 = 1, near = 0.1, far = 2e3) { + super(); + this.isPerspectiveCamera = true; + this.type = "PerspectiveCamera"; + this.fov = fov2; + this.zoom = 1; + this.near = near; + this.far = far; + this.focus = 10; + this.aspect = aspect2; + this.view = null; + this.filmGauge = 35; + this.filmOffset = 0; + this.updateProjectionMatrix(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.fov = source.fov; + this.zoom = source.zoom; + this.near = source.near; + this.far = source.far; + this.focus = source.focus; + this.aspect = source.aspect; + this.view = source.view === null ? null : Object.assign({}, source.view); + this.filmGauge = source.filmGauge; + this.filmOffset = source.filmOffset; + return this; + } + setFocalLength(focalLength) { + const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; + this.fov = RAD2DEG * 2 * Math.atan(vExtentSlope); + this.updateProjectionMatrix(); + } + getFocalLength() { + const vExtentSlope = Math.tan(DEG2RAD * 0.5 * this.fov); + return 0.5 * this.getFilmHeight() / vExtentSlope; + } + getEffectiveFOV() { + return RAD2DEG * 2 * Math.atan(Math.tan(DEG2RAD * 0.5 * this.fov) / this.zoom); + } + getFilmWidth() { + return this.filmGauge * Math.min(this.aspect, 1); + } + getFilmHeight() { + return this.filmGauge / Math.max(this.aspect, 1); + } + setViewOffset(fullWidth, fullHeight, x2, y2, width, height) { + this.aspect = fullWidth / fullHeight; + if (this.view === null) { + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; + } + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x2; + this.view.offsetY = y2; + this.view.width = width; + this.view.height = height; + this.updateProjectionMatrix(); + } + clearViewOffset() { + if (this.view !== null) { + this.view.enabled = false; + } + this.updateProjectionMatrix(); + } + updateProjectionMatrix() { + const near = this.near; + let top = near * Math.tan(DEG2RAD * 0.5 * this.fov) / this.zoom; + let height = 2 * top; + let width = this.aspect * height; + let left = -0.5 * width; + const view = this.view; + if (this.view !== null && this.view.enabled) { + const fullWidth = view.fullWidth, fullHeight = view.fullHeight; + left += view.offsetX * width / fullWidth; + top -= view.offsetY * height / fullHeight; + width *= view.width / fullWidth; + height *= view.height / fullHeight; + } + const skew = this.filmOffset; + if (skew !== 0) + left += near * skew / this.getFilmWidth(); + this.projectionMatrix.makePerspective(left, left + width, top, top - height, near, this.far); + this.projectionMatrixInverse.copy(this.projectionMatrix).invert(); + } + toJSON(meta) { + const data = super.toJSON(meta); + data.object.fov = this.fov; + data.object.zoom = this.zoom; + data.object.near = this.near; + data.object.far = this.far; + data.object.focus = this.focus; + data.object.aspect = this.aspect; + if (this.view !== null) + data.object.view = Object.assign({}, this.view); + data.object.filmGauge = this.filmGauge; + data.object.filmOffset = this.filmOffset; + return data; + } + }; + var fov = 90; + var aspect = 1; + var CubeCamera = class extends Object3D { + constructor(near, far, renderTarget) { + super(); + this.type = "CubeCamera"; + if (renderTarget.isWebGLCubeRenderTarget !== true) { + console.error("THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter."); + return; + } + this.renderTarget = renderTarget; + const cameraPX = new PerspectiveCamera(fov, aspect, near, far); + cameraPX.layers = this.layers; + cameraPX.up.set(0, -1, 0); + cameraPX.lookAt(new Vector3(1, 0, 0)); + this.add(cameraPX); + const cameraNX = new PerspectiveCamera(fov, aspect, near, far); + cameraNX.layers = this.layers; + cameraNX.up.set(0, -1, 0); + cameraNX.lookAt(new Vector3(-1, 0, 0)); + this.add(cameraNX); + const cameraPY = new PerspectiveCamera(fov, aspect, near, far); + cameraPY.layers = this.layers; + cameraPY.up.set(0, 0, 1); + cameraPY.lookAt(new Vector3(0, 1, 0)); + this.add(cameraPY); + const cameraNY = new PerspectiveCamera(fov, aspect, near, far); + cameraNY.layers = this.layers; + cameraNY.up.set(0, 0, -1); + cameraNY.lookAt(new Vector3(0, -1, 0)); + this.add(cameraNY); + const cameraPZ = new PerspectiveCamera(fov, aspect, near, far); + cameraPZ.layers = this.layers; + cameraPZ.up.set(0, -1, 0); + cameraPZ.lookAt(new Vector3(0, 0, 1)); + this.add(cameraPZ); + const cameraNZ = new PerspectiveCamera(fov, aspect, near, far); + cameraNZ.layers = this.layers; + cameraNZ.up.set(0, -1, 0); + cameraNZ.lookAt(new Vector3(0, 0, -1)); + this.add(cameraNZ); + } + update(renderer, scene) { + if (this.parent === null) + this.updateMatrixWorld(); + const renderTarget = this.renderTarget; + const [cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ] = this.children; + const currentRenderTarget = renderer.getRenderTarget(); + const currentToneMapping = renderer.toneMapping; + const currentXrEnabled = renderer.xr.enabled; + renderer.toneMapping = NoToneMapping; + renderer.xr.enabled = false; + const generateMipmaps = renderTarget.texture.generateMipmaps; + renderTarget.texture.generateMipmaps = false; + renderer.setRenderTarget(renderTarget, 0); + renderer.render(scene, cameraPX); + renderer.setRenderTarget(renderTarget, 1); + renderer.render(scene, cameraNX); + renderer.setRenderTarget(renderTarget, 2); + renderer.render(scene, cameraPY); + renderer.setRenderTarget(renderTarget, 3); + renderer.render(scene, cameraNY); + renderer.setRenderTarget(renderTarget, 4); + renderer.render(scene, cameraPZ); + renderTarget.texture.generateMipmaps = generateMipmaps; + renderer.setRenderTarget(renderTarget, 5); + renderer.render(scene, cameraNZ); + renderer.setRenderTarget(currentRenderTarget); + renderer.toneMapping = currentToneMapping; + renderer.xr.enabled = currentXrEnabled; + renderTarget.texture.needsPMREMUpdate = true; + } + }; + var CubeTexture = class extends Texture { + constructor(images, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy, encoding) { + images = images !== void 0 ? images : []; + mapping = mapping !== void 0 ? mapping : CubeReflectionMapping; + super(images, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy, encoding); + this.isCubeTexture = true; + this.flipY = false; + } + get images() { + return this.image; + } + set images(value) { + this.image = value; + } + }; + var WebGLCubeRenderTarget = class extends WebGLRenderTarget { + constructor(size, options = {}) { + super(size, size, options); + this.isWebGLCubeRenderTarget = true; + const image = { width: size, height: size, depth: 1 }; + const images = [image, image, image, image, image, image]; + this.texture = new CubeTexture(images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding); + this.texture.isRenderTargetTexture = true; + this.texture.generateMipmaps = options.generateMipmaps !== void 0 ? options.generateMipmaps : false; + this.texture.minFilter = options.minFilter !== void 0 ? options.minFilter : LinearFilter; + } + fromEquirectangularTexture(renderer, texture) { + this.texture.type = texture.type; + this.texture.encoding = texture.encoding; + this.texture.generateMipmaps = texture.generateMipmaps; + this.texture.minFilter = texture.minFilter; + this.texture.magFilter = texture.magFilter; + const shader = { + uniforms: { + tEquirect: { value: null } + }, + vertexShader: ` + + varying vec3 vWorldDirection; + + vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); + + } + + void main() { + + vWorldDirection = transformDirection( position, modelMatrix ); + + #include + #include + + } + `, + fragmentShader: ` + + uniform sampler2D tEquirect; + + varying vec3 vWorldDirection; + + #include + + void main() { + + vec3 direction = normalize( vWorldDirection ); + + vec2 sampleUV = equirectUv( direction ); + + gl_FragColor = texture2D( tEquirect, sampleUV ); + + } + ` + }; + const geometry = new BoxGeometry(5, 5, 5); + const material = new ShaderMaterial({ + name: "CubemapFromEquirect", + uniforms: cloneUniforms(shader.uniforms), + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + side: BackSide, + blending: NoBlending + }); + material.uniforms.tEquirect.value = texture; + const mesh = new Mesh(geometry, material); + const currentMinFilter = texture.minFilter; + if (texture.minFilter === LinearMipmapLinearFilter) + texture.minFilter = LinearFilter; + const camera = new CubeCamera(1, 10, this); + camera.update(renderer, mesh); + texture.minFilter = currentMinFilter; + mesh.geometry.dispose(); + mesh.material.dispose(); + return this; + } + clear(renderer, color2, depth, stencil) { + const currentRenderTarget = renderer.getRenderTarget(); + for (let i = 0; i < 6; i++) { + renderer.setRenderTarget(this, i); + renderer.clear(color2, depth, stencil); + } + renderer.setRenderTarget(currentRenderTarget); + } + }; + var _vector1 = /* @__PURE__ */ new Vector3(); + var _vector2 = /* @__PURE__ */ new Vector3(); + var _normalMatrix = /* @__PURE__ */ new Matrix3(); + var Plane = class { + constructor(normal = new Vector3(1, 0, 0), constant = 0) { + this.isPlane = true; + this.normal = normal; + this.constant = constant; + } + set(normal, constant) { + this.normal.copy(normal); + this.constant = constant; + return this; + } + setComponents(x2, y2, z, w) { + this.normal.set(x2, y2, z); + this.constant = w; + return this; + } + setFromNormalAndCoplanarPoint(normal, point) { + this.normal.copy(normal); + this.constant = -point.dot(this.normal); + return this; + } + setFromCoplanarPoints(a2, b, c2) { + const normal = _vector1.subVectors(c2, b).cross(_vector2.subVectors(a2, b)).normalize(); + this.setFromNormalAndCoplanarPoint(normal, a2); + return this; + } + copy(plane) { + this.normal.copy(plane.normal); + this.constant = plane.constant; + return this; + } + normalize() { + const inverseNormalLength = 1 / this.normal.length(); + this.normal.multiplyScalar(inverseNormalLength); + this.constant *= inverseNormalLength; + return this; + } + negate() { + this.constant *= -1; + this.normal.negate(); + return this; + } + distanceToPoint(point) { + return this.normal.dot(point) + this.constant; + } + distanceToSphere(sphere) { + return this.distanceToPoint(sphere.center) - sphere.radius; + } + projectPoint(point, target) { + return target.copy(this.normal).multiplyScalar(-this.distanceToPoint(point)).add(point); + } + intersectLine(line, target) { + const direction = line.delta(_vector1); + const denominator = this.normal.dot(direction); + if (denominator === 0) { + if (this.distanceToPoint(line.start) === 0) { + return target.copy(line.start); + } + return null; + } + const t = -(line.start.dot(this.normal) + this.constant) / denominator; + if (t < 0 || t > 1) { + return null; + } + return target.copy(direction).multiplyScalar(t).add(line.start); + } + intersectsLine(line) { + const startSign = this.distanceToPoint(line.start); + const endSign = this.distanceToPoint(line.end); + return startSign < 0 && endSign > 0 || endSign < 0 && startSign > 0; + } + intersectsBox(box) { + return box.intersectsPlane(this); + } + intersectsSphere(sphere) { + return sphere.intersectsPlane(this); + } + coplanarPoint(target) { + return target.copy(this.normal).multiplyScalar(-this.constant); + } + applyMatrix4(matrix, optionalNormalMatrix) { + const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix(matrix); + const referencePoint = this.coplanarPoint(_vector1).applyMatrix4(matrix); + const normal = this.normal.applyMatrix3(normalMatrix).normalize(); + this.constant = -referencePoint.dot(normal); + return this; + } + translate(offset) { + this.constant -= offset.dot(this.normal); + return this; + } + equals(plane) { + return plane.normal.equals(this.normal) && plane.constant === this.constant; + } + clone() { + return new this.constructor().copy(this); + } + }; + var _sphere$2 = /* @__PURE__ */ new Sphere(); + var _vector$7 = /* @__PURE__ */ new Vector3(); + var Frustum = class { + constructor(p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane()) { + this.planes = [p0, p1, p2, p3, p4, p5]; + } + set(p0, p1, p2, p3, p4, p5) { + const planes = this.planes; + planes[0].copy(p0); + planes[1].copy(p1); + planes[2].copy(p2); + planes[3].copy(p3); + planes[4].copy(p4); + planes[5].copy(p5); + return this; + } + copy(frustum) { + const planes = this.planes; + for (let i = 0; i < 6; i++) { + planes[i].copy(frustum.planes[i]); + } + return this; + } + setFromProjectionMatrix(m2) { + const planes = this.planes; + const me = m2.elements; + const me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3]; + const me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7]; + const me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11]; + const me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15]; + planes[0].setComponents(me3 - me0, me7 - me4, me11 - me8, me15 - me12).normalize(); + planes[1].setComponents(me3 + me0, me7 + me4, me11 + me8, me15 + me12).normalize(); + planes[2].setComponents(me3 + me1, me7 + me5, me11 + me9, me15 + me13).normalize(); + planes[3].setComponents(me3 - me1, me7 - me5, me11 - me9, me15 - me13).normalize(); + planes[4].setComponents(me3 - me2, me7 - me6, me11 - me10, me15 - me14).normalize(); + planes[5].setComponents(me3 + me2, me7 + me6, me11 + me10, me15 + me14).normalize(); + return this; + } + intersectsObject(object) { + const geometry = object.geometry; + if (geometry.boundingSphere === null) + geometry.computeBoundingSphere(); + _sphere$2.copy(geometry.boundingSphere).applyMatrix4(object.matrixWorld); + return this.intersectsSphere(_sphere$2); + } + intersectsSprite(sprite) { + _sphere$2.center.set(0, 0, 0); + _sphere$2.radius = 0.7071067811865476; + _sphere$2.applyMatrix4(sprite.matrixWorld); + return this.intersectsSphere(_sphere$2); + } + intersectsSphere(sphere) { + const planes = this.planes; + const center = sphere.center; + const negRadius = -sphere.radius; + for (let i = 0; i < 6; i++) { + const distance = planes[i].distanceToPoint(center); + if (distance < negRadius) { + return false; + } + } + return true; + } + intersectsBox(box) { + const planes = this.planes; + for (let i = 0; i < 6; i++) { + const plane = planes[i]; + _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x; + _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y; + _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z; + if (plane.distanceToPoint(_vector$7) < 0) { + return false; + } + } + return true; + } + containsPoint(point) { + const planes = this.planes; + for (let i = 0; i < 6; i++) { + if (planes[i].distanceToPoint(point) < 0) { + return false; + } + } + return true; + } + clone() { + return new this.constructor().copy(this); + } + }; + function WebGLAnimation() { + let context = null; + let isAnimating = false; + let animationLoop = null; + let requestId = null; + function onAnimationFrame(time, frame2) { + animationLoop(time, frame2); + requestId = context.requestAnimationFrame(onAnimationFrame); + } + return { + start: function() { + if (isAnimating === true) + return; + if (animationLoop === null) + return; + requestId = context.requestAnimationFrame(onAnimationFrame); + isAnimating = true; + }, + stop: function() { + context.cancelAnimationFrame(requestId); + isAnimating = false; + }, + setAnimationLoop: function(callback) { + animationLoop = callback; + }, + setContext: function(value) { + context = value; + } + }; + } + function WebGLAttributes(gl, capabilities) { + const isWebGL2 = capabilities.isWebGL2; + const buffers = /* @__PURE__ */ new WeakMap(); + function createBuffer(attribute, bufferType) { + const array2 = attribute.array; + const usage = attribute.usage; + const buffer = gl.createBuffer(); + gl.bindBuffer(bufferType, buffer); + gl.bufferData(bufferType, array2, usage); + attribute.onUploadCallback(); + let type2; + if (array2 instanceof Float32Array) { + type2 = 5126; + } else if (array2 instanceof Uint16Array) { + if (attribute.isFloat16BufferAttribute) { + if (isWebGL2) { + type2 = 5131; + } else { + throw new Error("THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2."); + } + } else { + type2 = 5123; + } + } else if (array2 instanceof Int16Array) { + type2 = 5122; + } else if (array2 instanceof Uint32Array) { + type2 = 5125; + } else if (array2 instanceof Int32Array) { + type2 = 5124; + } else if (array2 instanceof Int8Array) { + type2 = 5120; + } else if (array2 instanceof Uint8Array) { + type2 = 5121; + } else if (array2 instanceof Uint8ClampedArray) { + type2 = 5121; + } else { + throw new Error("THREE.WebGLAttributes: Unsupported buffer data format: " + array2); + } + return { + buffer, + type: type2, + bytesPerElement: array2.BYTES_PER_ELEMENT, + version: attribute.version + }; + } + function updateBuffer(buffer, attribute, bufferType) { + const array2 = attribute.array; + const updateRange = attribute.updateRange; + gl.bindBuffer(bufferType, buffer); + if (updateRange.count === -1) { + gl.bufferSubData(bufferType, 0, array2); + } else { + if (isWebGL2) { + gl.bufferSubData(bufferType, updateRange.offset * array2.BYTES_PER_ELEMENT, array2, updateRange.offset, updateRange.count); + } else { + gl.bufferSubData(bufferType, updateRange.offset * array2.BYTES_PER_ELEMENT, array2.subarray(updateRange.offset, updateRange.offset + updateRange.count)); + } + updateRange.count = -1; + } + } + function get3(attribute) { + if (attribute.isInterleavedBufferAttribute) + attribute = attribute.data; + return buffers.get(attribute); + } + function remove2(attribute) { + if (attribute.isInterleavedBufferAttribute) + attribute = attribute.data; + const data = buffers.get(attribute); + if (data) { + gl.deleteBuffer(data.buffer); + buffers.delete(attribute); + } + } + function update(attribute, bufferType) { + if (attribute.isGLBufferAttribute) { + const cached = buffers.get(attribute); + if (!cached || cached.version < attribute.version) { + buffers.set(attribute, { + buffer: attribute.buffer, + type: attribute.type, + bytesPerElement: attribute.elementSize, + version: attribute.version + }); + } + return; + } + if (attribute.isInterleavedBufferAttribute) + attribute = attribute.data; + const data = buffers.get(attribute); + if (data === void 0) { + buffers.set(attribute, createBuffer(attribute, bufferType)); + } else if (data.version < attribute.version) { + updateBuffer(data.buffer, attribute, bufferType); + data.version = attribute.version; + } + } + return { + get: get3, + remove: remove2, + update + }; + } + var PlaneGeometry = class extends BufferGeometry { + constructor(width = 1, height = 1, widthSegments = 1, heightSegments = 1) { + super(); + this.type = "PlaneGeometry"; + this.parameters = { + width, + height, + widthSegments, + heightSegments + }; + const width_half = width / 2; + const height_half = height / 2; + const gridX = Math.floor(widthSegments); + const gridY = Math.floor(heightSegments); + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; + const segment_width = width / gridX; + const segment_height = height / gridY; + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + for (let iy = 0; iy < gridY1; iy++) { + const y2 = iy * segment_height - height_half; + for (let ix = 0; ix < gridX1; ix++) { + const x2 = ix * segment_width - width_half; + vertices.push(x2, -y2, 0); + normals.push(0, 0, 1); + uvs.push(ix / gridX); + uvs.push(1 - iy / gridY); + } + } + for (let iy = 0; iy < gridY; iy++) { + for (let ix = 0; ix < gridX; ix++) { + const a2 = ix + gridX1 * iy; + const b = ix + gridX1 * (iy + 1); + const c2 = ix + 1 + gridX1 * (iy + 1); + const d = ix + 1 + gridX1 * iy; + indices.push(a2, b, d); + indices.push(b, c2, d); + } + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute(uvs, 2)); + } + static fromJSON(data) { + return new PlaneGeometry(data.width, data.height, data.widthSegments, data.heightSegments); + } + }; + var alphamap_fragment = "#ifdef USE_ALPHAMAP\n diffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif"; + var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n uniform sampler2D alphaMap;\n#endif"; + var alphatest_fragment = "#ifdef USE_ALPHATEST\n if ( diffuseColor.a < alphaTest ) discard;\n#endif"; + var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n uniform float alphaTest;\n#endif"; + var aomap_fragment = "#ifdef USE_AOMAP\n float ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n reflectedLight.indirectDiffuse *= ambientOcclusion;\n #if defined( USE_ENVMAP ) && defined( STANDARD )\n float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n reflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n #endif\n#endif"; + var aomap_pars_fragment = "#ifdef USE_AOMAP\n uniform sampler2D aoMap;\n uniform float aoMapIntensity;\n#endif"; + var begin_vertex = "vec3 transformed = vec3( position );"; + var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n vec3 objectTangent = vec3( tangent.xyz );\n#endif"; + var bsdfs = "vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n return RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n float a2 = pow2( alpha );\n float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n return 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n float a2 = pow2( alpha );\n float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n return RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) {\n float alpha = pow2( roughness );\n vec3 halfDir = normalize( lightDir + viewDir );\n float dotNL = saturate( dot( normal, lightDir ) );\n float dotNV = saturate( dot( normal, viewDir ) );\n float dotNH = saturate( dot( normal, halfDir ) );\n float dotVH = saturate( dot( viewDir, halfDir ) );\n vec3 F = F_Schlick( f0, f90, dotVH );\n float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n float D = D_GGX( alpha, dotNH );\n return F * ( V * D );\n}\n#ifdef USE_IRIDESCENCE\n vec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) {\n float alpha = pow2( roughness );\n vec3 halfDir = normalize( lightDir + viewDir );\n float dotNL = saturate( dot( normal, lightDir ) );\n float dotNV = saturate( dot( normal, viewDir ) );\n float dotNH = saturate( dot( normal, halfDir ) );\n float dotVH = saturate( dot( viewDir, halfDir ) );\n vec3 F = mix( F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence );\n float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n float D = D_GGX( alpha, dotNH );\n return F * ( V * D );\n }\n#endif\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n const float LUT_SIZE = 64.0;\n const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n const float LUT_BIAS = 0.5 / LUT_SIZE;\n float dotNV = saturate( dot( N, V ) );\n vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n uv = uv * LUT_SCALE + LUT_BIAS;\n return uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n float l = length( f );\n return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n float x = dot( v1, v2 );\n float y = abs( x );\n float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n float b = 3.4175940 + ( 4.1616724 + y ) * y;\n float v = a / b;\n float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n return cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n vec3 lightNormal = cross( v1, v2 );\n if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n vec3 T1, T2;\n T1 = normalize( V - N * dot( V, N ) );\n T2 = - cross( N, T1 );\n mat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n vec3 coords[ 4 ];\n coords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n coords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n coords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n coords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n coords[ 0 ] = normalize( coords[ 0 ] );\n coords[ 1 ] = normalize( coords[ 1 ] );\n coords[ 2 ] = normalize( coords[ 2 ] );\n coords[ 3 ] = normalize( coords[ 3 ] );\n vec3 vectorFormFactor = vec3( 0.0 );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n float result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n return vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n return 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n vec3 halfDir = normalize( lightDir + viewDir );\n float dotNH = saturate( dot( normal, halfDir ) );\n float dotVH = saturate( dot( viewDir, halfDir ) );\n vec3 F = F_Schlick( specularColor, 1.0, dotVH );\n float G = G_BlinnPhong_Implicit( );\n float D = D_BlinnPhong( shininess, dotNH );\n return F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n float alpha = pow2( roughness );\n float invAlpha = 1.0 / alpha;\n float cos2h = dotNH * dotNH;\n float sin2h = max( 1.0 - cos2h, 0.0078125 );\n return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n return saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n vec3 halfDir = normalize( lightDir + viewDir );\n float dotNL = saturate( dot( normal, lightDir ) );\n float dotNV = saturate( dot( normal, viewDir ) );\n float dotNH = saturate( dot( normal, halfDir ) );\n float D = D_Charlie( sheenRoughness, dotNH );\n float V = V_Neubelt( dotNV, dotNL );\n return sheenColor * ( D * V );\n}\n#endif"; + var iridescence_fragment = "#ifdef USE_IRIDESCENCE\n const mat3 XYZ_TO_REC709 = mat3(\n 3.2404542, -0.9692660, 0.0556434,\n -1.5371385, 1.8760108, -0.2040259,\n -0.4985314, 0.0415560, 1.0572252\n );\n vec3 Fresnel0ToIor( vec3 fresnel0 ) {\n vec3 sqrtF0 = sqrt( fresnel0 );\n return ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n }\n vec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n return pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n }\n float IorToFresnel0( float transmittedIor, float incidentIor ) {\n return pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n }\n vec3 evalSensitivity( float OPD, vec3 shift ) {\n float phase = 2.0 * PI * OPD * 1.0e-9;\n vec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n vec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n vec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n vec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n xyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n xyz /= 1.0685e-7;\n vec3 rgb = XYZ_TO_REC709 * xyz;\n return rgb;\n }\n vec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n vec3 I;\n float iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n float sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n float cosTheta2Sq = 1.0 - sinTheta2Sq;\n if ( cosTheta2Sq < 0.0 ) {\n return vec3( 1.0 );\n }\n float cosTheta2 = sqrt( cosTheta2Sq );\n float R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n float R12 = F_Schlick( R0, 1.0, cosTheta1 );\n float R21 = R12;\n float T121 = 1.0 - R12;\n float phi12 = 0.0;\n if ( iridescenceIOR < outsideIOR ) phi12 = PI;\n float phi21 = PI - phi12;\n vec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) ); vec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n vec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n vec3 phi23 = vec3( 0.0 );\n if ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n if ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n if ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n float OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n vec3 phi = vec3( phi21 ) + phi23;\n vec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n vec3 r123 = sqrt( R123 );\n vec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n vec3 C0 = R12 + Rs;\n I = C0;\n vec3 Cm = Rs - T121;\n for ( int m = 1; m <= 2; ++ m ) {\n Cm *= r123;\n vec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n I += Cm * Sm;\n }\n return max( I, vec3( 0.0 ) );\n }\n#endif"; + var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n uniform sampler2D bumpMap;\n uniform float bumpScale;\n vec2 dHdxy_fwd() {\n vec2 dSTdx = dFdx( vUv );\n vec2 dSTdy = dFdy( vUv );\n float Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n return vec2( dBx, dBy );\n }\n vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n vec3 vSigmaX = dFdx( surf_pos.xyz );\n vec3 vSigmaY = dFdy( surf_pos.xyz );\n vec3 vN = surf_norm;\n vec3 R1 = cross( vSigmaY, vN );\n vec3 R2 = cross( vN, vSigmaX );\n float fDet = dot( vSigmaX, R1 ) * faceDirection;\n vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n return normalize( abs( fDet ) * surf_norm - vGrad );\n }\n#endif"; + var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n vec4 plane;\n #pragma unroll_loop_start\n for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n plane = clippingPlanes[ i ];\n if ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n }\n #pragma unroll_loop_end\n #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n bool clipped = true;\n #pragma unroll_loop_start\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n plane = clippingPlanes[ i ];\n clipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n }\n #pragma unroll_loop_end\n if ( clipped ) discard;\n #endif\n#endif"; + var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n varying vec3 vClipPosition;\n uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif"; + var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n varying vec3 vClipPosition;\n#endif"; + var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n vClipPosition = - mvPosition.xyz;\n#endif"; + var color_fragment = "#if defined( USE_COLOR_ALPHA )\n diffuseColor *= vColor;\n#elif defined( USE_COLOR )\n diffuseColor.rgb *= vColor;\n#endif"; + var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n varying vec4 vColor;\n#elif defined( USE_COLOR )\n varying vec3 vColor;\n#endif"; + var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n varying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n varying vec3 vColor;\n#endif"; + var color_vertex = "#if defined( USE_COLOR_ALPHA )\n vColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n vColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n vColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n vColor.xyz *= instanceColor.xyz;\n#endif"; + var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n const highp float a = 12.9898, b = 78.233, c = 43758.5453;\n highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n return fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n float precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n float precisionSafeLength( vec3 v ) {\n float maxComponent = max3( abs( v ) );\n return length( v / maxComponent ) * maxComponent;\n }\n#endif\nstruct IncidentLight {\n vec3 color;\n vec3 direction;\n bool visible;\n};\nstruct ReflectedLight {\n vec3 directDiffuse;\n vec3 directSpecular;\n vec3 indirectDiffuse;\n vec3 indirectSpecular;\n};\nstruct GeometricContext {\n vec3 position;\n vec3 normal;\n vec3 viewDir;\n#ifdef USE_CLEARCOAT\n vec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n mat3 tmp;\n tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n return tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n const vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n return dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n return m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n return vec2( u, v );\n}"; + var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n #define cubeUV_minMipLevel 4.0\n #define cubeUV_minTileSize 16.0\n float getFace( vec3 direction ) {\n vec3 absDirection = abs( direction );\n float face = - 1.0;\n if ( absDirection.x > absDirection.z ) {\n if ( absDirection.x > absDirection.y )\n face = direction.x > 0.0 ? 0.0 : 3.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n } else {\n if ( absDirection.z > absDirection.y )\n face = direction.z > 0.0 ? 2.0 : 5.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n }\n return face;\n }\n vec2 getUV( vec3 direction, float face ) {\n vec2 uv;\n if ( face == 0.0 ) {\n uv = vec2( direction.z, direction.y ) / abs( direction.x );\n } else if ( face == 1.0 ) {\n uv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n } else if ( face == 2.0 ) {\n uv = vec2( - direction.x, direction.y ) / abs( direction.z );\n } else if ( face == 3.0 ) {\n uv = vec2( - direction.z, direction.y ) / abs( direction.x );\n } else if ( face == 4.0 ) {\n uv = vec2( - direction.x, direction.z ) / abs( direction.y );\n } else {\n uv = vec2( direction.x, direction.y ) / abs( direction.z );\n }\n return 0.5 * ( uv + 1.0 );\n }\n vec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n float face = getFace( direction );\n float filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n mipInt = max( mipInt, cubeUV_minMipLevel );\n float faceSize = exp2( mipInt );\n vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n if ( face > 2.0 ) {\n uv.y += faceSize;\n face -= 3.0;\n }\n uv.x += face * faceSize;\n uv.x += filterInt * 3.0 * cubeUV_minTileSize;\n uv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n uv.x *= CUBEUV_TEXEL_WIDTH;\n uv.y *= CUBEUV_TEXEL_HEIGHT;\n #ifdef texture2DGradEXT\n return texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n #else\n return texture2D( envMap, uv ).rgb;\n #endif\n }\n #define r0 1.0\n #define v0 0.339\n #define m0 - 2.0\n #define r1 0.8\n #define v1 0.276\n #define m1 - 1.0\n #define r4 0.4\n #define v4 0.046\n #define m4 2.0\n #define r5 0.305\n #define v5 0.016\n #define m5 3.0\n #define r6 0.21\n #define v6 0.0038\n #define m6 4.0\n float roughnessToMip( float roughness ) {\n float mip = 0.0;\n if ( roughness >= r1 ) {\n mip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n } else if ( roughness >= r4 ) {\n mip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n } else if ( roughness >= r5 ) {\n mip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n } else if ( roughness >= r6 ) {\n mip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n } else {\n mip = - 2.0 * log2( 1.16 * roughness ); }\n return mip;\n }\n vec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n float mip = clamp( roughnessToMip( roughness ), m0, CUBEUV_MAX_MIP );\n float mipF = fract( mip );\n float mipInt = floor( mip );\n vec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n if ( mipF == 0.0 ) {\n return vec4( color0, 1.0 );\n } else {\n vec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n return vec4( mix( color0, color1, mipF ), 1.0 );\n }\n }\n#endif"; + var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n mat3 m = mat3( instanceMatrix );\n transformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n transformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n transformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n vec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n #ifdef FLIP_SIDED\n transformedTangent = - transformedTangent;\n #endif\n#endif"; + var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n uniform sampler2D displacementMap;\n uniform float displacementScale;\n uniform float displacementBias;\n#endif"; + var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif"; + var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n vec4 emissiveColor = texture2D( emissiveMap, vUv );\n totalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; + var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n uniform sampler2D emissiveMap;\n#endif"; + var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; + var encodings_pars_fragment = "vec4 LinearToLinear( in vec4 value ) {\n return value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}"; + var envmap_fragment = "#ifdef USE_ENVMAP\n #ifdef ENV_WORLDPOS\n vec3 cameraToFrag;\n if ( isOrthographic ) {\n cameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n } else {\n cameraToFrag = normalize( vWorldPosition - cameraPosition );\n }\n vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n #ifdef ENVMAP_MODE_REFLECTION\n vec3 reflectVec = reflect( cameraToFrag, worldNormal );\n #else\n vec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n #endif\n #else\n vec3 reflectVec = vReflect;\n #endif\n #ifdef ENVMAP_TYPE_CUBE\n vec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n #elif defined( ENVMAP_TYPE_CUBE_UV )\n vec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n #else\n vec4 envColor = vec4( 0.0 );\n #endif\n #ifdef ENVMAP_BLENDING_MULTIPLY\n outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n #elif defined( ENVMAP_BLENDING_MIX )\n outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n #elif defined( ENVMAP_BLENDING_ADD )\n outgoingLight += envColor.xyz * specularStrength * reflectivity;\n #endif\n#endif"; + var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n uniform float envMapIntensity;\n uniform float flipEnvMap;\n #ifdef ENVMAP_TYPE_CUBE\n uniform samplerCube envMap;\n #else\n uniform sampler2D envMap;\n #endif\n \n#endif"; + var envmap_pars_fragment = "#ifdef USE_ENVMAP\n uniform float reflectivity;\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n #define ENV_WORLDPOS\n #endif\n #ifdef ENV_WORLDPOS\n varying vec3 vWorldPosition;\n uniform float refractionRatio;\n #else\n varying vec3 vReflect;\n #endif\n#endif"; + var envmap_pars_vertex = "#ifdef USE_ENVMAP\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n #define ENV_WORLDPOS\n #endif\n #ifdef ENV_WORLDPOS\n \n varying vec3 vWorldPosition;\n #else\n varying vec3 vReflect;\n uniform float refractionRatio;\n #endif\n#endif"; + var envmap_vertex = "#ifdef USE_ENVMAP\n #ifdef ENV_WORLDPOS\n vWorldPosition = worldPosition.xyz;\n #else\n vec3 cameraToVertex;\n if ( isOrthographic ) {\n cameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n } else {\n cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n }\n vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n #ifdef ENVMAP_MODE_REFLECTION\n vReflect = reflect( cameraToVertex, worldNormal );\n #else\n vReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n #endif\n #endif\n#endif"; + var fog_vertex = "#ifdef USE_FOG\n vFogDepth = - mvPosition.z;\n#endif"; + var fog_pars_vertex = "#ifdef USE_FOG\n varying float vFogDepth;\n#endif"; + var fog_fragment = "#ifdef USE_FOG\n #ifdef FOG_EXP2\n float fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n #else\n float fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n #endif\n gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif"; + var fog_pars_fragment = "#ifdef USE_FOG\n uniform vec3 fogColor;\n varying float vFogDepth;\n #ifdef FOG_EXP2\n uniform float fogDensity;\n #else\n uniform float fogNear;\n uniform float fogFar;\n #endif\n#endif"; + var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n uniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n float dotNL = dot( normal, lightDirection );\n vec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n #ifdef USE_GRADIENTMAP\n return vec3( texture2D( gradientMap, coord ).r );\n #else\n return ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n #endif\n}"; + var lightmap_fragment = "#ifdef USE_LIGHTMAP\n vec4 lightMapTexel = texture2D( lightMap, vUv2 );\n vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n reflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; + var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n uniform sampler2D lightMap;\n uniform float lightMapIntensity;\n#endif"; + var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n vLightBack = vec3( 0.0 );\n vIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry.normal );\n#ifdef DOUBLE_SIDED\n vIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n vIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry.normal );\n#endif\n#if NUM_POINT_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n getPointLightInfo( pointLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n #endif\n }\n #pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n getSpotLightInfo( spotLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n #endif\n }\n #pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n getDirectionalLightInfo( directionalLights[ i ], geometry, directLight );\n dotNL = dot( geometry.normal, directLight.direction );\n directLightColor_Diffuse = directLight.color;\n vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n #ifdef DOUBLE_SIDED\n vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n #endif\n }\n #pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n vIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n #ifdef DOUBLE_SIDED\n vIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry.normal );\n #endif\n }\n #pragma unroll_loop_end\n#endif"; + var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n float x = normal.x, y = normal.y, z = normal.z;\n vec3 result = shCoefficients[ 0 ] * 0.886227;\n result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n return result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n vec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n return irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n vec3 irradiance = ambientLightColor;\n return irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n #if defined ( PHYSICALLY_CORRECT_LIGHTS )\n float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n if ( cutoffDistance > 0.0 ) {\n distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n }\n return distanceFalloff;\n #else\n if ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n return pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n }\n return 1.0;\n #endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n return smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n struct DirectionalLight {\n vec3 direction;\n vec3 color;\n };\n uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n void getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n light.color = directionalLight.color;\n light.direction = directionalLight.direction;\n light.visible = true;\n }\n#endif\n#if NUM_POINT_LIGHTS > 0\n struct PointLight {\n vec3 position;\n vec3 color;\n float distance;\n float decay;\n };\n uniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n void getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n vec3 lVector = pointLight.position - geometry.position;\n light.direction = normalize( lVector );\n float lightDistance = length( lVector );\n light.color = pointLight.color;\n light.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n light.visible = ( light.color != vec3( 0.0 ) );\n }\n#endif\n#if NUM_SPOT_LIGHTS > 0\n struct SpotLight {\n vec3 position;\n vec3 direction;\n vec3 color;\n float distance;\n float decay;\n float coneCos;\n float penumbraCos;\n };\n uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n void getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n vec3 lVector = spotLight.position - geometry.position;\n light.direction = normalize( lVector );\n float angleCos = dot( light.direction, spotLight.direction );\n float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n if ( spotAttenuation > 0.0 ) {\n float lightDistance = length( lVector );\n light.color = spotLight.color * spotAttenuation;\n light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n light.visible = ( light.color != vec3( 0.0 ) );\n } else {\n light.color = vec3( 0.0 );\n light.visible = false;\n }\n }\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n struct RectAreaLight {\n vec3 color;\n vec3 position;\n vec3 halfWidth;\n vec3 halfHeight;\n };\n uniform sampler2D ltc_1; uniform sampler2D ltc_2;\n uniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n struct HemisphereLight {\n vec3 direction;\n vec3 skyColor;\n vec3 groundColor;\n };\n uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n float dotNL = dot( normal, hemiLight.direction );\n float hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n return irradiance;\n }\n#endif"; + var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n vec3 getIBLIrradiance( const in vec3 normal ) {\n #if defined( ENVMAP_TYPE_CUBE_UV )\n vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n vec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n return PI * envMapColor.rgb * envMapIntensity;\n #else\n return vec3( 0.0 );\n #endif\n }\n vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n #if defined( ENVMAP_TYPE_CUBE_UV )\n vec3 reflectVec = reflect( - viewDir, normal );\n reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n reflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n vec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n return envMapColor.rgb * envMapIntensity;\n #else\n return vec3( 0.0 );\n #endif\n }\n#endif"; + var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; + var lights_toon_pars_fragment = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n vec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n vec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct RE_Direct_Toon\n#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material ) (0)"; + var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;"; + var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n vec3 diffuseColor;\n vec3 specularColor;\n float specularShininess;\n float specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n vec3 irradiance = dotNL * directLight.color;\n reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n reflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct RE_Direct_BlinnPhong\n#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material ) (0)"; + var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n #ifdef SPECULAR\n float specularIntensityFactor = specularIntensity;\n vec3 specularColorFactor = specularColor;\n #ifdef USE_SPECULARINTENSITYMAP\n specularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n #endif\n #ifdef USE_SPECULARCOLORMAP\n specularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n #endif\n material.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n #else\n float specularIntensityFactor = 1.0;\n vec3 specularColorFactor = vec3( 1.0 );\n material.specularF90 = 1.0;\n #endif\n material.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n material.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n material.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n material.clearcoat = clearcoat;\n material.clearcoatRoughness = clearcoatRoughness;\n material.clearcoatF0 = vec3( 0.04 );\n material.clearcoatF90 = 1.0;\n #ifdef USE_CLEARCOATMAP\n material.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n #endif\n #ifdef USE_CLEARCOAT_ROUGHNESSMAP\n material.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n #endif\n material.clearcoat = saturate( material.clearcoat ); material.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n material.clearcoatRoughness += geometryRoughness;\n material.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n material.iridescence = iridescence;\n material.iridescenceIOR = iridescenceIOR;\n #ifdef USE_IRIDESCENCEMAP\n material.iridescence *= texture2D( iridescenceMap, vUv ).r;\n #endif\n #ifdef USE_IRIDESCENCE_THICKNESSMAP\n material.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n #else\n material.iridescenceThickness = iridescenceThicknessMaximum;\n #endif\n#endif\n#ifdef USE_SHEEN\n material.sheenColor = sheenColor;\n #ifdef USE_SHEENCOLORMAP\n material.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n #endif\n material.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n #ifdef USE_SHEENROUGHNESSMAP\n material.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n #endif\n#endif"; + var lights_physical_pars_fragment = "struct PhysicalMaterial {\n vec3 diffuseColor;\n float roughness;\n vec3 specularColor;\n float specularF90;\n #ifdef USE_CLEARCOAT\n float clearcoat;\n float clearcoatRoughness;\n vec3 clearcoatF0;\n float clearcoatF90;\n #endif\n #ifdef USE_IRIDESCENCE\n float iridescence;\n float iridescenceIOR;\n float iridescenceThickness;\n vec3 iridescenceFresnel;\n vec3 iridescenceF0;\n #endif\n #ifdef USE_SHEEN\n vec3 sheenColor;\n float sheenRoughness;\n #endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness) {\n float dotNV = saturate( dot( normal, viewDir ) );\n float r2 = roughness * roughness;\n float a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n float b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n float DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n return saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n float dotNV = saturate( dot( normal, viewDir ) );\n const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n vec4 r = roughness * c0 + c1;\n float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n vec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n return fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n vec2 fab = DFGApprox( normal, viewDir, roughness );\n return specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n vec2 fab = DFGApprox( normal, viewDir, roughness );\n #ifdef USE_IRIDESCENCE\n vec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n #else\n vec3 Fr = specularColor;\n #endif\n vec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n float Ess = fab.x + fab.y;\n float Ems = 1.0 - Ess;\n vec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619; vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n singleScatter += FssEss;\n multiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n void RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n vec3 normal = geometry.normal;\n vec3 viewDir = geometry.viewDir;\n vec3 position = geometry.position;\n vec3 lightPos = rectAreaLight.position;\n vec3 halfWidth = rectAreaLight.halfWidth;\n vec3 halfHeight = rectAreaLight.halfHeight;\n vec3 lightColor = rectAreaLight.color;\n float roughness = material.roughness;\n vec3 rectCoords[ 4 ];\n rectCoords[ 0 ] = lightPos + halfWidth - halfHeight; rectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n rectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n rectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n vec2 uv = LTC_Uv( normal, viewDir, roughness );\n vec4 t1 = texture2D( ltc_1, uv );\n vec4 t2 = texture2D( ltc_2, uv );\n mat3 mInv = mat3(\n vec3( t1.x, 0, t1.y ),\n vec3( 0, 1, 0 ),\n vec3( t1.z, 0, t1.w )\n );\n vec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n reflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n reflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n }\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n vec3 irradiance = dotNL * directLight.color;\n #ifdef USE_CLEARCOAT\n float dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n vec3 ccIrradiance = dotNLcc * directLight.color;\n clearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n #endif\n #ifdef USE_SHEEN\n sheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n #endif\n #ifdef USE_IRIDESCENCE\n reflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n #else\n reflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n #endif\n reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n #ifdef USE_CLEARCOAT\n clearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n #endif\n #ifdef USE_SHEEN\n sheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n #endif\n vec3 singleScattering = vec3( 0.0 );\n vec3 multiScattering = vec3( 0.0 );\n vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n #ifdef USE_IRIDESCENCE\n computeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n #else\n computeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n #endif\n vec3 totalScattering = singleScattering + multiScattering;\n vec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n reflectedLight.indirectSpecular += radiance * singleScattering;\n reflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct RE_Direct_Physical\n#define RE_Direct_RectArea RE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular RE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; + var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n geometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n float dotNVi = saturate( dot( normal, geometry.viewDir ) );\n if ( material.iridescenceThickness == 0.0 ) {\n material.iridescence = 0.0;\n } else {\n material.iridescence = saturate( material.iridescence );\n }\n if ( material.iridescence > 0.0 ) {\n material.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n material.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n }\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n PointLight pointLight;\n #if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n PointLightShadow pointLightShadow;\n #endif\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n pointLight = pointLights[ i ];\n getPointLightInfo( pointLight, geometry, directLight );\n #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n pointLightShadow = pointLightShadows[ i ];\n directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n SpotLight spotLight;\n #if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n SpotLightShadow spotLightShadow;\n #endif\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n spotLight = spotLights[ i ];\n getSpotLightInfo( spotLight, geometry, directLight );\n #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n spotLightShadow = spotLightShadows[ i ];\n directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n DirectionalLight directionalLight;\n #if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n DirectionalLightShadow directionalLightShadow;\n #endif\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n directionalLight = directionalLights[ i ];\n getDirectionalLightInfo( directionalLight, geometry, directLight );\n #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n directionalLightShadow = directionalLightShadows[ i ];\n directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n #endif\n RE_Direct( directLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n RectAreaLight rectAreaLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n rectAreaLight = rectAreaLights[ i ];\n RE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n }\n #pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n vec3 iblIrradiance = vec3( 0.0 );\n vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n irradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n #if ( NUM_HEMI_LIGHTS > 0 )\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n }\n #pragma unroll_loop_end\n #endif\n#endif\n#if defined( RE_IndirectSpecular )\n vec3 radiance = vec3( 0.0 );\n vec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; + var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n #ifdef USE_LIGHTMAP\n vec4 lightMapTexel = texture2D( lightMap, vUv2 );\n vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n irradiance += lightMapIrradiance;\n #endif\n #if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n iblIrradiance += getIBLIrradiance( geometry.normal );\n #endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n radiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n #ifdef USE_CLEARCOAT\n clearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n #endif\n#endif"; + var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n RE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n RE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif"; + var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n gl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; + var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n uniform float logDepthBufFC;\n varying float vFragDepth;\n varying float vIsPerspective;\n#endif"; + var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n #ifdef USE_LOGDEPTHBUF_EXT\n varying float vFragDepth;\n varying float vIsPerspective;\n #else\n uniform float logDepthBufFC;\n #endif\n#endif"; + var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n #ifdef USE_LOGDEPTHBUF_EXT\n vFragDepth = 1.0 + gl_Position.w;\n vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n #else\n if ( isPerspectiveMatrix( projectionMatrix ) ) {\n gl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n gl_Position.z *= gl_Position.w;\n }\n #endif\n#endif"; + var map_fragment = "#ifdef USE_MAP\n vec4 sampledDiffuseColor = texture2D( map, vUv );\n #ifdef DECODE_VIDEO_TEXTURE\n sampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n #endif\n diffuseColor *= sampledDiffuseColor;\n#endif"; + var map_pars_fragment = "#ifdef USE_MAP\n uniform sampler2D map;\n#endif"; + var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n diffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n diffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; + var map_particle_pars_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n uniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n uniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n uniform sampler2D alphaMap;\n#endif"; + var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n vec4 texelMetalness = texture2D( metalnessMap, vUv );\n metalnessFactor *= texelMetalness.b;\n#endif"; + var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n uniform sampler2D metalnessMap;\n#endif"; + var morphcolor_vertex = "#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n vColor *= morphTargetBaseInfluence;\n for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n #if defined( USE_COLOR_ALPHA )\n if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n #elif defined( USE_COLOR )\n if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n #endif\n }\n#endif"; + var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n objectNormal *= morphTargetBaseInfluence;\n #ifdef MORPHTARGETS_TEXTURE\n for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n if ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n }\n #else\n objectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n objectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n objectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n objectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n #endif\n#endif"; + var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n uniform float morphTargetBaseInfluence;\n #ifdef MORPHTARGETS_TEXTURE\n uniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n uniform sampler2DArray morphTargetsTexture;\n uniform ivec2 morphTargetsTextureSize;\n vec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n int texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n int y = texelIndex / morphTargetsTextureSize.x;\n int x = texelIndex - y * morphTargetsTextureSize.x;\n ivec3 morphUV = ivec3( x, y, morphTargetIndex );\n return texelFetch( morphTargetsTexture, morphUV, 0 );\n }\n #else\n #ifndef USE_MORPHNORMALS\n uniform float morphTargetInfluences[ 8 ];\n #else\n uniform float morphTargetInfluences[ 4 ];\n #endif\n #endif\n#endif"; + var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n transformed *= morphTargetBaseInfluence;\n #ifdef MORPHTARGETS_TEXTURE\n for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n if ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n }\n #else\n transformed += morphTarget0 * morphTargetInfluences[ 0 ];\n transformed += morphTarget1 * morphTargetInfluences[ 1 ];\n transformed += morphTarget2 * morphTargetInfluences[ 2 ];\n transformed += morphTarget3 * morphTargetInfluences[ 3 ];\n #ifndef USE_MORPHNORMALS\n transformed += morphTarget4 * morphTargetInfluences[ 4 ];\n transformed += morphTarget5 * morphTargetInfluences[ 5 ];\n transformed += morphTarget6 * morphTargetInfluences[ 6 ];\n transformed += morphTarget7 * morphTargetInfluences[ 7 ];\n #endif\n #endif\n#endif"; + var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n vec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n vec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n vec3 normal = normalize( cross( fdx, fdy ) );\n#else\n vec3 normal = normalize( vNormal );\n #ifdef DOUBLE_SIDED\n normal = normal * faceDirection;\n #endif\n #ifdef USE_TANGENT\n vec3 tangent = normalize( vTangent );\n vec3 bitangent = normalize( vBitangent );\n #ifdef DOUBLE_SIDED\n tangent = tangent * faceDirection;\n bitangent = bitangent * faceDirection;\n #endif\n #if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n mat3 vTBN = mat3( tangent, bitangent, normal );\n #endif\n #endif\n#endif\nvec3 geometryNormal = normal;"; + var normal_fragment_maps = "#ifdef OBJECTSPACE_NORMALMAP\n normal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n #ifdef FLIP_SIDED\n normal = - normal;\n #endif\n #ifdef DOUBLE_SIDED\n normal = normal * faceDirection;\n #endif\n normal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n mapN.xy *= normalScale;\n #ifdef USE_TANGENT\n normal = normalize( vTBN * mapN );\n #else\n normal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n #endif\n#elif defined( USE_BUMPMAP )\n normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; + var normal_pars_fragment = "#ifndef FLAT_SHADED\n varying vec3 vNormal;\n #ifdef USE_TANGENT\n varying vec3 vTangent;\n varying vec3 vBitangent;\n #endif\n#endif"; + var normal_pars_vertex = "#ifndef FLAT_SHADED\n varying vec3 vNormal;\n #ifdef USE_TANGENT\n varying vec3 vTangent;\n varying vec3 vBitangent;\n #endif\n#endif"; + var normal_vertex = "#ifndef FLAT_SHADED\n vNormal = normalize( transformedNormal );\n #ifdef USE_TANGENT\n vTangent = normalize( transformedTangent );\n vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n #endif\n#endif"; + var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n uniform sampler2D normalMap;\n uniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n uniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n vec3 q0 = dFdx( eye_pos.xyz );\n vec3 q1 = dFdy( eye_pos.xyz );\n vec2 st0 = dFdx( vUv.st );\n vec2 st1 = dFdy( vUv.st );\n vec3 N = surf_norm;\n vec3 q1perp = cross( q1, N );\n vec3 q0perp = cross( N, q0 );\n vec3 T = q1perp * st0.x + q0perp * st1.x;\n vec3 B = q1perp * st0.y + q0perp * st1.y;\n float det = max( dot( T, T ), dot( B, B ) );\n float scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n return normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n }\n#endif"; + var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n vec3 clearcoatNormal = geometryNormal;\n#endif"; + var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n clearcoatMapN.xy *= clearcoatNormalScale;\n #ifdef USE_TANGENT\n clearcoatNormal = normalize( vTBN * clearcoatMapN );\n #else\n clearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n #endif\n#endif"; + var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n uniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n uniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n uniform sampler2D clearcoatNormalMap;\n uniform vec2 clearcoatNormalScale;\n#endif"; + var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n uniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n uniform sampler2D iridescenceThicknessMap;\n#endif"; + var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; + var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n return normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n return 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n vec4 r = vec4( fract( v * PackFactors ), v );\n r.yzw -= r.xyz * ShiftRight8; return r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n return dot( v, UnpackFactors );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n vec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n return vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n return ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n return linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n return ( near * far ) / ( ( far - near ) * invClipZ - far );\n}"; + var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n gl_FragColor.rgb *= gl_FragColor.a;\n#endif"; + var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n mvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;"; + var dithering_fragment = "#ifdef DITHERING\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif"; + var dithering_pars_fragment = "#ifdef DITHERING\n vec3 dithering( vec3 color ) {\n float grid_position = rand( gl_FragCoord.xy );\n vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n return color + dither_shift_RGB;\n }\n#endif"; + var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n vec4 texelRoughness = texture2D( roughnessMap, vUv );\n roughnessFactor *= texelRoughness.g;\n#endif"; + var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n uniform sampler2D roughnessMap;\n#endif"; + var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0\n uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n struct DirectionalLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n struct SpotLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n uniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n struct PointLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n float shadowCameraNear;\n float shadowCameraFar;\n };\n uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n #endif\n float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n }\n vec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n return unpackRGBATo2Half( texture2D( shadow, uv ) );\n }\n float VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n float occlusion = 1.0;\n vec2 distribution = texture2DDistribution( shadow, uv );\n float hard_shadow = step( compare , distribution.x );\n if (hard_shadow != 1.0 ) {\n float distance = compare - distribution.x ;\n float variance = max( 0.00000, distribution.y * distribution.y );\n float softness_probability = variance / (variance + distance * distance ); softness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); occlusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n }\n return occlusion;\n }\n float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n float shadow = 1.0;\n shadowCoord.xyz /= shadowCoord.w;\n shadowCoord.z += shadowBias;\n bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n bool inFrustum = all( inFrustumVec );\n bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n bool frustumTest = all( frustumTestVec );\n if ( frustumTest ) {\n #if defined( SHADOWMAP_TYPE_PCF )\n vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n float dx0 = - texelSize.x * shadowRadius;\n float dy0 = - texelSize.y * shadowRadius;\n float dx1 = + texelSize.x * shadowRadius;\n float dy1 = + texelSize.y * shadowRadius;\n float dx2 = dx0 / 2.0;\n float dy2 = dy0 / 2.0;\n float dx3 = dx1 / 2.0;\n float dy3 = dy1 / 2.0;\n shadow = (\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n ) * ( 1.0 / 17.0 );\n #elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n float dx = texelSize.x;\n float dy = texelSize.y;\n vec2 uv = shadowCoord.xy;\n vec2 f = fract( uv * shadowMapSize + 0.5 );\n uv -= f * texelSize;\n shadow = (\n texture2DCompare( shadowMap, uv, shadowCoord.z ) +\n texture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n texture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n texture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n mix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n f.x ) +\n mix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n f.x ) +\n mix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n f.y ) +\n mix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n f.y ) +\n mix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n f.x ),\n mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n f.x ),\n f.y )\n ) * ( 1.0 / 9.0 );\n #elif defined( SHADOWMAP_TYPE_VSM )\n shadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n #else\n shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n #endif\n }\n return shadow;\n }\n vec2 cubeToUV( vec3 v, float texelSizeY ) {\n vec3 absV = abs( v );\n float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n absV *= scaleToCube;\n v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n vec2 planar = v.xy;\n float almostATexel = 1.5 * texelSizeY;\n float almostOne = 1.0 - almostATexel;\n if ( absV.z >= almostOne ) {\n if ( v.z > 0.0 )\n planar.x = 4.0 - v.x;\n } else if ( absV.x >= almostOne ) {\n float signX = sign( v.x );\n planar.x = v.z * signX + 2.0 * signX;\n } else if ( absV.y >= almostOne ) {\n float signY = sign( v.y );\n planar.x = v.x + 2.0 * signY + 2.0;\n planar.y = v.z * signY - 2.0;\n }\n return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n }\n float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n vec3 lightToPosition = shadowCoord.xyz;\n float dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); dp += shadowBias;\n vec3 bd3D = normalize( lightToPosition );\n #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n return (\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n ) * ( 1.0 / 9.0 );\n #else\n return texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n #endif\n }\n#endif"; + var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0\n uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n struct DirectionalLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n uniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n struct SpotLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n };\n uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n struct PointLightShadow {\n float shadowBias;\n float shadowNormalBias;\n float shadowRadius;\n vec2 shadowMapSize;\n float shadowCameraNear;\n float shadowCameraFar;\n };\n uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n #endif\n#endif"; + var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0\n vec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n vec4 shadowWorldPosition;\n #endif\n #if NUM_DIR_LIGHT_SHADOWS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias, 0 );\n vSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * shadowWorldPosition;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n }\n #pragma unroll_loop_end\n #endif\n#endif"; + var shadowmask_pars_fragment = "float getShadowMask() {\n float shadow = 1.0;\n #ifdef USE_SHADOWMAP\n #if NUM_DIR_LIGHT_SHADOWS > 0\n DirectionalLightShadow directionalLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n directionalLight = directionalLightShadows[ i ];\n shadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_SPOT_LIGHT_SHADOWS > 0\n SpotLightShadow spotLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n spotLight = spotLightShadows[ i ];\n shadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n }\n #pragma unroll_loop_end\n #endif\n #if NUM_POINT_LIGHT_SHADOWS > 0\n PointLightShadow pointLight;\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n pointLight = pointLightShadows[ i ];\n shadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n }\n #pragma unroll_loop_end\n #endif\n #endif\n return shadow;\n}"; + var skinbase_vertex = "#ifdef USE_SKINNING\n mat4 boneMatX = getBoneMatrix( skinIndex.x );\n mat4 boneMatY = getBoneMatrix( skinIndex.y );\n mat4 boneMatZ = getBoneMatrix( skinIndex.z );\n mat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; + var skinning_pars_vertex = "#ifdef USE_SKINNING\n uniform mat4 bindMatrix;\n uniform mat4 bindMatrixInverse;\n uniform highp sampler2D boneTexture;\n uniform int boneTextureSize;\n mat4 getBoneMatrix( const in float i ) {\n float j = i * 4.0;\n float x = mod( j, float( boneTextureSize ) );\n float y = floor( j / float( boneTextureSize ) );\n float dx = 1.0 / float( boneTextureSize );\n float dy = 1.0 / float( boneTextureSize );\n y = dy * ( y + 0.5 );\n vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n mat4 bone = mat4( v1, v2, v3, v4 );\n return bone;\n }\n#endif"; + var skinning_vertex = "#ifdef USE_SKINNING\n vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n vec4 skinned = vec4( 0.0 );\n skinned += boneMatX * skinVertex * skinWeight.x;\n skinned += boneMatY * skinVertex * skinWeight.y;\n skinned += boneMatZ * skinVertex * skinWeight.z;\n skinned += boneMatW * skinVertex * skinWeight.w;\n transformed = ( bindMatrixInverse * skinned ).xyz;\n#endif"; + var skinnormal_vertex = "#ifdef USE_SKINNING\n mat4 skinMatrix = mat4( 0.0 );\n skinMatrix += skinWeight.x * boneMatX;\n skinMatrix += skinWeight.y * boneMatY;\n skinMatrix += skinWeight.z * boneMatZ;\n skinMatrix += skinWeight.w * boneMatW;\n skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n #ifdef USE_TANGENT\n objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n #endif\n#endif"; + var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n vec4 texelSpecular = texture2D( specularMap, vUv );\n specularStrength = texelSpecular.r;\n#else\n specularStrength = 1.0;\n#endif"; + var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n uniform sampler2D specularMap;\n#endif"; + var tonemapping_fragment = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif"; + var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n return toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n color *= toneMappingExposure;\n return saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n color *= toneMappingExposure;\n color = max( vec3( 0.0 ), color - 0.004 );\n return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n vec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n return a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n const mat3 ACESInputMat = mat3(\n vec3( 0.59719, 0.07600, 0.02840 ), vec3( 0.35458, 0.90834, 0.13383 ),\n vec3( 0.04823, 0.01566, 0.83777 )\n );\n const mat3 ACESOutputMat = mat3(\n vec3( 1.60475, -0.10208, -0.00327 ), vec3( -0.53108, 1.10813, -0.07276 ),\n vec3( -0.07367, -0.00605, 1.07602 )\n );\n color *= toneMappingExposure / 0.6;\n color = ACESInputMat * color;\n color = RRTAndODTFit( color );\n color = ACESOutputMat * color;\n return saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; + var transmission_fragment = "#ifdef USE_TRANSMISSION\n float transmissionAlpha = 1.0;\n float transmissionFactor = transmission;\n float thicknessFactor = thickness;\n #ifdef USE_TRANSMISSIONMAP\n transmissionFactor *= texture2D( transmissionMap, vUv ).r;\n #endif\n #ifdef USE_THICKNESSMAP\n thicknessFactor *= texture2D( thicknessMap, vUv ).g;\n #endif\n vec3 pos = vWorldPosition;\n vec3 v = normalize( cameraPosition - pos );\n vec3 n = inverseTransformDirection( normal, viewMatrix );\n vec4 transmission = getIBLVolumeRefraction(\n n, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,\n pos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,\n attenuationColor, attenuationDistance );\n totalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );\n transmissionAlpha = mix( transmissionAlpha, transmission.a, transmissionFactor );\n#endif"; + var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n uniform float transmission;\n uniform float thickness;\n uniform float attenuationDistance;\n uniform vec3 attenuationColor;\n #ifdef USE_TRANSMISSIONMAP\n uniform sampler2D transmissionMap;\n #endif\n #ifdef USE_THICKNESSMAP\n uniform sampler2D thicknessMap;\n #endif\n uniform vec2 transmissionSamplerSize;\n uniform sampler2D transmissionSamplerMap;\n uniform mat4 modelMatrix;\n uniform mat4 projectionMatrix;\n varying vec3 vWorldPosition;\n vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n vec3 modelScale;\n modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n return normalize( refractionVector ) * thickness * modelScale;\n }\n float applyIorToRoughness( const in float roughness, const in float ior ) {\n return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n }\n vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n float framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n #ifdef texture2DLodEXT\n return texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n #else\n return texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n #endif\n }\n vec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n if ( attenuationDistance == 0.0 ) {\n return radiance;\n } else {\n vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); return transmittance * radiance;\n }\n }\n vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n const in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n const in vec3 attenuationColor, const in float attenuationDistance ) {\n vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n vec3 refractedRayExit = position + transmissionRay;\n vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n vec2 refractionCoords = ndcPos.xy / ndcPos.w;\n refractionCoords += 1.0;\n refractionCoords /= 2.0;\n vec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n vec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n return vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n }\n#endif"; + var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n varying vec2 vUv;\n#endif"; + var uv_pars_vertex = "#ifdef USE_UV\n #ifdef UVS_VERTEX_ONLY\n vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n uniform mat3 uvTransform;\n#endif"; + var uv_vertex = "#ifdef USE_UV\n vUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; + var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n varying vec2 vUv2;\n#endif"; + var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n attribute vec2 uv2;\n varying vec2 vUv2;\n uniform mat3 uv2Transform;\n#endif"; + var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n vUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif"; + var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION )\n vec4 worldPosition = vec4( transformed, 1.0 );\n #ifdef USE_INSTANCING\n worldPosition = instanceMatrix * worldPosition;\n #endif\n worldPosition = modelMatrix * worldPosition;\n#endif"; + var vertex$g = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n vUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n gl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; + var fragment$g = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n gl_FragColor = texture2D( t2D, vUv );\n #ifdef DECODE_VIDEO_TEXTURE\n gl_FragColor = vec4( mix( pow( gl_FragColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), gl_FragColor.rgb * 0.0773993808, vec3( lessThanEqual( gl_FragColor.rgb, vec3( 0.04045 ) ) ) ), gl_FragColor.w );\n #endif\n #include \n #include \n}"; + var vertex$f = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n vWorldDirection = transformDirection( position, modelMatrix );\n #include \n #include \n gl_Position.z = gl_Position.w;\n}"; + var fragment$f = "#include \nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n vec3 vReflect = vWorldDirection;\n #include \n gl_FragColor = envColor;\n gl_FragColor.a *= opacity;\n #include \n #include \n}"; + var vertex$e = "#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n #include \n #include \n #ifdef USE_DISPLACEMENTMAP\n #include \n #include \n #include \n #endif\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vHighPrecisionZW = gl_Position.zw;\n}"; + var fragment$e = "#if DEPTH_PACKING == 3200\n uniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n #include \n vec4 diffuseColor = vec4( 1.0 );\n #if DEPTH_PACKING == 3200\n diffuseColor.a = opacity;\n #endif\n #include \n #include \n #include \n #include \n float fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n #if DEPTH_PACKING == 3200\n gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n #elif DEPTH_PACKING == 3201\n gl_FragColor = packDepthToRGBA( fragCoordZ );\n #endif\n}"; + var vertex$d = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #ifdef USE_DISPLACEMENTMAP\n #include \n #include \n #include \n #endif\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vWorldPosition = worldPosition.xyz;\n}"; + var fragment$d = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n #include \n vec4 diffuseColor = vec4( 1.0 );\n #include \n #include \n #include \n float dist = length( vWorldPosition - referencePosition );\n dist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n dist = saturate( dist );\n gl_FragColor = packDepthToRGBA( dist );\n}"; + var vertex$c = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n vWorldDirection = transformDirection( position, modelMatrix );\n #include \n #include \n}"; + var fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n vec3 direction = normalize( vWorldDirection );\n vec2 sampleUV = equirectUv( direction );\n gl_FragColor = texture2D( tEquirect, sampleUV );\n #include \n #include \n}"; + var vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n vLineDistance = scale * lineDistance;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n if ( mod( vLineDistance, totalSize ) > dashSize ) {\n discard;\n }\n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n outgoingLight = diffuseColor.rgb;\n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n #include \n #include \n #include \n #include \n #include \n #endif\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n varying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n #include \n #include \n #include \n #include \n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n #ifdef USE_LIGHTMAP\n vec4 lightMapTexel = texture2D( lightMap, vUv2 );\n reflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n #else\n reflectedLight.indirectDiffuse += vec3( 1.0 );\n #endif\n #include \n reflectedLight.indirectDiffuse *= diffuseColor.rgb;\n vec3 outgoingLight = reflectedLight.indirectDiffuse;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$9 = "#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n varying vec3 vLightBack;\n varying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var fragment$9 = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n varying vec3 vLightBack;\n varying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #ifdef DOUBLE_SIDED\n reflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n #else\n reflectedLight.indirectDiffuse += vIndirectFront;\n #endif\n #include \n reflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb );\n #ifdef DOUBLE_SIDED\n reflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n #else\n reflectedLight.directDiffuse = vLightFront;\n #endif\n reflectedLight.directDiffuse *= BRDF_Lambert( diffuseColor.rgb ) * getShadowMask();\n #include \n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vViewPosition = - mvPosition.xyz;\n}"; + var fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vec3 viewDir = normalize( vViewPosition );\n vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n vec3 y = cross( viewDir, x );\n vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n #ifdef USE_MATCAP\n vec4 matcapColor = texture2D( matcap, uv );\n #else\n vec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n #endif\n vec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n varying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n vViewPosition = - mvPosition.xyz;\n#endif\n}"; + var fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n varying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n gl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n #ifdef OPAQUE\n gl_FragColor.a = 1.0;\n #endif\n}"; + var vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vViewPosition = - mvPosition.xyz;\n #include \n #include \n #include \n #include \n}"; + var fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n varying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vViewPosition = - mvPosition.xyz;\n #include \n #include \n #include \n#ifdef USE_TRANSMISSION\n vWorldPosition = worldPosition.xyz;\n#endif\n}"; + var fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n #define IOR\n #define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n uniform float ior;\n#endif\n#ifdef SPECULAR\n uniform float specularIntensity;\n uniform vec3 specularColor;\n #ifdef USE_SPECULARINTENSITYMAP\n uniform sampler2D specularIntensityMap;\n #endif\n #ifdef USE_SPECULARCOLORMAP\n uniform sampler2D specularColorMap;\n #endif\n#endif\n#ifdef USE_CLEARCOAT\n uniform float clearcoat;\n uniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n uniform float iridescence;\n uniform float iridescenceIOR;\n uniform float iridescenceThicknessMinimum;\n uniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n uniform vec3 sheenColor;\n uniform float sheenRoughness;\n #ifdef USE_SHEENCOLORMAP\n uniform sampler2D sheenColorMap;\n #endif\n #ifdef USE_SHEENROUGHNESSMAP\n uniform sampler2D sheenRoughnessMap;\n #endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n #include \n vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n #ifdef USE_SHEEN\n float sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n #endif\n #ifdef USE_CLEARCOAT\n float dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n #endif\n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vViewPosition = - mvPosition.xyz;\n #include \n #include \n #include \n}"; + var fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n gl_PointSize = size;\n #ifdef USE_SIZEATTENUATION\n bool isPerspective = isPerspectiveMatrix( projectionMatrix );\n if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n #endif\n #include \n #include \n #include \n #include \n}"; + var fragment$3 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n #include \n #include \n outgoingLight = diffuseColor.rgb;\n #include \n #include \n #include \n #include \n #include \n}"; + var vertex$2 = "#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n}"; + var fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n gl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n #include \n #include \n #include \n}"; + var vertex$1 = "uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n vec2 scale;\n scale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n scale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n #ifndef USE_SIZEATTENUATION\n bool isPerspective = isPerspectiveMatrix( projectionMatrix );\n if ( isPerspective ) scale *= - mvPosition.z;\n #endif\n vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n vec2 rotatedPosition;\n rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n mvPosition.xy += rotatedPosition;\n gl_Position = projectionMatrix * mvPosition;\n #include \n #include \n #include \n}"; + var fragment$1 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n #include \n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n #include \n #include \n #include \n #include \n outgoingLight = diffuseColor.rgb;\n #include \n #include \n #include \n #include \n}"; + var ShaderChunk = { + alphamap_fragment, + alphamap_pars_fragment, + alphatest_fragment, + alphatest_pars_fragment, + aomap_fragment, + aomap_pars_fragment, + begin_vertex, + beginnormal_vertex, + bsdfs, + iridescence_fragment, + bumpmap_pars_fragment, + clipping_planes_fragment, + clipping_planes_pars_fragment, + clipping_planes_pars_vertex, + clipping_planes_vertex, + color_fragment, + color_pars_fragment, + color_pars_vertex, + color_vertex, + common, + cube_uv_reflection_fragment, + defaultnormal_vertex, + displacementmap_pars_vertex, + displacementmap_vertex, + emissivemap_fragment, + emissivemap_pars_fragment, + encodings_fragment, + encodings_pars_fragment, + envmap_fragment, + envmap_common_pars_fragment, + envmap_pars_fragment, + envmap_pars_vertex, + envmap_physical_pars_fragment, + envmap_vertex, + fog_vertex, + fog_pars_vertex, + fog_fragment, + fog_pars_fragment, + gradientmap_pars_fragment, + lightmap_fragment, + lightmap_pars_fragment, + lights_lambert_vertex, + lights_pars_begin, + lights_toon_fragment, + lights_toon_pars_fragment, + lights_phong_fragment, + lights_phong_pars_fragment, + lights_physical_fragment, + lights_physical_pars_fragment, + lights_fragment_begin, + lights_fragment_maps, + lights_fragment_end, + logdepthbuf_fragment, + logdepthbuf_pars_fragment, + logdepthbuf_pars_vertex, + logdepthbuf_vertex, + map_fragment, + map_pars_fragment, + map_particle_fragment, + map_particle_pars_fragment, + metalnessmap_fragment, + metalnessmap_pars_fragment, + morphcolor_vertex, + morphnormal_vertex, + morphtarget_pars_vertex, + morphtarget_vertex, + normal_fragment_begin, + normal_fragment_maps, + normal_pars_fragment, + normal_pars_vertex, + normal_vertex, + normalmap_pars_fragment, + clearcoat_normal_fragment_begin, + clearcoat_normal_fragment_maps, + clearcoat_pars_fragment, + iridescence_pars_fragment, + output_fragment, + packing, + premultiplied_alpha_fragment, + project_vertex, + dithering_fragment, + dithering_pars_fragment, + roughnessmap_fragment, + roughnessmap_pars_fragment, + shadowmap_pars_fragment, + shadowmap_pars_vertex, + shadowmap_vertex, + shadowmask_pars_fragment, + skinbase_vertex, + skinning_pars_vertex, + skinning_vertex, + skinnormal_vertex, + specularmap_fragment, + specularmap_pars_fragment, + tonemapping_fragment, + tonemapping_pars_fragment, + transmission_fragment, + transmission_pars_fragment, + uv_pars_fragment, + uv_pars_vertex, + uv_vertex, + uv2_pars_fragment, + uv2_pars_vertex, + uv2_vertex, + worldpos_vertex, + background_vert: vertex$g, + background_frag: fragment$g, + cube_vert: vertex$f, + cube_frag: fragment$f, + depth_vert: vertex$e, + depth_frag: fragment$e, + distanceRGBA_vert: vertex$d, + distanceRGBA_frag: fragment$d, + equirect_vert: vertex$c, + equirect_frag: fragment$c, + linedashed_vert: vertex$b, + linedashed_frag: fragment$b, + meshbasic_vert: vertex$a, + meshbasic_frag: fragment$a, + meshlambert_vert: vertex$9, + meshlambert_frag: fragment$9, + meshmatcap_vert: vertex$8, + meshmatcap_frag: fragment$8, + meshnormal_vert: vertex$7, + meshnormal_frag: fragment$7, + meshphong_vert: vertex$6, + meshphong_frag: fragment$6, + meshphysical_vert: vertex$5, + meshphysical_frag: fragment$5, + meshtoon_vert: vertex$4, + meshtoon_frag: fragment$4, + points_vert: vertex$3, + points_frag: fragment$3, + shadow_vert: vertex$2, + shadow_frag: fragment$2, + sprite_vert: vertex$1, + sprite_frag: fragment$1 + }; + var UniformsLib = { + common: { + diffuse: { value: /* @__PURE__ */ new Color2(16777215) }, + opacity: { value: 1 }, + map: { value: null }, + uvTransform: { value: /* @__PURE__ */ new Matrix3() }, + uv2Transform: { value: /* @__PURE__ */ new Matrix3() }, + alphaMap: { value: null }, + alphaTest: { value: 0 } + }, + specularmap: { + specularMap: { value: null } + }, + envmap: { + envMap: { value: null }, + flipEnvMap: { value: -1 }, + reflectivity: { value: 1 }, + ior: { value: 1.5 }, + refractionRatio: { value: 0.98 } + }, + aomap: { + aoMap: { value: null }, + aoMapIntensity: { value: 1 } + }, + lightmap: { + lightMap: { value: null }, + lightMapIntensity: { value: 1 } + }, + emissivemap: { + emissiveMap: { value: null } + }, + bumpmap: { + bumpMap: { value: null }, + bumpScale: { value: 1 } + }, + normalmap: { + normalMap: { value: null }, + normalScale: { value: /* @__PURE__ */ new Vector2(1, 1) } + }, + displacementmap: { + displacementMap: { value: null }, + displacementScale: { value: 1 }, + displacementBias: { value: 0 } + }, + roughnessmap: { + roughnessMap: { value: null } + }, + metalnessmap: { + metalnessMap: { value: null } + }, + gradientmap: { + gradientMap: { value: null } + }, + fog: { + fogDensity: { value: 25e-5 }, + fogNear: { value: 1 }, + fogFar: { value: 2e3 }, + fogColor: { value: /* @__PURE__ */ new Color2(16777215) } + }, + lights: { + ambientLightColor: { value: [] }, + lightProbe: { value: [] }, + directionalLights: { value: [], properties: { + direction: {}, + color: {} + } }, + directionalLightShadows: { value: [], properties: { + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {} + } }, + directionalShadowMap: { value: [] }, + directionalShadowMatrix: { value: [] }, + spotLights: { value: [], properties: { + color: {}, + position: {}, + direction: {}, + distance: {}, + coneCos: {}, + penumbraCos: {}, + decay: {} + } }, + spotLightShadows: { value: [], properties: { + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {} + } }, + spotShadowMap: { value: [] }, + spotShadowMatrix: { value: [] }, + pointLights: { value: [], properties: { + color: {}, + position: {}, + decay: {}, + distance: {} + } }, + pointLightShadows: { value: [], properties: { + shadowBias: {}, + shadowNormalBias: {}, + shadowRadius: {}, + shadowMapSize: {}, + shadowCameraNear: {}, + shadowCameraFar: {} + } }, + pointShadowMap: { value: [] }, + pointShadowMatrix: { value: [] }, + hemisphereLights: { value: [], properties: { + direction: {}, + skyColor: {}, + groundColor: {} + } }, + rectAreaLights: { value: [], properties: { + color: {}, + position: {}, + width: {}, + height: {} + } }, + ltc_1: { value: null }, + ltc_2: { value: null } + }, + points: { + diffuse: { value: /* @__PURE__ */ new Color2(16777215) }, + opacity: { value: 1 }, + size: { value: 1 }, + scale: { value: 1 }, + map: { value: null }, + alphaMap: { value: null }, + alphaTest: { value: 0 }, + uvTransform: { value: /* @__PURE__ */ new Matrix3() } + }, + sprite: { + diffuse: { value: /* @__PURE__ */ new Color2(16777215) }, + opacity: { value: 1 }, + center: { value: /* @__PURE__ */ new Vector2(0.5, 0.5) }, + rotation: { value: 0 }, + map: { value: null }, + alphaMap: { value: null }, + alphaTest: { value: 0 }, + uvTransform: { value: /* @__PURE__ */ new Matrix3() } + } + }; + var ShaderLib = { + basic: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, + UniformsLib.aomap, + UniformsLib.lightmap, + UniformsLib.fog + ]), + vertexShader: ShaderChunk.meshbasic_vert, + fragmentShader: ShaderChunk.meshbasic_frag + }, + lambert: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, + UniformsLib.aomap, + UniformsLib.lightmap, + UniformsLib.emissivemap, + UniformsLib.fog, + UniformsLib.lights, + { + emissive: { value: /* @__PURE__ */ new Color2(0) } + } + ]), + vertexShader: ShaderChunk.meshlambert_vert, + fragmentShader: ShaderChunk.meshlambert_frag + }, + phong: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.common, + UniformsLib.specularmap, + UniformsLib.envmap, + UniformsLib.aomap, + UniformsLib.lightmap, + UniformsLib.emissivemap, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + UniformsLib.fog, + UniformsLib.lights, + { + emissive: { value: /* @__PURE__ */ new Color2(0) }, + specular: { value: /* @__PURE__ */ new Color2(1118481) }, + shininess: { value: 30 } + } + ]), + vertexShader: ShaderChunk.meshphong_vert, + fragmentShader: ShaderChunk.meshphong_frag + }, + standard: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.common, + UniformsLib.envmap, + UniformsLib.aomap, + UniformsLib.lightmap, + UniformsLib.emissivemap, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + UniformsLib.roughnessmap, + UniformsLib.metalnessmap, + UniformsLib.fog, + UniformsLib.lights, + { + emissive: { value: /* @__PURE__ */ new Color2(0) }, + roughness: { value: 1 }, + metalness: { value: 0 }, + envMapIntensity: { value: 1 } + } + ]), + vertexShader: ShaderChunk.meshphysical_vert, + fragmentShader: ShaderChunk.meshphysical_frag + }, + toon: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.common, + UniformsLib.aomap, + UniformsLib.lightmap, + UniformsLib.emissivemap, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + UniformsLib.gradientmap, + UniformsLib.fog, + UniformsLib.lights, + { + emissive: { value: /* @__PURE__ */ new Color2(0) } + } + ]), + vertexShader: ShaderChunk.meshtoon_vert, + fragmentShader: ShaderChunk.meshtoon_frag + }, + matcap: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.common, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + UniformsLib.fog, + { + matcap: { value: null } + } + ]), + vertexShader: ShaderChunk.meshmatcap_vert, + fragmentShader: ShaderChunk.meshmatcap_frag + }, + points: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.points, + UniformsLib.fog + ]), + vertexShader: ShaderChunk.points_vert, + fragmentShader: ShaderChunk.points_frag + }, + dashed: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.common, + UniformsLib.fog, + { + scale: { value: 1 }, + dashSize: { value: 1 }, + totalSize: { value: 2 } + } + ]), + vertexShader: ShaderChunk.linedashed_vert, + fragmentShader: ShaderChunk.linedashed_frag + }, + depth: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.common, + UniformsLib.displacementmap + ]), + vertexShader: ShaderChunk.depth_vert, + fragmentShader: ShaderChunk.depth_frag + }, + normal: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.common, + UniformsLib.bumpmap, + UniformsLib.normalmap, + UniformsLib.displacementmap, + { + opacity: { value: 1 } + } + ]), + vertexShader: ShaderChunk.meshnormal_vert, + fragmentShader: ShaderChunk.meshnormal_frag + }, + sprite: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.sprite, + UniformsLib.fog + ]), + vertexShader: ShaderChunk.sprite_vert, + fragmentShader: ShaderChunk.sprite_frag + }, + background: { + uniforms: { + uvTransform: { value: /* @__PURE__ */ new Matrix3() }, + t2D: { value: null } + }, + vertexShader: ShaderChunk.background_vert, + fragmentShader: ShaderChunk.background_frag + }, + cube: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.envmap, + { + opacity: { value: 1 } + } + ]), + vertexShader: ShaderChunk.cube_vert, + fragmentShader: ShaderChunk.cube_frag + }, + equirect: { + uniforms: { + tEquirect: { value: null } + }, + vertexShader: ShaderChunk.equirect_vert, + fragmentShader: ShaderChunk.equirect_frag + }, + distanceRGBA: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.common, + UniformsLib.displacementmap, + { + referencePosition: { value: /* @__PURE__ */ new Vector3() }, + nearDistance: { value: 1 }, + farDistance: { value: 1e3 } + } + ]), + vertexShader: ShaderChunk.distanceRGBA_vert, + fragmentShader: ShaderChunk.distanceRGBA_frag + }, + shadow: { + uniforms: /* @__PURE__ */ mergeUniforms([ + UniformsLib.lights, + UniformsLib.fog, + { + color: { value: /* @__PURE__ */ new Color2(0) }, + opacity: { value: 1 } + } + ]), + vertexShader: ShaderChunk.shadow_vert, + fragmentShader: ShaderChunk.shadow_frag + } + }; + ShaderLib.physical = { + uniforms: /* @__PURE__ */ mergeUniforms([ + ShaderLib.standard.uniforms, + { + clearcoat: { value: 0 }, + clearcoatMap: { value: null }, + clearcoatRoughness: { value: 0 }, + clearcoatRoughnessMap: { value: null }, + clearcoatNormalScale: { value: /* @__PURE__ */ new Vector2(1, 1) }, + clearcoatNormalMap: { value: null }, + iridescence: { value: 0 }, + iridescenceMap: { value: null }, + iridescenceIOR: { value: 1.3 }, + iridescenceThicknessMinimum: { value: 100 }, + iridescenceThicknessMaximum: { value: 400 }, + iridescenceThicknessMap: { value: null }, + sheen: { value: 0 }, + sheenColor: { value: /* @__PURE__ */ new Color2(0) }, + sheenColorMap: { value: null }, + sheenRoughness: { value: 1 }, + sheenRoughnessMap: { value: null }, + transmission: { value: 0 }, + transmissionMap: { value: null }, + transmissionSamplerSize: { value: /* @__PURE__ */ new Vector2() }, + transmissionSamplerMap: { value: null }, + thickness: { value: 0 }, + thicknessMap: { value: null }, + attenuationDistance: { value: 0 }, + attenuationColor: { value: /* @__PURE__ */ new Color2(0) }, + specularIntensity: { value: 1 }, + specularIntensityMap: { value: null }, + specularColor: { value: /* @__PURE__ */ new Color2(1, 1, 1) }, + specularColorMap: { value: null } + } + ]), + vertexShader: ShaderChunk.meshphysical_vert, + fragmentShader: ShaderChunk.meshphysical_frag + }; + function WebGLBackground(renderer, cubemaps, state, objects, alpha, premultipliedAlpha) { + const clearColor = new Color2(0); + let clearAlpha = alpha === true ? 0 : 1; + let planeMesh; + let boxMesh; + let currentBackground = null; + let currentBackgroundVersion = 0; + let currentTonemapping = null; + function render(renderList, scene) { + let forceClear = false; + let background = scene.isScene === true ? scene.background : null; + if (background && background.isTexture) { + background = cubemaps.get(background); + } + const xr = renderer.xr; + const session = xr.getSession && xr.getSession(); + if (session && session.environmentBlendMode === "additive") { + background = null; + } + if (background === null) { + setClear(clearColor, clearAlpha); + } else if (background && background.isColor) { + setClear(background, 1); + forceClear = true; + } + if (renderer.autoClear || forceClear) { + renderer.clear(renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil); + } + if (background && (background.isCubeTexture || background.mapping === CubeUVReflectionMapping)) { + if (boxMesh === void 0) { + boxMesh = new Mesh(new BoxGeometry(1, 1, 1), new ShaderMaterial({ + name: "BackgroundCubeMaterial", + uniforms: cloneUniforms(ShaderLib.cube.uniforms), + vertexShader: ShaderLib.cube.vertexShader, + fragmentShader: ShaderLib.cube.fragmentShader, + side: BackSide, + depthTest: false, + depthWrite: false, + fog: false + })); + boxMesh.geometry.deleteAttribute("normal"); + boxMesh.geometry.deleteAttribute("uv"); + boxMesh.onBeforeRender = function(renderer2, scene2, camera) { + this.matrixWorld.copyPosition(camera.matrixWorld); + }; + Object.defineProperty(boxMesh.material, "envMap", { + get: function() { + return this.uniforms.envMap.value; + } + }); + objects.update(boxMesh); + } + boxMesh.material.uniforms.envMap.value = background; + boxMesh.material.uniforms.flipEnvMap.value = background.isCubeTexture && background.isRenderTargetTexture === false ? -1 : 1; + if (currentBackground !== background || currentBackgroundVersion !== background.version || currentTonemapping !== renderer.toneMapping) { + boxMesh.material.needsUpdate = true; + currentBackground = background; + currentBackgroundVersion = background.version; + currentTonemapping = renderer.toneMapping; + } + boxMesh.layers.enableAll(); + renderList.unshift(boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null); + } else if (background && background.isTexture) { + if (planeMesh === void 0) { + planeMesh = new Mesh(new PlaneGeometry(2, 2), new ShaderMaterial({ + name: "BackgroundMaterial", + uniforms: cloneUniforms(ShaderLib.background.uniforms), + vertexShader: ShaderLib.background.vertexShader, + fragmentShader: ShaderLib.background.fragmentShader, + side: FrontSide, + depthTest: false, + depthWrite: false, + fog: false + })); + planeMesh.geometry.deleteAttribute("normal"); + Object.defineProperty(planeMesh.material, "map", { + get: function() { + return this.uniforms.t2D.value; + } + }); + objects.update(planeMesh); + } + planeMesh.material.uniforms.t2D.value = background; + if (background.matrixAutoUpdate === true) { + background.updateMatrix(); + } + planeMesh.material.uniforms.uvTransform.value.copy(background.matrix); + if (currentBackground !== background || currentBackgroundVersion !== background.version || currentTonemapping !== renderer.toneMapping) { + planeMesh.material.needsUpdate = true; + currentBackground = background; + currentBackgroundVersion = background.version; + currentTonemapping = renderer.toneMapping; + } + planeMesh.layers.enableAll(); + renderList.unshift(planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null); + } + } + function setClear(color2, alpha2) { + state.buffers.color.setClear(color2.r, color2.g, color2.b, alpha2, premultipliedAlpha); + } + return { + getClearColor: function() { + return clearColor; + }, + setClearColor: function(color2, alpha2 = 1) { + clearColor.set(color2); + clearAlpha = alpha2; + setClear(clearColor, clearAlpha); + }, + getClearAlpha: function() { + return clearAlpha; + }, + setClearAlpha: function(alpha2) { + clearAlpha = alpha2; + setClear(clearColor, clearAlpha); + }, + render + }; + } + function WebGLBindingStates(gl, extensions, attributes, capabilities) { + const maxVertexAttributes = gl.getParameter(34921); + const extension = capabilities.isWebGL2 ? null : extensions.get("OES_vertex_array_object"); + const vaoAvailable = capabilities.isWebGL2 || extension !== null; + const bindingStates = {}; + const defaultState = createBindingState(null); + let currentState = defaultState; + let forceUpdate = false; + function setup(object, material, program, geometry, index2) { + let updateBuffers = false; + if (vaoAvailable) { + const state = getBindingState(geometry, program, material); + if (currentState !== state) { + currentState = state; + bindVertexArrayObject(currentState.object); + } + updateBuffers = needsUpdate(object, geometry, program, index2); + if (updateBuffers) + saveCache(object, geometry, program, index2); + } else { + const wireframe = material.wireframe === true; + if (currentState.geometry !== geometry.id || currentState.program !== program.id || currentState.wireframe !== wireframe) { + currentState.geometry = geometry.id; + currentState.program = program.id; + currentState.wireframe = wireframe; + updateBuffers = true; + } + } + if (index2 !== null) { + attributes.update(index2, 34963); + } + if (updateBuffers || forceUpdate) { + forceUpdate = false; + setupVertexAttributes(object, material, program, geometry); + if (index2 !== null) { + gl.bindBuffer(34963, attributes.get(index2).buffer); + } + } + } + function createVertexArrayObject() { + if (capabilities.isWebGL2) + return gl.createVertexArray(); + return extension.createVertexArrayOES(); + } + function bindVertexArrayObject(vao) { + if (capabilities.isWebGL2) + return gl.bindVertexArray(vao); + return extension.bindVertexArrayOES(vao); + } + function deleteVertexArrayObject(vao) { + if (capabilities.isWebGL2) + return gl.deleteVertexArray(vao); + return extension.deleteVertexArrayOES(vao); + } + function getBindingState(geometry, program, material) { + const wireframe = material.wireframe === true; + let programMap = bindingStates[geometry.id]; + if (programMap === void 0) { + programMap = {}; + bindingStates[geometry.id] = programMap; + } + let stateMap = programMap[program.id]; + if (stateMap === void 0) { + stateMap = {}; + programMap[program.id] = stateMap; + } + let state = stateMap[wireframe]; + if (state === void 0) { + state = createBindingState(createVertexArrayObject()); + stateMap[wireframe] = state; + } + return state; + } + function createBindingState(vao) { + const newAttributes = []; + const enabledAttributes = []; + const attributeDivisors = []; + for (let i = 0; i < maxVertexAttributes; i++) { + newAttributes[i] = 0; + enabledAttributes[i] = 0; + attributeDivisors[i] = 0; + } + return { + geometry: null, + program: null, + wireframe: false, + newAttributes, + enabledAttributes, + attributeDivisors, + object: vao, + attributes: {}, + index: null + }; + } + function needsUpdate(object, geometry, program, index2) { + const cachedAttributes = currentState.attributes; + const geometryAttributes = geometry.attributes; + let attributesNum = 0; + const programAttributes = program.getAttributes(); + for (const name in programAttributes) { + const programAttribute = programAttributes[name]; + if (programAttribute.location >= 0) { + const cachedAttribute = cachedAttributes[name]; + let geometryAttribute = geometryAttributes[name]; + if (geometryAttribute === void 0) { + if (name === "instanceMatrix" && object.instanceMatrix) + geometryAttribute = object.instanceMatrix; + if (name === "instanceColor" && object.instanceColor) + geometryAttribute = object.instanceColor; + } + if (cachedAttribute === void 0) + return true; + if (cachedAttribute.attribute !== geometryAttribute) + return true; + if (geometryAttribute && cachedAttribute.data !== geometryAttribute.data) + return true; + attributesNum++; + } + } + if (currentState.attributesNum !== attributesNum) + return true; + if (currentState.index !== index2) + return true; + return false; + } + function saveCache(object, geometry, program, index2) { + const cache2 = {}; + const attributes2 = geometry.attributes; + let attributesNum = 0; + const programAttributes = program.getAttributes(); + for (const name in programAttributes) { + const programAttribute = programAttributes[name]; + if (programAttribute.location >= 0) { + let attribute = attributes2[name]; + if (attribute === void 0) { + if (name === "instanceMatrix" && object.instanceMatrix) + attribute = object.instanceMatrix; + if (name === "instanceColor" && object.instanceColor) + attribute = object.instanceColor; + } + const data = {}; + data.attribute = attribute; + if (attribute && attribute.data) { + data.data = attribute.data; + } + cache2[name] = data; + attributesNum++; + } + } + currentState.attributes = cache2; + currentState.attributesNum = attributesNum; + currentState.index = index2; + } + function initAttributes() { + const newAttributes = currentState.newAttributes; + for (let i = 0, il = newAttributes.length; i < il; i++) { + newAttributes[i] = 0; + } + } + function enableAttribute(attribute) { + enableAttributeAndDivisor(attribute, 0); + } + function enableAttributeAndDivisor(attribute, meshPerAttribute) { + const newAttributes = currentState.newAttributes; + const enabledAttributes = currentState.enabledAttributes; + const attributeDivisors = currentState.attributeDivisors; + newAttributes[attribute] = 1; + if (enabledAttributes[attribute] === 0) { + gl.enableVertexAttribArray(attribute); + enabledAttributes[attribute] = 1; + } + if (attributeDivisors[attribute] !== meshPerAttribute) { + const extension2 = capabilities.isWebGL2 ? gl : extensions.get("ANGLE_instanced_arrays"); + extension2[capabilities.isWebGL2 ? "vertexAttribDivisor" : "vertexAttribDivisorANGLE"](attribute, meshPerAttribute); + attributeDivisors[attribute] = meshPerAttribute; + } + } + function disableUnusedAttributes() { + const newAttributes = currentState.newAttributes; + const enabledAttributes = currentState.enabledAttributes; + for (let i = 0, il = enabledAttributes.length; i < il; i++) { + if (enabledAttributes[i] !== newAttributes[i]) { + gl.disableVertexAttribArray(i); + enabledAttributes[i] = 0; + } + } + } + function vertexAttribPointer(index2, size, type2, normalized, stride, offset) { + if (capabilities.isWebGL2 === true && (type2 === 5124 || type2 === 5125)) { + gl.vertexAttribIPointer(index2, size, type2, stride, offset); + } else { + gl.vertexAttribPointer(index2, size, type2, normalized, stride, offset); + } + } + function setupVertexAttributes(object, material, program, geometry) { + if (capabilities.isWebGL2 === false && (object.isInstancedMesh || geometry.isInstancedBufferGeometry)) { + if (extensions.get("ANGLE_instanced_arrays") === null) + return; + } + initAttributes(); + const geometryAttributes = geometry.attributes; + const programAttributes = program.getAttributes(); + const materialDefaultAttributeValues = material.defaultAttributeValues; + for (const name in programAttributes) { + const programAttribute = programAttributes[name]; + if (programAttribute.location >= 0) { + let geometryAttribute = geometryAttributes[name]; + if (geometryAttribute === void 0) { + if (name === "instanceMatrix" && object.instanceMatrix) + geometryAttribute = object.instanceMatrix; + if (name === "instanceColor" && object.instanceColor) + geometryAttribute = object.instanceColor; + } + if (geometryAttribute !== void 0) { + const normalized = geometryAttribute.normalized; + const size = geometryAttribute.itemSize; + const attribute = attributes.get(geometryAttribute); + if (attribute === void 0) + continue; + const buffer = attribute.buffer; + const type2 = attribute.type; + const bytesPerElement = attribute.bytesPerElement; + if (geometryAttribute.isInterleavedBufferAttribute) { + const data = geometryAttribute.data; + const stride = data.stride; + const offset = geometryAttribute.offset; + if (data.isInstancedInterleavedBuffer) { + for (let i = 0; i < programAttribute.locationSize; i++) { + enableAttributeAndDivisor(programAttribute.location + i, data.meshPerAttribute); + } + if (object.isInstancedMesh !== true && geometry._maxInstanceCount === void 0) { + geometry._maxInstanceCount = data.meshPerAttribute * data.count; + } + } else { + for (let i = 0; i < programAttribute.locationSize; i++) { + enableAttribute(programAttribute.location + i); + } + } + gl.bindBuffer(34962, buffer); + for (let i = 0; i < programAttribute.locationSize; i++) { + vertexAttribPointer(programAttribute.location + i, size / programAttribute.locationSize, type2, normalized, stride * bytesPerElement, (offset + size / programAttribute.locationSize * i) * bytesPerElement); + } + } else { + if (geometryAttribute.isInstancedBufferAttribute) { + for (let i = 0; i < programAttribute.locationSize; i++) { + enableAttributeAndDivisor(programAttribute.location + i, geometryAttribute.meshPerAttribute); + } + if (object.isInstancedMesh !== true && geometry._maxInstanceCount === void 0) { + geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; + } + } else { + for (let i = 0; i < programAttribute.locationSize; i++) { + enableAttribute(programAttribute.location + i); + } + } + gl.bindBuffer(34962, buffer); + for (let i = 0; i < programAttribute.locationSize; i++) { + vertexAttribPointer(programAttribute.location + i, size / programAttribute.locationSize, type2, normalized, size * bytesPerElement, size / programAttribute.locationSize * i * bytesPerElement); + } + } + } else if (materialDefaultAttributeValues !== void 0) { + const value = materialDefaultAttributeValues[name]; + if (value !== void 0) { + switch (value.length) { + case 2: + gl.vertexAttrib2fv(programAttribute.location, value); + break; + case 3: + gl.vertexAttrib3fv(programAttribute.location, value); + break; + case 4: + gl.vertexAttrib4fv(programAttribute.location, value); + break; + default: + gl.vertexAttrib1fv(programAttribute.location, value); + } + } + } + } + } + disableUnusedAttributes(); + } + function dispose() { + reset(); + for (const geometryId in bindingStates) { + const programMap = bindingStates[geometryId]; + for (const programId in programMap) { + const stateMap = programMap[programId]; + for (const wireframe in stateMap) { + deleteVertexArrayObject(stateMap[wireframe].object); + delete stateMap[wireframe]; + } + delete programMap[programId]; + } + delete bindingStates[geometryId]; + } + } + function releaseStatesOfGeometry(geometry) { + if (bindingStates[geometry.id] === void 0) + return; + const programMap = bindingStates[geometry.id]; + for (const programId in programMap) { + const stateMap = programMap[programId]; + for (const wireframe in stateMap) { + deleteVertexArrayObject(stateMap[wireframe].object); + delete stateMap[wireframe]; + } + delete programMap[programId]; + } + delete bindingStates[geometry.id]; + } + function releaseStatesOfProgram(program) { + for (const geometryId in bindingStates) { + const programMap = bindingStates[geometryId]; + if (programMap[program.id] === void 0) + continue; + const stateMap = programMap[program.id]; + for (const wireframe in stateMap) { + deleteVertexArrayObject(stateMap[wireframe].object); + delete stateMap[wireframe]; + } + delete programMap[program.id]; + } + } + function reset() { + resetDefaultState(); + forceUpdate = true; + if (currentState === defaultState) + return; + currentState = defaultState; + bindVertexArrayObject(currentState.object); + } + function resetDefaultState() { + defaultState.geometry = null; + defaultState.program = null; + defaultState.wireframe = false; + } + return { + setup, + reset, + resetDefaultState, + dispose, + releaseStatesOfGeometry, + releaseStatesOfProgram, + initAttributes, + enableAttribute, + disableUnusedAttributes + }; + } + function WebGLBufferRenderer(gl, extensions, info, capabilities) { + const isWebGL2 = capabilities.isWebGL2; + let mode; + function setMode(value) { + mode = value; + } + function render(start2, count) { + gl.drawArrays(mode, start2, count); + info.update(count, mode, 1); + } + function renderInstances(start2, count, primcount) { + if (primcount === 0) + return; + let extension, methodName; + if (isWebGL2) { + extension = gl; + methodName = "drawArraysInstanced"; + } else { + extension = extensions.get("ANGLE_instanced_arrays"); + methodName = "drawArraysInstancedANGLE"; + if (extension === null) { + console.error("THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays."); + return; + } + } + extension[methodName](mode, start2, count, primcount); + info.update(count, mode, primcount); + } + this.setMode = setMode; + this.render = render; + this.renderInstances = renderInstances; + } + function WebGLCapabilities(gl, extensions, parameters) { + let maxAnisotropy; + function getMaxAnisotropy() { + if (maxAnisotropy !== void 0) + return maxAnisotropy; + if (extensions.has("EXT_texture_filter_anisotropic") === true) { + const extension = extensions.get("EXT_texture_filter_anisotropic"); + maxAnisotropy = gl.getParameter(extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT); + } else { + maxAnisotropy = 0; + } + return maxAnisotropy; + } + function getMaxPrecision(precision2) { + if (precision2 === "highp") { + if (gl.getShaderPrecisionFormat(35633, 36338).precision > 0 && gl.getShaderPrecisionFormat(35632, 36338).precision > 0) { + return "highp"; + } + precision2 = "mediump"; + } + if (precision2 === "mediump") { + if (gl.getShaderPrecisionFormat(35633, 36337).precision > 0 && gl.getShaderPrecisionFormat(35632, 36337).precision > 0) { + return "mediump"; + } + } + return "lowp"; + } + const isWebGL2 = typeof WebGL2RenderingContext !== "undefined" && gl instanceof WebGL2RenderingContext || typeof WebGL2ComputeRenderingContext !== "undefined" && gl instanceof WebGL2ComputeRenderingContext; + let precision = parameters.precision !== void 0 ? parameters.precision : "highp"; + const maxPrecision = getMaxPrecision(precision); + if (maxPrecision !== precision) { + console.warn("THREE.WebGLRenderer:", precision, "not supported, using", maxPrecision, "instead."); + precision = maxPrecision; + } + const drawBuffers = isWebGL2 || extensions.has("WEBGL_draw_buffers"); + const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; + const maxTextures = gl.getParameter(34930); + const maxVertexTextures = gl.getParameter(35660); + const maxTextureSize = gl.getParameter(3379); + const maxCubemapSize = gl.getParameter(34076); + const maxAttributes = gl.getParameter(34921); + const maxVertexUniforms = gl.getParameter(36347); + const maxVaryings = gl.getParameter(36348); + const maxFragmentUniforms = gl.getParameter(36349); + const vertexTextures = maxVertexTextures > 0; + const floatFragmentTextures = isWebGL2 || extensions.has("OES_texture_float"); + const floatVertexTextures = vertexTextures && floatFragmentTextures; + const maxSamples = isWebGL2 ? gl.getParameter(36183) : 0; + return { + isWebGL2, + drawBuffers, + getMaxAnisotropy, + getMaxPrecision, + precision, + logarithmicDepthBuffer, + maxTextures, + maxVertexTextures, + maxTextureSize, + maxCubemapSize, + maxAttributes, + maxVertexUniforms, + maxVaryings, + maxFragmentUniforms, + vertexTextures, + floatFragmentTextures, + floatVertexTextures, + maxSamples + }; + } + function WebGLClipping(properties) { + const scope = this; + let globalState = null, numGlobalPlanes = 0, localClippingEnabled = false, renderingShadows = false; + const plane = new Plane(), viewNormalMatrix = new Matrix3(), uniform = { value: null, needsUpdate: false }; + this.uniform = uniform; + this.numPlanes = 0; + this.numIntersection = 0; + this.init = function(planes, enableLocalClipping, camera) { + const enabled = planes.length !== 0 || enableLocalClipping || numGlobalPlanes !== 0 || localClippingEnabled; + localClippingEnabled = enableLocalClipping; + globalState = projectPlanes(planes, camera, 0); + numGlobalPlanes = planes.length; + return enabled; + }; + this.beginShadows = function() { + renderingShadows = true; + projectPlanes(null); + }; + this.endShadows = function() { + renderingShadows = false; + resetGlobalState(); + }; + this.setState = function(material, camera, useCache) { + const planes = material.clippingPlanes, clipIntersection = material.clipIntersection, clipShadows = material.clipShadows; + const materialProperties = properties.get(material); + if (!localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && !clipShadows) { + if (renderingShadows) { + projectPlanes(null); + } else { + resetGlobalState(); + } + } else { + const nGlobal = renderingShadows ? 0 : numGlobalPlanes, lGlobal = nGlobal * 4; + let dstArray = materialProperties.clippingState || null; + uniform.value = dstArray; + dstArray = projectPlanes(planes, camera, lGlobal, useCache); + for (let i = 0; i !== lGlobal; ++i) { + dstArray[i] = globalState[i]; + } + materialProperties.clippingState = dstArray; + this.numIntersection = clipIntersection ? this.numPlanes : 0; + this.numPlanes += nGlobal; + } + }; + function resetGlobalState() { + if (uniform.value !== globalState) { + uniform.value = globalState; + uniform.needsUpdate = numGlobalPlanes > 0; + } + scope.numPlanes = numGlobalPlanes; + scope.numIntersection = 0; + } + function projectPlanes(planes, camera, dstOffset, skipTransform) { + const nPlanes = planes !== null ? planes.length : 0; + let dstArray = null; + if (nPlanes !== 0) { + dstArray = uniform.value; + if (skipTransform !== true || dstArray === null) { + const flatSize = dstOffset + nPlanes * 4, viewMatrix = camera.matrixWorldInverse; + viewNormalMatrix.getNormalMatrix(viewMatrix); + if (dstArray === null || dstArray.length < flatSize) { + dstArray = new Float32Array(flatSize); + } + for (let i = 0, i4 = dstOffset; i !== nPlanes; ++i, i4 += 4) { + plane.copy(planes[i]).applyMatrix4(viewMatrix, viewNormalMatrix); + plane.normal.toArray(dstArray, i4); + dstArray[i4 + 3] = plane.constant; + } + } + uniform.value = dstArray; + uniform.needsUpdate = true; + } + scope.numPlanes = nPlanes; + scope.numIntersection = 0; + return dstArray; + } + } + function WebGLCubeMaps(renderer) { + let cubemaps = /* @__PURE__ */ new WeakMap(); + function mapTextureMapping(texture, mapping) { + if (mapping === EquirectangularReflectionMapping) { + texture.mapping = CubeReflectionMapping; + } else if (mapping === EquirectangularRefractionMapping) { + texture.mapping = CubeRefractionMapping; + } + return texture; + } + function get3(texture) { + if (texture && texture.isTexture && texture.isRenderTargetTexture === false) { + const mapping = texture.mapping; + if (mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping) { + if (cubemaps.has(texture)) { + const cubemap = cubemaps.get(texture).texture; + return mapTextureMapping(cubemap, texture.mapping); + } else { + const image = texture.image; + if (image && image.height > 0) { + const renderTarget = new WebGLCubeRenderTarget(image.height / 2); + renderTarget.fromEquirectangularTexture(renderer, texture); + cubemaps.set(texture, renderTarget); + texture.addEventListener("dispose", onTextureDispose); + return mapTextureMapping(renderTarget.texture, texture.mapping); + } else { + return null; + } + } + } + } + return texture; + } + function onTextureDispose(event) { + const texture = event.target; + texture.removeEventListener("dispose", onTextureDispose); + const cubemap = cubemaps.get(texture); + if (cubemap !== void 0) { + cubemaps.delete(texture); + cubemap.dispose(); + } + } + function dispose() { + cubemaps = /* @__PURE__ */ new WeakMap(); + } + return { + get: get3, + dispose + }; + } + var OrthographicCamera = class extends Camera { + constructor(left = -1, right = 1, top = 1, bottom = -1, near = 0.1, far = 2e3) { + super(); + this.isOrthographicCamera = true; + this.type = "OrthographicCamera"; + this.zoom = 1; + this.view = null; + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; + this.near = near; + this.far = far; + this.updateProjectionMatrix(); + } + copy(source, recursive) { + super.copy(source, recursive); + this.left = source.left; + this.right = source.right; + this.top = source.top; + this.bottom = source.bottom; + this.near = source.near; + this.far = source.far; + this.zoom = source.zoom; + this.view = source.view === null ? null : Object.assign({}, source.view); + return this; + } + setViewOffset(fullWidth, fullHeight, x2, y2, width, height) { + if (this.view === null) { + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; + } + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x2; + this.view.offsetY = y2; + this.view.width = width; + this.view.height = height; + this.updateProjectionMatrix(); + } + clearViewOffset() { + if (this.view !== null) { + this.view.enabled = false; + } + this.updateProjectionMatrix(); + } + updateProjectionMatrix() { + const dx = (this.right - this.left) / (2 * this.zoom); + const dy = (this.top - this.bottom) / (2 * this.zoom); + const cx = (this.right + this.left) / 2; + const cy = (this.top + this.bottom) / 2; + let left = cx - dx; + let right = cx + dx; + let top = cy + dy; + let bottom = cy - dy; + if (this.view !== null && this.view.enabled) { + const scaleW = (this.right - this.left) / this.view.fullWidth / this.zoom; + const scaleH = (this.top - this.bottom) / this.view.fullHeight / this.zoom; + left += scaleW * this.view.offsetX; + right = left + scaleW * this.view.width; + top -= scaleH * this.view.offsetY; + bottom = top - scaleH * this.view.height; + } + this.projectionMatrix.makeOrthographic(left, right, top, bottom, this.near, this.far); + this.projectionMatrixInverse.copy(this.projectionMatrix).invert(); + } + toJSON(meta) { + const data = super.toJSON(meta); + data.object.zoom = this.zoom; + data.object.left = this.left; + data.object.right = this.right; + data.object.top = this.top; + data.object.bottom = this.bottom; + data.object.near = this.near; + data.object.far = this.far; + if (this.view !== null) + data.object.view = Object.assign({}, this.view); + return data; + } + }; + var LOD_MIN = 4; + var EXTRA_LOD_SIGMA = [0.125, 0.215, 0.35, 0.446, 0.526, 0.582]; + var MAX_SAMPLES = 20; + var _flatCamera = /* @__PURE__ */ new OrthographicCamera(); + var _clearColor = /* @__PURE__ */ new Color2(); + var _oldTarget = null; + var PHI = (1 + Math.sqrt(5)) / 2; + var INV_PHI = 1 / PHI; + var _axisDirections = [ + /* @__PURE__ */ new Vector3(1, 1, 1), + /* @__PURE__ */ new Vector3(-1, 1, 1), + /* @__PURE__ */ new Vector3(1, 1, -1), + /* @__PURE__ */ new Vector3(-1, 1, -1), + /* @__PURE__ */ new Vector3(0, PHI, INV_PHI), + /* @__PURE__ */ new Vector3(0, PHI, -INV_PHI), + /* @__PURE__ */ new Vector3(INV_PHI, 0, PHI), + /* @__PURE__ */ new Vector3(-INV_PHI, 0, PHI), + /* @__PURE__ */ new Vector3(PHI, INV_PHI, 0), + /* @__PURE__ */ new Vector3(-PHI, INV_PHI, 0) + ]; + var PMREMGenerator = class { + constructor(renderer) { + this._renderer = renderer; + this._pingPongRenderTarget = null; + this._lodMax = 0; + this._cubeSize = 0; + this._lodPlanes = []; + this._sizeLods = []; + this._sigmas = []; + this._blurMaterial = null; + this._cubemapMaterial = null; + this._equirectMaterial = null; + this._compileMaterial(this._blurMaterial); + } + fromScene(scene, sigma = 0, near = 0.1, far = 100) { + _oldTarget = this._renderer.getRenderTarget(); + this._setSize(256); + const cubeUVRenderTarget = this._allocateTargets(); + cubeUVRenderTarget.depthBuffer = true; + this._sceneToCubeUV(scene, near, far, cubeUVRenderTarget); + if (sigma > 0) { + this._blur(cubeUVRenderTarget, 0, 0, sigma); + } + this._applyPMREM(cubeUVRenderTarget); + this._cleanup(cubeUVRenderTarget); + return cubeUVRenderTarget; + } + fromEquirectangular(equirectangular, renderTarget = null) { + return this._fromTexture(equirectangular, renderTarget); + } + fromCubemap(cubemap, renderTarget = null) { + return this._fromTexture(cubemap, renderTarget); + } + compileCubemapShader() { + if (this._cubemapMaterial === null) { + this._cubemapMaterial = _getCubemapMaterial(); + this._compileMaterial(this._cubemapMaterial); + } + } + compileEquirectangularShader() { + if (this._equirectMaterial === null) { + this._equirectMaterial = _getEquirectMaterial(); + this._compileMaterial(this._equirectMaterial); + } + } + dispose() { + this._dispose(); + if (this._cubemapMaterial !== null) + this._cubemapMaterial.dispose(); + if (this._equirectMaterial !== null) + this._equirectMaterial.dispose(); + } + _setSize(cubeSize) { + this._lodMax = Math.floor(Math.log2(cubeSize)); + this._cubeSize = Math.pow(2, this._lodMax); + } + _dispose() { + if (this._blurMaterial !== null) + this._blurMaterial.dispose(); + if (this._pingPongRenderTarget !== null) + this._pingPongRenderTarget.dispose(); + for (let i = 0; i < this._lodPlanes.length; i++) { + this._lodPlanes[i].dispose(); + } + } + _cleanup(outputTarget) { + this._renderer.setRenderTarget(_oldTarget); + outputTarget.scissorTest = false; + _setViewport(outputTarget, 0, 0, outputTarget.width, outputTarget.height); + } + _fromTexture(texture, renderTarget) { + if (texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping) { + this._setSize(texture.image.length === 0 ? 16 : texture.image[0].width || texture.image[0].image.width); + } else { + this._setSize(texture.image.width / 4); + } + _oldTarget = this._renderer.getRenderTarget(); + const cubeUVRenderTarget = renderTarget || this._allocateTargets(); + this._textureToCubeUV(texture, cubeUVRenderTarget); + this._applyPMREM(cubeUVRenderTarget); + this._cleanup(cubeUVRenderTarget); + return cubeUVRenderTarget; + } + _allocateTargets() { + const width = 3 * Math.max(this._cubeSize, 16 * 7); + const height = 4 * this._cubeSize; + const params = { + magFilter: LinearFilter, + minFilter: LinearFilter, + generateMipmaps: false, + type: HalfFloatType, + format: RGBAFormat, + encoding: LinearEncoding, + depthBuffer: false + }; + const cubeUVRenderTarget = _createRenderTarget(width, height, params); + if (this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width) { + if (this._pingPongRenderTarget !== null) { + this._dispose(); + } + this._pingPongRenderTarget = _createRenderTarget(width, height, params); + const { _lodMax } = this; + ({ sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes(_lodMax)); + this._blurMaterial = _getBlurShader(_lodMax, width, height); + } + return cubeUVRenderTarget; + } + _compileMaterial(material) { + const tmpMesh = new Mesh(this._lodPlanes[0], material); + this._renderer.compile(tmpMesh, _flatCamera); + } + _sceneToCubeUV(scene, near, far, cubeUVRenderTarget) { + const fov2 = 90; + const aspect2 = 1; + const cubeCamera = new PerspectiveCamera(fov2, aspect2, near, far); + const upSign = [1, -1, 1, 1, 1, 1]; + const forwardSign = [1, 1, 1, -1, -1, -1]; + const renderer = this._renderer; + const originalAutoClear = renderer.autoClear; + const toneMapping = renderer.toneMapping; + renderer.getClearColor(_clearColor); + renderer.toneMapping = NoToneMapping; + renderer.autoClear = false; + const backgroundMaterial = new MeshBasicMaterial({ + name: "PMREM.Background", + side: BackSide, + depthWrite: false, + depthTest: false + }); + const backgroundBox = new Mesh(new BoxGeometry(), backgroundMaterial); + let useSolidColor = false; + const background = scene.background; + if (background) { + if (background.isColor) { + backgroundMaterial.color.copy(background); + scene.background = null; + useSolidColor = true; + } + } else { + backgroundMaterial.color.copy(_clearColor); + useSolidColor = true; + } + for (let i = 0; i < 6; i++) { + const col = i % 3; + if (col === 0) { + cubeCamera.up.set(0, upSign[i], 0); + cubeCamera.lookAt(forwardSign[i], 0, 0); + } else if (col === 1) { + cubeCamera.up.set(0, 0, upSign[i]); + cubeCamera.lookAt(0, forwardSign[i], 0); + } else { + cubeCamera.up.set(0, upSign[i], 0); + cubeCamera.lookAt(0, 0, forwardSign[i]); + } + const size = this._cubeSize; + _setViewport(cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size); + renderer.setRenderTarget(cubeUVRenderTarget); + if (useSolidColor) { + renderer.render(backgroundBox, cubeCamera); + } + renderer.render(scene, cubeCamera); + } + backgroundBox.geometry.dispose(); + backgroundBox.material.dispose(); + renderer.toneMapping = toneMapping; + renderer.autoClear = originalAutoClear; + scene.background = background; + } + _textureToCubeUV(texture, cubeUVRenderTarget) { + const renderer = this._renderer; + const isCubeTexture = texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping; + if (isCubeTexture) { + if (this._cubemapMaterial === null) { + this._cubemapMaterial = _getCubemapMaterial(); + } + this._cubemapMaterial.uniforms.flipEnvMap.value = texture.isRenderTargetTexture === false ? -1 : 1; + } else { + if (this._equirectMaterial === null) { + this._equirectMaterial = _getEquirectMaterial(); + } + } + const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; + const mesh = new Mesh(this._lodPlanes[0], material); + const uniforms = material.uniforms; + uniforms["envMap"].value = texture; + const size = this._cubeSize; + _setViewport(cubeUVRenderTarget, 0, 0, 3 * size, 2 * size); + renderer.setRenderTarget(cubeUVRenderTarget); + renderer.render(mesh, _flatCamera); + } + _applyPMREM(cubeUVRenderTarget) { + const renderer = this._renderer; + const autoClear = renderer.autoClear; + renderer.autoClear = false; + for (let i = 1; i < this._lodPlanes.length; i++) { + const sigma = Math.sqrt(this._sigmas[i] * this._sigmas[i] - this._sigmas[i - 1] * this._sigmas[i - 1]); + const poleAxis = _axisDirections[(i - 1) % _axisDirections.length]; + this._blur(cubeUVRenderTarget, i - 1, i, sigma, poleAxis); + } + renderer.autoClear = autoClear; + } + _blur(cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis) { + const pingPongRenderTarget = this._pingPongRenderTarget; + this._halfBlur(cubeUVRenderTarget, pingPongRenderTarget, lodIn, lodOut, sigma, "latitudinal", poleAxis); + this._halfBlur(pingPongRenderTarget, cubeUVRenderTarget, lodOut, lodOut, sigma, "longitudinal", poleAxis); + } + _halfBlur(targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis) { + const renderer = this._renderer; + const blurMaterial = this._blurMaterial; + if (direction !== "latitudinal" && direction !== "longitudinal") { + console.error("blur direction must be either latitudinal or longitudinal!"); + } + const STANDARD_DEVIATIONS = 3; + const blurMesh = new Mesh(this._lodPlanes[lodOut], blurMaterial); + const blurUniforms = blurMaterial.uniforms; + const pixels = this._sizeLods[lodIn] - 1; + const radiansPerPixel = isFinite(sigmaRadians) ? Math.PI / (2 * pixels) : 2 * Math.PI / (2 * MAX_SAMPLES - 1); + const sigmaPixels = sigmaRadians / radiansPerPixel; + const samples = isFinite(sigmaRadians) ? 1 + Math.floor(STANDARD_DEVIATIONS * sigmaPixels) : MAX_SAMPLES; + if (samples > MAX_SAMPLES) { + console.warn(`sigmaRadians, ${sigmaRadians}, is too large and will clip, as it requested ${samples} samples when the maximum is set to ${MAX_SAMPLES}`); + } + const weights = []; + let sum = 0; + for (let i = 0; i < MAX_SAMPLES; ++i) { + const x3 = i / sigmaPixels; + const weight = Math.exp(-x3 * x3 / 2); + weights.push(weight); + if (i === 0) { + sum += weight; + } else if (i < samples) { + sum += 2 * weight; + } + } + for (let i = 0; i < weights.length; i++) { + weights[i] = weights[i] / sum; + } + blurUniforms["envMap"].value = targetIn.texture; + blurUniforms["samples"].value = samples; + blurUniforms["weights"].value = weights; + blurUniforms["latitudinal"].value = direction === "latitudinal"; + if (poleAxis) { + blurUniforms["poleAxis"].value = poleAxis; + } + const { _lodMax } = this; + blurUniforms["dTheta"].value = radiansPerPixel; + blurUniforms["mipInt"].value = _lodMax - lodIn; + const outputSize = this._sizeLods[lodOut]; + const x2 = 3 * outputSize * (lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0); + const y2 = 4 * (this._cubeSize - outputSize); + _setViewport(targetOut, x2, y2, 3 * outputSize, 2 * outputSize); + renderer.setRenderTarget(targetOut); + renderer.render(blurMesh, _flatCamera); + } + }; + function _createPlanes(lodMax) { + const lodPlanes = []; + const sizeLods = []; + const sigmas = []; + let lod = lodMax; + const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; + for (let i = 0; i < totalLods; i++) { + const sizeLod = Math.pow(2, lod); + sizeLods.push(sizeLod); + let sigma = 1 / sizeLod; + if (i > lodMax - LOD_MIN) { + sigma = EXTRA_LOD_SIGMA[i - lodMax + LOD_MIN - 1]; + } else if (i === 0) { + sigma = 0; + } + sigmas.push(sigma); + const texelSize = 1 / (sizeLod - 2); + const min2 = -texelSize; + const max2 = 1 + texelSize; + const uv1 = [min2, min2, max2, min2, max2, max2, min2, min2, max2, max2, min2, max2]; + const cubeFaces = 6; + const vertices = 6; + const positionSize = 3; + const uvSize = 2; + const faceIndexSize = 1; + const position = new Float32Array(positionSize * vertices * cubeFaces); + const uv = new Float32Array(uvSize * vertices * cubeFaces); + const faceIndex = new Float32Array(faceIndexSize * vertices * cubeFaces); + for (let face = 0; face < cubeFaces; face++) { + const x2 = face % 3 * 2 / 3 - 1; + const y2 = face > 2 ? 0 : -1; + const coordinates = [ + x2, + y2, + 0, + x2 + 2 / 3, + y2, + 0, + x2 + 2 / 3, + y2 + 1, + 0, + x2, + y2, + 0, + x2 + 2 / 3, + y2 + 1, + 0, + x2, + y2 + 1, + 0 + ]; + position.set(coordinates, positionSize * vertices * face); + uv.set(uv1, uvSize * vertices * face); + const fill = [face, face, face, face, face, face]; + faceIndex.set(fill, faceIndexSize * vertices * face); + } + const planes = new BufferGeometry(); + planes.setAttribute("position", new BufferAttribute(position, positionSize)); + planes.setAttribute("uv", new BufferAttribute(uv, uvSize)); + planes.setAttribute("faceIndex", new BufferAttribute(faceIndex, faceIndexSize)); + lodPlanes.push(planes); + if (lod > LOD_MIN) { + lod--; + } + } + return { lodPlanes, sizeLods, sigmas }; + } + function _createRenderTarget(width, height, params) { + const cubeUVRenderTarget = new WebGLRenderTarget(width, height, params); + cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; + cubeUVRenderTarget.texture.name = "PMREM.cubeUv"; + cubeUVRenderTarget.scissorTest = true; + return cubeUVRenderTarget; + } + function _setViewport(target, x2, y2, width, height) { + target.viewport.set(x2, y2, width, height); + target.scissor.set(x2, y2, width, height); + } + function _getBlurShader(lodMax, width, height) { + const weights = new Float32Array(MAX_SAMPLES); + const poleAxis = new Vector3(0, 1, 0); + const shaderMaterial = new ShaderMaterial({ + name: "SphericalGaussianBlur", + defines: { + "n": MAX_SAMPLES, + "CUBEUV_TEXEL_WIDTH": 1 / width, + "CUBEUV_TEXEL_HEIGHT": 1 / height, + "CUBEUV_MAX_MIP": `${lodMax}.0` + }, + uniforms: { + "envMap": { value: null }, + "samples": { value: 1 }, + "weights": { value: weights }, + "latitudinal": { value: false }, + "dTheta": { value: 0 }, + "mipInt": { value: 0 }, + "poleAxis": { value: poleAxis } + }, + vertexShader: _getCommonVertexShader(), + fragmentShader: ` + + precision mediump float; + precision mediump int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + uniform int samples; + uniform float weights[ n ]; + uniform bool latitudinal; + uniform float dTheta; + uniform float mipInt; + uniform vec3 poleAxis; + + #define ENVMAP_TYPE_CUBE_UV + #include + + vec3 getSample( float theta, vec3 axis ) { + + float cosTheta = cos( theta ); + // Rodrigues' axis-angle rotation + vec3 sampleDirection = vOutputDirection * cosTheta + + cross( axis, vOutputDirection ) * sin( theta ) + + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta ); + + return bilinearCubeUV( envMap, sampleDirection, mipInt ); + + } + + void main() { + + vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); + + if ( all( equal( axis, vec3( 0.0 ) ) ) ) { + + axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); + + } + + axis = normalize( axis ); + + gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); + + for ( int i = 1; i < n; i++ ) { + + if ( i >= samples ) { + + break; + + } + + float theta = dTheta * float( i ); + gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); + gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); + + } + + } + `, + blending: NoBlending, + depthTest: false, + depthWrite: false + }); + return shaderMaterial; + } + function _getEquirectMaterial() { + return new ShaderMaterial({ + name: "EquirectangularToCubeUV", + uniforms: { + "envMap": { value: null } + }, + vertexShader: _getCommonVertexShader(), + fragmentShader: ` + + precision mediump float; + precision mediump int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + + #include + + void main() { + + vec3 outputDirection = normalize( vOutputDirection ); + vec2 uv = equirectUv( outputDirection ); + + gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); + + } + `, + blending: NoBlending, + depthTest: false, + depthWrite: false + }); + } + function _getCubemapMaterial() { + return new ShaderMaterial({ + name: "CubemapToCubeUV", + uniforms: { + "envMap": { value: null }, + "flipEnvMap": { value: -1 } + }, + vertexShader: _getCommonVertexShader(), + fragmentShader: ` + + precision mediump float; + precision mediump int; + + uniform float flipEnvMap; + + varying vec3 vOutputDirection; + + uniform samplerCube envMap; + + void main() { + + gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); + + } + `, + blending: NoBlending, + depthTest: false, + depthWrite: false + }); + } + function _getCommonVertexShader() { + return ` + + precision mediump float; + precision mediump int; + + attribute float faceIndex; + + varying vec3 vOutputDirection; + + // RH coordinate system; PMREM face-indexing convention + vec3 getDirection( vec2 uv, float face ) { + + uv = 2.0 * uv - 1.0; + + vec3 direction = vec3( uv, 1.0 ); + + if ( face == 0.0 ) { + + direction = direction.zyx; // ( 1, v, u ) pos x + + } else if ( face == 1.0 ) { + + direction = direction.xzy; + direction.xz *= -1.0; // ( -u, 1, -v ) pos y + + } else if ( face == 2.0 ) { + + direction.x *= -1.0; // ( -u, v, 1 ) pos z + + } else if ( face == 3.0 ) { + + direction = direction.zyx; + direction.xz *= -1.0; // ( -1, v, -u ) neg x + + } else if ( face == 4.0 ) { + + direction = direction.xzy; + direction.xy *= -1.0; // ( -u, -1, v ) neg y + + } else if ( face == 5.0 ) { + + direction.z *= -1.0; // ( u, v, -1 ) neg z + + } + + return direction; + + } + + void main() { + + vOutputDirection = getDirection( uv, faceIndex ); + gl_Position = vec4( position, 1.0 ); + + } + `; + } + function WebGLCubeUVMaps(renderer) { + let cubeUVmaps = /* @__PURE__ */ new WeakMap(); + let pmremGenerator = null; + function get3(texture) { + if (texture && texture.isTexture) { + const mapping = texture.mapping; + const isEquirectMap = mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping; + const isCubeMap = mapping === CubeReflectionMapping || mapping === CubeRefractionMapping; + if (isEquirectMap || isCubeMap) { + if (texture.isRenderTargetTexture && texture.needsPMREMUpdate === true) { + texture.needsPMREMUpdate = false; + let renderTarget = cubeUVmaps.get(texture); + if (pmremGenerator === null) + pmremGenerator = new PMREMGenerator(renderer); + renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture, renderTarget) : pmremGenerator.fromCubemap(texture, renderTarget); + cubeUVmaps.set(texture, renderTarget); + return renderTarget.texture; + } else { + if (cubeUVmaps.has(texture)) { + return cubeUVmaps.get(texture).texture; + } else { + const image = texture.image; + if (isEquirectMap && image && image.height > 0 || isCubeMap && image && isCubeTextureComplete(image)) { + if (pmremGenerator === null) + pmremGenerator = new PMREMGenerator(renderer); + const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture) : pmremGenerator.fromCubemap(texture); + cubeUVmaps.set(texture, renderTarget); + texture.addEventListener("dispose", onTextureDispose); + return renderTarget.texture; + } else { + return null; + } + } + } + } + } + return texture; + } + function isCubeTextureComplete(image) { + let count = 0; + const length = 6; + for (let i = 0; i < length; i++) { + if (image[i] !== void 0) + count++; + } + return count === length; + } + function onTextureDispose(event) { + const texture = event.target; + texture.removeEventListener("dispose", onTextureDispose); + const cubemapUV = cubeUVmaps.get(texture); + if (cubemapUV !== void 0) { + cubeUVmaps.delete(texture); + cubemapUV.dispose(); + } + } + function dispose() { + cubeUVmaps = /* @__PURE__ */ new WeakMap(); + if (pmremGenerator !== null) { + pmremGenerator.dispose(); + pmremGenerator = null; + } + } + return { + get: get3, + dispose + }; + } + function WebGLExtensions(gl) { + const extensions = {}; + function getExtension(name) { + if (extensions[name] !== void 0) { + return extensions[name]; + } + let extension; + switch (name) { + case "WEBGL_depth_texture": + extension = gl.getExtension("WEBGL_depth_texture") || gl.getExtension("MOZ_WEBGL_depth_texture") || gl.getExtension("WEBKIT_WEBGL_depth_texture"); + break; + case "EXT_texture_filter_anisotropic": + extension = gl.getExtension("EXT_texture_filter_anisotropic") || gl.getExtension("MOZ_EXT_texture_filter_anisotropic") || gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic"); + break; + case "WEBGL_compressed_texture_s3tc": + extension = gl.getExtension("WEBGL_compressed_texture_s3tc") || gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc"); + break; + case "WEBGL_compressed_texture_pvrtc": + extension = gl.getExtension("WEBGL_compressed_texture_pvrtc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc"); + break; + default: + extension = gl.getExtension(name); + } + extensions[name] = extension; + return extension; + } + return { + has: function(name) { + return getExtension(name) !== null; + }, + init: function(capabilities) { + if (capabilities.isWebGL2) { + getExtension("EXT_color_buffer_float"); + } else { + getExtension("WEBGL_depth_texture"); + getExtension("OES_texture_float"); + getExtension("OES_texture_half_float"); + getExtension("OES_texture_half_float_linear"); + getExtension("OES_standard_derivatives"); + getExtension("OES_element_index_uint"); + getExtension("OES_vertex_array_object"); + getExtension("ANGLE_instanced_arrays"); + } + getExtension("OES_texture_float_linear"); + getExtension("EXT_color_buffer_half_float"); + getExtension("WEBGL_multisampled_render_to_texture"); + }, + get: function(name) { + const extension = getExtension(name); + if (extension === null) { + console.warn("THREE.WebGLRenderer: " + name + " extension not supported."); + } + return extension; + } + }; + } + function WebGLGeometries(gl, attributes, info, bindingStates) { + const geometries = {}; + const wireframeAttributes = /* @__PURE__ */ new WeakMap(); + function onGeometryDispose(event) { + const geometry = event.target; + if (geometry.index !== null) { + attributes.remove(geometry.index); + } + for (const name in geometry.attributes) { + attributes.remove(geometry.attributes[name]); + } + geometry.removeEventListener("dispose", onGeometryDispose); + delete geometries[geometry.id]; + const attribute = wireframeAttributes.get(geometry); + if (attribute) { + attributes.remove(attribute); + wireframeAttributes.delete(geometry); + } + bindingStates.releaseStatesOfGeometry(geometry); + if (geometry.isInstancedBufferGeometry === true) { + delete geometry._maxInstanceCount; + } + info.memory.geometries--; + } + function get3(object, geometry) { + if (geometries[geometry.id] === true) + return geometry; + geometry.addEventListener("dispose", onGeometryDispose); + geometries[geometry.id] = true; + info.memory.geometries++; + return geometry; + } + function update(geometry) { + const geometryAttributes = geometry.attributes; + for (const name in geometryAttributes) { + attributes.update(geometryAttributes[name], 34962); + } + const morphAttributes = geometry.morphAttributes; + for (const name in morphAttributes) { + const array2 = morphAttributes[name]; + for (let i = 0, l = array2.length; i < l; i++) { + attributes.update(array2[i], 34962); + } + } + } + function updateWireframeAttribute(geometry) { + const indices = []; + const geometryIndex = geometry.index; + const geometryPosition = geometry.attributes.position; + let version = 0; + if (geometryIndex !== null) { + const array2 = geometryIndex.array; + version = geometryIndex.version; + for (let i = 0, l = array2.length; i < l; i += 3) { + const a2 = array2[i + 0]; + const b = array2[i + 1]; + const c2 = array2[i + 2]; + indices.push(a2, b, b, c2, c2, a2); + } + } else { + const array2 = geometryPosition.array; + version = geometryPosition.version; + for (let i = 0, l = array2.length / 3 - 1; i < l; i += 3) { + const a2 = i + 0; + const b = i + 1; + const c2 = i + 2; + indices.push(a2, b, b, c2, c2, a2); + } + } + const attribute = new (arrayNeedsUint32(indices) ? Uint32BufferAttribute : Uint16BufferAttribute)(indices, 1); + attribute.version = version; + const previousAttribute = wireframeAttributes.get(geometry); + if (previousAttribute) + attributes.remove(previousAttribute); + wireframeAttributes.set(geometry, attribute); + } + function getWireframeAttribute(geometry) { + const currentAttribute = wireframeAttributes.get(geometry); + if (currentAttribute) { + const geometryIndex = geometry.index; + if (geometryIndex !== null) { + if (currentAttribute.version < geometryIndex.version) { + updateWireframeAttribute(geometry); + } + } + } else { + updateWireframeAttribute(geometry); + } + return wireframeAttributes.get(geometry); + } + return { + get: get3, + update, + getWireframeAttribute + }; + } + function WebGLIndexedBufferRenderer(gl, extensions, info, capabilities) { + const isWebGL2 = capabilities.isWebGL2; + let mode; + function setMode(value) { + mode = value; + } + let type2, bytesPerElement; + function setIndex(value) { + type2 = value.type; + bytesPerElement = value.bytesPerElement; + } + function render(start2, count) { + gl.drawElements(mode, count, type2, start2 * bytesPerElement); + info.update(count, mode, 1); + } + function renderInstances(start2, count, primcount) { + if (primcount === 0) + return; + let extension, methodName; + if (isWebGL2) { + extension = gl; + methodName = "drawElementsInstanced"; + } else { + extension = extensions.get("ANGLE_instanced_arrays"); + methodName = "drawElementsInstancedANGLE"; + if (extension === null) { + console.error("THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays."); + return; + } + } + extension[methodName](mode, count, type2, start2 * bytesPerElement, primcount); + info.update(count, mode, primcount); + } + this.setMode = setMode; + this.setIndex = setIndex; + this.render = render; + this.renderInstances = renderInstances; + } + function WebGLInfo(gl) { + const memory = { + geometries: 0, + textures: 0 + }; + const render = { + frame: 0, + calls: 0, + triangles: 0, + points: 0, + lines: 0 + }; + function update(count, mode, instanceCount) { + render.calls++; + switch (mode) { + case 4: + render.triangles += instanceCount * (count / 3); + break; + case 1: + render.lines += instanceCount * (count / 2); + break; + case 3: + render.lines += instanceCount * (count - 1); + break; + case 2: + render.lines += instanceCount * count; + break; + case 0: + render.points += instanceCount * count; + break; + default: + console.error("THREE.WebGLInfo: Unknown draw mode:", mode); + break; + } + } + function reset() { + render.frame++; + render.calls = 0; + render.triangles = 0; + render.points = 0; + render.lines = 0; + } + return { + memory, + render, + programs: null, + autoReset: true, + reset, + update + }; + } + function numericalSort(a2, b) { + return a2[0] - b[0]; + } + function absNumericalSort(a2, b) { + return Math.abs(b[1]) - Math.abs(a2[1]); + } + function denormalize(morph, attribute) { + let denominator = 1; + const array2 = attribute.isInterleavedBufferAttribute ? attribute.data.array : attribute.array; + if (array2 instanceof Int8Array) + denominator = 127; + else if (array2 instanceof Uint8Array) + denominator = 255; + else if (array2 instanceof Uint16Array) + denominator = 65535; + else if (array2 instanceof Int16Array) + denominator = 32767; + else if (array2 instanceof Int32Array) + denominator = 2147483647; + else + console.error("THREE.WebGLMorphtargets: Unsupported morph attribute data type: ", array2); + morph.divideScalar(denominator); + } + function WebGLMorphtargets(gl, capabilities, textures) { + const influencesList = {}; + const morphInfluences = new Float32Array(8); + const morphTextures = /* @__PURE__ */ new WeakMap(); + const morph = new Vector4(); + const workInfluences = []; + for (let i = 0; i < 8; i++) { + workInfluences[i] = [i, 0]; + } + function update(object, geometry, material, program) { + const objectInfluences = object.morphTargetInfluences; + if (capabilities.isWebGL2 === true) { + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = morphAttribute !== void 0 ? morphAttribute.length : 0; + let entry = morphTextures.get(geometry); + if (entry === void 0 || entry.count !== morphTargetsCount) { + let disposeTexture = function() { + texture.dispose(); + morphTextures.delete(geometry); + geometry.removeEventListener("dispose", disposeTexture); + }; + if (entry !== void 0) + entry.texture.dispose(); + const hasMorphPosition = geometry.morphAttributes.position !== void 0; + const hasMorphNormals = geometry.morphAttributes.normal !== void 0; + const hasMorphColors = geometry.morphAttributes.color !== void 0; + const morphTargets = geometry.morphAttributes.position || []; + const morphNormals = geometry.morphAttributes.normal || []; + const morphColors = geometry.morphAttributes.color || []; + let vertexDataCount = 0; + if (hasMorphPosition === true) + vertexDataCount = 1; + if (hasMorphNormals === true) + vertexDataCount = 2; + if (hasMorphColors === true) + vertexDataCount = 3; + let width = geometry.attributes.position.count * vertexDataCount; + let height = 1; + if (width > capabilities.maxTextureSize) { + height = Math.ceil(width / capabilities.maxTextureSize); + width = capabilities.maxTextureSize; + } + const buffer = new Float32Array(width * height * 4 * morphTargetsCount); + const texture = new DataArrayTexture(buffer, width, height, morphTargetsCount); + texture.type = FloatType; + texture.needsUpdate = true; + const vertexDataStride = vertexDataCount * 4; + for (let i = 0; i < morphTargetsCount; i++) { + const morphTarget = morphTargets[i]; + const morphNormal = morphNormals[i]; + const morphColor = morphColors[i]; + const offset = width * height * 4 * i; + for (let j = 0; j < morphTarget.count; j++) { + const stride = j * vertexDataStride; + if (hasMorphPosition === true) { + morph.fromBufferAttribute(morphTarget, j); + if (morphTarget.normalized === true) + denormalize(morph, morphTarget); + buffer[offset + stride + 0] = morph.x; + buffer[offset + stride + 1] = morph.y; + buffer[offset + stride + 2] = morph.z; + buffer[offset + stride + 3] = 0; + } + if (hasMorphNormals === true) { + morph.fromBufferAttribute(morphNormal, j); + if (morphNormal.normalized === true) + denormalize(morph, morphNormal); + buffer[offset + stride + 4] = morph.x; + buffer[offset + stride + 5] = morph.y; + buffer[offset + stride + 6] = morph.z; + buffer[offset + stride + 7] = 0; + } + if (hasMorphColors === true) { + morph.fromBufferAttribute(morphColor, j); + if (morphColor.normalized === true) + denormalize(morph, morphColor); + buffer[offset + stride + 8] = morph.x; + buffer[offset + stride + 9] = morph.y; + buffer[offset + stride + 10] = morph.z; + buffer[offset + stride + 11] = morphColor.itemSize === 4 ? morph.w : 1; + } + } + } + entry = { + count: morphTargetsCount, + texture, + size: new Vector2(width, height) + }; + morphTextures.set(geometry, entry); + geometry.addEventListener("dispose", disposeTexture); + } + let morphInfluencesSum = 0; + for (let i = 0; i < objectInfluences.length; i++) { + morphInfluencesSum += objectInfluences[i]; + } + const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; + program.getUniforms().setValue(gl, "morphTargetBaseInfluence", morphBaseInfluence); + program.getUniforms().setValue(gl, "morphTargetInfluences", objectInfluences); + program.getUniforms().setValue(gl, "morphTargetsTexture", entry.texture, textures); + program.getUniforms().setValue(gl, "morphTargetsTextureSize", entry.size); + } else { + const length = objectInfluences === void 0 ? 0 : objectInfluences.length; + let influences = influencesList[geometry.id]; + if (influences === void 0 || influences.length !== length) { + influences = []; + for (let i = 0; i < length; i++) { + influences[i] = [i, 0]; + } + influencesList[geometry.id] = influences; + } + for (let i = 0; i < length; i++) { + const influence = influences[i]; + influence[0] = i; + influence[1] = objectInfluences[i]; + } + influences.sort(absNumericalSort); + for (let i = 0; i < 8; i++) { + if (i < length && influences[i][1]) { + workInfluences[i][0] = influences[i][0]; + workInfluences[i][1] = influences[i][1]; + } else { + workInfluences[i][0] = Number.MAX_SAFE_INTEGER; + workInfluences[i][1] = 0; + } + } + workInfluences.sort(numericalSort); + const morphTargets = geometry.morphAttributes.position; + const morphNormals = geometry.morphAttributes.normal; + let morphInfluencesSum = 0; + for (let i = 0; i < 8; i++) { + const influence = workInfluences[i]; + const index2 = influence[0]; + const value = influence[1]; + if (index2 !== Number.MAX_SAFE_INTEGER && value) { + if (morphTargets && geometry.getAttribute("morphTarget" + i) !== morphTargets[index2]) { + geometry.setAttribute("morphTarget" + i, morphTargets[index2]); + } + if (morphNormals && geometry.getAttribute("morphNormal" + i) !== morphNormals[index2]) { + geometry.setAttribute("morphNormal" + i, morphNormals[index2]); + } + morphInfluences[i] = value; + morphInfluencesSum += value; + } else { + if (morphTargets && geometry.hasAttribute("morphTarget" + i) === true) { + geometry.deleteAttribute("morphTarget" + i); + } + if (morphNormals && geometry.hasAttribute("morphNormal" + i) === true) { + geometry.deleteAttribute("morphNormal" + i); + } + morphInfluences[i] = 0; + } + } + const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; + program.getUniforms().setValue(gl, "morphTargetBaseInfluence", morphBaseInfluence); + program.getUniforms().setValue(gl, "morphTargetInfluences", morphInfluences); + } + } + return { + update + }; + } + function WebGLObjects(gl, geometries, attributes, info) { + let updateMap = /* @__PURE__ */ new WeakMap(); + function update(object) { + const frame2 = info.render.frame; + const geometry = object.geometry; + const buffergeometry = geometries.get(object, geometry); + if (updateMap.get(buffergeometry) !== frame2) { + geometries.update(buffergeometry); + updateMap.set(buffergeometry, frame2); + } + if (object.isInstancedMesh) { + if (object.hasEventListener("dispose", onInstancedMeshDispose) === false) { + object.addEventListener("dispose", onInstancedMeshDispose); + } + attributes.update(object.instanceMatrix, 34962); + if (object.instanceColor !== null) { + attributes.update(object.instanceColor, 34962); + } + } + return buffergeometry; + } + function dispose() { + updateMap = /* @__PURE__ */ new WeakMap(); + } + function onInstancedMeshDispose(event) { + const instancedMesh = event.target; + instancedMesh.removeEventListener("dispose", onInstancedMeshDispose); + attributes.remove(instancedMesh.instanceMatrix); + if (instancedMesh.instanceColor !== null) + attributes.remove(instancedMesh.instanceColor); + } + return { + update, + dispose + }; + } + var emptyTexture = /* @__PURE__ */ new Texture(); + var emptyArrayTexture = /* @__PURE__ */ new DataArrayTexture(); + var empty3dTexture = /* @__PURE__ */ new Data3DTexture(); + var emptyCubeTexture = /* @__PURE__ */ new CubeTexture(); + var arrayCacheF32 = []; + var arrayCacheI32 = []; + var mat4array = new Float32Array(16); + var mat3array = new Float32Array(9); + var mat2array = new Float32Array(4); + function flatten(array2, nBlocks, blockSize) { + const firstElem = array2[0]; + if (firstElem <= 0 || firstElem > 0) + return array2; + const n = nBlocks * blockSize; + let r = arrayCacheF32[n]; + if (r === void 0) { + r = new Float32Array(n); + arrayCacheF32[n] = r; + } + if (nBlocks !== 0) { + firstElem.toArray(r, 0); + for (let i = 1, offset = 0; i !== nBlocks; ++i) { + offset += blockSize; + array2[i].toArray(r, offset); + } + } + return r; + } + function arraysEqual(a2, b) { + if (a2.length !== b.length) + return false; + for (let i = 0, l = a2.length; i < l; i++) { + if (a2[i] !== b[i]) + return false; + } + return true; + } + function copyArray(a2, b) { + for (let i = 0, l = b.length; i < l; i++) { + a2[i] = b[i]; + } + } + function allocTexUnits(textures, n) { + let r = arrayCacheI32[n]; + if (r === void 0) { + r = new Int32Array(n); + arrayCacheI32[n] = r; + } + for (let i = 0; i !== n; ++i) { + r[i] = textures.allocateTextureUnit(); + } + return r; + } + function setValueV1f(gl, v) { + const cache2 = this.cache; + if (cache2[0] === v) + return; + gl.uniform1f(this.addr, v); + cache2[0] = v; + } + function setValueV2f(gl, v) { + const cache2 = this.cache; + if (v.x !== void 0) { + if (cache2[0] !== v.x || cache2[1] !== v.y) { + gl.uniform2f(this.addr, v.x, v.y); + cache2[0] = v.x; + cache2[1] = v.y; + } + } else { + if (arraysEqual(cache2, v)) + return; + gl.uniform2fv(this.addr, v); + copyArray(cache2, v); + } + } + function setValueV3f(gl, v) { + const cache2 = this.cache; + if (v.x !== void 0) { + if (cache2[0] !== v.x || cache2[1] !== v.y || cache2[2] !== v.z) { + gl.uniform3f(this.addr, v.x, v.y, v.z); + cache2[0] = v.x; + cache2[1] = v.y; + cache2[2] = v.z; + } + } else if (v.r !== void 0) { + if (cache2[0] !== v.r || cache2[1] !== v.g || cache2[2] !== v.b) { + gl.uniform3f(this.addr, v.r, v.g, v.b); + cache2[0] = v.r; + cache2[1] = v.g; + cache2[2] = v.b; + } + } else { + if (arraysEqual(cache2, v)) + return; + gl.uniform3fv(this.addr, v); + copyArray(cache2, v); + } + } + function setValueV4f(gl, v) { + const cache2 = this.cache; + if (v.x !== void 0) { + if (cache2[0] !== v.x || cache2[1] !== v.y || cache2[2] !== v.z || cache2[3] !== v.w) { + gl.uniform4f(this.addr, v.x, v.y, v.z, v.w); + cache2[0] = v.x; + cache2[1] = v.y; + cache2[2] = v.z; + cache2[3] = v.w; + } + } else { + if (arraysEqual(cache2, v)) + return; + gl.uniform4fv(this.addr, v); + copyArray(cache2, v); + } + } + function setValueM2(gl, v) { + const cache2 = this.cache; + const elements = v.elements; + if (elements === void 0) { + if (arraysEqual(cache2, v)) + return; + gl.uniformMatrix2fv(this.addr, false, v); + copyArray(cache2, v); + } else { + if (arraysEqual(cache2, elements)) + return; + mat2array.set(elements); + gl.uniformMatrix2fv(this.addr, false, mat2array); + copyArray(cache2, elements); + } + } + function setValueM3(gl, v) { + const cache2 = this.cache; + const elements = v.elements; + if (elements === void 0) { + if (arraysEqual(cache2, v)) + return; + gl.uniformMatrix3fv(this.addr, false, v); + copyArray(cache2, v); + } else { + if (arraysEqual(cache2, elements)) + return; + mat3array.set(elements); + gl.uniformMatrix3fv(this.addr, false, mat3array); + copyArray(cache2, elements); + } + } + function setValueM4(gl, v) { + const cache2 = this.cache; + const elements = v.elements; + if (elements === void 0) { + if (arraysEqual(cache2, v)) + return; + gl.uniformMatrix4fv(this.addr, false, v); + copyArray(cache2, v); + } else { + if (arraysEqual(cache2, elements)) + return; + mat4array.set(elements); + gl.uniformMatrix4fv(this.addr, false, mat4array); + copyArray(cache2, elements); + } + } + function setValueV1i(gl, v) { + const cache2 = this.cache; + if (cache2[0] === v) + return; + gl.uniform1i(this.addr, v); + cache2[0] = v; + } + function setValueV2i(gl, v) { + const cache2 = this.cache; + if (arraysEqual(cache2, v)) + return; + gl.uniform2iv(this.addr, v); + copyArray(cache2, v); + } + function setValueV3i(gl, v) { + const cache2 = this.cache; + if (arraysEqual(cache2, v)) + return; + gl.uniform3iv(this.addr, v); + copyArray(cache2, v); + } + function setValueV4i(gl, v) { + const cache2 = this.cache; + if (arraysEqual(cache2, v)) + return; + gl.uniform4iv(this.addr, v); + copyArray(cache2, v); + } + function setValueV1ui(gl, v) { + const cache2 = this.cache; + if (cache2[0] === v) + return; + gl.uniform1ui(this.addr, v); + cache2[0] = v; + } + function setValueV2ui(gl, v) { + const cache2 = this.cache; + if (arraysEqual(cache2, v)) + return; + gl.uniform2uiv(this.addr, v); + copyArray(cache2, v); + } + function setValueV3ui(gl, v) { + const cache2 = this.cache; + if (arraysEqual(cache2, v)) + return; + gl.uniform3uiv(this.addr, v); + copyArray(cache2, v); + } + function setValueV4ui(gl, v) { + const cache2 = this.cache; + if (arraysEqual(cache2, v)) + return; + gl.uniform4uiv(this.addr, v); + copyArray(cache2, v); + } + function setValueT1(gl, v, textures) { + const cache2 = this.cache; + const unit2 = textures.allocateTextureUnit(); + if (cache2[0] !== unit2) { + gl.uniform1i(this.addr, unit2); + cache2[0] = unit2; + } + textures.setTexture2D(v || emptyTexture, unit2); + } + function setValueT3D1(gl, v, textures) { + const cache2 = this.cache; + const unit2 = textures.allocateTextureUnit(); + if (cache2[0] !== unit2) { + gl.uniform1i(this.addr, unit2); + cache2[0] = unit2; + } + textures.setTexture3D(v || empty3dTexture, unit2); + } + function setValueT6(gl, v, textures) { + const cache2 = this.cache; + const unit2 = textures.allocateTextureUnit(); + if (cache2[0] !== unit2) { + gl.uniform1i(this.addr, unit2); + cache2[0] = unit2; + } + textures.setTextureCube(v || emptyCubeTexture, unit2); + } + function setValueT2DArray1(gl, v, textures) { + const cache2 = this.cache; + const unit2 = textures.allocateTextureUnit(); + if (cache2[0] !== unit2) { + gl.uniform1i(this.addr, unit2); + cache2[0] = unit2; + } + textures.setTexture2DArray(v || emptyArrayTexture, unit2); + } + function getSingularSetter(type2) { + switch (type2) { + case 5126: + return setValueV1f; + case 35664: + return setValueV2f; + case 35665: + return setValueV3f; + case 35666: + return setValueV4f; + case 35674: + return setValueM2; + case 35675: + return setValueM3; + case 35676: + return setValueM4; + case 5124: + case 35670: + return setValueV1i; + case 35667: + case 35671: + return setValueV2i; + case 35668: + case 35672: + return setValueV3i; + case 35669: + case 35673: + return setValueV4i; + case 5125: + return setValueV1ui; + case 36294: + return setValueV2ui; + case 36295: + return setValueV3ui; + case 36296: + return setValueV4ui; + case 35678: + case 36198: + case 36298: + case 36306: + case 35682: + return setValueT1; + case 35679: + case 36299: + case 36307: + return setValueT3D1; + case 35680: + case 36300: + case 36308: + case 36293: + return setValueT6; + case 36289: + case 36303: + case 36311: + case 36292: + return setValueT2DArray1; + } + } + function setValueV1fArray(gl, v) { + gl.uniform1fv(this.addr, v); + } + function setValueV2fArray(gl, v) { + const data = flatten(v, this.size, 2); + gl.uniform2fv(this.addr, data); + } + function setValueV3fArray(gl, v) { + const data = flatten(v, this.size, 3); + gl.uniform3fv(this.addr, data); + } + function setValueV4fArray(gl, v) { + const data = flatten(v, this.size, 4); + gl.uniform4fv(this.addr, data); + } + function setValueM2Array(gl, v) { + const data = flatten(v, this.size, 4); + gl.uniformMatrix2fv(this.addr, false, data); + } + function setValueM3Array(gl, v) { + const data = flatten(v, this.size, 9); + gl.uniformMatrix3fv(this.addr, false, data); + } + function setValueM4Array(gl, v) { + const data = flatten(v, this.size, 16); + gl.uniformMatrix4fv(this.addr, false, data); + } + function setValueV1iArray(gl, v) { + gl.uniform1iv(this.addr, v); + } + function setValueV2iArray(gl, v) { + gl.uniform2iv(this.addr, v); + } + function setValueV3iArray(gl, v) { + gl.uniform3iv(this.addr, v); + } + function setValueV4iArray(gl, v) { + gl.uniform4iv(this.addr, v); + } + function setValueV1uiArray(gl, v) { + gl.uniform1uiv(this.addr, v); + } + function setValueV2uiArray(gl, v) { + gl.uniform2uiv(this.addr, v); + } + function setValueV3uiArray(gl, v) { + gl.uniform3uiv(this.addr, v); + } + function setValueV4uiArray(gl, v) { + gl.uniform4uiv(this.addr, v); + } + function setValueT1Array(gl, v, textures) { + const n = v.length; + const units = allocTexUnits(textures, n); + gl.uniform1iv(this.addr, units); + for (let i = 0; i !== n; ++i) { + textures.setTexture2D(v[i] || emptyTexture, units[i]); + } + } + function setValueT3DArray(gl, v, textures) { + const n = v.length; + const units = allocTexUnits(textures, n); + gl.uniform1iv(this.addr, units); + for (let i = 0; i !== n; ++i) { + textures.setTexture3D(v[i] || empty3dTexture, units[i]); + } + } + function setValueT6Array(gl, v, textures) { + const n = v.length; + const units = allocTexUnits(textures, n); + gl.uniform1iv(this.addr, units); + for (let i = 0; i !== n; ++i) { + textures.setTextureCube(v[i] || emptyCubeTexture, units[i]); + } + } + function setValueT2DArrayArray(gl, v, textures) { + const n = v.length; + const units = allocTexUnits(textures, n); + gl.uniform1iv(this.addr, units); + for (let i = 0; i !== n; ++i) { + textures.setTexture2DArray(v[i] || emptyArrayTexture, units[i]); + } + } + function getPureArraySetter(type2) { + switch (type2) { + case 5126: + return setValueV1fArray; + case 35664: + return setValueV2fArray; + case 35665: + return setValueV3fArray; + case 35666: + return setValueV4fArray; + case 35674: + return setValueM2Array; + case 35675: + return setValueM3Array; + case 35676: + return setValueM4Array; + case 5124: + case 35670: + return setValueV1iArray; + case 35667: + case 35671: + return setValueV2iArray; + case 35668: + case 35672: + return setValueV3iArray; + case 35669: + case 35673: + return setValueV4iArray; + case 5125: + return setValueV1uiArray; + case 36294: + return setValueV2uiArray; + case 36295: + return setValueV3uiArray; + case 36296: + return setValueV4uiArray; + case 35678: + case 36198: + case 36298: + case 36306: + case 35682: + return setValueT1Array; + case 35679: + case 36299: + case 36307: + return setValueT3DArray; + case 35680: + case 36300: + case 36308: + case 36293: + return setValueT6Array; + case 36289: + case 36303: + case 36311: + case 36292: + return setValueT2DArrayArray; + } + } + var SingleUniform = class { + constructor(id2, activeInfo, addr) { + this.id = id2; + this.addr = addr; + this.cache = []; + this.setValue = getSingularSetter(activeInfo.type); + } + }; + var PureArrayUniform = class { + constructor(id2, activeInfo, addr) { + this.id = id2; + this.addr = addr; + this.cache = []; + this.size = activeInfo.size; + this.setValue = getPureArraySetter(activeInfo.type); + } + }; + var StructuredUniform = class { + constructor(id2) { + this.id = id2; + this.seq = []; + this.map = {}; + } + setValue(gl, value, textures) { + const seq = this.seq; + for (let i = 0, n = seq.length; i !== n; ++i) { + const u = seq[i]; + u.setValue(gl, value[u.id], textures); + } + } + }; + var RePathPart = /(\w+)(\])?(\[|\.)?/g; + function addUniform(container, uniformObject) { + container.seq.push(uniformObject); + container.map[uniformObject.id] = uniformObject; + } + function parseUniform(activeInfo, addr, container) { + const path = activeInfo.name, pathLength = path.length; + RePathPart.lastIndex = 0; + while (true) { + const match = RePathPart.exec(path), matchEnd = RePathPart.lastIndex; + let id2 = match[1]; + const idIsIndex = match[2] === "]", subscript = match[3]; + if (idIsIndex) + id2 = id2 | 0; + if (subscript === void 0 || subscript === "[" && matchEnd + 2 === pathLength) { + addUniform(container, subscript === void 0 ? new SingleUniform(id2, activeInfo, addr) : new PureArrayUniform(id2, activeInfo, addr)); + break; + } else { + const map2 = container.map; + let next = map2[id2]; + if (next === void 0) { + next = new StructuredUniform(id2); + addUniform(container, next); + } + container = next; + } + } + } + var WebGLUniforms = class { + constructor(gl, program) { + this.seq = []; + this.map = {}; + const n = gl.getProgramParameter(program, 35718); + for (let i = 0; i < n; ++i) { + const info = gl.getActiveUniform(program, i), addr = gl.getUniformLocation(program, info.name); + parseUniform(info, addr, this); + } + } + setValue(gl, name, value, textures) { + const u = this.map[name]; + if (u !== void 0) + u.setValue(gl, value, textures); + } + setOptional(gl, object, name) { + const v = object[name]; + if (v !== void 0) + this.setValue(gl, name, v); + } + static upload(gl, seq, values, textures) { + for (let i = 0, n = seq.length; i !== n; ++i) { + const u = seq[i], v = values[u.id]; + if (v.needsUpdate !== false) { + u.setValue(gl, v.value, textures); + } + } + } + static seqWithValue(seq, values) { + const r = []; + for (let i = 0, n = seq.length; i !== n; ++i) { + const u = seq[i]; + if (u.id in values) + r.push(u); + } + return r; + } + }; + function WebGLShader(gl, type2, string) { + const shader = gl.createShader(type2); + gl.shaderSource(shader, string); + gl.compileShader(shader); + return shader; + } + var programIdCount = 0; + function handleSource(string, errorLine) { + const lines = string.split("\n"); + const lines2 = []; + const from = Math.max(errorLine - 6, 0); + const to = Math.min(errorLine + 6, lines.length); + for (let i = from; i < to; i++) { + const line = i + 1; + lines2.push(`${line === errorLine ? ">" : " "} ${line}: ${lines[i]}`); + } + return lines2.join("\n"); + } + function getEncodingComponents(encoding) { + switch (encoding) { + case LinearEncoding: + return ["Linear", "( value )"]; + case sRGBEncoding: + return ["sRGB", "( value )"]; + default: + console.warn("THREE.WebGLProgram: Unsupported encoding:", encoding); + return ["Linear", "( value )"]; + } + } + function getShaderErrors(gl, shader, type2) { + const status = gl.getShaderParameter(shader, 35713); + const errors = gl.getShaderInfoLog(shader).trim(); + if (status && errors === "") + return ""; + const errorMatches = /ERROR: 0:(\d+)/.exec(errors); + if (errorMatches) { + const errorLine = parseInt(errorMatches[1]); + return type2.toUpperCase() + "\n\n" + errors + "\n\n" + handleSource(gl.getShaderSource(shader), errorLine); + } else { + return errors; + } + } + function getTexelEncodingFunction(functionName, encoding) { + const components = getEncodingComponents(encoding); + return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[0] + components[1] + "; }"; + } + function getToneMappingFunction(functionName, toneMapping) { + let toneMappingName; + switch (toneMapping) { + case LinearToneMapping: + toneMappingName = "Linear"; + break; + case ReinhardToneMapping: + toneMappingName = "Reinhard"; + break; + case CineonToneMapping: + toneMappingName = "OptimizedCineon"; + break; + case ACESFilmicToneMapping: + toneMappingName = "ACESFilmic"; + break; + case CustomToneMapping: + toneMappingName = "Custom"; + break; + default: + console.warn("THREE.WebGLProgram: Unsupported toneMapping:", toneMapping); + toneMappingName = "Linear"; + } + return "vec3 " + functionName + "( vec3 color ) { return " + toneMappingName + "ToneMapping( color ); }"; + } + function generateExtensions(parameters) { + const chunks = [ + parameters.extensionDerivatives || !!parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === "physical" ? "#extension GL_OES_standard_derivatives : enable" : "", + (parameters.extensionFragDepth || parameters.logarithmicDepthBuffer) && parameters.rendererExtensionFragDepth ? "#extension GL_EXT_frag_depth : enable" : "", + parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ? "#extension GL_EXT_draw_buffers : require" : "", + (parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission) && parameters.rendererExtensionShaderTextureLod ? "#extension GL_EXT_shader_texture_lod : enable" : "" + ]; + return chunks.filter(filterEmptyLine).join("\n"); + } + function generateDefines(defines) { + const chunks = []; + for (const name in defines) { + const value = defines[name]; + if (value === false) + continue; + chunks.push("#define " + name + " " + value); + } + return chunks.join("\n"); + } + function fetchAttributeLocations(gl, program) { + const attributes = {}; + const n = gl.getProgramParameter(program, 35721); + for (let i = 0; i < n; i++) { + const info = gl.getActiveAttrib(program, i); + const name = info.name; + let locationSize = 1; + if (info.type === 35674) + locationSize = 2; + if (info.type === 35675) + locationSize = 3; + if (info.type === 35676) + locationSize = 4; + attributes[name] = { + type: info.type, + location: gl.getAttribLocation(program, name), + locationSize + }; + } + return attributes; + } + function filterEmptyLine(string) { + return string !== ""; + } + function replaceLightNums(string, parameters) { + return string.replace(/NUM_DIR_LIGHTS/g, parameters.numDirLights).replace(/NUM_SPOT_LIGHTS/g, parameters.numSpotLights).replace(/NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g, parameters.numPointLights).replace(/NUM_HEMI_LIGHTS/g, parameters.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows); + } + function replaceClippingPlaneNums(string, parameters) { + return string.replace(/NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g, parameters.numClippingPlanes - parameters.numClipIntersection); + } + var includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm; + function resolveIncludes(string) { + return string.replace(includePattern, includeReplacer); + } + function includeReplacer(match, include) { + const string = ShaderChunk[include]; + if (string === void 0) { + throw new Error("Can not resolve #include <" + include + ">"); + } + return resolveIncludes(string); + } + var deprecatedUnrollLoopPattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g; + var unrollLoopPattern = /#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g; + function unrollLoops(string) { + return string.replace(unrollLoopPattern, loopReplacer).replace(deprecatedUnrollLoopPattern, deprecatedLoopReplacer); + } + function deprecatedLoopReplacer(match, start2, end, snippet) { + console.warn("WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead."); + return loopReplacer(match, start2, end, snippet); + } + function loopReplacer(match, start2, end, snippet) { + let string = ""; + for (let i = parseInt(start2); i < parseInt(end); i++) { + string += snippet.replace(/\[\s*i\s*\]/g, "[ " + i + " ]").replace(/UNROLLED_LOOP_INDEX/g, i); + } + return string; + } + function generatePrecision(parameters) { + let precisionstring = "precision " + parameters.precision + " float;\nprecision " + parameters.precision + " int;"; + if (parameters.precision === "highp") { + precisionstring += "\n#define HIGH_PRECISION"; + } else if (parameters.precision === "mediump") { + precisionstring += "\n#define MEDIUM_PRECISION"; + } else if (parameters.precision === "lowp") { + precisionstring += "\n#define LOW_PRECISION"; + } + return precisionstring; + } + function generateShadowMapTypeDefine(parameters) { + let shadowMapTypeDefine = "SHADOWMAP_TYPE_BASIC"; + if (parameters.shadowMapType === PCFShadowMap) { + shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF"; + } else if (parameters.shadowMapType === PCFSoftShadowMap) { + shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF_SOFT"; + } else if (parameters.shadowMapType === VSMShadowMap) { + shadowMapTypeDefine = "SHADOWMAP_TYPE_VSM"; + } + return shadowMapTypeDefine; + } + function generateEnvMapTypeDefine(parameters) { + let envMapTypeDefine = "ENVMAP_TYPE_CUBE"; + if (parameters.envMap) { + switch (parameters.envMapMode) { + case CubeReflectionMapping: + case CubeRefractionMapping: + envMapTypeDefine = "ENVMAP_TYPE_CUBE"; + break; + case CubeUVReflectionMapping: + envMapTypeDefine = "ENVMAP_TYPE_CUBE_UV"; + break; + } + } + return envMapTypeDefine; + } + function generateEnvMapModeDefine(parameters) { + let envMapModeDefine = "ENVMAP_MODE_REFLECTION"; + if (parameters.envMap) { + switch (parameters.envMapMode) { + case CubeRefractionMapping: + envMapModeDefine = "ENVMAP_MODE_REFRACTION"; + break; + } + } + return envMapModeDefine; + } + function generateEnvMapBlendingDefine(parameters) { + let envMapBlendingDefine = "ENVMAP_BLENDING_NONE"; + if (parameters.envMap) { + switch (parameters.combine) { + case MultiplyOperation: + envMapBlendingDefine = "ENVMAP_BLENDING_MULTIPLY"; + break; + case MixOperation: + envMapBlendingDefine = "ENVMAP_BLENDING_MIX"; + break; + case AddOperation: + envMapBlendingDefine = "ENVMAP_BLENDING_ADD"; + break; + } + } + return envMapBlendingDefine; + } + function generateCubeUVSize(parameters) { + const imageHeight = parameters.envMapCubeUVHeight; + if (imageHeight === null) + return null; + const maxMip = Math.log2(imageHeight) - 2; + const texelHeight = 1 / imageHeight; + const texelWidth = 1 / (3 * Math.max(Math.pow(2, maxMip), 7 * 16)); + return { texelWidth, texelHeight, maxMip }; + } + function WebGLProgram(renderer, cacheKey, parameters, bindingStates) { + const gl = renderer.getContext(); + const defines = parameters.defines; + let vertexShader = parameters.vertexShader; + let fragmentShader = parameters.fragmentShader; + const shadowMapTypeDefine = generateShadowMapTypeDefine(parameters); + const envMapTypeDefine = generateEnvMapTypeDefine(parameters); + const envMapModeDefine = generateEnvMapModeDefine(parameters); + const envMapBlendingDefine = generateEnvMapBlendingDefine(parameters); + const envMapCubeUVSize = generateCubeUVSize(parameters); + const customExtensions = parameters.isWebGL2 ? "" : generateExtensions(parameters); + const customDefines = generateDefines(defines); + const program = gl.createProgram(); + let prefixVertex, prefixFragment; + let versionString = parameters.glslVersion ? "#version " + parameters.glslVersion + "\n" : ""; + if (parameters.isRawShaderMaterial) { + prefixVertex = [ + customDefines + ].filter(filterEmptyLine).join("\n"); + if (prefixVertex.length > 0) { + prefixVertex += "\n"; + } + prefixFragment = [ + customExtensions, + customDefines + ].filter(filterEmptyLine).join("\n"); + if (prefixFragment.length > 0) { + prefixFragment += "\n"; + } + } else { + prefixVertex = [ + generatePrecision(parameters), + "#define SHADER_NAME " + parameters.shaderName, + customDefines, + parameters.instancing ? "#define USE_INSTANCING" : "", + parameters.instancingColor ? "#define USE_INSTANCING_COLOR" : "", + parameters.supportsVertexTextures ? "#define VERTEX_TEXTURES" : "", + parameters.useFog && parameters.fog ? "#define USE_FOG" : "", + parameters.useFog && parameters.fogExp2 ? "#define FOG_EXP2" : "", + parameters.map ? "#define USE_MAP" : "", + parameters.envMap ? "#define USE_ENVMAP" : "", + parameters.envMap ? "#define " + envMapModeDefine : "", + parameters.lightMap ? "#define USE_LIGHTMAP" : "", + parameters.aoMap ? "#define USE_AOMAP" : "", + parameters.emissiveMap ? "#define USE_EMISSIVEMAP" : "", + parameters.bumpMap ? "#define USE_BUMPMAP" : "", + parameters.normalMap ? "#define USE_NORMALMAP" : "", + parameters.normalMap && parameters.objectSpaceNormalMap ? "#define OBJECTSPACE_NORMALMAP" : "", + parameters.normalMap && parameters.tangentSpaceNormalMap ? "#define TANGENTSPACE_NORMALMAP" : "", + parameters.clearcoatMap ? "#define USE_CLEARCOATMAP" : "", + parameters.clearcoatRoughnessMap ? "#define USE_CLEARCOAT_ROUGHNESSMAP" : "", + parameters.clearcoatNormalMap ? "#define USE_CLEARCOAT_NORMALMAP" : "", + parameters.iridescenceMap ? "#define USE_IRIDESCENCEMAP" : "", + parameters.iridescenceThicknessMap ? "#define USE_IRIDESCENCE_THICKNESSMAP" : "", + parameters.displacementMap && parameters.supportsVertexTextures ? "#define USE_DISPLACEMENTMAP" : "", + parameters.specularMap ? "#define USE_SPECULARMAP" : "", + parameters.specularIntensityMap ? "#define USE_SPECULARINTENSITYMAP" : "", + parameters.specularColorMap ? "#define USE_SPECULARCOLORMAP" : "", + parameters.roughnessMap ? "#define USE_ROUGHNESSMAP" : "", + parameters.metalnessMap ? "#define USE_METALNESSMAP" : "", + parameters.alphaMap ? "#define USE_ALPHAMAP" : "", + parameters.transmission ? "#define USE_TRANSMISSION" : "", + parameters.transmissionMap ? "#define USE_TRANSMISSIONMAP" : "", + parameters.thicknessMap ? "#define USE_THICKNESSMAP" : "", + parameters.sheenColorMap ? "#define USE_SHEENCOLORMAP" : "", + parameters.sheenRoughnessMap ? "#define USE_SHEENROUGHNESSMAP" : "", + parameters.vertexTangents ? "#define USE_TANGENT" : "", + parameters.vertexColors ? "#define USE_COLOR" : "", + parameters.vertexAlphas ? "#define USE_COLOR_ALPHA" : "", + parameters.vertexUvs ? "#define USE_UV" : "", + parameters.uvsVertexOnly ? "#define UVS_VERTEX_ONLY" : "", + parameters.flatShading ? "#define FLAT_SHADED" : "", + parameters.skinning ? "#define USE_SKINNING" : "", + parameters.morphTargets ? "#define USE_MORPHTARGETS" : "", + parameters.morphNormals && parameters.flatShading === false ? "#define USE_MORPHNORMALS" : "", + parameters.morphColors && parameters.isWebGL2 ? "#define USE_MORPHCOLORS" : "", + parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? "#define MORPHTARGETS_TEXTURE" : "", + parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? "#define MORPHTARGETS_TEXTURE_STRIDE " + parameters.morphTextureStride : "", + parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? "#define MORPHTARGETS_COUNT " + parameters.morphTargetsCount : "", + parameters.doubleSided ? "#define DOUBLE_SIDED" : "", + parameters.flipSided ? "#define FLIP_SIDED" : "", + parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "", + parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "", + parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "", + parameters.logarithmicDepthBuffer ? "#define USE_LOGDEPTHBUF" : "", + parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? "#define USE_LOGDEPTHBUF_EXT" : "", + "uniform mat4 modelMatrix;", + "uniform mat4 modelViewMatrix;", + "uniform mat4 projectionMatrix;", + "uniform mat4 viewMatrix;", + "uniform mat3 normalMatrix;", + "uniform vec3 cameraPosition;", + "uniform bool isOrthographic;", + "#ifdef USE_INSTANCING", + " attribute mat4 instanceMatrix;", + "#endif", + "#ifdef USE_INSTANCING_COLOR", + " attribute vec3 instanceColor;", + "#endif", + "attribute vec3 position;", + "attribute vec3 normal;", + "attribute vec2 uv;", + "#ifdef USE_TANGENT", + " attribute vec4 tangent;", + "#endif", + "#if defined( USE_COLOR_ALPHA )", + " attribute vec4 color;", + "#elif defined( USE_COLOR )", + " attribute vec3 color;", + "#endif", + "#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )", + " attribute vec3 morphTarget0;", + " attribute vec3 morphTarget1;", + " attribute vec3 morphTarget2;", + " attribute vec3 morphTarget3;", + " #ifdef USE_MORPHNORMALS", + " attribute vec3 morphNormal0;", + " attribute vec3 morphNormal1;", + " attribute vec3 morphNormal2;", + " attribute vec3 morphNormal3;", + " #else", + " attribute vec3 morphTarget4;", + " attribute vec3 morphTarget5;", + " attribute vec3 morphTarget6;", + " attribute vec3 morphTarget7;", + " #endif", + "#endif", + "#ifdef USE_SKINNING", + " attribute vec4 skinIndex;", + " attribute vec4 skinWeight;", + "#endif", + "\n" + ].filter(filterEmptyLine).join("\n"); + prefixFragment = [ + customExtensions, + generatePrecision(parameters), + "#define SHADER_NAME " + parameters.shaderName, + customDefines, + parameters.useFog && parameters.fog ? "#define USE_FOG" : "", + parameters.useFog && parameters.fogExp2 ? "#define FOG_EXP2" : "", + parameters.map ? "#define USE_MAP" : "", + parameters.matcap ? "#define USE_MATCAP" : "", + parameters.envMap ? "#define USE_ENVMAP" : "", + parameters.envMap ? "#define " + envMapTypeDefine : "", + parameters.envMap ? "#define " + envMapModeDefine : "", + parameters.envMap ? "#define " + envMapBlendingDefine : "", + envMapCubeUVSize ? "#define CUBEUV_TEXEL_WIDTH " + envMapCubeUVSize.texelWidth : "", + envMapCubeUVSize ? "#define CUBEUV_TEXEL_HEIGHT " + envMapCubeUVSize.texelHeight : "", + envMapCubeUVSize ? "#define CUBEUV_MAX_MIP " + envMapCubeUVSize.maxMip + ".0" : "", + parameters.lightMap ? "#define USE_LIGHTMAP" : "", + parameters.aoMap ? "#define USE_AOMAP" : "", + parameters.emissiveMap ? "#define USE_EMISSIVEMAP" : "", + parameters.bumpMap ? "#define USE_BUMPMAP" : "", + parameters.normalMap ? "#define USE_NORMALMAP" : "", + parameters.normalMap && parameters.objectSpaceNormalMap ? "#define OBJECTSPACE_NORMALMAP" : "", + parameters.normalMap && parameters.tangentSpaceNormalMap ? "#define TANGENTSPACE_NORMALMAP" : "", + parameters.clearcoat ? "#define USE_CLEARCOAT" : "", + parameters.clearcoatMap ? "#define USE_CLEARCOATMAP" : "", + parameters.clearcoatRoughnessMap ? "#define USE_CLEARCOAT_ROUGHNESSMAP" : "", + parameters.clearcoatNormalMap ? "#define USE_CLEARCOAT_NORMALMAP" : "", + parameters.iridescence ? "#define USE_IRIDESCENCE" : "", + parameters.iridescenceMap ? "#define USE_IRIDESCENCEMAP" : "", + parameters.iridescenceThicknessMap ? "#define USE_IRIDESCENCE_THICKNESSMAP" : "", + parameters.specularMap ? "#define USE_SPECULARMAP" : "", + parameters.specularIntensityMap ? "#define USE_SPECULARINTENSITYMAP" : "", + parameters.specularColorMap ? "#define USE_SPECULARCOLORMAP" : "", + parameters.roughnessMap ? "#define USE_ROUGHNESSMAP" : "", + parameters.metalnessMap ? "#define USE_METALNESSMAP" : "", + parameters.alphaMap ? "#define USE_ALPHAMAP" : "", + parameters.alphaTest ? "#define USE_ALPHATEST" : "", + parameters.sheen ? "#define USE_SHEEN" : "", + parameters.sheenColorMap ? "#define USE_SHEENCOLORMAP" : "", + parameters.sheenRoughnessMap ? "#define USE_SHEENROUGHNESSMAP" : "", + parameters.transmission ? "#define USE_TRANSMISSION" : "", + parameters.transmissionMap ? "#define USE_TRANSMISSIONMAP" : "", + parameters.thicknessMap ? "#define USE_THICKNESSMAP" : "", + parameters.decodeVideoTexture ? "#define DECODE_VIDEO_TEXTURE" : "", + parameters.vertexTangents ? "#define USE_TANGENT" : "", + parameters.vertexColors || parameters.instancingColor ? "#define USE_COLOR" : "", + parameters.vertexAlphas ? "#define USE_COLOR_ALPHA" : "", + parameters.vertexUvs ? "#define USE_UV" : "", + parameters.uvsVertexOnly ? "#define UVS_VERTEX_ONLY" : "", + parameters.gradientMap ? "#define USE_GRADIENTMAP" : "", + parameters.flatShading ? "#define FLAT_SHADED" : "", + parameters.doubleSided ? "#define DOUBLE_SIDED" : "", + parameters.flipSided ? "#define FLIP_SIDED" : "", + parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "", + parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "", + parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : "", + parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : "", + parameters.logarithmicDepthBuffer ? "#define USE_LOGDEPTHBUF" : "", + parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? "#define USE_LOGDEPTHBUF_EXT" : "", + "uniform mat4 viewMatrix;", + "uniform vec3 cameraPosition;", + "uniform bool isOrthographic;", + parameters.toneMapping !== NoToneMapping ? "#define TONE_MAPPING" : "", + parameters.toneMapping !== NoToneMapping ? ShaderChunk["tonemapping_pars_fragment"] : "", + parameters.toneMapping !== NoToneMapping ? getToneMappingFunction("toneMapping", parameters.toneMapping) : "", + parameters.dithering ? "#define DITHERING" : "", + parameters.opaque ? "#define OPAQUE" : "", + ShaderChunk["encodings_pars_fragment"], + getTexelEncodingFunction("linearToOutputTexel", parameters.outputEncoding), + parameters.useDepthPacking ? "#define DEPTH_PACKING " + parameters.depthPacking : "", + "\n" + ].filter(filterEmptyLine).join("\n"); + } + vertexShader = resolveIncludes(vertexShader); + vertexShader = replaceLightNums(vertexShader, parameters); + vertexShader = replaceClippingPlaneNums(vertexShader, parameters); + fragmentShader = resolveIncludes(fragmentShader); + fragmentShader = replaceLightNums(fragmentShader, parameters); + fragmentShader = replaceClippingPlaneNums(fragmentShader, parameters); + vertexShader = unrollLoops(vertexShader); + fragmentShader = unrollLoops(fragmentShader); + if (parameters.isWebGL2 && parameters.isRawShaderMaterial !== true) { + versionString = "#version 300 es\n"; + prefixVertex = [ + "precision mediump sampler2DArray;", + "#define attribute in", + "#define varying out", + "#define texture2D texture" + ].join("\n") + "\n" + prefixVertex; + prefixFragment = [ + "#define varying in", + parameters.glslVersion === GLSL3 ? "" : "layout(location = 0) out highp vec4 pc_fragColor;", + parameters.glslVersion === GLSL3 ? "" : "#define gl_FragColor pc_fragColor", + "#define gl_FragDepthEXT gl_FragDepth", + "#define texture2D texture", + "#define textureCube texture", + "#define texture2DProj textureProj", + "#define texture2DLodEXT textureLod", + "#define texture2DProjLodEXT textureProjLod", + "#define textureCubeLodEXT textureLod", + "#define texture2DGradEXT textureGrad", + "#define texture2DProjGradEXT textureProjGrad", + "#define textureCubeGradEXT textureGrad" + ].join("\n") + "\n" + prefixFragment; + } + const vertexGlsl = versionString + prefixVertex + vertexShader; + const fragmentGlsl = versionString + prefixFragment + fragmentShader; + const glVertexShader = WebGLShader(gl, 35633, vertexGlsl); + const glFragmentShader = WebGLShader(gl, 35632, fragmentGlsl); + gl.attachShader(program, glVertexShader); + gl.attachShader(program, glFragmentShader); + if (parameters.index0AttributeName !== void 0) { + gl.bindAttribLocation(program, 0, parameters.index0AttributeName); + } else if (parameters.morphTargets === true) { + gl.bindAttribLocation(program, 0, "position"); + } + gl.linkProgram(program); + if (renderer.debug.checkShaderErrors) { + const programLog = gl.getProgramInfoLog(program).trim(); + const vertexLog = gl.getShaderInfoLog(glVertexShader).trim(); + const fragmentLog = gl.getShaderInfoLog(glFragmentShader).trim(); + let runnable = true; + let haveDiagnostics = true; + if (gl.getProgramParameter(program, 35714) === false) { + runnable = false; + const vertexErrors = getShaderErrors(gl, glVertexShader, "vertex"); + const fragmentErrors = getShaderErrors(gl, glFragmentShader, "fragment"); + console.error("THREE.WebGLProgram: Shader Error " + gl.getError() + " - VALIDATE_STATUS " + gl.getProgramParameter(program, 35715) + "\n\nProgram Info Log: " + programLog + "\n" + vertexErrors + "\n" + fragmentErrors); + } else if (programLog !== "") { + console.warn("THREE.WebGLProgram: Program Info Log:", programLog); + } else if (vertexLog === "" || fragmentLog === "") { + haveDiagnostics = false; + } + if (haveDiagnostics) { + this.diagnostics = { + runnable, + programLog, + vertexShader: { + log: vertexLog, + prefix: prefixVertex + }, + fragmentShader: { + log: fragmentLog, + prefix: prefixFragment + } + }; + } + } + gl.deleteShader(glVertexShader); + gl.deleteShader(glFragmentShader); + let cachedUniforms; + this.getUniforms = function() { + if (cachedUniforms === void 0) { + cachedUniforms = new WebGLUniforms(gl, program); + } + return cachedUniforms; + }; + let cachedAttributes; + this.getAttributes = function() { + if (cachedAttributes === void 0) { + cachedAttributes = fetchAttributeLocations(gl, program); + } + return cachedAttributes; + }; + this.destroy = function() { + bindingStates.releaseStatesOfProgram(this); + gl.deleteProgram(program); + this.program = void 0; + }; + this.name = parameters.shaderName; + this.id = programIdCount++; + this.cacheKey = cacheKey; + this.usedTimes = 1; + this.program = program; + this.vertexShader = glVertexShader; + this.fragmentShader = glFragmentShader; + return this; + } + var _id = 0; + var WebGLShaderCache = class { + constructor() { + this.shaderCache = /* @__PURE__ */ new Map(); + this.materialCache = /* @__PURE__ */ new Map(); + } + update(material) { + const vertexShader = material.vertexShader; + const fragmentShader = material.fragmentShader; + const vertexShaderStage = this._getShaderStage(vertexShader); + const fragmentShaderStage = this._getShaderStage(fragmentShader); + const materialShaders = this._getShaderCacheForMaterial(material); + if (materialShaders.has(vertexShaderStage) === false) { + materialShaders.add(vertexShaderStage); + vertexShaderStage.usedTimes++; + } + if (materialShaders.has(fragmentShaderStage) === false) { + materialShaders.add(fragmentShaderStage); + fragmentShaderStage.usedTimes++; + } + return this; + } + remove(material) { + const materialShaders = this.materialCache.get(material); + for (const shaderStage of materialShaders) { + shaderStage.usedTimes--; + if (shaderStage.usedTimes === 0) + this.shaderCache.delete(shaderStage.code); + } + this.materialCache.delete(material); + return this; + } + getVertexShaderID(material) { + return this._getShaderStage(material.vertexShader).id; + } + getFragmentShaderID(material) { + return this._getShaderStage(material.fragmentShader).id; + } + dispose() { + this.shaderCache.clear(); + this.materialCache.clear(); + } + _getShaderCacheForMaterial(material) { + const cache2 = this.materialCache; + if (cache2.has(material) === false) { + cache2.set(material, /* @__PURE__ */ new Set()); + } + return cache2.get(material); + } + _getShaderStage(code) { + const cache2 = this.shaderCache; + if (cache2.has(code) === false) { + const stage = new WebGLShaderStage(code); + cache2.set(code, stage); + } + return cache2.get(code); + } + }; + var WebGLShaderStage = class { + constructor(code) { + this.id = _id++; + this.code = code; + this.usedTimes = 0; + } + }; + function WebGLPrograms(renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping) { + const _programLayers = new Layers(); + const _customShaders = new WebGLShaderCache(); + const programs = []; + const isWebGL2 = capabilities.isWebGL2; + const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; + const vertexTextures = capabilities.vertexTextures; + let precision = capabilities.precision; + const shaderIDs = { + MeshDepthMaterial: "depth", + MeshDistanceMaterial: "distanceRGBA", + MeshNormalMaterial: "normal", + MeshBasicMaterial: "basic", + MeshLambertMaterial: "lambert", + MeshPhongMaterial: "phong", + MeshToonMaterial: "toon", + MeshStandardMaterial: "physical", + MeshPhysicalMaterial: "physical", + MeshMatcapMaterial: "matcap", + LineBasicMaterial: "basic", + LineDashedMaterial: "dashed", + PointsMaterial: "points", + ShadowMaterial: "shadow", + SpriteMaterial: "sprite" + }; + function getParameters(material, lights, shadows, scene, object) { + const fog = scene.fog; + const geometry = object.geometry; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment); + const envMapCubeUVHeight = !!envMap && envMap.mapping === CubeUVReflectionMapping ? envMap.image.height : null; + const shaderID = shaderIDs[material.type]; + if (material.precision !== null) { + precision = capabilities.getMaxPrecision(material.precision); + if (precision !== material.precision) { + console.warn("THREE.WebGLProgram.getParameters:", material.precision, "not supported, using", precision, "instead."); + } + } + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = morphAttribute !== void 0 ? morphAttribute.length : 0; + let morphTextureStride = 0; + if (geometry.morphAttributes.position !== void 0) + morphTextureStride = 1; + if (geometry.morphAttributes.normal !== void 0) + morphTextureStride = 2; + if (geometry.morphAttributes.color !== void 0) + morphTextureStride = 3; + let vertexShader, fragmentShader; + let customVertexShaderID, customFragmentShaderID; + if (shaderID) { + const shader = ShaderLib[shaderID]; + vertexShader = shader.vertexShader; + fragmentShader = shader.fragmentShader; + } else { + vertexShader = material.vertexShader; + fragmentShader = material.fragmentShader; + _customShaders.update(material); + customVertexShaderID = _customShaders.getVertexShaderID(material); + customFragmentShaderID = _customShaders.getFragmentShaderID(material); + } + const currentRenderTarget = renderer.getRenderTarget(); + const useAlphaTest = material.alphaTest > 0; + const useClearcoat = material.clearcoat > 0; + const useIridescence = material.iridescence > 0; + const parameters = { + isWebGL2, + shaderID, + shaderName: material.type, + vertexShader, + fragmentShader, + defines: material.defines, + customVertexShaderID, + customFragmentShaderID, + isRawShaderMaterial: material.isRawShaderMaterial === true, + glslVersion: material.glslVersion, + precision, + instancing: object.isInstancedMesh === true, + instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, + supportsVertexTextures: vertexTextures, + outputEncoding: currentRenderTarget === null ? renderer.outputEncoding : currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding, + map: !!material.map, + matcap: !!material.matcap, + envMap: !!envMap, + envMapMode: envMap && envMap.mapping, + envMapCubeUVHeight, + lightMap: !!material.lightMap, + aoMap: !!material.aoMap, + emissiveMap: !!material.emissiveMap, + bumpMap: !!material.bumpMap, + normalMap: !!material.normalMap, + objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, + tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, + decodeVideoTexture: !!material.map && material.map.isVideoTexture === true && material.map.encoding === sRGBEncoding, + clearcoat: useClearcoat, + clearcoatMap: useClearcoat && !!material.clearcoatMap, + clearcoatRoughnessMap: useClearcoat && !!material.clearcoatRoughnessMap, + clearcoatNormalMap: useClearcoat && !!material.clearcoatNormalMap, + iridescence: useIridescence, + iridescenceMap: useIridescence && !!material.iridescenceMap, + iridescenceThicknessMap: useIridescence && !!material.iridescenceThicknessMap, + displacementMap: !!material.displacementMap, + roughnessMap: !!material.roughnessMap, + metalnessMap: !!material.metalnessMap, + specularMap: !!material.specularMap, + specularIntensityMap: !!material.specularIntensityMap, + specularColorMap: !!material.specularColorMap, + opaque: material.transparent === false && material.blending === NormalBlending, + alphaMap: !!material.alphaMap, + alphaTest: useAlphaTest, + gradientMap: !!material.gradientMap, + sheen: material.sheen > 0, + sheenColorMap: !!material.sheenColorMap, + sheenRoughnessMap: !!material.sheenRoughnessMap, + transmission: material.transmission > 0, + transmissionMap: !!material.transmissionMap, + thicknessMap: !!material.thicknessMap, + combine: material.combine, + vertexTangents: !!material.normalMap && !!geometry.attributes.tangent, + vertexColors: material.vertexColors, + vertexAlphas: material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4, + vertexUvs: !!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatMap || !!material.clearcoatRoughnessMap || !!material.clearcoatNormalMap || !!material.iridescenceMap || !!material.iridescenceThicknessMap || !!material.displacementMap || !!material.transmissionMap || !!material.thicknessMap || !!material.specularIntensityMap || !!material.specularColorMap || !!material.sheenColorMap || !!material.sheenRoughnessMap, + uvsVertexOnly: !(!!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatNormalMap || !!material.iridescenceMap || !!material.iridescenceThicknessMap || material.transmission > 0 || !!material.transmissionMap || !!material.thicknessMap || !!material.specularIntensityMap || !!material.specularColorMap || material.sheen > 0 || !!material.sheenColorMap || !!material.sheenRoughnessMap) && !!material.displacementMap, + fog: !!fog, + useFog: material.fog === true, + fogExp2: fog && fog.isFogExp2, + flatShading: !!material.flatShading, + sizeAttenuation: material.sizeAttenuation, + logarithmicDepthBuffer, + skinning: object.isSkinnedMesh === true, + morphTargets: geometry.morphAttributes.position !== void 0, + morphNormals: geometry.morphAttributes.normal !== void 0, + morphColors: geometry.morphAttributes.color !== void 0, + morphTargetsCount, + morphTextureStride, + numDirLights: lights.directional.length, + numPointLights: lights.point.length, + numSpotLights: lights.spot.length, + numRectAreaLights: lights.rectArea.length, + numHemiLights: lights.hemi.length, + numDirLightShadows: lights.directionalShadowMap.length, + numPointLightShadows: lights.pointShadowMap.length, + numSpotLightShadows: lights.spotShadowMap.length, + numClippingPlanes: clipping.numPlanes, + numClipIntersection: clipping.numIntersection, + dithering: material.dithering, + shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, + shadowMapType: renderer.shadowMap.type, + toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping, + physicallyCorrectLights: renderer.physicallyCorrectLights, + premultipliedAlpha: material.premultipliedAlpha, + doubleSided: material.side === DoubleSide, + flipSided: material.side === BackSide, + useDepthPacking: !!material.depthPacking, + depthPacking: material.depthPacking || 0, + index0AttributeName: material.index0AttributeName, + extensionDerivatives: material.extensions && material.extensions.derivatives, + extensionFragDepth: material.extensions && material.extensions.fragDepth, + extensionDrawBuffers: material.extensions && material.extensions.drawBuffers, + extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD, + rendererExtensionFragDepth: isWebGL2 || extensions.has("EXT_frag_depth"), + rendererExtensionDrawBuffers: isWebGL2 || extensions.has("WEBGL_draw_buffers"), + rendererExtensionShaderTextureLod: isWebGL2 || extensions.has("EXT_shader_texture_lod"), + customProgramCacheKey: material.customProgramCacheKey() + }; + return parameters; + } + function getProgramCacheKey(parameters) { + const array2 = []; + if (parameters.shaderID) { + array2.push(parameters.shaderID); + } else { + array2.push(parameters.customVertexShaderID); + array2.push(parameters.customFragmentShaderID); + } + if (parameters.defines !== void 0) { + for (const name in parameters.defines) { + array2.push(name); + array2.push(parameters.defines[name]); + } + } + if (parameters.isRawShaderMaterial === false) { + getProgramCacheKeyParameters(array2, parameters); + getProgramCacheKeyBooleans(array2, parameters); + array2.push(renderer.outputEncoding); + } + array2.push(parameters.customProgramCacheKey); + return array2.join(); + } + function getProgramCacheKeyParameters(array2, parameters) { + array2.push(parameters.precision); + array2.push(parameters.outputEncoding); + array2.push(parameters.envMapMode); + array2.push(parameters.envMapCubeUVHeight); + array2.push(parameters.combine); + array2.push(parameters.vertexUvs); + array2.push(parameters.fogExp2); + array2.push(parameters.sizeAttenuation); + array2.push(parameters.morphTargetsCount); + array2.push(parameters.morphAttributeCount); + array2.push(parameters.numDirLights); + array2.push(parameters.numPointLights); + array2.push(parameters.numSpotLights); + array2.push(parameters.numHemiLights); + array2.push(parameters.numRectAreaLights); + array2.push(parameters.numDirLightShadows); + array2.push(parameters.numPointLightShadows); + array2.push(parameters.numSpotLightShadows); + array2.push(parameters.shadowMapType); + array2.push(parameters.toneMapping); + array2.push(parameters.numClippingPlanes); + array2.push(parameters.numClipIntersection); + array2.push(parameters.depthPacking); + } + function getProgramCacheKeyBooleans(array2, parameters) { + _programLayers.disableAll(); + if (parameters.isWebGL2) + _programLayers.enable(0); + if (parameters.supportsVertexTextures) + _programLayers.enable(1); + if (parameters.instancing) + _programLayers.enable(2); + if (parameters.instancingColor) + _programLayers.enable(3); + if (parameters.map) + _programLayers.enable(4); + if (parameters.matcap) + _programLayers.enable(5); + if (parameters.envMap) + _programLayers.enable(6); + if (parameters.lightMap) + _programLayers.enable(7); + if (parameters.aoMap) + _programLayers.enable(8); + if (parameters.emissiveMap) + _programLayers.enable(9); + if (parameters.bumpMap) + _programLayers.enable(10); + if (parameters.normalMap) + _programLayers.enable(11); + if (parameters.objectSpaceNormalMap) + _programLayers.enable(12); + if (parameters.tangentSpaceNormalMap) + _programLayers.enable(13); + if (parameters.clearcoat) + _programLayers.enable(14); + if (parameters.clearcoatMap) + _programLayers.enable(15); + if (parameters.clearcoatRoughnessMap) + _programLayers.enable(16); + if (parameters.clearcoatNormalMap) + _programLayers.enable(17); + if (parameters.iridescence) + _programLayers.enable(18); + if (parameters.iridescenceMap) + _programLayers.enable(19); + if (parameters.iridescenceThicknessMap) + _programLayers.enable(20); + if (parameters.displacementMap) + _programLayers.enable(21); + if (parameters.specularMap) + _programLayers.enable(22); + if (parameters.roughnessMap) + _programLayers.enable(23); + if (parameters.metalnessMap) + _programLayers.enable(24); + if (parameters.gradientMap) + _programLayers.enable(25); + if (parameters.alphaMap) + _programLayers.enable(26); + if (parameters.alphaTest) + _programLayers.enable(27); + if (parameters.vertexColors) + _programLayers.enable(28); + if (parameters.vertexAlphas) + _programLayers.enable(29); + if (parameters.vertexUvs) + _programLayers.enable(30); + if (parameters.vertexTangents) + _programLayers.enable(31); + if (parameters.uvsVertexOnly) + _programLayers.enable(32); + if (parameters.fog) + _programLayers.enable(33); + array2.push(_programLayers.mask); + _programLayers.disableAll(); + if (parameters.useFog) + _programLayers.enable(0); + if (parameters.flatShading) + _programLayers.enable(1); + if (parameters.logarithmicDepthBuffer) + _programLayers.enable(2); + if (parameters.skinning) + _programLayers.enable(3); + if (parameters.morphTargets) + _programLayers.enable(4); + if (parameters.morphNormals) + _programLayers.enable(5); + if (parameters.morphColors) + _programLayers.enable(6); + if (parameters.premultipliedAlpha) + _programLayers.enable(7); + if (parameters.shadowMapEnabled) + _programLayers.enable(8); + if (parameters.physicallyCorrectLights) + _programLayers.enable(9); + if (parameters.doubleSided) + _programLayers.enable(10); + if (parameters.flipSided) + _programLayers.enable(11); + if (parameters.useDepthPacking) + _programLayers.enable(12); + if (parameters.dithering) + _programLayers.enable(13); + if (parameters.specularIntensityMap) + _programLayers.enable(14); + if (parameters.specularColorMap) + _programLayers.enable(15); + if (parameters.transmission) + _programLayers.enable(16); + if (parameters.transmissionMap) + _programLayers.enable(17); + if (parameters.thicknessMap) + _programLayers.enable(18); + if (parameters.sheen) + _programLayers.enable(19); + if (parameters.sheenColorMap) + _programLayers.enable(20); + if (parameters.sheenRoughnessMap) + _programLayers.enable(21); + if (parameters.decodeVideoTexture) + _programLayers.enable(22); + if (parameters.opaque) + _programLayers.enable(23); + array2.push(_programLayers.mask); + } + function getUniforms(material) { + const shaderID = shaderIDs[material.type]; + let uniforms; + if (shaderID) { + const shader = ShaderLib[shaderID]; + uniforms = UniformsUtils.clone(shader.uniforms); + } else { + uniforms = material.uniforms; + } + return uniforms; + } + function acquireProgram(parameters, cacheKey) { + let program; + for (let p = 0, pl = programs.length; p < pl; p++) { + const preexistingProgram = programs[p]; + if (preexistingProgram.cacheKey === cacheKey) { + program = preexistingProgram; + ++program.usedTimes; + break; + } + } + if (program === void 0) { + program = new WebGLProgram(renderer, cacheKey, parameters, bindingStates); + programs.push(program); + } + return program; + } + function releaseProgram(program) { + if (--program.usedTimes === 0) { + const i = programs.indexOf(program); + programs[i] = programs[programs.length - 1]; + programs.pop(); + program.destroy(); + } + } + function releaseShaderCache(material) { + _customShaders.remove(material); + } + function dispose() { + _customShaders.dispose(); + } + return { + getParameters, + getProgramCacheKey, + getUniforms, + acquireProgram, + releaseProgram, + releaseShaderCache, + programs, + dispose + }; + } + function WebGLProperties() { + let properties = /* @__PURE__ */ new WeakMap(); + function get3(object) { + let map2 = properties.get(object); + if (map2 === void 0) { + map2 = {}; + properties.set(object, map2); + } + return map2; + } + function remove2(object) { + properties.delete(object); + } + function update(object, key, value) { + properties.get(object)[key] = value; + } + function dispose() { + properties = /* @__PURE__ */ new WeakMap(); + } + return { + get: get3, + remove: remove2, + update, + dispose + }; + } + function painterSortStable(a2, b) { + if (a2.groupOrder !== b.groupOrder) { + return a2.groupOrder - b.groupOrder; + } else if (a2.renderOrder !== b.renderOrder) { + return a2.renderOrder - b.renderOrder; + } else if (a2.material.id !== b.material.id) { + return a2.material.id - b.material.id; + } else if (a2.z !== b.z) { + return a2.z - b.z; + } else { + return a2.id - b.id; + } + } + function reversePainterSortStable(a2, b) { + if (a2.groupOrder !== b.groupOrder) { + return a2.groupOrder - b.groupOrder; + } else if (a2.renderOrder !== b.renderOrder) { + return a2.renderOrder - b.renderOrder; + } else if (a2.z !== b.z) { + return b.z - a2.z; + } else { + return a2.id - b.id; + } + } + function WebGLRenderList() { + const renderItems = []; + let renderItemsIndex = 0; + const opaque = []; + const transmissive = []; + const transparent = []; + function init2() { + renderItemsIndex = 0; + opaque.length = 0; + transmissive.length = 0; + transparent.length = 0; + } + function getNextRenderItem(object, geometry, material, groupOrder, z, group) { + let renderItem = renderItems[renderItemsIndex]; + if (renderItem === void 0) { + renderItem = { + id: object.id, + object, + geometry, + material, + groupOrder, + renderOrder: object.renderOrder, + z, + group + }; + renderItems[renderItemsIndex] = renderItem; + } else { + renderItem.id = object.id; + renderItem.object = object; + renderItem.geometry = geometry; + renderItem.material = material; + renderItem.groupOrder = groupOrder; + renderItem.renderOrder = object.renderOrder; + renderItem.z = z; + renderItem.group = group; + } + renderItemsIndex++; + return renderItem; + } + function push(object, geometry, material, groupOrder, z, group) { + const renderItem = getNextRenderItem(object, geometry, material, groupOrder, z, group); + if (material.transmission > 0) { + transmissive.push(renderItem); + } else if (material.transparent === true) { + transparent.push(renderItem); + } else { + opaque.push(renderItem); + } + } + function unshift(object, geometry, material, groupOrder, z, group) { + const renderItem = getNextRenderItem(object, geometry, material, groupOrder, z, group); + if (material.transmission > 0) { + transmissive.unshift(renderItem); + } else if (material.transparent === true) { + transparent.unshift(renderItem); + } else { + opaque.unshift(renderItem); + } + } + function sort(customOpaqueSort, customTransparentSort) { + if (opaque.length > 1) + opaque.sort(customOpaqueSort || painterSortStable); + if (transmissive.length > 1) + transmissive.sort(customTransparentSort || reversePainterSortStable); + if (transparent.length > 1) + transparent.sort(customTransparentSort || reversePainterSortStable); + } + function finish() { + for (let i = renderItemsIndex, il = renderItems.length; i < il; i++) { + const renderItem = renderItems[i]; + if (renderItem.id === null) + break; + renderItem.id = null; + renderItem.object = null; + renderItem.geometry = null; + renderItem.material = null; + renderItem.group = null; + } + } + return { + opaque, + transmissive, + transparent, + init: init2, + push, + unshift, + finish, + sort + }; + } + function WebGLRenderLists() { + let lists = /* @__PURE__ */ new WeakMap(); + function get3(scene, renderCallDepth) { + let list; + if (lists.has(scene) === false) { + list = new WebGLRenderList(); + lists.set(scene, [list]); + } else { + if (renderCallDepth >= lists.get(scene).length) { + list = new WebGLRenderList(); + lists.get(scene).push(list); + } else { + list = lists.get(scene)[renderCallDepth]; + } + } + return list; + } + function dispose() { + lists = /* @__PURE__ */ new WeakMap(); + } + return { + get: get3, + dispose + }; + } + function UniformsCache() { + const lights = {}; + return { + get: function(light) { + if (lights[light.id] !== void 0) { + return lights[light.id]; + } + let uniforms; + switch (light.type) { + case "DirectionalLight": + uniforms = { + direction: new Vector3(), + color: new Color2() + }; + break; + case "SpotLight": + uniforms = { + position: new Vector3(), + direction: new Vector3(), + color: new Color2(), + distance: 0, + coneCos: 0, + penumbraCos: 0, + decay: 0 + }; + break; + case "PointLight": + uniforms = { + position: new Vector3(), + color: new Color2(), + distance: 0, + decay: 0 + }; + break; + case "HemisphereLight": + uniforms = { + direction: new Vector3(), + skyColor: new Color2(), + groundColor: new Color2() + }; + break; + case "RectAreaLight": + uniforms = { + color: new Color2(), + position: new Vector3(), + halfWidth: new Vector3(), + halfHeight: new Vector3() + }; + break; + } + lights[light.id] = uniforms; + return uniforms; + } + }; + } + function ShadowUniformsCache() { + const lights = {}; + return { + get: function(light) { + if (lights[light.id] !== void 0) { + return lights[light.id]; + } + let uniforms; + switch (light.type) { + case "DirectionalLight": + uniforms = { + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2() + }; + break; + case "SpotLight": + uniforms = { + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2() + }; + break; + case "PointLight": + uniforms = { + shadowBias: 0, + shadowNormalBias: 0, + shadowRadius: 1, + shadowMapSize: new Vector2(), + shadowCameraNear: 1, + shadowCameraFar: 1e3 + }; + break; + } + lights[light.id] = uniforms; + return uniforms; + } + }; + } + var nextVersion = 0; + function shadowCastingLightsFirst(lightA, lightB) { + return (lightB.castShadow ? 1 : 0) - (lightA.castShadow ? 1 : 0); + } + function WebGLLights(extensions, capabilities) { + const cache2 = new UniformsCache(); + const shadowCache = ShadowUniformsCache(); + const state = { + version: 0, + hash: { + directionalLength: -1, + pointLength: -1, + spotLength: -1, + rectAreaLength: -1, + hemiLength: -1, + numDirectionalShadows: -1, + numPointShadows: -1, + numSpotShadows: -1 + }, + ambient: [0, 0, 0], + probe: [], + directional: [], + directionalShadow: [], + directionalShadowMap: [], + directionalShadowMatrix: [], + spot: [], + spotShadow: [], + spotShadowMap: [], + spotShadowMatrix: [], + rectArea: [], + rectAreaLTC1: null, + rectAreaLTC2: null, + point: [], + pointShadow: [], + pointShadowMap: [], + pointShadowMatrix: [], + hemi: [] + }; + for (let i = 0; i < 9; i++) + state.probe.push(new Vector3()); + const vector3 = new Vector3(); + const matrix4 = new Matrix4(); + const matrix42 = new Matrix4(); + function setup(lights, physicallyCorrectLights) { + let r = 0, g = 0, b = 0; + for (let i = 0; i < 9; i++) + state.probe[i].set(0, 0, 0); + let directionalLength = 0; + let pointLength = 0; + let spotLength = 0; + let rectAreaLength = 0; + let hemiLength = 0; + let numDirectionalShadows = 0; + let numPointShadows = 0; + let numSpotShadows = 0; + lights.sort(shadowCastingLightsFirst); + const scaleFactor = physicallyCorrectLights !== true ? Math.PI : 1; + for (let i = 0, l = lights.length; i < l; i++) { + const light = lights[i]; + const color2 = light.color; + const intensity = light.intensity; + const distance = light.distance; + const shadowMap = light.shadow && light.shadow.map ? light.shadow.map.texture : null; + if (light.isAmbientLight) { + r += color2.r * intensity * scaleFactor; + g += color2.g * intensity * scaleFactor; + b += color2.b * intensity * scaleFactor; + } else if (light.isLightProbe) { + for (let j = 0; j < 9; j++) { + state.probe[j].addScaledVector(light.sh.coefficients[j], intensity); + } + } else if (light.isDirectionalLight) { + const uniforms = cache2.get(light); + uniforms.color.copy(light.color).multiplyScalar(light.intensity * scaleFactor); + if (light.castShadow) { + const shadow = light.shadow; + const shadowUniforms = shadowCache.get(light); + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; + state.directionalShadow[directionalLength] = shadowUniforms; + state.directionalShadowMap[directionalLength] = shadowMap; + state.directionalShadowMatrix[directionalLength] = light.shadow.matrix; + numDirectionalShadows++; + } + state.directional[directionalLength] = uniforms; + directionalLength++; + } else if (light.isSpotLight) { + const uniforms = cache2.get(light); + uniforms.position.setFromMatrixPosition(light.matrixWorld); + uniforms.color.copy(color2).multiplyScalar(intensity * scaleFactor); + uniforms.distance = distance; + uniforms.coneCos = Math.cos(light.angle); + uniforms.penumbraCos = Math.cos(light.angle * (1 - light.penumbra)); + uniforms.decay = light.decay; + if (light.castShadow) { + const shadow = light.shadow; + const shadowUniforms = shadowCache.get(light); + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; + state.spotShadow[spotLength] = shadowUniforms; + state.spotShadowMap[spotLength] = shadowMap; + state.spotShadowMatrix[spotLength] = light.shadow.matrix; + numSpotShadows++; + } + state.spot[spotLength] = uniforms; + spotLength++; + } else if (light.isRectAreaLight) { + const uniforms = cache2.get(light); + uniforms.color.copy(color2).multiplyScalar(intensity); + uniforms.halfWidth.set(light.width * 0.5, 0, 0); + uniforms.halfHeight.set(0, light.height * 0.5, 0); + state.rectArea[rectAreaLength] = uniforms; + rectAreaLength++; + } else if (light.isPointLight) { + const uniforms = cache2.get(light); + uniforms.color.copy(light.color).multiplyScalar(light.intensity * scaleFactor); + uniforms.distance = light.distance; + uniforms.decay = light.decay; + if (light.castShadow) { + const shadow = light.shadow; + const shadowUniforms = shadowCache.get(light); + shadowUniforms.shadowBias = shadow.bias; + shadowUniforms.shadowNormalBias = shadow.normalBias; + shadowUniforms.shadowRadius = shadow.radius; + shadowUniforms.shadowMapSize = shadow.mapSize; + shadowUniforms.shadowCameraNear = shadow.camera.near; + shadowUniforms.shadowCameraFar = shadow.camera.far; + state.pointShadow[pointLength] = shadowUniforms; + state.pointShadowMap[pointLength] = shadowMap; + state.pointShadowMatrix[pointLength] = light.shadow.matrix; + numPointShadows++; + } + state.point[pointLength] = uniforms; + pointLength++; + } else if (light.isHemisphereLight) { + const uniforms = cache2.get(light); + uniforms.skyColor.copy(light.color).multiplyScalar(intensity * scaleFactor); + uniforms.groundColor.copy(light.groundColor).multiplyScalar(intensity * scaleFactor); + state.hemi[hemiLength] = uniforms; + hemiLength++; + } + } + if (rectAreaLength > 0) { + if (capabilities.isWebGL2) { + state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; + state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; + } else { + if (extensions.has("OES_texture_float_linear") === true) { + state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; + state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; + } else if (extensions.has("OES_texture_half_float_linear") === true) { + state.rectAreaLTC1 = UniformsLib.LTC_HALF_1; + state.rectAreaLTC2 = UniformsLib.LTC_HALF_2; + } else { + console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions."); + } + } + } + state.ambient[0] = r; + state.ambient[1] = g; + state.ambient[2] = b; + const hash = state.hash; + if (hash.directionalLength !== directionalLength || hash.pointLength !== pointLength || hash.spotLength !== spotLength || hash.rectAreaLength !== rectAreaLength || hash.hemiLength !== hemiLength || hash.numDirectionalShadows !== numDirectionalShadows || hash.numPointShadows !== numPointShadows || hash.numSpotShadows !== numSpotShadows) { + state.directional.length = directionalLength; + state.spot.length = spotLength; + state.rectArea.length = rectAreaLength; + state.point.length = pointLength; + state.hemi.length = hemiLength; + state.directionalShadow.length = numDirectionalShadows; + state.directionalShadowMap.length = numDirectionalShadows; + state.pointShadow.length = numPointShadows; + state.pointShadowMap.length = numPointShadows; + state.spotShadow.length = numSpotShadows; + state.spotShadowMap.length = numSpotShadows; + state.directionalShadowMatrix.length = numDirectionalShadows; + state.pointShadowMatrix.length = numPointShadows; + state.spotShadowMatrix.length = numSpotShadows; + hash.directionalLength = directionalLength; + hash.pointLength = pointLength; + hash.spotLength = spotLength; + hash.rectAreaLength = rectAreaLength; + hash.hemiLength = hemiLength; + hash.numDirectionalShadows = numDirectionalShadows; + hash.numPointShadows = numPointShadows; + hash.numSpotShadows = numSpotShadows; + state.version = nextVersion++; + } + } + function setupView(lights, camera) { + let directionalLength = 0; + let pointLength = 0; + let spotLength = 0; + let rectAreaLength = 0; + let hemiLength = 0; + const viewMatrix = camera.matrixWorldInverse; + for (let i = 0, l = lights.length; i < l; i++) { + const light = lights[i]; + if (light.isDirectionalLight) { + const uniforms = state.directional[directionalLength]; + uniforms.direction.setFromMatrixPosition(light.matrixWorld); + vector3.setFromMatrixPosition(light.target.matrixWorld); + uniforms.direction.sub(vector3); + uniforms.direction.transformDirection(viewMatrix); + directionalLength++; + } else if (light.isSpotLight) { + const uniforms = state.spot[spotLength]; + uniforms.position.setFromMatrixPosition(light.matrixWorld); + uniforms.position.applyMatrix4(viewMatrix); + uniforms.direction.setFromMatrixPosition(light.matrixWorld); + vector3.setFromMatrixPosition(light.target.matrixWorld); + uniforms.direction.sub(vector3); + uniforms.direction.transformDirection(viewMatrix); + spotLength++; + } else if (light.isRectAreaLight) { + const uniforms = state.rectArea[rectAreaLength]; + uniforms.position.setFromMatrixPosition(light.matrixWorld); + uniforms.position.applyMatrix4(viewMatrix); + matrix42.identity(); + matrix4.copy(light.matrixWorld); + matrix4.premultiply(viewMatrix); + matrix42.extractRotation(matrix4); + uniforms.halfWidth.set(light.width * 0.5, 0, 0); + uniforms.halfHeight.set(0, light.height * 0.5, 0); + uniforms.halfWidth.applyMatrix4(matrix42); + uniforms.halfHeight.applyMatrix4(matrix42); + rectAreaLength++; + } else if (light.isPointLight) { + const uniforms = state.point[pointLength]; + uniforms.position.setFromMatrixPosition(light.matrixWorld); + uniforms.position.applyMatrix4(viewMatrix); + pointLength++; + } else if (light.isHemisphereLight) { + const uniforms = state.hemi[hemiLength]; + uniforms.direction.setFromMatrixPosition(light.matrixWorld); + uniforms.direction.transformDirection(viewMatrix); + hemiLength++; + } + } + } + return { + setup, + setupView, + state + }; + } + function WebGLRenderState(extensions, capabilities) { + const lights = new WebGLLights(extensions, capabilities); + const lightsArray = []; + const shadowsArray = []; + function init2() { + lightsArray.length = 0; + shadowsArray.length = 0; + } + function pushLight(light) { + lightsArray.push(light); + } + function pushShadow(shadowLight) { + shadowsArray.push(shadowLight); + } + function setupLights(physicallyCorrectLights) { + lights.setup(lightsArray, physicallyCorrectLights); + } + function setupLightsView(camera) { + lights.setupView(lightsArray, camera); + } + const state = { + lightsArray, + shadowsArray, + lights + }; + return { + init: init2, + state, + setupLights, + setupLightsView, + pushLight, + pushShadow + }; + } + function WebGLRenderStates(extensions, capabilities) { + let renderStates = /* @__PURE__ */ new WeakMap(); + function get3(scene, renderCallDepth = 0) { + let renderState; + if (renderStates.has(scene) === false) { + renderState = new WebGLRenderState(extensions, capabilities); + renderStates.set(scene, [renderState]); + } else { + if (renderCallDepth >= renderStates.get(scene).length) { + renderState = new WebGLRenderState(extensions, capabilities); + renderStates.get(scene).push(renderState); + } else { + renderState = renderStates.get(scene)[renderCallDepth]; + } + } + return renderState; + } + function dispose() { + renderStates = /* @__PURE__ */ new WeakMap(); + } + return { + get: get3, + dispose + }; + } + var MeshDepthMaterial = class extends Material { + constructor(parameters) { + super(); + this.isMeshDepthMaterial = true; + this.type = "MeshDepthMaterial"; + this.depthPacking = BasicDepthPacking; + this.map = null; + this.alphaMap = null; + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.depthPacking = source.depthPacking; + this.map = source.map; + this.alphaMap = source.alphaMap; + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + return this; + } + }; + var MeshDistanceMaterial = class extends Material { + constructor(parameters) { + super(); + this.isMeshDistanceMaterial = true; + this.type = "MeshDistanceMaterial"; + this.referencePosition = new Vector3(); + this.nearDistance = 1; + this.farDistance = 1e3; + this.map = null; + this.alphaMap = null; + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + this.setValues(parameters); + } + copy(source) { + super.copy(source); + this.referencePosition.copy(source.referencePosition); + this.nearDistance = source.nearDistance; + this.farDistance = source.farDistance; + this.map = source.map; + this.alphaMap = source.alphaMap; + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + return this; + } + }; + var vertex = "void main() {\n gl_Position = vec4( position, 1.0 );\n}"; + var fragment = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n const float samples = float( VSM_SAMPLES );\n float mean = 0.0;\n float squared_mean = 0.0;\n float uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n float uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n for ( float i = 0.0; i < samples; i ++ ) {\n float uvOffset = uvStart + i * uvStride;\n #ifdef HORIZONTAL_PASS\n vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n mean += distribution.x;\n squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n #else\n float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n mean += depth;\n squared_mean += depth * depth;\n #endif\n }\n mean = mean / samples;\n squared_mean = squared_mean / samples;\n float std_dev = sqrt( squared_mean - mean * mean );\n gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"; + function WebGLShadowMap(_renderer, _objects, _capabilities) { + let _frustum = new Frustum(); + const _shadowMapSize = new Vector2(), _viewportSize = new Vector2(), _viewport = new Vector4(), _depthMaterial = new MeshDepthMaterial({ depthPacking: RGBADepthPacking }), _distanceMaterial = new MeshDistanceMaterial(), _materialCache = {}, _maxTextureSize = _capabilities.maxTextureSize; + const shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide }; + const shadowMaterialVertical = new ShaderMaterial({ + defines: { + VSM_SAMPLES: 8 + }, + uniforms: { + shadow_pass: { value: null }, + resolution: { value: new Vector2() }, + radius: { value: 4 } + }, + vertexShader: vertex, + fragmentShader: fragment + }); + const shadowMaterialHorizontal = shadowMaterialVertical.clone(); + shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1; + const fullScreenTri = new BufferGeometry(); + fullScreenTri.setAttribute("position", new BufferAttribute(new Float32Array([-1, -1, 0.5, 3, -1, 0.5, -1, 3, 0.5]), 3)); + const fullScreenMesh = new Mesh(fullScreenTri, shadowMaterialVertical); + const scope = this; + this.enabled = false; + this.autoUpdate = true; + this.needsUpdate = false; + this.type = PCFShadowMap; + this.render = function(lights, scene, camera) { + if (scope.enabled === false) + return; + if (scope.autoUpdate === false && scope.needsUpdate === false) + return; + if (lights.length === 0) + return; + const currentRenderTarget = _renderer.getRenderTarget(); + const activeCubeFace = _renderer.getActiveCubeFace(); + const activeMipmapLevel = _renderer.getActiveMipmapLevel(); + const _state = _renderer.state; + _state.setBlending(NoBlending); + _state.buffers.color.setClear(1, 1, 1, 1); + _state.buffers.depth.setTest(true); + _state.setScissorTest(false); + for (let i = 0, il = lights.length; i < il; i++) { + const light = lights[i]; + const shadow = light.shadow; + if (shadow === void 0) { + console.warn("THREE.WebGLShadowMap:", light, "has no shadow."); + continue; + } + if (shadow.autoUpdate === false && shadow.needsUpdate === false) + continue; + _shadowMapSize.copy(shadow.mapSize); + const shadowFrameExtents = shadow.getFrameExtents(); + _shadowMapSize.multiply(shadowFrameExtents); + _viewportSize.copy(shadow.mapSize); + if (_shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize) { + if (_shadowMapSize.x > _maxTextureSize) { + _viewportSize.x = Math.floor(_maxTextureSize / shadowFrameExtents.x); + _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x; + shadow.mapSize.x = _viewportSize.x; + } + if (_shadowMapSize.y > _maxTextureSize) { + _viewportSize.y = Math.floor(_maxTextureSize / shadowFrameExtents.y); + _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y; + shadow.mapSize.y = _viewportSize.y; + } + } + if (shadow.map === null) { + const pars = this.type !== VSMShadowMap ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; + shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars); + shadow.map.texture.name = light.name + ".shadowMap"; + shadow.camera.updateProjectionMatrix(); + } + _renderer.setRenderTarget(shadow.map); + _renderer.clear(); + const viewportCount = shadow.getViewportCount(); + for (let vp = 0; vp < viewportCount; vp++) { + const viewport = shadow.getViewport(vp); + _viewport.set(_viewportSize.x * viewport.x, _viewportSize.y * viewport.y, _viewportSize.x * viewport.z, _viewportSize.y * viewport.w); + _state.viewport(_viewport); + shadow.updateMatrices(light, vp); + _frustum = shadow.getFrustum(); + renderObject(scene, camera, shadow.camera, light, this.type); + } + if (shadow.isPointLightShadow !== true && this.type === VSMShadowMap) { + VSMPass(shadow, camera); + } + shadow.needsUpdate = false; + } + scope.needsUpdate = false; + _renderer.setRenderTarget(currentRenderTarget, activeCubeFace, activeMipmapLevel); + }; + function VSMPass(shadow, camera) { + const geometry = _objects.update(fullScreenMesh); + if (shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples) { + shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples; + shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples; + shadowMaterialVertical.needsUpdate = true; + shadowMaterialHorizontal.needsUpdate = true; + } + if (shadow.mapPass === null) { + shadow.mapPass = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y); + } + shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture; + shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize; + shadowMaterialVertical.uniforms.radius.value = shadow.radius; + _renderer.setRenderTarget(shadow.mapPass); + _renderer.clear(); + _renderer.renderBufferDirect(camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null); + shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture; + shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize; + shadowMaterialHorizontal.uniforms.radius.value = shadow.radius; + _renderer.setRenderTarget(shadow.map); + _renderer.clear(); + _renderer.renderBufferDirect(camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null); + } + function getDepthMaterial(object, material, light, shadowCameraNear, shadowCameraFar, type2) { + let result = null; + const customMaterial = light.isPointLight === true ? object.customDistanceMaterial : object.customDepthMaterial; + if (customMaterial !== void 0) { + result = customMaterial; + } else { + result = light.isPointLight === true ? _distanceMaterial : _depthMaterial; + } + if (_renderer.localClippingEnabled && material.clipShadows === true && Array.isArray(material.clippingPlanes) && material.clippingPlanes.length !== 0 || material.displacementMap && material.displacementScale !== 0 || material.alphaMap && material.alphaTest > 0) { + const keyA = result.uuid, keyB = material.uuid; + let materialsForVariant = _materialCache[keyA]; + if (materialsForVariant === void 0) { + materialsForVariant = {}; + _materialCache[keyA] = materialsForVariant; + } + let cachedMaterial = materialsForVariant[keyB]; + if (cachedMaterial === void 0) { + cachedMaterial = result.clone(); + materialsForVariant[keyB] = cachedMaterial; + } + result = cachedMaterial; + } + result.visible = material.visible; + result.wireframe = material.wireframe; + if (type2 === VSMShadowMap) { + result.side = material.shadowSide !== null ? material.shadowSide : material.side; + } else { + result.side = material.shadowSide !== null ? material.shadowSide : shadowSide[material.side]; + } + result.alphaMap = material.alphaMap; + result.alphaTest = material.alphaTest; + result.clipShadows = material.clipShadows; + result.clippingPlanes = material.clippingPlanes; + result.clipIntersection = material.clipIntersection; + result.displacementMap = material.displacementMap; + result.displacementScale = material.displacementScale; + result.displacementBias = material.displacementBias; + result.wireframeLinewidth = material.wireframeLinewidth; + result.linewidth = material.linewidth; + if (light.isPointLight === true && result.isMeshDistanceMaterial === true) { + result.referencePosition.setFromMatrixPosition(light.matrixWorld); + result.nearDistance = shadowCameraNear; + result.farDistance = shadowCameraFar; + } + return result; + } + function renderObject(object, camera, shadowCamera, light, type2) { + if (object.visible === false) + return; + const visible = object.layers.test(camera.layers); + if (visible && (object.isMesh || object.isLine || object.isPoints)) { + if ((object.castShadow || object.receiveShadow && type2 === VSMShadowMap) && (!object.frustumCulled || _frustum.intersectsObject(object))) { + object.modelViewMatrix.multiplyMatrices(shadowCamera.matrixWorldInverse, object.matrixWorld); + const geometry = _objects.update(object); + const material = object.material; + if (Array.isArray(material)) { + const groups = geometry.groups; + for (let k = 0, kl = groups.length; k < kl; k++) { + const group = groups[k]; + const groupMaterial = material[group.materialIndex]; + if (groupMaterial && groupMaterial.visible) { + const depthMaterial = getDepthMaterial(object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type2); + _renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, group); + } + } + } else if (material.visible) { + const depthMaterial = getDepthMaterial(object, material, light, shadowCamera.near, shadowCamera.far, type2); + _renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, null); + } + } + } + const children2 = object.children; + for (let i = 0, l = children2.length; i < l; i++) { + renderObject(children2[i], camera, shadowCamera, light, type2); + } + } + } + function WebGLState(gl, extensions, capabilities) { + const isWebGL2 = capabilities.isWebGL2; + function ColorBuffer() { + let locked = false; + const color2 = new Vector4(); + let currentColorMask = null; + const currentColorClear = new Vector4(0, 0, 0, 0); + return { + setMask: function(colorMask) { + if (currentColorMask !== colorMask && !locked) { + gl.colorMask(colorMask, colorMask, colorMask, colorMask); + currentColorMask = colorMask; + } + }, + setLocked: function(lock) { + locked = lock; + }, + setClear: function(r, g, b, a2, premultipliedAlpha) { + if (premultipliedAlpha === true) { + r *= a2; + g *= a2; + b *= a2; + } + color2.set(r, g, b, a2); + if (currentColorClear.equals(color2) === false) { + gl.clearColor(r, g, b, a2); + currentColorClear.copy(color2); + } + }, + reset: function() { + locked = false; + currentColorMask = null; + currentColorClear.set(-1, 0, 0, 0); + } + }; + } + function DepthBuffer() { + let locked = false; + let currentDepthMask = null; + let currentDepthFunc = null; + let currentDepthClear = null; + return { + setTest: function(depthTest) { + if (depthTest) { + enable(2929); + } else { + disable(2929); + } + }, + setMask: function(depthMask) { + if (currentDepthMask !== depthMask && !locked) { + gl.depthMask(depthMask); + currentDepthMask = depthMask; + } + }, + setFunc: function(depthFunc) { + if (currentDepthFunc !== depthFunc) { + if (depthFunc) { + switch (depthFunc) { + case NeverDepth: + gl.depthFunc(512); + break; + case AlwaysDepth: + gl.depthFunc(519); + break; + case LessDepth: + gl.depthFunc(513); + break; + case LessEqualDepth: + gl.depthFunc(515); + break; + case EqualDepth: + gl.depthFunc(514); + break; + case GreaterEqualDepth: + gl.depthFunc(518); + break; + case GreaterDepth: + gl.depthFunc(516); + break; + case NotEqualDepth: + gl.depthFunc(517); + break; + default: + gl.depthFunc(515); + } + } else { + gl.depthFunc(515); + } + currentDepthFunc = depthFunc; + } + }, + setLocked: function(lock) { + locked = lock; + }, + setClear: function(depth) { + if (currentDepthClear !== depth) { + gl.clearDepth(depth); + currentDepthClear = depth; + } + }, + reset: function() { + locked = false; + currentDepthMask = null; + currentDepthFunc = null; + currentDepthClear = null; + } + }; + } + function StencilBuffer() { + let locked = false; + let currentStencilMask = null; + let currentStencilFunc = null; + let currentStencilRef = null; + let currentStencilFuncMask = null; + let currentStencilFail = null; + let currentStencilZFail = null; + let currentStencilZPass = null; + let currentStencilClear = null; + return { + setTest: function(stencilTest) { + if (!locked) { + if (stencilTest) { + enable(2960); + } else { + disable(2960); + } + } + }, + setMask: function(stencilMask) { + if (currentStencilMask !== stencilMask && !locked) { + gl.stencilMask(stencilMask); + currentStencilMask = stencilMask; + } + }, + setFunc: function(stencilFunc, stencilRef, stencilMask) { + if (currentStencilFunc !== stencilFunc || currentStencilRef !== stencilRef || currentStencilFuncMask !== stencilMask) { + gl.stencilFunc(stencilFunc, stencilRef, stencilMask); + currentStencilFunc = stencilFunc; + currentStencilRef = stencilRef; + currentStencilFuncMask = stencilMask; + } + }, + setOp: function(stencilFail, stencilZFail, stencilZPass) { + if (currentStencilFail !== stencilFail || currentStencilZFail !== stencilZFail || currentStencilZPass !== stencilZPass) { + gl.stencilOp(stencilFail, stencilZFail, stencilZPass); + currentStencilFail = stencilFail; + currentStencilZFail = stencilZFail; + currentStencilZPass = stencilZPass; + } + }, + setLocked: function(lock) { + locked = lock; + }, + setClear: function(stencil) { + if (currentStencilClear !== stencil) { + gl.clearStencil(stencil); + currentStencilClear = stencil; + } + }, + reset: function() { + locked = false; + currentStencilMask = null; + currentStencilFunc = null; + currentStencilRef = null; + currentStencilFuncMask = null; + currentStencilFail = null; + currentStencilZFail = null; + currentStencilZPass = null; + currentStencilClear = null; + } + }; + } + const colorBuffer = new ColorBuffer(); + const depthBuffer = new DepthBuffer(); + const stencilBuffer = new StencilBuffer(); + const uboBindings = /* @__PURE__ */ new WeakMap(); + const uboProgamMap = /* @__PURE__ */ new WeakMap(); + let enabledCapabilities = {}; + let currentBoundFramebuffers = {}; + let currentDrawbuffers = /* @__PURE__ */ new WeakMap(); + let defaultDrawbuffers = []; + let currentProgram = null; + let currentBlendingEnabled = false; + let currentBlending = null; + let currentBlendEquation = null; + let currentBlendSrc = null; + let currentBlendDst = null; + let currentBlendEquationAlpha = null; + let currentBlendSrcAlpha = null; + let currentBlendDstAlpha = null; + let currentPremultipledAlpha = false; + let currentFlipSided = null; + let currentCullFace = null; + let currentLineWidth = null; + let currentPolygonOffsetFactor = null; + let currentPolygonOffsetUnits = null; + const maxTextures = gl.getParameter(35661); + let lineWidthAvailable = false; + let version = 0; + const glVersion = gl.getParameter(7938); + if (glVersion.indexOf("WebGL") !== -1) { + version = parseFloat(/^WebGL (\d)/.exec(glVersion)[1]); + lineWidthAvailable = version >= 1; + } else if (glVersion.indexOf("OpenGL ES") !== -1) { + version = parseFloat(/^OpenGL ES (\d)/.exec(glVersion)[1]); + lineWidthAvailable = version >= 2; + } + let currentTextureSlot = null; + let currentBoundTextures = {}; + const scissorParam = gl.getParameter(3088); + const viewportParam = gl.getParameter(2978); + const currentScissor = new Vector4().fromArray(scissorParam); + const currentViewport = new Vector4().fromArray(viewportParam); + function createTexture(type2, target, count) { + const data = new Uint8Array(4); + const texture = gl.createTexture(); + gl.bindTexture(type2, texture); + gl.texParameteri(type2, 10241, 9728); + gl.texParameteri(type2, 10240, 9728); + for (let i = 0; i < count; i++) { + gl.texImage2D(target + i, 0, 6408, 1, 1, 0, 6408, 5121, data); + } + return texture; + } + const emptyTextures = {}; + emptyTextures[3553] = createTexture(3553, 3553, 1); + emptyTextures[34067] = createTexture(34067, 34069, 6); + colorBuffer.setClear(0, 0, 0, 1); + depthBuffer.setClear(1); + stencilBuffer.setClear(0); + enable(2929); + depthBuffer.setFunc(LessEqualDepth); + setFlipSided(false); + setCullFace(CullFaceBack); + enable(2884); + setBlending(NoBlending); + function enable(id2) { + if (enabledCapabilities[id2] !== true) { + gl.enable(id2); + enabledCapabilities[id2] = true; + } + } + function disable(id2) { + if (enabledCapabilities[id2] !== false) { + gl.disable(id2); + enabledCapabilities[id2] = false; + } + } + function bindFramebuffer(target, framebuffer) { + if (currentBoundFramebuffers[target] !== framebuffer) { + gl.bindFramebuffer(target, framebuffer); + currentBoundFramebuffers[target] = framebuffer; + if (isWebGL2) { + if (target === 36009) { + currentBoundFramebuffers[36160] = framebuffer; + } + if (target === 36160) { + currentBoundFramebuffers[36009] = framebuffer; + } + } + return true; + } + return false; + } + function drawBuffers(renderTarget, framebuffer) { + let drawBuffers2 = defaultDrawbuffers; + let needsUpdate = false; + if (renderTarget) { + drawBuffers2 = currentDrawbuffers.get(framebuffer); + if (drawBuffers2 === void 0) { + drawBuffers2 = []; + currentDrawbuffers.set(framebuffer, drawBuffers2); + } + if (renderTarget.isWebGLMultipleRenderTargets) { + const textures = renderTarget.texture; + if (drawBuffers2.length !== textures.length || drawBuffers2[0] !== 36064) { + for (let i = 0, il = textures.length; i < il; i++) { + drawBuffers2[i] = 36064 + i; + } + drawBuffers2.length = textures.length; + needsUpdate = true; + } + } else { + if (drawBuffers2[0] !== 36064) { + drawBuffers2[0] = 36064; + needsUpdate = true; + } + } + } else { + if (drawBuffers2[0] !== 1029) { + drawBuffers2[0] = 1029; + needsUpdate = true; + } + } + if (needsUpdate) { + if (capabilities.isWebGL2) { + gl.drawBuffers(drawBuffers2); + } else { + extensions.get("WEBGL_draw_buffers").drawBuffersWEBGL(drawBuffers2); + } + } + } + function useProgram(program) { + if (currentProgram !== program) { + gl.useProgram(program); + currentProgram = program; + return true; + } + return false; + } + const equationToGL = { + [AddEquation]: 32774, + [SubtractEquation]: 32778, + [ReverseSubtractEquation]: 32779 + }; + if (isWebGL2) { + equationToGL[MinEquation] = 32775; + equationToGL[MaxEquation] = 32776; + } else { + const extension = extensions.get("EXT_blend_minmax"); + if (extension !== null) { + equationToGL[MinEquation] = extension.MIN_EXT; + equationToGL[MaxEquation] = extension.MAX_EXT; + } + } + const factorToGL = { + [ZeroFactor]: 0, + [OneFactor]: 1, + [SrcColorFactor]: 768, + [SrcAlphaFactor]: 770, + [SrcAlphaSaturateFactor]: 776, + [DstColorFactor]: 774, + [DstAlphaFactor]: 772, + [OneMinusSrcColorFactor]: 769, + [OneMinusSrcAlphaFactor]: 771, + [OneMinusDstColorFactor]: 775, + [OneMinusDstAlphaFactor]: 773 + }; + function setBlending(blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha) { + if (blending === NoBlending) { + if (currentBlendingEnabled === true) { + disable(3042); + currentBlendingEnabled = false; + } + return; + } + if (currentBlendingEnabled === false) { + enable(3042); + currentBlendingEnabled = true; + } + if (blending !== CustomBlending) { + if (blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha) { + if (currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation) { + gl.blendEquation(32774); + currentBlendEquation = AddEquation; + currentBlendEquationAlpha = AddEquation; + } + if (premultipliedAlpha) { + switch (blending) { + case NormalBlending: + gl.blendFuncSeparate(1, 771, 1, 771); + break; + case AdditiveBlending: + gl.blendFunc(1, 1); + break; + case SubtractiveBlending: + gl.blendFuncSeparate(0, 769, 0, 1); + break; + case MultiplyBlending: + gl.blendFuncSeparate(0, 768, 0, 770); + break; + default: + console.error("THREE.WebGLState: Invalid blending: ", blending); + break; + } + } else { + switch (blending) { + case NormalBlending: + gl.blendFuncSeparate(770, 771, 1, 771); + break; + case AdditiveBlending: + gl.blendFunc(770, 1); + break; + case SubtractiveBlending: + gl.blendFuncSeparate(0, 769, 0, 1); + break; + case MultiplyBlending: + gl.blendFunc(0, 768); + break; + default: + console.error("THREE.WebGLState: Invalid blending: ", blending); + break; + } + } + currentBlendSrc = null; + currentBlendDst = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + currentBlending = blending; + currentPremultipledAlpha = premultipliedAlpha; + } + return; + } + blendEquationAlpha = blendEquationAlpha || blendEquation; + blendSrcAlpha = blendSrcAlpha || blendSrc; + blendDstAlpha = blendDstAlpha || blendDst; + if (blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha) { + gl.blendEquationSeparate(equationToGL[blendEquation], equationToGL[blendEquationAlpha]); + currentBlendEquation = blendEquation; + currentBlendEquationAlpha = blendEquationAlpha; + } + if (blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha) { + gl.blendFuncSeparate(factorToGL[blendSrc], factorToGL[blendDst], factorToGL[blendSrcAlpha], factorToGL[blendDstAlpha]); + currentBlendSrc = blendSrc; + currentBlendDst = blendDst; + currentBlendSrcAlpha = blendSrcAlpha; + currentBlendDstAlpha = blendDstAlpha; + } + currentBlending = blending; + currentPremultipledAlpha = null; + } + function setMaterial(material, frontFaceCW) { + material.side === DoubleSide ? disable(2884) : enable(2884); + let flipSided = material.side === BackSide; + if (frontFaceCW) + flipSided = !flipSided; + setFlipSided(flipSided); + material.blending === NormalBlending && material.transparent === false ? setBlending(NoBlending) : setBlending(material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha); + depthBuffer.setFunc(material.depthFunc); + depthBuffer.setTest(material.depthTest); + depthBuffer.setMask(material.depthWrite); + colorBuffer.setMask(material.colorWrite); + const stencilWrite = material.stencilWrite; + stencilBuffer.setTest(stencilWrite); + if (stencilWrite) { + stencilBuffer.setMask(material.stencilWriteMask); + stencilBuffer.setFunc(material.stencilFunc, material.stencilRef, material.stencilFuncMask); + stencilBuffer.setOp(material.stencilFail, material.stencilZFail, material.stencilZPass); + } + setPolygonOffset(material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits); + material.alphaToCoverage === true ? enable(32926) : disable(32926); + } + function setFlipSided(flipSided) { + if (currentFlipSided !== flipSided) { + if (flipSided) { + gl.frontFace(2304); + } else { + gl.frontFace(2305); + } + currentFlipSided = flipSided; + } + } + function setCullFace(cullFace) { + if (cullFace !== CullFaceNone) { + enable(2884); + if (cullFace !== currentCullFace) { + if (cullFace === CullFaceBack) { + gl.cullFace(1029); + } else if (cullFace === CullFaceFront) { + gl.cullFace(1028); + } else { + gl.cullFace(1032); + } + } + } else { + disable(2884); + } + currentCullFace = cullFace; + } + function setLineWidth(width) { + if (width !== currentLineWidth) { + if (lineWidthAvailable) + gl.lineWidth(width); + currentLineWidth = width; + } + } + function setPolygonOffset(polygonOffset, factor, units) { + if (polygonOffset) { + enable(32823); + if (currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units) { + gl.polygonOffset(factor, units); + currentPolygonOffsetFactor = factor; + currentPolygonOffsetUnits = units; + } + } else { + disable(32823); + } + } + function setScissorTest(scissorTest) { + if (scissorTest) { + enable(3089); + } else { + disable(3089); + } + } + function activeTexture(webglSlot) { + if (webglSlot === void 0) + webglSlot = 33984 + maxTextures - 1; + if (currentTextureSlot !== webglSlot) { + gl.activeTexture(webglSlot); + currentTextureSlot = webglSlot; + } + } + function bindTexture(webglType, webglTexture) { + if (currentTextureSlot === null) { + activeTexture(); + } + let boundTexture = currentBoundTextures[currentTextureSlot]; + if (boundTexture === void 0) { + boundTexture = { type: void 0, texture: void 0 }; + currentBoundTextures[currentTextureSlot] = boundTexture; + } + if (boundTexture.type !== webglType || boundTexture.texture !== webglTexture) { + gl.bindTexture(webglType, webglTexture || emptyTextures[webglType]); + boundTexture.type = webglType; + boundTexture.texture = webglTexture; + } + } + function unbindTexture() { + const boundTexture = currentBoundTextures[currentTextureSlot]; + if (boundTexture !== void 0 && boundTexture.type !== void 0) { + gl.bindTexture(boundTexture.type, null); + boundTexture.type = void 0; + boundTexture.texture = void 0; + } + } + function compressedTexImage2D() { + try { + gl.compressedTexImage2D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texSubImage2D() { + try { + gl.texSubImage2D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texSubImage3D() { + try { + gl.texSubImage3D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function compressedTexSubImage2D() { + try { + gl.compressedTexSubImage2D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texStorage2D() { + try { + gl.texStorage2D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texStorage3D() { + try { + gl.texStorage3D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texImage2D() { + try { + gl.texImage2D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function texImage3D() { + try { + gl.texImage3D.apply(gl, arguments); + } catch (error) { + console.error("THREE.WebGLState:", error); + } + } + function scissor(scissor2) { + if (currentScissor.equals(scissor2) === false) { + gl.scissor(scissor2.x, scissor2.y, scissor2.z, scissor2.w); + currentScissor.copy(scissor2); + } + } + function viewport(viewport2) { + if (currentViewport.equals(viewport2) === false) { + gl.viewport(viewport2.x, viewport2.y, viewport2.z, viewport2.w); + currentViewport.copy(viewport2); + } + } + function updateUBOMapping(uniformsGroup, program) { + let mapping = uboProgamMap.get(program); + if (mapping === void 0) { + mapping = /* @__PURE__ */ new WeakMap(); + uboProgamMap.set(program, mapping); + } + let blockIndex = mapping.get(uniformsGroup); + if (blockIndex === void 0) { + blockIndex = gl.getUniformBlockIndex(program, uniformsGroup.name); + mapping.set(uniformsGroup, blockIndex); + } + } + function uniformBlockBinding(uniformsGroup, program) { + const mapping = uboProgamMap.get(program); + const blockIndex = mapping.get(uniformsGroup); + if (uboBindings.get(uniformsGroup) !== blockIndex) { + gl.uniformBlockBinding(program, blockIndex, uniformsGroup.__bindingPointIndex); + uboBindings.set(uniformsGroup, blockIndex); + } + } + function reset() { + gl.disable(3042); + gl.disable(2884); + gl.disable(2929); + gl.disable(32823); + gl.disable(3089); + gl.disable(2960); + gl.disable(32926); + gl.blendEquation(32774); + gl.blendFunc(1, 0); + gl.blendFuncSeparate(1, 0, 1, 0); + gl.colorMask(true, true, true, true); + gl.clearColor(0, 0, 0, 0); + gl.depthMask(true); + gl.depthFunc(513); + gl.clearDepth(1); + gl.stencilMask(4294967295); + gl.stencilFunc(519, 0, 4294967295); + gl.stencilOp(7680, 7680, 7680); + gl.clearStencil(0); + gl.cullFace(1029); + gl.frontFace(2305); + gl.polygonOffset(0, 0); + gl.activeTexture(33984); + gl.bindFramebuffer(36160, null); + if (isWebGL2 === true) { + gl.bindFramebuffer(36009, null); + gl.bindFramebuffer(36008, null); + } + gl.useProgram(null); + gl.lineWidth(1); + gl.scissor(0, 0, gl.canvas.width, gl.canvas.height); + gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); + enabledCapabilities = {}; + currentTextureSlot = null; + currentBoundTextures = {}; + currentBoundFramebuffers = {}; + currentDrawbuffers = /* @__PURE__ */ new WeakMap(); + defaultDrawbuffers = []; + currentProgram = null; + currentBlendingEnabled = false; + currentBlending = null; + currentBlendEquation = null; + currentBlendSrc = null; + currentBlendDst = null; + currentBlendEquationAlpha = null; + currentBlendSrcAlpha = null; + currentBlendDstAlpha = null; + currentPremultipledAlpha = false; + currentFlipSided = null; + currentCullFace = null; + currentLineWidth = null; + currentPolygonOffsetFactor = null; + currentPolygonOffsetUnits = null; + currentScissor.set(0, 0, gl.canvas.width, gl.canvas.height); + currentViewport.set(0, 0, gl.canvas.width, gl.canvas.height); + colorBuffer.reset(); + depthBuffer.reset(); + stencilBuffer.reset(); + } + return { + buffers: { + color: colorBuffer, + depth: depthBuffer, + stencil: stencilBuffer + }, + enable, + disable, + bindFramebuffer, + drawBuffers, + useProgram, + setBlending, + setMaterial, + setFlipSided, + setCullFace, + setLineWidth, + setPolygonOffset, + setScissorTest, + activeTexture, + bindTexture, + unbindTexture, + compressedTexImage2D, + texImage2D, + texImage3D, + updateUBOMapping, + uniformBlockBinding, + texStorage2D, + texStorage3D, + texSubImage2D, + texSubImage3D, + compressedTexSubImage2D, + scissor, + viewport, + reset + }; + } + function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, info) { + const isWebGL2 = capabilities.isWebGL2; + const maxTextures = capabilities.maxTextures; + const maxCubemapSize = capabilities.maxCubemapSize; + const maxTextureSize = capabilities.maxTextureSize; + const maxSamples = capabilities.maxSamples; + const multisampledRTTExt = extensions.has("WEBGL_multisampled_render_to_texture") ? extensions.get("WEBGL_multisampled_render_to_texture") : null; + const supportsInvalidateFramebuffer = /OculusBrowser/g.test(navigator.userAgent); + const _videoTextures = /* @__PURE__ */ new WeakMap(); + let _canvas2; + const _sources = /* @__PURE__ */ new WeakMap(); + let useOffscreenCanvas = false; + try { + useOffscreenCanvas = typeof OffscreenCanvas !== "undefined" && new OffscreenCanvas(1, 1).getContext("2d") !== null; + } catch (err) { + } + function createCanvas(width, height) { + return useOffscreenCanvas ? new OffscreenCanvas(width, height) : createElementNS("canvas"); + } + function resizeImage(image, needsPowerOfTwo, needsNewCanvas, maxSize) { + let scale = 1; + if (image.width > maxSize || image.height > maxSize) { + scale = maxSize / Math.max(image.width, image.height); + } + if (scale < 1 || needsPowerOfTwo === true) { + if (typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && image instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) { + const floor = needsPowerOfTwo ? floorPowerOfTwo : Math.floor; + const width = floor(scale * image.width); + const height = floor(scale * image.height); + if (_canvas2 === void 0) + _canvas2 = createCanvas(width, height); + const canvas = needsNewCanvas ? createCanvas(width, height) : _canvas2; + canvas.width = width; + canvas.height = height; + const context = canvas.getContext("2d"); + context.drawImage(image, 0, 0, width, height); + console.warn("THREE.WebGLRenderer: Texture has been resized from (" + image.width + "x" + image.height + ") to (" + width + "x" + height + ")."); + return canvas; + } else { + if ("data" in image) { + console.warn("THREE.WebGLRenderer: Image in DataTexture is too big (" + image.width + "x" + image.height + ")."); + } + return image; + } + } + return image; + } + function isPowerOfTwo$1(image) { + return isPowerOfTwo(image.width) && isPowerOfTwo(image.height); + } + function textureNeedsPowerOfTwo(texture) { + if (isWebGL2) + return false; + return texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping || texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; + } + function textureNeedsGenerateMipmaps(texture, supportsMips) { + return texture.generateMipmaps && supportsMips && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; + } + function generateMipmap(target) { + _gl.generateMipmap(target); + } + function getInternalFormat(internalFormatName, glFormat, glType, encoding, isVideoTexture = false) { + if (isWebGL2 === false) + return glFormat; + if (internalFormatName !== null) { + if (_gl[internalFormatName] !== void 0) + return _gl[internalFormatName]; + console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '" + internalFormatName + "'"); + } + let internalFormat = glFormat; + if (glFormat === 6403) { + if (glType === 5126) + internalFormat = 33326; + if (glType === 5131) + internalFormat = 33325; + if (glType === 5121) + internalFormat = 33321; + } + if (glFormat === 33319) { + if (glType === 5126) + internalFormat = 33328; + if (glType === 5131) + internalFormat = 33327; + if (glType === 5121) + internalFormat = 33323; + } + if (glFormat === 6408) { + if (glType === 5126) + internalFormat = 34836; + if (glType === 5131) + internalFormat = 34842; + if (glType === 5121) + internalFormat = encoding === sRGBEncoding && isVideoTexture === false ? 35907 : 32856; + if (glType === 32819) + internalFormat = 32854; + if (glType === 32820) + internalFormat = 32855; + } + if (internalFormat === 33325 || internalFormat === 33326 || internalFormat === 33327 || internalFormat === 33328 || internalFormat === 34842 || internalFormat === 34836) { + extensions.get("EXT_color_buffer_float"); + } + return internalFormat; + } + function getMipLevels(texture, image, supportsMips) { + if (textureNeedsGenerateMipmaps(texture, supportsMips) === true || texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter) { + return Math.log2(Math.max(image.width, image.height)) + 1; + } else if (texture.mipmaps !== void 0 && texture.mipmaps.length > 0) { + return texture.mipmaps.length; + } else if (texture.isCompressedTexture && Array.isArray(texture.image)) { + return image.mipmaps.length; + } else { + return 1; + } + } + function filterFallback(f) { + if (f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter) { + return 9728; + } + return 9729; + } + function onTextureDispose(event) { + const texture = event.target; + texture.removeEventListener("dispose", onTextureDispose); + deallocateTexture(texture); + if (texture.isVideoTexture) { + _videoTextures.delete(texture); + } + } + function onRenderTargetDispose(event) { + const renderTarget = event.target; + renderTarget.removeEventListener("dispose", onRenderTargetDispose); + deallocateRenderTarget(renderTarget); + } + function deallocateTexture(texture) { + const textureProperties = properties.get(texture); + if (textureProperties.__webglInit === void 0) + return; + const source = texture.source; + const webglTextures = _sources.get(source); + if (webglTextures) { + const webglTexture = webglTextures[textureProperties.__cacheKey]; + webglTexture.usedTimes--; + if (webglTexture.usedTimes === 0) { + deleteTexture(texture); + } + if (Object.keys(webglTextures).length === 0) { + _sources.delete(source); + } + } + properties.remove(texture); + } + function deleteTexture(texture) { + const textureProperties = properties.get(texture); + _gl.deleteTexture(textureProperties.__webglTexture); + const source = texture.source; + const webglTextures = _sources.get(source); + delete webglTextures[textureProperties.__cacheKey]; + info.memory.textures--; + } + function deallocateRenderTarget(renderTarget) { + const texture = renderTarget.texture; + const renderTargetProperties = properties.get(renderTarget); + const textureProperties = properties.get(texture); + if (textureProperties.__webglTexture !== void 0) { + _gl.deleteTexture(textureProperties.__webglTexture); + info.memory.textures--; + } + if (renderTarget.depthTexture) { + renderTarget.depthTexture.dispose(); + } + if (renderTarget.isWebGLCubeRenderTarget) { + for (let i = 0; i < 6; i++) { + _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer[i]); + if (renderTargetProperties.__webglDepthbuffer) + _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer[i]); + } + } else { + _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer); + if (renderTargetProperties.__webglDepthbuffer) + _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer); + if (renderTargetProperties.__webglMultisampledFramebuffer) + _gl.deleteFramebuffer(renderTargetProperties.__webglMultisampledFramebuffer); + if (renderTargetProperties.__webglColorRenderbuffer) { + for (let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i++) { + if (renderTargetProperties.__webglColorRenderbuffer[i]) + _gl.deleteRenderbuffer(renderTargetProperties.__webglColorRenderbuffer[i]); + } + } + if (renderTargetProperties.__webglDepthRenderbuffer) + _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthRenderbuffer); + } + if (renderTarget.isWebGLMultipleRenderTargets) { + for (let i = 0, il = texture.length; i < il; i++) { + const attachmentProperties = properties.get(texture[i]); + if (attachmentProperties.__webglTexture) { + _gl.deleteTexture(attachmentProperties.__webglTexture); + info.memory.textures--; + } + properties.remove(texture[i]); + } + } + properties.remove(texture); + properties.remove(renderTarget); + } + let textureUnits = 0; + function resetTextureUnits() { + textureUnits = 0; + } + function allocateTextureUnit() { + const textureUnit = textureUnits; + if (textureUnit >= maxTextures) { + console.warn("THREE.WebGLTextures: Trying to use " + textureUnit + " texture units while this GPU supports only " + maxTextures); + } + textureUnits += 1; + return textureUnit; + } + function getTextureCacheKey(texture) { + const array2 = []; + array2.push(texture.wrapS); + array2.push(texture.wrapT); + array2.push(texture.magFilter); + array2.push(texture.minFilter); + array2.push(texture.anisotropy); + array2.push(texture.internalFormat); + array2.push(texture.format); + array2.push(texture.type); + array2.push(texture.generateMipmaps); + array2.push(texture.premultiplyAlpha); + array2.push(texture.flipY); + array2.push(texture.unpackAlignment); + array2.push(texture.encoding); + return array2.join(); + } + function setTexture2D(texture, slot) { + const textureProperties = properties.get(texture); + if (texture.isVideoTexture) + updateVideoTexture(texture); + if (texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version) { + const image = texture.image; + if (image === null) { + console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found."); + } else if (image.complete === false) { + console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete"); + } else { + uploadTexture(textureProperties, texture, slot); + return; + } + } + state.activeTexture(33984 + slot); + state.bindTexture(3553, textureProperties.__webglTexture); + } + function setTexture2DArray(texture, slot) { + const textureProperties = properties.get(texture); + if (texture.version > 0 && textureProperties.__version !== texture.version) { + uploadTexture(textureProperties, texture, slot); + return; + } + state.activeTexture(33984 + slot); + state.bindTexture(35866, textureProperties.__webglTexture); + } + function setTexture3D(texture, slot) { + const textureProperties = properties.get(texture); + if (texture.version > 0 && textureProperties.__version !== texture.version) { + uploadTexture(textureProperties, texture, slot); + return; + } + state.activeTexture(33984 + slot); + state.bindTexture(32879, textureProperties.__webglTexture); + } + function setTextureCube(texture, slot) { + const textureProperties = properties.get(texture); + if (texture.version > 0 && textureProperties.__version !== texture.version) { + uploadCubeTexture(textureProperties, texture, slot); + return; + } + state.activeTexture(33984 + slot); + state.bindTexture(34067, textureProperties.__webglTexture); + } + const wrappingToGL = { + [RepeatWrapping]: 10497, + [ClampToEdgeWrapping]: 33071, + [MirroredRepeatWrapping]: 33648 + }; + const filterToGL = { + [NearestFilter]: 9728, + [NearestMipmapNearestFilter]: 9984, + [NearestMipmapLinearFilter]: 9986, + [LinearFilter]: 9729, + [LinearMipmapNearestFilter]: 9985, + [LinearMipmapLinearFilter]: 9987 + }; + function setTextureParameters(textureType, texture, supportsMips) { + if (supportsMips) { + _gl.texParameteri(textureType, 10242, wrappingToGL[texture.wrapS]); + _gl.texParameteri(textureType, 10243, wrappingToGL[texture.wrapT]); + if (textureType === 32879 || textureType === 35866) { + _gl.texParameteri(textureType, 32882, wrappingToGL[texture.wrapR]); + } + _gl.texParameteri(textureType, 10240, filterToGL[texture.magFilter]); + _gl.texParameteri(textureType, 10241, filterToGL[texture.minFilter]); + } else { + _gl.texParameteri(textureType, 10242, 33071); + _gl.texParameteri(textureType, 10243, 33071); + if (textureType === 32879 || textureType === 35866) { + _gl.texParameteri(textureType, 32882, 33071); + } + if (texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping) { + console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."); + } + _gl.texParameteri(textureType, 10240, filterFallback(texture.magFilter)); + _gl.texParameteri(textureType, 10241, filterFallback(texture.minFilter)); + if (texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter) { + console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter."); + } + } + if (extensions.has("EXT_texture_filter_anisotropic") === true) { + const extension = extensions.get("EXT_texture_filter_anisotropic"); + if (texture.type === FloatType && extensions.has("OES_texture_float_linear") === false) + return; + if (isWebGL2 === false && (texture.type === HalfFloatType && extensions.has("OES_texture_half_float_linear") === false)) + return; + if (texture.anisotropy > 1 || properties.get(texture).__currentAnisotropy) { + _gl.texParameterf(textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(texture.anisotropy, capabilities.getMaxAnisotropy())); + properties.get(texture).__currentAnisotropy = texture.anisotropy; + } + } + } + function initTexture(textureProperties, texture) { + let forceUpload = false; + if (textureProperties.__webglInit === void 0) { + textureProperties.__webglInit = true; + texture.addEventListener("dispose", onTextureDispose); + } + const source = texture.source; + let webglTextures = _sources.get(source); + if (webglTextures === void 0) { + webglTextures = {}; + _sources.set(source, webglTextures); + } + const textureCacheKey = getTextureCacheKey(texture); + if (textureCacheKey !== textureProperties.__cacheKey) { + if (webglTextures[textureCacheKey] === void 0) { + webglTextures[textureCacheKey] = { + texture: _gl.createTexture(), + usedTimes: 0 + }; + info.memory.textures++; + forceUpload = true; + } + webglTextures[textureCacheKey].usedTimes++; + const webglTexture = webglTextures[textureProperties.__cacheKey]; + if (webglTexture !== void 0) { + webglTextures[textureProperties.__cacheKey].usedTimes--; + if (webglTexture.usedTimes === 0) { + deleteTexture(texture); + } + } + textureProperties.__cacheKey = textureCacheKey; + textureProperties.__webglTexture = webglTextures[textureCacheKey].texture; + } + return forceUpload; + } + function uploadTexture(textureProperties, texture, slot) { + let textureType = 3553; + if (texture.isDataArrayTexture) + textureType = 35866; + if (texture.isData3DTexture) + textureType = 32879; + const forceUpload = initTexture(textureProperties, texture); + const source = texture.source; + state.activeTexture(33984 + slot); + state.bindTexture(textureType, textureProperties.__webglTexture); + if (source.version !== source.__currentVersion || forceUpload === true) { + _gl.pixelStorei(37440, texture.flipY); + _gl.pixelStorei(37441, texture.premultiplyAlpha); + _gl.pixelStorei(3317, texture.unpackAlignment); + _gl.pixelStorei(37443, 0); + const needsPowerOfTwo = textureNeedsPowerOfTwo(texture) && isPowerOfTwo$1(texture.image) === false; + let image = resizeImage(texture.image, needsPowerOfTwo, false, maxTextureSize); + image = verifyColorSpace(texture, image); + const supportsMips = isPowerOfTwo$1(image) || isWebGL2, glFormat = utils.convert(texture.format, texture.encoding); + let glType = utils.convert(texture.type), glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture); + setTextureParameters(textureType, texture, supportsMips); + let mipmap; + const mipmaps = texture.mipmaps; + const useTexStorage = isWebGL2 && texture.isVideoTexture !== true; + const allocateMemory = source.__currentVersion === void 0 || forceUpload === true; + const levels = getMipLevels(texture, image, supportsMips); + if (texture.isDepthTexture) { + glInternalFormat = 6402; + if (isWebGL2) { + if (texture.type === FloatType) { + glInternalFormat = 36012; + } else if (texture.type === UnsignedIntType) { + glInternalFormat = 33190; + } else if (texture.type === UnsignedInt248Type) { + glInternalFormat = 35056; + } else { + glInternalFormat = 33189; + } + } else { + if (texture.type === FloatType) { + console.error("WebGLRenderer: Floating point depth texture requires WebGL2."); + } + } + if (texture.format === DepthFormat && glInternalFormat === 6402) { + if (texture.type !== UnsignedShortType && texture.type !== UnsignedIntType) { + console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."); + texture.type = UnsignedIntType; + glType = utils.convert(texture.type); + } + } + if (texture.format === DepthStencilFormat && glInternalFormat === 6402) { + glInternalFormat = 34041; + if (texture.type !== UnsignedInt248Type) { + console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."); + texture.type = UnsignedInt248Type; + glType = utils.convert(texture.type); + } + } + if (allocateMemory) { + if (useTexStorage) { + state.texStorage2D(3553, 1, glInternalFormat, image.width, image.height); + } else { + state.texImage2D(3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null); + } + } + } else if (texture.isDataTexture) { + if (mipmaps.length > 0 && supportsMips) { + if (useTexStorage && allocateMemory) { + state.texStorage2D(3553, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height); + } + for (let i = 0, il = mipmaps.length; i < il; i++) { + mipmap = mipmaps[i]; + if (useTexStorage) { + state.texSubImage2D(3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data); + } else { + state.texImage2D(3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data); + } + } + texture.generateMipmaps = false; + } else { + if (useTexStorage) { + if (allocateMemory) { + state.texStorage2D(3553, levels, glInternalFormat, image.width, image.height); + } + state.texSubImage2D(3553, 0, 0, 0, image.width, image.height, glFormat, glType, image.data); + } else { + state.texImage2D(3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data); + } + } + } else if (texture.isCompressedTexture) { + if (useTexStorage && allocateMemory) { + state.texStorage2D(3553, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height); + } + for (let i = 0, il = mipmaps.length; i < il; i++) { + mipmap = mipmaps[i]; + if (texture.format !== RGBAFormat) { + if (glFormat !== null) { + if (useTexStorage) { + state.compressedTexSubImage2D(3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data); + } else { + state.compressedTexImage2D(3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data); + } + } else { + console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"); + } + } else { + if (useTexStorage) { + state.texSubImage2D(3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data); + } else { + state.texImage2D(3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data); + } + } + } + } else if (texture.isDataArrayTexture) { + if (useTexStorage) { + if (allocateMemory) { + state.texStorage3D(35866, levels, glInternalFormat, image.width, image.height, image.depth); + } + state.texSubImage3D(35866, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data); + } else { + state.texImage3D(35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data); + } + } else if (texture.isData3DTexture) { + if (useTexStorage) { + if (allocateMemory) { + state.texStorage3D(32879, levels, glInternalFormat, image.width, image.height, image.depth); + } + state.texSubImage3D(32879, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data); + } else { + state.texImage3D(32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data); + } + } else if (texture.isFramebufferTexture) { + if (allocateMemory) { + if (useTexStorage) { + state.texStorage2D(3553, levels, glInternalFormat, image.width, image.height); + } else { + let width = image.width, height = image.height; + for (let i = 0; i < levels; i++) { + state.texImage2D(3553, i, glInternalFormat, width, height, 0, glFormat, glType, null); + width >>= 1; + height >>= 1; + } + } + } + } else { + if (mipmaps.length > 0 && supportsMips) { + if (useTexStorage && allocateMemory) { + state.texStorage2D(3553, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height); + } + for (let i = 0, il = mipmaps.length; i < il; i++) { + mipmap = mipmaps[i]; + if (useTexStorage) { + state.texSubImage2D(3553, i, 0, 0, glFormat, glType, mipmap); + } else { + state.texImage2D(3553, i, glInternalFormat, glFormat, glType, mipmap); + } + } + texture.generateMipmaps = false; + } else { + if (useTexStorage) { + if (allocateMemory) { + state.texStorage2D(3553, levels, glInternalFormat, image.width, image.height); + } + state.texSubImage2D(3553, 0, 0, 0, glFormat, glType, image); + } else { + state.texImage2D(3553, 0, glInternalFormat, glFormat, glType, image); + } + } + } + if (textureNeedsGenerateMipmaps(texture, supportsMips)) { + generateMipmap(textureType); + } + source.__currentVersion = source.version; + if (texture.onUpdate) + texture.onUpdate(texture); + } + textureProperties.__version = texture.version; + } + function uploadCubeTexture(textureProperties, texture, slot) { + if (texture.image.length !== 6) + return; + const forceUpload = initTexture(textureProperties, texture); + const source = texture.source; + state.activeTexture(33984 + slot); + state.bindTexture(34067, textureProperties.__webglTexture); + if (source.version !== source.__currentVersion || forceUpload === true) { + _gl.pixelStorei(37440, texture.flipY); + _gl.pixelStorei(37441, texture.premultiplyAlpha); + _gl.pixelStorei(3317, texture.unpackAlignment); + _gl.pixelStorei(37443, 0); + const isCompressed = texture.isCompressedTexture || texture.image[0].isCompressedTexture; + const isDataTexture = texture.image[0] && texture.image[0].isDataTexture; + const cubeImage = []; + for (let i = 0; i < 6; i++) { + if (!isCompressed && !isDataTexture) { + cubeImage[i] = resizeImage(texture.image[i], false, true, maxCubemapSize); + } else { + cubeImage[i] = isDataTexture ? texture.image[i].image : texture.image[i]; + } + cubeImage[i] = verifyColorSpace(texture, cubeImage[i]); + } + const image = cubeImage[0], supportsMips = isPowerOfTwo$1(image) || isWebGL2, glFormat = utils.convert(texture.format, texture.encoding), glType = utils.convert(texture.type), glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); + const useTexStorage = isWebGL2 && texture.isVideoTexture !== true; + const allocateMemory = source.__currentVersion === void 0 || forceUpload === true; + let levels = getMipLevels(texture, image, supportsMips); + setTextureParameters(34067, texture, supportsMips); + let mipmaps; + if (isCompressed) { + if (useTexStorage && allocateMemory) { + state.texStorage2D(34067, levels, glInternalFormat, image.width, image.height); + } + for (let i = 0; i < 6; i++) { + mipmaps = cubeImage[i].mipmaps; + for (let j = 0; j < mipmaps.length; j++) { + const mipmap = mipmaps[j]; + if (texture.format !== RGBAFormat) { + if (glFormat !== null) { + if (useTexStorage) { + state.compressedTexSubImage2D(34069 + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data); + } else { + state.compressedTexImage2D(34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data); + } + } else { + console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"); + } + } else { + if (useTexStorage) { + state.texSubImage2D(34069 + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data); + } else { + state.texImage2D(34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data); + } + } + } + } + } else { + mipmaps = texture.mipmaps; + if (useTexStorage && allocateMemory) { + if (mipmaps.length > 0) + levels++; + state.texStorage2D(34067, levels, glInternalFormat, cubeImage[0].width, cubeImage[0].height); + } + for (let i = 0; i < 6; i++) { + if (isDataTexture) { + if (useTexStorage) { + state.texSubImage2D(34069 + i, 0, 0, 0, cubeImage[i].width, cubeImage[i].height, glFormat, glType, cubeImage[i].data); + } else { + state.texImage2D(34069 + i, 0, glInternalFormat, cubeImage[i].width, cubeImage[i].height, 0, glFormat, glType, cubeImage[i].data); + } + for (let j = 0; j < mipmaps.length; j++) { + const mipmap = mipmaps[j]; + const mipmapImage = mipmap.image[i].image; + if (useTexStorage) { + state.texSubImage2D(34069 + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data); + } else { + state.texImage2D(34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data); + } + } + } else { + if (useTexStorage) { + state.texSubImage2D(34069 + i, 0, 0, 0, glFormat, glType, cubeImage[i]); + } else { + state.texImage2D(34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[i]); + } + for (let j = 0; j < mipmaps.length; j++) { + const mipmap = mipmaps[j]; + if (useTexStorage) { + state.texSubImage2D(34069 + i, j + 1, 0, 0, glFormat, glType, mipmap.image[i]); + } else { + state.texImage2D(34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[i]); + } + } + } + } + } + if (textureNeedsGenerateMipmaps(texture, supportsMips)) { + generateMipmap(34067); + } + source.__currentVersion = source.version; + if (texture.onUpdate) + texture.onUpdate(texture); + } + textureProperties.__version = texture.version; + } + function setupFrameBufferTexture(framebuffer, renderTarget, texture, attachment, textureTarget) { + const glFormat = utils.convert(texture.format, texture.encoding); + const glType = utils.convert(texture.type); + const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); + const renderTargetProperties = properties.get(renderTarget); + if (!renderTargetProperties.__hasExternalTextures) { + if (textureTarget === 32879 || textureTarget === 35866) { + state.texImage3D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null); + } else { + state.texImage2D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null); + } + } + state.bindFramebuffer(36160, framebuffer); + if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.framebufferTexture2DMultisampleEXT(36160, attachment, textureTarget, properties.get(texture).__webglTexture, 0, getRenderTargetSamples(renderTarget)); + } else { + _gl.framebufferTexture2D(36160, attachment, textureTarget, properties.get(texture).__webglTexture, 0); + } + state.bindFramebuffer(36160, null); + } + function setupRenderBufferStorage(renderbuffer, renderTarget, isMultisample) { + _gl.bindRenderbuffer(36161, renderbuffer); + if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) { + let glInternalFormat = 33189; + if (isMultisample || useMultisampledRTT(renderTarget)) { + const depthTexture = renderTarget.depthTexture; + if (depthTexture && depthTexture.isDepthTexture) { + if (depthTexture.type === FloatType) { + glInternalFormat = 36012; + } else if (depthTexture.type === UnsignedIntType) { + glInternalFormat = 33190; + } + } + const samples = getRenderTargetSamples(renderTarget); + if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.renderbufferStorageMultisampleEXT(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height); + } else { + _gl.renderbufferStorageMultisample(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height); + } + } else { + _gl.renderbufferStorage(36161, glInternalFormat, renderTarget.width, renderTarget.height); + } + _gl.framebufferRenderbuffer(36160, 36096, 36161, renderbuffer); + } else if (renderTarget.depthBuffer && renderTarget.stencilBuffer) { + const samples = getRenderTargetSamples(renderTarget); + if (isMultisample && useMultisampledRTT(renderTarget) === false) { + _gl.renderbufferStorageMultisample(36161, samples, 35056, renderTarget.width, renderTarget.height); + } else if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.renderbufferStorageMultisampleEXT(36161, samples, 35056, renderTarget.width, renderTarget.height); + } else { + _gl.renderbufferStorage(36161, 34041, renderTarget.width, renderTarget.height); + } + _gl.framebufferRenderbuffer(36160, 33306, 36161, renderbuffer); + } else { + const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [renderTarget.texture]; + for (let i = 0; i < textures.length; i++) { + const texture = textures[i]; + const glFormat = utils.convert(texture.format, texture.encoding); + const glType = utils.convert(texture.type); + const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding); + const samples = getRenderTargetSamples(renderTarget); + if (isMultisample && useMultisampledRTT(renderTarget) === false) { + _gl.renderbufferStorageMultisample(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height); + } else if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.renderbufferStorageMultisampleEXT(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height); + } else { + _gl.renderbufferStorage(36161, glInternalFormat, renderTarget.width, renderTarget.height); + } + } + } + _gl.bindRenderbuffer(36161, null); + } + function setupDepthTexture(framebuffer, renderTarget) { + const isCube = renderTarget && renderTarget.isWebGLCubeRenderTarget; + if (isCube) + throw new Error("Depth Texture with cube render targets is not supported"); + state.bindFramebuffer(36160, framebuffer); + if (!(renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture)) { + throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture"); + } + if (!properties.get(renderTarget.depthTexture).__webglTexture || renderTarget.depthTexture.image.width !== renderTarget.width || renderTarget.depthTexture.image.height !== renderTarget.height) { + renderTarget.depthTexture.image.width = renderTarget.width; + renderTarget.depthTexture.image.height = renderTarget.height; + renderTarget.depthTexture.needsUpdate = true; + } + setTexture2D(renderTarget.depthTexture, 0); + const webglDepthTexture = properties.get(renderTarget.depthTexture).__webglTexture; + const samples = getRenderTargetSamples(renderTarget); + if (renderTarget.depthTexture.format === DepthFormat) { + if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.framebufferTexture2DMultisampleEXT(36160, 36096, 3553, webglDepthTexture, 0, samples); + } else { + _gl.framebufferTexture2D(36160, 36096, 3553, webglDepthTexture, 0); + } + } else if (renderTarget.depthTexture.format === DepthStencilFormat) { + if (useMultisampledRTT(renderTarget)) { + multisampledRTTExt.framebufferTexture2DMultisampleEXT(36160, 33306, 3553, webglDepthTexture, 0, samples); + } else { + _gl.framebufferTexture2D(36160, 33306, 3553, webglDepthTexture, 0); + } + } else { + throw new Error("Unknown depthTexture format"); + } + } + function setupDepthRenderbuffer(renderTarget) { + const renderTargetProperties = properties.get(renderTarget); + const isCube = renderTarget.isWebGLCubeRenderTarget === true; + if (renderTarget.depthTexture && !renderTargetProperties.__autoAllocateDepthBuffer) { + if (isCube) + throw new Error("target.depthTexture not supported in Cube render targets"); + setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget); + } else { + if (isCube) { + renderTargetProperties.__webglDepthbuffer = []; + for (let i = 0; i < 6; i++) { + state.bindFramebuffer(36160, renderTargetProperties.__webglFramebuffer[i]); + renderTargetProperties.__webglDepthbuffer[i] = _gl.createRenderbuffer(); + setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer[i], renderTarget, false); + } + } else { + state.bindFramebuffer(36160, renderTargetProperties.__webglFramebuffer); + renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer, renderTarget, false); + } + } + state.bindFramebuffer(36160, null); + } + function rebindTextures(renderTarget, colorTexture, depthTexture) { + const renderTargetProperties = properties.get(renderTarget); + if (colorTexture !== void 0) { + setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, 36064, 3553); + } + if (depthTexture !== void 0) { + setupDepthRenderbuffer(renderTarget); + } + } + function setupRenderTarget(renderTarget) { + const texture = renderTarget.texture; + const renderTargetProperties = properties.get(renderTarget); + const textureProperties = properties.get(texture); + renderTarget.addEventListener("dispose", onRenderTargetDispose); + if (renderTarget.isWebGLMultipleRenderTargets !== true) { + if (textureProperties.__webglTexture === void 0) { + textureProperties.__webglTexture = _gl.createTexture(); + } + textureProperties.__version = texture.version; + info.memory.textures++; + } + const isCube = renderTarget.isWebGLCubeRenderTarget === true; + const isMultipleRenderTargets = renderTarget.isWebGLMultipleRenderTargets === true; + const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2; + if (isCube) { + renderTargetProperties.__webglFramebuffer = []; + for (let i = 0; i < 6; i++) { + renderTargetProperties.__webglFramebuffer[i] = _gl.createFramebuffer(); + } + } else { + renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); + if (isMultipleRenderTargets) { + if (capabilities.drawBuffers) { + const textures = renderTarget.texture; + for (let i = 0, il = textures.length; i < il; i++) { + const attachmentProperties = properties.get(textures[i]); + if (attachmentProperties.__webglTexture === void 0) { + attachmentProperties.__webglTexture = _gl.createTexture(); + info.memory.textures++; + } + } + } else { + console.warn("THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension."); + } + } + if (isWebGL2 && renderTarget.samples > 0 && useMultisampledRTT(renderTarget) === false) { + const textures = isMultipleRenderTargets ? texture : [texture]; + renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer(); + renderTargetProperties.__webglColorRenderbuffer = []; + state.bindFramebuffer(36160, renderTargetProperties.__webglMultisampledFramebuffer); + for (let i = 0; i < textures.length; i++) { + const texture2 = textures[i]; + renderTargetProperties.__webglColorRenderbuffer[i] = _gl.createRenderbuffer(); + _gl.bindRenderbuffer(36161, renderTargetProperties.__webglColorRenderbuffer[i]); + const glFormat = utils.convert(texture2.format, texture2.encoding); + const glType = utils.convert(texture2.type); + const glInternalFormat = getInternalFormat(texture2.internalFormat, glFormat, glType, texture2.encoding); + const samples = getRenderTargetSamples(renderTarget); + _gl.renderbufferStorageMultisample(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height); + _gl.framebufferRenderbuffer(36160, 36064 + i, 36161, renderTargetProperties.__webglColorRenderbuffer[i]); + } + _gl.bindRenderbuffer(36161, null); + if (renderTarget.depthBuffer) { + renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer(); + setupRenderBufferStorage(renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true); + } + state.bindFramebuffer(36160, null); + } + } + if (isCube) { + state.bindTexture(34067, textureProperties.__webglTexture); + setTextureParameters(34067, texture, supportsMips); + for (let i = 0; i < 6; i++) { + setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[i], renderTarget, texture, 36064, 34069 + i); + } + if (textureNeedsGenerateMipmaps(texture, supportsMips)) { + generateMipmap(34067); + } + state.unbindTexture(); + } else if (isMultipleRenderTargets) { + const textures = renderTarget.texture; + for (let i = 0, il = textures.length; i < il; i++) { + const attachment = textures[i]; + const attachmentProperties = properties.get(attachment); + state.bindTexture(3553, attachmentProperties.__webglTexture); + setTextureParameters(3553, attachment, supportsMips); + setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, attachment, 36064 + i, 3553); + if (textureNeedsGenerateMipmaps(attachment, supportsMips)) { + generateMipmap(3553); + } + } + state.unbindTexture(); + } else { + let glTextureType = 3553; + if (renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget) { + if (isWebGL2) { + glTextureType = renderTarget.isWebGL3DRenderTarget ? 32879 : 35866; + } else { + console.error("THREE.WebGLTextures: THREE.Data3DTexture and THREE.DataArrayTexture only supported with WebGL2."); + } + } + state.bindTexture(glTextureType, textureProperties.__webglTexture); + setTextureParameters(glTextureType, texture, supportsMips); + setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, texture, 36064, glTextureType); + if (textureNeedsGenerateMipmaps(texture, supportsMips)) { + generateMipmap(glTextureType); + } + state.unbindTexture(); + } + if (renderTarget.depthBuffer) { + setupDepthRenderbuffer(renderTarget); + } + } + function updateRenderTargetMipmap(renderTarget) { + const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2; + const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [renderTarget.texture]; + for (let i = 0, il = textures.length; i < il; i++) { + const texture = textures[i]; + if (textureNeedsGenerateMipmaps(texture, supportsMips)) { + const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553; + const webglTexture = properties.get(texture).__webglTexture; + state.bindTexture(target, webglTexture); + generateMipmap(target); + state.unbindTexture(); + } + } + } + function updateMultisampleRenderTarget(renderTarget) { + if (isWebGL2 && renderTarget.samples > 0 && useMultisampledRTT(renderTarget) === false) { + const textures = renderTarget.isWebGLMultipleRenderTargets ? renderTarget.texture : [renderTarget.texture]; + const width = renderTarget.width; + const height = renderTarget.height; + let mask = 16384; + const invalidationArray = []; + const depthStyle = renderTarget.stencilBuffer ? 33306 : 36096; + const renderTargetProperties = properties.get(renderTarget); + const isMultipleRenderTargets = renderTarget.isWebGLMultipleRenderTargets === true; + if (isMultipleRenderTargets) { + for (let i = 0; i < textures.length; i++) { + state.bindFramebuffer(36160, renderTargetProperties.__webglMultisampledFramebuffer); + _gl.framebufferRenderbuffer(36160, 36064 + i, 36161, null); + state.bindFramebuffer(36160, renderTargetProperties.__webglFramebuffer); + _gl.framebufferTexture2D(36009, 36064 + i, 3553, null, 0); + } + } + state.bindFramebuffer(36008, renderTargetProperties.__webglMultisampledFramebuffer); + state.bindFramebuffer(36009, renderTargetProperties.__webglFramebuffer); + for (let i = 0; i < textures.length; i++) { + invalidationArray.push(36064 + i); + if (renderTarget.depthBuffer) { + invalidationArray.push(depthStyle); + } + const ignoreDepthValues = renderTargetProperties.__ignoreDepthValues !== void 0 ? renderTargetProperties.__ignoreDepthValues : false; + if (ignoreDepthValues === false) { + if (renderTarget.depthBuffer) + mask |= 256; + if (renderTarget.stencilBuffer) + mask |= 1024; + } + if (isMultipleRenderTargets) { + _gl.framebufferRenderbuffer(36008, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer[i]); + } + if (ignoreDepthValues === true) { + _gl.invalidateFramebuffer(36008, [depthStyle]); + _gl.invalidateFramebuffer(36009, [depthStyle]); + } + if (isMultipleRenderTargets) { + const webglTexture = properties.get(textures[i]).__webglTexture; + _gl.framebufferTexture2D(36009, 36064, 3553, webglTexture, 0); + } + _gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, mask, 9728); + if (supportsInvalidateFramebuffer) { + _gl.invalidateFramebuffer(36008, invalidationArray); + } + } + state.bindFramebuffer(36008, null); + state.bindFramebuffer(36009, null); + if (isMultipleRenderTargets) { + for (let i = 0; i < textures.length; i++) { + state.bindFramebuffer(36160, renderTargetProperties.__webglMultisampledFramebuffer); + _gl.framebufferRenderbuffer(36160, 36064 + i, 36161, renderTargetProperties.__webglColorRenderbuffer[i]); + const webglTexture = properties.get(textures[i]).__webglTexture; + state.bindFramebuffer(36160, renderTargetProperties.__webglFramebuffer); + _gl.framebufferTexture2D(36009, 36064 + i, 3553, webglTexture, 0); + } + } + state.bindFramebuffer(36009, renderTargetProperties.__webglMultisampledFramebuffer); + } + } + function getRenderTargetSamples(renderTarget) { + return Math.min(maxSamples, renderTarget.samples); + } + function useMultisampledRTT(renderTarget) { + const renderTargetProperties = properties.get(renderTarget); + return isWebGL2 && renderTarget.samples > 0 && extensions.has("WEBGL_multisampled_render_to_texture") === true && renderTargetProperties.__useRenderToTexture !== false; + } + function updateVideoTexture(texture) { + const frame2 = info.render.frame; + if (_videoTextures.get(texture) !== frame2) { + _videoTextures.set(texture, frame2); + texture.update(); + } + } + function verifyColorSpace(texture, image) { + const encoding = texture.encoding; + const format2 = texture.format; + const type2 = texture.type; + if (texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat) + return image; + if (encoding !== LinearEncoding) { + if (encoding === sRGBEncoding) { + if (isWebGL2 === false) { + if (extensions.has("EXT_sRGB") === true && format2 === RGBAFormat) { + texture.format = _SRGBAFormat; + texture.minFilter = LinearFilter; + texture.generateMipmaps = false; + } else { + image = ImageUtils.sRGBToLinear(image); + } + } else { + if (format2 !== RGBAFormat || type2 !== UnsignedByteType) { + console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."); + } + } + } else { + console.error("THREE.WebGLTextures: Unsupported texture encoding:", encoding); + } + } + return image; + } + this.allocateTextureUnit = allocateTextureUnit; + this.resetTextureUnits = resetTextureUnits; + this.setTexture2D = setTexture2D; + this.setTexture2DArray = setTexture2DArray; + this.setTexture3D = setTexture3D; + this.setTextureCube = setTextureCube; + this.rebindTextures = rebindTextures; + this.setupRenderTarget = setupRenderTarget; + this.updateRenderTargetMipmap = updateRenderTargetMipmap; + this.updateMultisampleRenderTarget = updateMultisampleRenderTarget; + this.setupDepthRenderbuffer = setupDepthRenderbuffer; + this.setupFrameBufferTexture = setupFrameBufferTexture; + this.useMultisampledRTT = useMultisampledRTT; + } + function WebGLUtils(gl, extensions, capabilities) { + const isWebGL2 = capabilities.isWebGL2; + function convert(p, encoding = null) { + let extension; + if (p === UnsignedByteType) + return 5121; + if (p === UnsignedShort4444Type) + return 32819; + if (p === UnsignedShort5551Type) + return 32820; + if (p === ByteType) + return 5120; + if (p === ShortType) + return 5122; + if (p === UnsignedShortType) + return 5123; + if (p === IntType) + return 5124; + if (p === UnsignedIntType) + return 5125; + if (p === FloatType) + return 5126; + if (p === HalfFloatType) { + if (isWebGL2) + return 5131; + extension = extensions.get("OES_texture_half_float"); + if (extension !== null) { + return extension.HALF_FLOAT_OES; + } else { + return null; + } + } + if (p === AlphaFormat) + return 6406; + if (p === RGBAFormat) + return 6408; + if (p === LuminanceFormat) + return 6409; + if (p === LuminanceAlphaFormat) + return 6410; + if (p === DepthFormat) + return 6402; + if (p === DepthStencilFormat) + return 34041; + if (p === RedFormat) + return 6403; + if (p === RGBFormat) { + console.warn("THREE.WebGLRenderer: THREE.RGBFormat has been removed. Use THREE.RGBAFormat instead. https://github.com/mrdoob/three.js/pull/23228"); + return 6408; + } + if (p === _SRGBAFormat) { + extension = extensions.get("EXT_sRGB"); + if (extension !== null) { + return extension.SRGB_ALPHA_EXT; + } else { + return null; + } + } + if (p === RedIntegerFormat) + return 36244; + if (p === RGFormat) + return 33319; + if (p === RGIntegerFormat) + return 33320; + if (p === RGBAIntegerFormat) + return 36249; + if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) { + if (encoding === sRGBEncoding) { + extension = extensions.get("WEBGL_compressed_texture_s3tc_srgb"); + if (extension !== null) { + if (p === RGB_S3TC_DXT1_Format) + return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT1_Format) + return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT3_Format) + return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + if (p === RGBA_S3TC_DXT5_Format) + return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + } else { + return null; + } + } else { + extension = extensions.get("WEBGL_compressed_texture_s3tc"); + if (extension !== null) { + if (p === RGB_S3TC_DXT1_Format) + return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT1_Format) + return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; + if (p === RGBA_S3TC_DXT3_Format) + return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; + if (p === RGBA_S3TC_DXT5_Format) + return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + } else { + return null; + } + } + } + if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) { + extension = extensions.get("WEBGL_compressed_texture_pvrtc"); + if (extension !== null) { + if (p === RGB_PVRTC_4BPPV1_Format) + return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; + if (p === RGB_PVRTC_2BPPV1_Format) + return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; + if (p === RGBA_PVRTC_4BPPV1_Format) + return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; + if (p === RGBA_PVRTC_2BPPV1_Format) + return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + } else { + return null; + } + } + if (p === RGB_ETC1_Format) { + extension = extensions.get("WEBGL_compressed_texture_etc1"); + if (extension !== null) { + return extension.COMPRESSED_RGB_ETC1_WEBGL; + } else { + return null; + } + } + if (p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format) { + extension = extensions.get("WEBGL_compressed_texture_etc"); + if (extension !== null) { + if (p === RGB_ETC2_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if (p === RGBA_ETC2_EAC_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + } else { + return null; + } + } + if (p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format) { + extension = extensions.get("WEBGL_compressed_texture_astc"); + if (extension !== null) { + if (p === RGBA_ASTC_4x4_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if (p === RGBA_ASTC_5x4_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if (p === RGBA_ASTC_5x5_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if (p === RGBA_ASTC_6x5_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if (p === RGBA_ASTC_6x6_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if (p === RGBA_ASTC_8x5_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if (p === RGBA_ASTC_8x6_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if (p === RGBA_ASTC_8x8_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if (p === RGBA_ASTC_10x5_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if (p === RGBA_ASTC_10x6_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if (p === RGBA_ASTC_10x8_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if (p === RGBA_ASTC_10x10_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if (p === RGBA_ASTC_12x10_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if (p === RGBA_ASTC_12x12_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; + } else { + return null; + } + } + if (p === RGBA_BPTC_Format) { + extension = extensions.get("EXT_texture_compression_bptc"); + if (extension !== null) { + if (p === RGBA_BPTC_Format) + return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; + } else { + return null; + } + } + if (p === UnsignedInt248Type) { + if (isWebGL2) + return 34042; + extension = extensions.get("WEBGL_depth_texture"); + if (extension !== null) { + return extension.UNSIGNED_INT_24_8_WEBGL; + } else { + return null; + } + } + return gl[p] !== void 0 ? gl[p] : null; + } + return { convert }; + } + var ArrayCamera = class extends PerspectiveCamera { + constructor(array2 = []) { + super(); + this.isArrayCamera = true; + this.cameras = array2; + } + }; + var Group = class extends Object3D { + constructor() { + super(); + this.isGroup = true; + this.type = "Group"; + } + }; + var _moveEvent = { type: "move" }; + var WebXRController = class { + constructor() { + this._targetRay = null; + this._grip = null; + this._hand = null; + } + getHandSpace() { + if (this._hand === null) { + this._hand = new Group(); + this._hand.matrixAutoUpdate = false; + this._hand.visible = false; + this._hand.joints = {}; + this._hand.inputState = { pinching: false }; + } + return this._hand; + } + getTargetRaySpace() { + if (this._targetRay === null) { + this._targetRay = new Group(); + this._targetRay.matrixAutoUpdate = false; + this._targetRay.visible = false; + this._targetRay.hasLinearVelocity = false; + this._targetRay.linearVelocity = new Vector3(); + this._targetRay.hasAngularVelocity = false; + this._targetRay.angularVelocity = new Vector3(); + } + return this._targetRay; + } + getGripSpace() { + if (this._grip === null) { + this._grip = new Group(); + this._grip.matrixAutoUpdate = false; + this._grip.visible = false; + this._grip.hasLinearVelocity = false; + this._grip.linearVelocity = new Vector3(); + this._grip.hasAngularVelocity = false; + this._grip.angularVelocity = new Vector3(); + } + return this._grip; + } + dispatchEvent(event) { + if (this._targetRay !== null) { + this._targetRay.dispatchEvent(event); + } + if (this._grip !== null) { + this._grip.dispatchEvent(event); + } + if (this._hand !== null) { + this._hand.dispatchEvent(event); + } + return this; + } + disconnect(inputSource) { + this.dispatchEvent({ type: "disconnected", data: inputSource }); + if (this._targetRay !== null) { + this._targetRay.visible = false; + } + if (this._grip !== null) { + this._grip.visible = false; + } + if (this._hand !== null) { + this._hand.visible = false; + } + return this; + } + update(inputSource, frame2, referenceSpace) { + let inputPose = null; + let gripPose = null; + let handPose = null; + const targetRay = this._targetRay; + const grip = this._grip; + const hand = this._hand; + if (inputSource && frame2.session.visibilityState !== "visible-blurred") { + if (hand && inputSource.hand) { + handPose = true; + for (const inputjoint of inputSource.hand.values()) { + const jointPose = frame2.getJointPose(inputjoint, referenceSpace); + if (hand.joints[inputjoint.jointName] === void 0) { + const joint2 = new Group(); + joint2.matrixAutoUpdate = false; + joint2.visible = false; + hand.joints[inputjoint.jointName] = joint2; + hand.add(joint2); + } + const joint = hand.joints[inputjoint.jointName]; + if (jointPose !== null) { + joint.matrix.fromArray(jointPose.transform.matrix); + joint.matrix.decompose(joint.position, joint.rotation, joint.scale); + joint.jointRadius = jointPose.radius; + } + joint.visible = jointPose !== null; + } + const indexTip = hand.joints["index-finger-tip"]; + const thumbTip = hand.joints["thumb-tip"]; + const distance = indexTip.position.distanceTo(thumbTip.position); + const distanceToPinch = 0.02; + const threshold = 5e-3; + if (hand.inputState.pinching && distance > distanceToPinch + threshold) { + hand.inputState.pinching = false; + this.dispatchEvent({ + type: "pinchend", + handedness: inputSource.handedness, + target: this + }); + } else if (!hand.inputState.pinching && distance <= distanceToPinch - threshold) { + hand.inputState.pinching = true; + this.dispatchEvent({ + type: "pinchstart", + handedness: inputSource.handedness, + target: this + }); + } + } else { + if (grip !== null && inputSource.gripSpace) { + gripPose = frame2.getPose(inputSource.gripSpace, referenceSpace); + if (gripPose !== null) { + grip.matrix.fromArray(gripPose.transform.matrix); + grip.matrix.decompose(grip.position, grip.rotation, grip.scale); + if (gripPose.linearVelocity) { + grip.hasLinearVelocity = true; + grip.linearVelocity.copy(gripPose.linearVelocity); + } else { + grip.hasLinearVelocity = false; + } + if (gripPose.angularVelocity) { + grip.hasAngularVelocity = true; + grip.angularVelocity.copy(gripPose.angularVelocity); + } else { + grip.hasAngularVelocity = false; + } + } + } + } + if (targetRay !== null) { + inputPose = frame2.getPose(inputSource.targetRaySpace, referenceSpace); + if (inputPose === null && gripPose !== null) { + inputPose = gripPose; + } + if (inputPose !== null) { + targetRay.matrix.fromArray(inputPose.transform.matrix); + targetRay.matrix.decompose(targetRay.position, targetRay.rotation, targetRay.scale); + if (inputPose.linearVelocity) { + targetRay.hasLinearVelocity = true; + targetRay.linearVelocity.copy(inputPose.linearVelocity); + } else { + targetRay.hasLinearVelocity = false; + } + if (inputPose.angularVelocity) { + targetRay.hasAngularVelocity = true; + targetRay.angularVelocity.copy(inputPose.angularVelocity); + } else { + targetRay.hasAngularVelocity = false; + } + this.dispatchEvent(_moveEvent); + } + } + } + if (targetRay !== null) { + targetRay.visible = inputPose !== null; + } + if (grip !== null) { + grip.visible = gripPose !== null; + } + if (hand !== null) { + hand.visible = handPose !== null; + } + return this; + } + }; + var DepthTexture = class extends Texture { + constructor(width, height, type2, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format2) { + format2 = format2 !== void 0 ? format2 : DepthFormat; + if (format2 !== DepthFormat && format2 !== DepthStencilFormat) { + throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat"); + } + if (type2 === void 0 && format2 === DepthFormat) + type2 = UnsignedIntType; + if (type2 === void 0 && format2 === DepthStencilFormat) + type2 = UnsignedInt248Type; + super(null, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy); + this.isDepthTexture = true; + this.image = { width, height }; + this.magFilter = magFilter !== void 0 ? magFilter : NearestFilter; + this.minFilter = minFilter !== void 0 ? minFilter : NearestFilter; + this.flipY = false; + this.generateMipmaps = false; + } + }; + var WebXRManager = class extends EventDispatcher { + constructor(renderer, gl) { + super(); + const scope = this; + let session = null; + let framebufferScaleFactor = 1; + let referenceSpace = null; + let referenceSpaceType = "local-floor"; + let customReferenceSpace = null; + let pose = null; + let glBinding = null; + let glProjLayer = null; + let glBaseLayer = null; + let xrFrame = null; + const attributes = gl.getContextAttributes(); + let initialRenderTarget = null; + let newRenderTarget = null; + const controllers = []; + const controllerInputSources = []; + const cameraL = new PerspectiveCamera(); + cameraL.layers.enable(1); + cameraL.viewport = new Vector4(); + const cameraR = new PerspectiveCamera(); + cameraR.layers.enable(2); + cameraR.viewport = new Vector4(); + const cameras = [cameraL, cameraR]; + const cameraVR = new ArrayCamera(); + cameraVR.layers.enable(1); + cameraVR.layers.enable(2); + let _currentDepthNear = null; + let _currentDepthFar = null; + this.cameraAutoUpdate = true; + this.enabled = false; + this.isPresenting = false; + this.getController = function(index2) { + let controller = controllers[index2]; + if (controller === void 0) { + controller = new WebXRController(); + controllers[index2] = controller; + } + return controller.getTargetRaySpace(); + }; + this.getControllerGrip = function(index2) { + let controller = controllers[index2]; + if (controller === void 0) { + controller = new WebXRController(); + controllers[index2] = controller; + } + return controller.getGripSpace(); + }; + this.getHand = function(index2) { + let controller = controllers[index2]; + if (controller === void 0) { + controller = new WebXRController(); + controllers[index2] = controller; + } + return controller.getHandSpace(); + }; + function onSessionEvent(event) { + const controllerIndex = controllerInputSources.indexOf(event.inputSource); + if (controllerIndex === -1) { + return; + } + const controller = controllers[controllerIndex]; + if (controller !== void 0) { + controller.dispatchEvent({ type: event.type, data: event.inputSource }); + } + } + function onSessionEnd() { + session.removeEventListener("select", onSessionEvent); + session.removeEventListener("selectstart", onSessionEvent); + session.removeEventListener("selectend", onSessionEvent); + session.removeEventListener("squeeze", onSessionEvent); + session.removeEventListener("squeezestart", onSessionEvent); + session.removeEventListener("squeezeend", onSessionEvent); + session.removeEventListener("end", onSessionEnd); + session.removeEventListener("inputsourceschange", onInputSourcesChange); + for (let i = 0; i < controllers.length; i++) { + const inputSource = controllerInputSources[i]; + if (inputSource === null) + continue; + controllerInputSources[i] = null; + controllers[i].disconnect(inputSource); + } + _currentDepthNear = null; + _currentDepthFar = null; + renderer.setRenderTarget(initialRenderTarget); + glBaseLayer = null; + glProjLayer = null; + glBinding = null; + session = null; + newRenderTarget = null; + animation.stop(); + scope.isPresenting = false; + scope.dispatchEvent({ type: "sessionend" }); + } + this.setFramebufferScaleFactor = function(value) { + framebufferScaleFactor = value; + if (scope.isPresenting === true) { + console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting."); + } + }; + this.setReferenceSpaceType = function(value) { + referenceSpaceType = value; + if (scope.isPresenting === true) { + console.warn("THREE.WebXRManager: Cannot change reference space type while presenting."); + } + }; + this.getReferenceSpace = function() { + return customReferenceSpace || referenceSpace; + }; + this.setReferenceSpace = function(space) { + customReferenceSpace = space; + }; + this.getBaseLayer = function() { + return glProjLayer !== null ? glProjLayer : glBaseLayer; + }; + this.getBinding = function() { + return glBinding; + }; + this.getFrame = function() { + return xrFrame; + }; + this.getSession = function() { + return session; + }; + this.setSession = async function(value) { + session = value; + if (session !== null) { + initialRenderTarget = renderer.getRenderTarget(); + session.addEventListener("select", onSessionEvent); + session.addEventListener("selectstart", onSessionEvent); + session.addEventListener("selectend", onSessionEvent); + session.addEventListener("squeeze", onSessionEvent); + session.addEventListener("squeezestart", onSessionEvent); + session.addEventListener("squeezeend", onSessionEvent); + session.addEventListener("end", onSessionEnd); + session.addEventListener("inputsourceschange", onInputSourcesChange); + if (attributes.xrCompatible !== true) { + await gl.makeXRCompatible(); + } + if (session.renderState.layers === void 0 || renderer.capabilities.isWebGL2 === false) { + const layerInit = { + antialias: session.renderState.layers === void 0 ? attributes.antialias : true, + alpha: attributes.alpha, + depth: attributes.depth, + stencil: attributes.stencil, + framebufferScaleFactor + }; + glBaseLayer = new XRWebGLLayer(session, gl, layerInit); + session.updateRenderState({ baseLayer: glBaseLayer }); + newRenderTarget = new WebGLRenderTarget(glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, { + format: RGBAFormat, + type: UnsignedByteType, + encoding: renderer.outputEncoding + }); + } else { + let depthFormat = null; + let depthType = null; + let glDepthFormat = null; + if (attributes.depth) { + glDepthFormat = attributes.stencil ? 35056 : 33190; + depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat; + depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; + } + const projectionlayerInit = { + colorFormat: 32856, + depthFormat: glDepthFormat, + scaleFactor: framebufferScaleFactor + }; + glBinding = new XRWebGLBinding(session, gl); + glProjLayer = glBinding.createProjectionLayer(projectionlayerInit); + session.updateRenderState({ layers: [glProjLayer] }); + newRenderTarget = new WebGLRenderTarget(glProjLayer.textureWidth, glProjLayer.textureHeight, { + format: RGBAFormat, + type: UnsignedByteType, + depthTexture: new DepthTexture(glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, void 0, void 0, void 0, void 0, void 0, void 0, depthFormat), + stencilBuffer: attributes.stencil, + encoding: renderer.outputEncoding, + samples: attributes.antialias ? 4 : 0 + }); + const renderTargetProperties = renderer.properties.get(newRenderTarget); + renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues; + } + newRenderTarget.isXRRenderTarget = true; + this.setFoveation(1); + customReferenceSpace = null; + referenceSpace = await session.requestReferenceSpace(referenceSpaceType); + animation.setContext(session); + animation.start(); + scope.isPresenting = true; + scope.dispatchEvent({ type: "sessionstart" }); + } + }; + function onInputSourcesChange(event) { + for (let i = 0; i < event.removed.length; i++) { + const inputSource = event.removed[i]; + const index2 = controllerInputSources.indexOf(inputSource); + if (index2 >= 0) { + controllerInputSources[index2] = null; + controllers[index2].dispatchEvent({ type: "disconnected", data: inputSource }); + } + } + for (let i = 0; i < event.added.length; i++) { + const inputSource = event.added[i]; + let controllerIndex = controllerInputSources.indexOf(inputSource); + if (controllerIndex === -1) { + for (let i2 = 0; i2 < controllers.length; i2++) { + if (i2 >= controllerInputSources.length) { + controllerInputSources.push(inputSource); + controllerIndex = i2; + break; + } else if (controllerInputSources[i2] === null) { + controllerInputSources[i2] = inputSource; + controllerIndex = i2; + break; + } + } + if (controllerIndex === -1) + break; + } + const controller = controllers[controllerIndex]; + if (controller) { + controller.dispatchEvent({ type: "connected", data: inputSource }); + } + } + } + const cameraLPos = new Vector3(); + const cameraRPos = new Vector3(); + function setProjectionFromUnion(camera, cameraL2, cameraR2) { + cameraLPos.setFromMatrixPosition(cameraL2.matrixWorld); + cameraRPos.setFromMatrixPosition(cameraR2.matrixWorld); + const ipd = cameraLPos.distanceTo(cameraRPos); + const projL = cameraL2.projectionMatrix.elements; + const projR = cameraR2.projectionMatrix.elements; + const near = projL[14] / (projL[10] - 1); + const far = projL[14] / (projL[10] + 1); + const topFov = (projL[9] + 1) / projL[5]; + const bottomFov = (projL[9] - 1) / projL[5]; + const leftFov = (projL[8] - 1) / projL[0]; + const rightFov = (projR[8] + 1) / projR[0]; + const left = near * leftFov; + const right = near * rightFov; + const zOffset = ipd / (-leftFov + rightFov); + const xOffset = zOffset * -leftFov; + cameraL2.matrixWorld.decompose(camera.position, camera.quaternion, camera.scale); + camera.translateX(xOffset); + camera.translateZ(zOffset); + camera.matrixWorld.compose(camera.position, camera.quaternion, camera.scale); + camera.matrixWorldInverse.copy(camera.matrixWorld).invert(); + const near2 = near + zOffset; + const far2 = far + zOffset; + const left2 = left - xOffset; + const right2 = right + (ipd - xOffset); + const top2 = topFov * far / far2 * near2; + const bottom2 = bottomFov * far / far2 * near2; + camera.projectionMatrix.makePerspective(left2, right2, top2, bottom2, near2, far2); + } + function updateCamera(camera, parent) { + if (parent === null) { + camera.matrixWorld.copy(camera.matrix); + } else { + camera.matrixWorld.multiplyMatrices(parent.matrixWorld, camera.matrix); + } + camera.matrixWorldInverse.copy(camera.matrixWorld).invert(); + } + this.updateCamera = function(camera) { + if (session === null) + return; + cameraVR.near = cameraR.near = cameraL.near = camera.near; + cameraVR.far = cameraR.far = cameraL.far = camera.far; + if (_currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far) { + session.updateRenderState({ + depthNear: cameraVR.near, + depthFar: cameraVR.far + }); + _currentDepthNear = cameraVR.near; + _currentDepthFar = cameraVR.far; + } + const parent = camera.parent; + const cameras2 = cameraVR.cameras; + updateCamera(cameraVR, parent); + for (let i = 0; i < cameras2.length; i++) { + updateCamera(cameras2[i], parent); + } + cameraVR.matrixWorld.decompose(cameraVR.position, cameraVR.quaternion, cameraVR.scale); + camera.position.copy(cameraVR.position); + camera.quaternion.copy(cameraVR.quaternion); + camera.scale.copy(cameraVR.scale); + camera.matrix.copy(cameraVR.matrix); + camera.matrixWorld.copy(cameraVR.matrixWorld); + const children2 = camera.children; + for (let i = 0, l = children2.length; i < l; i++) { + children2[i].updateMatrixWorld(true); + } + if (cameras2.length === 2) { + setProjectionFromUnion(cameraVR, cameraL, cameraR); + } else { + cameraVR.projectionMatrix.copy(cameraL.projectionMatrix); + } + }; + this.getCamera = function() { + return cameraVR; + }; + this.getFoveation = function() { + if (glProjLayer !== null) { + return glProjLayer.fixedFoveation; + } + if (glBaseLayer !== null) { + return glBaseLayer.fixedFoveation; + } + return void 0; + }; + this.setFoveation = function(foveation) { + if (glProjLayer !== null) { + glProjLayer.fixedFoveation = foveation; + } + if (glBaseLayer !== null && glBaseLayer.fixedFoveation !== void 0) { + glBaseLayer.fixedFoveation = foveation; + } + }; + let onAnimationFrameCallback = null; + function onAnimationFrame(time, frame2) { + pose = frame2.getViewerPose(customReferenceSpace || referenceSpace); + xrFrame = frame2; + if (pose !== null) { + const views = pose.views; + if (glBaseLayer !== null) { + renderer.setRenderTargetFramebuffer(newRenderTarget, glBaseLayer.framebuffer); + renderer.setRenderTarget(newRenderTarget); + } + let cameraVRNeedsUpdate = false; + if (views.length !== cameraVR.cameras.length) { + cameraVR.cameras.length = 0; + cameraVRNeedsUpdate = true; + } + for (let i = 0; i < views.length; i++) { + const view = views[i]; + let viewport = null; + if (glBaseLayer !== null) { + viewport = glBaseLayer.getViewport(view); + } else { + const glSubImage = glBinding.getViewSubImage(glProjLayer, view); + viewport = glSubImage.viewport; + if (i === 0) { + renderer.setRenderTargetTextures(newRenderTarget, glSubImage.colorTexture, glProjLayer.ignoreDepthValues ? void 0 : glSubImage.depthStencilTexture); + renderer.setRenderTarget(newRenderTarget); + } + } + let camera = cameras[i]; + if (camera === void 0) { + camera = new PerspectiveCamera(); + camera.layers.enable(i); + camera.viewport = new Vector4(); + cameras[i] = camera; + } + camera.matrix.fromArray(view.transform.matrix); + camera.projectionMatrix.fromArray(view.projectionMatrix); + camera.viewport.set(viewport.x, viewport.y, viewport.width, viewport.height); + if (i === 0) { + cameraVR.matrix.copy(camera.matrix); + } + if (cameraVRNeedsUpdate === true) { + cameraVR.cameras.push(camera); + } + } + } + for (let i = 0; i < controllers.length; i++) { + const inputSource = controllerInputSources[i]; + const controller = controllers[i]; + if (inputSource !== null && controller !== void 0) { + controller.update(inputSource, frame2, customReferenceSpace || referenceSpace); + } + } + if (onAnimationFrameCallback) + onAnimationFrameCallback(time, frame2); + xrFrame = null; + } + const animation = new WebGLAnimation(); + animation.setAnimationLoop(onAnimationFrame); + this.setAnimationLoop = function(callback) { + onAnimationFrameCallback = callback; + }; + this.dispose = function() { + }; + } + }; + function WebGLMaterials(renderer, properties) { + function refreshFogUniforms(uniforms, fog) { + uniforms.fogColor.value.copy(fog.color); + if (fog.isFog) { + uniforms.fogNear.value = fog.near; + uniforms.fogFar.value = fog.far; + } else if (fog.isFogExp2) { + uniforms.fogDensity.value = fog.density; + } + } + function refreshMaterialUniforms(uniforms, material, pixelRatio, height, transmissionRenderTarget) { + if (material.isMeshBasicMaterial) { + refreshUniformsCommon(uniforms, material); + } else if (material.isMeshLambertMaterial) { + refreshUniformsCommon(uniforms, material); + } else if (material.isMeshToonMaterial) { + refreshUniformsCommon(uniforms, material); + refreshUniformsToon(uniforms, material); + } else if (material.isMeshPhongMaterial) { + refreshUniformsCommon(uniforms, material); + refreshUniformsPhong(uniforms, material); + } else if (material.isMeshStandardMaterial) { + refreshUniformsCommon(uniforms, material); + refreshUniformsStandard(uniforms, material); + if (material.isMeshPhysicalMaterial) { + refreshUniformsPhysical(uniforms, material, transmissionRenderTarget); + } + } else if (material.isMeshMatcapMaterial) { + refreshUniformsCommon(uniforms, material); + refreshUniformsMatcap(uniforms, material); + } else if (material.isMeshDepthMaterial) { + refreshUniformsCommon(uniforms, material); + } else if (material.isMeshDistanceMaterial) { + refreshUniformsCommon(uniforms, material); + refreshUniformsDistance(uniforms, material); + } else if (material.isMeshNormalMaterial) { + refreshUniformsCommon(uniforms, material); + } else if (material.isLineBasicMaterial) { + refreshUniformsLine(uniforms, material); + if (material.isLineDashedMaterial) { + refreshUniformsDash(uniforms, material); + } + } else if (material.isPointsMaterial) { + refreshUniformsPoints(uniforms, material, pixelRatio, height); + } else if (material.isSpriteMaterial) { + refreshUniformsSprites(uniforms, material); + } else if (material.isShadowMaterial) { + uniforms.color.value.copy(material.color); + uniforms.opacity.value = material.opacity; + } else if (material.isShaderMaterial) { + material.uniformsNeedUpdate = false; + } + } + function refreshUniformsCommon(uniforms, material) { + uniforms.opacity.value = material.opacity; + if (material.color) { + uniforms.diffuse.value.copy(material.color); + } + if (material.emissive) { + uniforms.emissive.value.copy(material.emissive).multiplyScalar(material.emissiveIntensity); + } + if (material.map) { + uniforms.map.value = material.map; + } + if (material.alphaMap) { + uniforms.alphaMap.value = material.alphaMap; + } + if (material.bumpMap) { + uniforms.bumpMap.value = material.bumpMap; + uniforms.bumpScale.value = material.bumpScale; + if (material.side === BackSide) + uniforms.bumpScale.value *= -1; + } + if (material.displacementMap) { + uniforms.displacementMap.value = material.displacementMap; + uniforms.displacementScale.value = material.displacementScale; + uniforms.displacementBias.value = material.displacementBias; + } + if (material.emissiveMap) { + uniforms.emissiveMap.value = material.emissiveMap; + } + if (material.normalMap) { + uniforms.normalMap.value = material.normalMap; + uniforms.normalScale.value.copy(material.normalScale); + if (material.side === BackSide) + uniforms.normalScale.value.negate(); + } + if (material.specularMap) { + uniforms.specularMap.value = material.specularMap; + } + if (material.alphaTest > 0) { + uniforms.alphaTest.value = material.alphaTest; + } + const envMap = properties.get(material).envMap; + if (envMap) { + uniforms.envMap.value = envMap; + uniforms.flipEnvMap.value = envMap.isCubeTexture && envMap.isRenderTargetTexture === false ? -1 : 1; + uniforms.reflectivity.value = material.reflectivity; + uniforms.ior.value = material.ior; + uniforms.refractionRatio.value = material.refractionRatio; + } + if (material.lightMap) { + uniforms.lightMap.value = material.lightMap; + const scaleFactor = renderer.physicallyCorrectLights !== true ? Math.PI : 1; + uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor; + } + if (material.aoMap) { + uniforms.aoMap.value = material.aoMap; + uniforms.aoMapIntensity.value = material.aoMapIntensity; + } + let uvScaleMap; + if (material.map) { + uvScaleMap = material.map; + } else if (material.specularMap) { + uvScaleMap = material.specularMap; + } else if (material.displacementMap) { + uvScaleMap = material.displacementMap; + } else if (material.normalMap) { + uvScaleMap = material.normalMap; + } else if (material.bumpMap) { + uvScaleMap = material.bumpMap; + } else if (material.roughnessMap) { + uvScaleMap = material.roughnessMap; + } else if (material.metalnessMap) { + uvScaleMap = material.metalnessMap; + } else if (material.alphaMap) { + uvScaleMap = material.alphaMap; + } else if (material.emissiveMap) { + uvScaleMap = material.emissiveMap; + } else if (material.clearcoatMap) { + uvScaleMap = material.clearcoatMap; + } else if (material.clearcoatNormalMap) { + uvScaleMap = material.clearcoatNormalMap; + } else if (material.clearcoatRoughnessMap) { + uvScaleMap = material.clearcoatRoughnessMap; + } else if (material.iridescenceMap) { + uvScaleMap = material.iridescenceMap; + } else if (material.iridescenceThicknessMap) { + uvScaleMap = material.iridescenceThicknessMap; + } else if (material.specularIntensityMap) { + uvScaleMap = material.specularIntensityMap; + } else if (material.specularColorMap) { + uvScaleMap = material.specularColorMap; + } else if (material.transmissionMap) { + uvScaleMap = material.transmissionMap; + } else if (material.thicknessMap) { + uvScaleMap = material.thicknessMap; + } else if (material.sheenColorMap) { + uvScaleMap = material.sheenColorMap; + } else if (material.sheenRoughnessMap) { + uvScaleMap = material.sheenRoughnessMap; + } + if (uvScaleMap !== void 0) { + if (uvScaleMap.isWebGLRenderTarget) { + uvScaleMap = uvScaleMap.texture; + } + if (uvScaleMap.matrixAutoUpdate === true) { + uvScaleMap.updateMatrix(); + } + uniforms.uvTransform.value.copy(uvScaleMap.matrix); + } + let uv2ScaleMap; + if (material.aoMap) { + uv2ScaleMap = material.aoMap; + } else if (material.lightMap) { + uv2ScaleMap = material.lightMap; + } + if (uv2ScaleMap !== void 0) { + if (uv2ScaleMap.isWebGLRenderTarget) { + uv2ScaleMap = uv2ScaleMap.texture; + } + if (uv2ScaleMap.matrixAutoUpdate === true) { + uv2ScaleMap.updateMatrix(); + } + uniforms.uv2Transform.value.copy(uv2ScaleMap.matrix); + } + } + function refreshUniformsLine(uniforms, material) { + uniforms.diffuse.value.copy(material.color); + uniforms.opacity.value = material.opacity; + } + function refreshUniformsDash(uniforms, material) { + uniforms.dashSize.value = material.dashSize; + uniforms.totalSize.value = material.dashSize + material.gapSize; + uniforms.scale.value = material.scale; + } + function refreshUniformsPoints(uniforms, material, pixelRatio, height) { + uniforms.diffuse.value.copy(material.color); + uniforms.opacity.value = material.opacity; + uniforms.size.value = material.size * pixelRatio; + uniforms.scale.value = height * 0.5; + if (material.map) { + uniforms.map.value = material.map; + } + if (material.alphaMap) { + uniforms.alphaMap.value = material.alphaMap; + } + if (material.alphaTest > 0) { + uniforms.alphaTest.value = material.alphaTest; + } + let uvScaleMap; + if (material.map) { + uvScaleMap = material.map; + } else if (material.alphaMap) { + uvScaleMap = material.alphaMap; + } + if (uvScaleMap !== void 0) { + if (uvScaleMap.matrixAutoUpdate === true) { + uvScaleMap.updateMatrix(); + } + uniforms.uvTransform.value.copy(uvScaleMap.matrix); + } + } + function refreshUniformsSprites(uniforms, material) { + uniforms.diffuse.value.copy(material.color); + uniforms.opacity.value = material.opacity; + uniforms.rotation.value = material.rotation; + if (material.map) { + uniforms.map.value = material.map; + } + if (material.alphaMap) { + uniforms.alphaMap.value = material.alphaMap; + } + if (material.alphaTest > 0) { + uniforms.alphaTest.value = material.alphaTest; + } + let uvScaleMap; + if (material.map) { + uvScaleMap = material.map; + } else if (material.alphaMap) { + uvScaleMap = material.alphaMap; + } + if (uvScaleMap !== void 0) { + if (uvScaleMap.matrixAutoUpdate === true) { + uvScaleMap.updateMatrix(); + } + uniforms.uvTransform.value.copy(uvScaleMap.matrix); + } + } + function refreshUniformsPhong(uniforms, material) { + uniforms.specular.value.copy(material.specular); + uniforms.shininess.value = Math.max(material.shininess, 1e-4); + } + function refreshUniformsToon(uniforms, material) { + if (material.gradientMap) { + uniforms.gradientMap.value = material.gradientMap; + } + } + function refreshUniformsStandard(uniforms, material) { + uniforms.roughness.value = material.roughness; + uniforms.metalness.value = material.metalness; + if (material.roughnessMap) { + uniforms.roughnessMap.value = material.roughnessMap; + } + if (material.metalnessMap) { + uniforms.metalnessMap.value = material.metalnessMap; + } + const envMap = properties.get(material).envMap; + if (envMap) { + uniforms.envMapIntensity.value = material.envMapIntensity; + } + } + function refreshUniformsPhysical(uniforms, material, transmissionRenderTarget) { + uniforms.ior.value = material.ior; + if (material.sheen > 0) { + uniforms.sheenColor.value.copy(material.sheenColor).multiplyScalar(material.sheen); + uniforms.sheenRoughness.value = material.sheenRoughness; + if (material.sheenColorMap) { + uniforms.sheenColorMap.value = material.sheenColorMap; + } + if (material.sheenRoughnessMap) { + uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; + } + } + if (material.clearcoat > 0) { + uniforms.clearcoat.value = material.clearcoat; + uniforms.clearcoatRoughness.value = material.clearcoatRoughness; + if (material.clearcoatMap) { + uniforms.clearcoatMap.value = material.clearcoatMap; + } + if (material.clearcoatRoughnessMap) { + uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; + } + if (material.clearcoatNormalMap) { + uniforms.clearcoatNormalScale.value.copy(material.clearcoatNormalScale); + uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; + if (material.side === BackSide) { + uniforms.clearcoatNormalScale.value.negate(); + } + } + } + if (material.iridescence > 0) { + uniforms.iridescence.value = material.iridescence; + uniforms.iridescenceIOR.value = material.iridescenceIOR; + uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[0]; + uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[1]; + if (material.iridescenceMap) { + uniforms.iridescenceMap.value = material.iridescenceMap; + } + if (material.iridescenceThicknessMap) { + uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; + } + } + if (material.transmission > 0) { + uniforms.transmission.value = material.transmission; + uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture; + uniforms.transmissionSamplerSize.value.set(transmissionRenderTarget.width, transmissionRenderTarget.height); + if (material.transmissionMap) { + uniforms.transmissionMap.value = material.transmissionMap; + } + uniforms.thickness.value = material.thickness; + if (material.thicknessMap) { + uniforms.thicknessMap.value = material.thicknessMap; + } + uniforms.attenuationDistance.value = material.attenuationDistance; + uniforms.attenuationColor.value.copy(material.attenuationColor); + } + uniforms.specularIntensity.value = material.specularIntensity; + uniforms.specularColor.value.copy(material.specularColor); + if (material.specularIntensityMap) { + uniforms.specularIntensityMap.value = material.specularIntensityMap; + } + if (material.specularColorMap) { + uniforms.specularColorMap.value = material.specularColorMap; + } + } + function refreshUniformsMatcap(uniforms, material) { + if (material.matcap) { + uniforms.matcap.value = material.matcap; + } + } + function refreshUniformsDistance(uniforms, material) { + uniforms.referencePosition.value.copy(material.referencePosition); + uniforms.nearDistance.value = material.nearDistance; + uniforms.farDistance.value = material.farDistance; + } + return { + refreshFogUniforms, + refreshMaterialUniforms + }; + } + function WebGLUniformsGroups(gl, info, capabilities, state) { + let buffers = {}; + let updateList = {}; + let allocatedBindingPoints = []; + const maxBindingPoints = capabilities.isWebGL2 ? gl.getParameter(35375) : 0; + function bind(uniformsGroup, program) { + const webglProgram = program.program; + state.uniformBlockBinding(uniformsGroup, webglProgram); + } + function update(uniformsGroup, program) { + let buffer = buffers[uniformsGroup.id]; + if (buffer === void 0) { + prepareUniformsGroup(uniformsGroup); + buffer = createBuffer(uniformsGroup); + buffers[uniformsGroup.id] = buffer; + uniformsGroup.addEventListener("dispose", onUniformsGroupsDispose); + } + const webglProgram = program.program; + state.updateUBOMapping(uniformsGroup, webglProgram); + const frame2 = info.render.frame; + if (updateList[uniformsGroup.id] !== frame2) { + updateBufferData(uniformsGroup); + updateList[uniformsGroup.id] = frame2; + } + } + function createBuffer(uniformsGroup) { + const bindingPointIndex = allocateBindingPointIndex(); + uniformsGroup.__bindingPointIndex = bindingPointIndex; + const buffer = gl.createBuffer(); + const size = uniformsGroup.__size; + const usage = uniformsGroup.usage; + gl.bindBuffer(35345, buffer); + gl.bufferData(35345, size, usage); + gl.bindBuffer(35345, null); + gl.bindBufferBase(35345, bindingPointIndex, buffer); + return buffer; + } + function allocateBindingPointIndex() { + for (let i = 0; i < maxBindingPoints; i++) { + if (allocatedBindingPoints.indexOf(i) === -1) { + allocatedBindingPoints.push(i); + return i; + } + } + console.error("THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached."); + return 0; + } + function updateBufferData(uniformsGroup) { + const buffer = buffers[uniformsGroup.id]; + const uniforms = uniformsGroup.uniforms; + const cache2 = uniformsGroup.__cache; + gl.bindBuffer(35345, buffer); + for (let i = 0, il = uniforms.length; i < il; i++) { + const uniform = uniforms[i]; + if (hasUniformChanged(uniform, i, cache2) === true) { + const value = uniform.value; + const offset = uniform.__offset; + if (typeof value === "number") { + uniform.__data[0] = value; + gl.bufferSubData(35345, offset, uniform.__data); + } else { + if (uniform.value.isMatrix3) { + uniform.__data[0] = uniform.value.elements[0]; + uniform.__data[1] = uniform.value.elements[1]; + uniform.__data[2] = uniform.value.elements[2]; + uniform.__data[3] = uniform.value.elements[0]; + uniform.__data[4] = uniform.value.elements[3]; + uniform.__data[5] = uniform.value.elements[4]; + uniform.__data[6] = uniform.value.elements[5]; + uniform.__data[7] = uniform.value.elements[0]; + uniform.__data[8] = uniform.value.elements[6]; + uniform.__data[9] = uniform.value.elements[7]; + uniform.__data[10] = uniform.value.elements[8]; + uniform.__data[11] = uniform.value.elements[0]; + } else { + value.toArray(uniform.__data); + } + gl.bufferSubData(35345, offset, uniform.__data); + } + } + } + gl.bindBuffer(35345, null); + } + function hasUniformChanged(uniform, index2, cache2) { + const value = uniform.value; + if (cache2[index2] === void 0) { + if (typeof value === "number") { + cache2[index2] = value; + } else { + cache2[index2] = value.clone(); + } + return true; + } else { + if (typeof value === "number") { + if (cache2[index2] !== value) { + cache2[index2] = value; + return true; + } + } else { + const cachedObject = cache2[index2]; + if (cachedObject.equals(value) === false) { + cachedObject.copy(value); + return true; + } + } + } + return false; + } + function prepareUniformsGroup(uniformsGroup) { + const uniforms = uniformsGroup.uniforms; + let offset = 0; + const chunkSize = 16; + let chunkOffset = 0; + for (let i = 0, l = uniforms.length; i < l; i++) { + const uniform = uniforms[i]; + const info2 = getUniformSize(uniform); + uniform.__data = new Float32Array(info2.storage / Float32Array.BYTES_PER_ELEMENT); + uniform.__offset = offset; + if (i > 0) { + chunkOffset = offset % chunkSize; + const remainingSizeInChunk = chunkSize - chunkOffset; + if (chunkOffset !== 0 && remainingSizeInChunk - info2.boundary < 0) { + offset += chunkSize - chunkOffset; + uniform.__offset = offset; + } + } + offset += info2.storage; + } + chunkOffset = offset % chunkSize; + if (chunkOffset > 0) + offset += chunkSize - chunkOffset; + uniformsGroup.__size = offset; + uniformsGroup.__cache = {}; + return this; + } + function getUniformSize(uniform) { + const value = uniform.value; + const info2 = { + boundary: 0, + storage: 0 + }; + if (typeof value === "number") { + info2.boundary = 4; + info2.storage = 4; + } else if (value.isVector2) { + info2.boundary = 8; + info2.storage = 8; + } else if (value.isVector3 || value.isColor) { + info2.boundary = 16; + info2.storage = 12; + } else if (value.isVector4) { + info2.boundary = 16; + info2.storage = 16; + } else if (value.isMatrix3) { + info2.boundary = 48; + info2.storage = 48; + } else if (value.isMatrix4) { + info2.boundary = 64; + info2.storage = 64; + } else if (value.isTexture) { + console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."); + } else { + console.warn("THREE.WebGLRenderer: Unsupported uniform value type.", value); + } + return info2; + } + function onUniformsGroupsDispose(event) { + const uniformsGroup = event.target; + uniformsGroup.removeEventListener("dispose", onUniformsGroupsDispose); + const index2 = allocatedBindingPoints.indexOf(uniformsGroup.__bindingPointIndex); + allocatedBindingPoints.splice(index2, 1); + gl.deleteBuffer(buffers[uniformsGroup.id]); + delete buffers[uniformsGroup.id]; + delete updateList[uniformsGroup.id]; + } + function dispose() { + for (const id2 in buffers) { + gl.deleteBuffer(buffers[id2]); + } + allocatedBindingPoints = []; + buffers = {}; + updateList = {}; + } + return { + bind, + update, + dispose + }; + } + function createCanvasElement() { + const canvas = createElementNS("canvas"); + canvas.style.display = "block"; + return canvas; + } + function WebGLRenderer(parameters = {}) { + this.isWebGLRenderer = true; + const _canvas2 = parameters.canvas !== void 0 ? parameters.canvas : createCanvasElement(), _context = parameters.context !== void 0 ? parameters.context : null, _depth = parameters.depth !== void 0 ? parameters.depth : true, _stencil = parameters.stencil !== void 0 ? parameters.stencil : true, _antialias = parameters.antialias !== void 0 ? parameters.antialias : false, _premultipliedAlpha = parameters.premultipliedAlpha !== void 0 ? parameters.premultipliedAlpha : true, _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== void 0 ? parameters.preserveDrawingBuffer : false, _powerPreference = parameters.powerPreference !== void 0 ? parameters.powerPreference : "default", _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== void 0 ? parameters.failIfMajorPerformanceCaveat : false; + let _alpha; + if (_context !== null) { + _alpha = _context.getContextAttributes().alpha; + } else { + _alpha = parameters.alpha !== void 0 ? parameters.alpha : false; + } + let currentRenderList = null; + let currentRenderState = null; + const renderListStack = []; + const renderStateStack = []; + this.domElement = _canvas2; + this.debug = { + checkShaderErrors: true + }; + this.autoClear = true; + this.autoClearColor = true; + this.autoClearDepth = true; + this.autoClearStencil = true; + this.sortObjects = true; + this.clippingPlanes = []; + this.localClippingEnabled = false; + this.outputEncoding = LinearEncoding; + this.physicallyCorrectLights = false; + this.toneMapping = NoToneMapping; + this.toneMappingExposure = 1; + Object.defineProperties(this, { + gammaFactor: { + get: function() { + console.warn("THREE.WebGLRenderer: .gammaFactor has been removed."); + return 2; + }, + set: function() { + console.warn("THREE.WebGLRenderer: .gammaFactor has been removed."); + } + } + }); + const _this = this; + let _isContextLost = false; + let _currentActiveCubeFace = 0; + let _currentActiveMipmapLevel = 0; + let _currentRenderTarget = null; + let _currentMaterialId = -1; + let _currentCamera = null; + const _currentViewport = new Vector4(); + const _currentScissor = new Vector4(); + let _currentScissorTest = null; + let _width = _canvas2.width; + let _height = _canvas2.height; + let _pixelRatio = 1; + let _opaqueSort = null; + let _transparentSort = null; + const _viewport = new Vector4(0, 0, _width, _height); + const _scissor = new Vector4(0, 0, _width, _height); + let _scissorTest = false; + const _frustum = new Frustum(); + let _clippingEnabled = false; + let _localClippingEnabled = false; + let _transmissionRenderTarget = null; + const _projScreenMatrix = new Matrix4(); + const _vector22 = new Vector2(); + const _vector3 = new Vector3(); + const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; + function getTargetPixelRatio() { + return _currentRenderTarget === null ? _pixelRatio : 1; + } + let _gl = _context; + function getContext(contextNames, contextAttributes) { + for (let i = 0; i < contextNames.length; i++) { + const contextName = contextNames[i]; + const context = _canvas2.getContext(contextName, contextAttributes); + if (context !== null) + return context; + } + return null; + } + try { + const contextAttributes = { + alpha: true, + depth: _depth, + stencil: _stencil, + antialias: _antialias, + premultipliedAlpha: _premultipliedAlpha, + preserveDrawingBuffer: _preserveDrawingBuffer, + powerPreference: _powerPreference, + failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat + }; + if ("setAttribute" in _canvas2) + _canvas2.setAttribute("data-engine", `three.js r${REVISION}`); + _canvas2.addEventListener("webglcontextlost", onContextLost, false); + _canvas2.addEventListener("webglcontextrestored", onContextRestore, false); + _canvas2.addEventListener("webglcontextcreationerror", onContextCreationError, false); + if (_gl === null) { + const contextNames = ["webgl2", "webgl", "experimental-webgl"]; + if (_this.isWebGL1Renderer === true) { + contextNames.shift(); + } + _gl = getContext(contextNames, contextAttributes); + if (_gl === null) { + if (getContext(contextNames)) { + throw new Error("Error creating WebGL context with your selected attributes."); + } else { + throw new Error("Error creating WebGL context."); + } + } + } + if (_gl.getShaderPrecisionFormat === void 0) { + _gl.getShaderPrecisionFormat = function() { + return { "rangeMin": 1, "rangeMax": 1, "precision": 1 }; + }; + } + } catch (error) { + console.error("THREE.WebGLRenderer: " + error.message); + throw error; + } + let extensions, capabilities, state, info; + let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let programCache, materials, renderLists, renderStates, clipping, shadowMap; + let background, morphtargets, bufferRenderer, indexedBufferRenderer; + let utils, bindingStates, uniformsGroups; + function initGLContext() { + extensions = new WebGLExtensions(_gl); + capabilities = new WebGLCapabilities(_gl, extensions, parameters); + extensions.init(capabilities); + utils = new WebGLUtils(_gl, extensions, capabilities); + state = new WebGLState(_gl, extensions, capabilities); + info = new WebGLInfo(); + properties = new WebGLProperties(); + textures = new WebGLTextures(_gl, extensions, state, properties, capabilities, utils, info); + cubemaps = new WebGLCubeMaps(_this); + cubeuvmaps = new WebGLCubeUVMaps(_this); + attributes = new WebGLAttributes(_gl, capabilities); + bindingStates = new WebGLBindingStates(_gl, extensions, attributes, capabilities); + geometries = new WebGLGeometries(_gl, attributes, info, bindingStates); + objects = new WebGLObjects(_gl, geometries, attributes, info); + morphtargets = new WebGLMorphtargets(_gl, capabilities, textures); + clipping = new WebGLClipping(properties); + programCache = new WebGLPrograms(_this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping); + materials = new WebGLMaterials(_this, properties); + renderLists = new WebGLRenderLists(); + renderStates = new WebGLRenderStates(extensions, capabilities); + background = new WebGLBackground(_this, cubemaps, state, objects, _alpha, _premultipliedAlpha); + shadowMap = new WebGLShadowMap(_this, objects, capabilities); + uniformsGroups = new WebGLUniformsGroups(_gl, info, capabilities, state); + bufferRenderer = new WebGLBufferRenderer(_gl, extensions, info, capabilities); + indexedBufferRenderer = new WebGLIndexedBufferRenderer(_gl, extensions, info, capabilities); + info.programs = programCache.programs; + _this.capabilities = capabilities; + _this.extensions = extensions; + _this.properties = properties; + _this.renderLists = renderLists; + _this.shadowMap = shadowMap; + _this.state = state; + _this.info = info; + } + initGLContext(); + const xr = new WebXRManager(_this, _gl); + this.xr = xr; + this.getContext = function() { + return _gl; + }; + this.getContextAttributes = function() { + return _gl.getContextAttributes(); + }; + this.forceContextLoss = function() { + const extension = extensions.get("WEBGL_lose_context"); + if (extension) + extension.loseContext(); + }; + this.forceContextRestore = function() { + const extension = extensions.get("WEBGL_lose_context"); + if (extension) + extension.restoreContext(); + }; + this.getPixelRatio = function() { + return _pixelRatio; + }; + this.setPixelRatio = function(value) { + if (value === void 0) + return; + _pixelRatio = value; + this.setSize(_width, _height, false); + }; + this.getSize = function(target) { + return target.set(_width, _height); + }; + this.setSize = function(width, height, updateStyle) { + if (xr.isPresenting) { + console.warn("THREE.WebGLRenderer: Can't change size while VR device is presenting."); + return; + } + _width = width; + _height = height; + _canvas2.width = Math.floor(width * _pixelRatio); + _canvas2.height = Math.floor(height * _pixelRatio); + if (updateStyle !== false) { + _canvas2.style.width = width + "px"; + _canvas2.style.height = height + "px"; + } + this.setViewport(0, 0, width, height); + }; + this.getDrawingBufferSize = function(target) { + return target.set(_width * _pixelRatio, _height * _pixelRatio).floor(); + }; + this.setDrawingBufferSize = function(width, height, pixelRatio) { + _width = width; + _height = height; + _pixelRatio = pixelRatio; + _canvas2.width = Math.floor(width * pixelRatio); + _canvas2.height = Math.floor(height * pixelRatio); + this.setViewport(0, 0, width, height); + }; + this.getCurrentViewport = function(target) { + return target.copy(_currentViewport); + }; + this.getViewport = function(target) { + return target.copy(_viewport); + }; + this.setViewport = function(x2, y2, width, height) { + if (x2.isVector4) { + _viewport.set(x2.x, x2.y, x2.z, x2.w); + } else { + _viewport.set(x2, y2, width, height); + } + state.viewport(_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor()); + }; + this.getScissor = function(target) { + return target.copy(_scissor); + }; + this.setScissor = function(x2, y2, width, height) { + if (x2.isVector4) { + _scissor.set(x2.x, x2.y, x2.z, x2.w); + } else { + _scissor.set(x2, y2, width, height); + } + state.scissor(_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor()); + }; + this.getScissorTest = function() { + return _scissorTest; + }; + this.setScissorTest = function(boolean) { + state.setScissorTest(_scissorTest = boolean); + }; + this.setOpaqueSort = function(method) { + _opaqueSort = method; + }; + this.setTransparentSort = function(method) { + _transparentSort = method; + }; + this.getClearColor = function(target) { + return target.copy(background.getClearColor()); + }; + this.setClearColor = function() { + background.setClearColor.apply(background, arguments); + }; + this.getClearAlpha = function() { + return background.getClearAlpha(); + }; + this.setClearAlpha = function() { + background.setClearAlpha.apply(background, arguments); + }; + this.clear = function(color2 = true, depth = true, stencil = true) { + let bits = 0; + if (color2) + bits |= 16384; + if (depth) + bits |= 256; + if (stencil) + bits |= 1024; + _gl.clear(bits); + }; + this.clearColor = function() { + this.clear(true, false, false); + }; + this.clearDepth = function() { + this.clear(false, true, false); + }; + this.clearStencil = function() { + this.clear(false, false, true); + }; + this.dispose = function() { + _canvas2.removeEventListener("webglcontextlost", onContextLost, false); + _canvas2.removeEventListener("webglcontextrestored", onContextRestore, false); + _canvas2.removeEventListener("webglcontextcreationerror", onContextCreationError, false); + renderLists.dispose(); + renderStates.dispose(); + properties.dispose(); + cubemaps.dispose(); + cubeuvmaps.dispose(); + objects.dispose(); + bindingStates.dispose(); + uniformsGroups.dispose(); + programCache.dispose(); + xr.dispose(); + xr.removeEventListener("sessionstart", onXRSessionStart); + xr.removeEventListener("sessionend", onXRSessionEnd); + if (_transmissionRenderTarget) { + _transmissionRenderTarget.dispose(); + _transmissionRenderTarget = null; + } + animation.stop(); + }; + function onContextLost(event) { + event.preventDefault(); + console.log("THREE.WebGLRenderer: Context Lost."); + _isContextLost = true; + } + function onContextRestore() { + console.log("THREE.WebGLRenderer: Context Restored."); + _isContextLost = false; + const infoAutoReset = info.autoReset; + const shadowMapEnabled = shadowMap.enabled; + const shadowMapAutoUpdate = shadowMap.autoUpdate; + const shadowMapNeedsUpdate = shadowMap.needsUpdate; + const shadowMapType = shadowMap.type; + initGLContext(); + info.autoReset = infoAutoReset; + shadowMap.enabled = shadowMapEnabled; + shadowMap.autoUpdate = shadowMapAutoUpdate; + shadowMap.needsUpdate = shadowMapNeedsUpdate; + shadowMap.type = shadowMapType; + } + function onContextCreationError(event) { + console.error("THREE.WebGLRenderer: A WebGL context could not be created. Reason: ", event.statusMessage); + } + function onMaterialDispose(event) { + const material = event.target; + material.removeEventListener("dispose", onMaterialDispose); + deallocateMaterial(material); + } + function deallocateMaterial(material) { + releaseMaterialProgramReferences(material); + properties.remove(material); + } + function releaseMaterialProgramReferences(material) { + const programs = properties.get(material).programs; + if (programs !== void 0) { + programs.forEach(function(program) { + programCache.releaseProgram(program); + }); + if (material.isShaderMaterial) { + programCache.releaseShaderCache(material); + } + } + } + this.renderBufferDirect = function(camera, scene, geometry, material, object, group) { + if (scene === null) + scene = _emptyScene; + const frontFaceCW = object.isMesh && object.matrixWorld.determinant() < 0; + const program = setProgram(camera, scene, geometry, material, object); + state.setMaterial(material, frontFaceCW); + let index2 = geometry.index; + const position = geometry.attributes.position; + if (index2 === null) { + if (position === void 0 || position.count === 0) + return; + } else if (index2.count === 0) { + return; + } + let rangeFactor = 1; + if (material.wireframe === true) { + index2 = geometries.getWireframeAttribute(geometry); + rangeFactor = 2; + } + bindingStates.setup(object, material, program, geometry, index2); + let attribute; + let renderer = bufferRenderer; + if (index2 !== null) { + attribute = attributes.get(index2); + renderer = indexedBufferRenderer; + renderer.setIndex(attribute); + } + const dataCount = index2 !== null ? index2.count : position.count; + const rangeStart = geometry.drawRange.start * rangeFactor; + const rangeCount = geometry.drawRange.count * rangeFactor; + const groupStart = group !== null ? group.start * rangeFactor : 0; + const groupCount = group !== null ? group.count * rangeFactor : Infinity; + const drawStart = Math.max(rangeStart, groupStart); + const drawEnd = Math.min(dataCount, rangeStart + rangeCount, groupStart + groupCount) - 1; + const drawCount = Math.max(0, drawEnd - drawStart + 1); + if (drawCount === 0) + return; + if (object.isMesh) { + if (material.wireframe === true) { + state.setLineWidth(material.wireframeLinewidth * getTargetPixelRatio()); + renderer.setMode(1); + } else { + renderer.setMode(4); + } + } else if (object.isLine) { + let lineWidth = material.linewidth; + if (lineWidth === void 0) + lineWidth = 1; + state.setLineWidth(lineWidth * getTargetPixelRatio()); + if (object.isLineSegments) { + renderer.setMode(1); + } else if (object.isLineLoop) { + renderer.setMode(2); + } else { + renderer.setMode(3); + } + } else if (object.isPoints) { + renderer.setMode(0); + } else if (object.isSprite) { + renderer.setMode(4); + } + if (object.isInstancedMesh) { + renderer.renderInstances(drawStart, drawCount, object.count); + } else if (geometry.isInstancedBufferGeometry) { + const instanceCount = Math.min(geometry.instanceCount, geometry._maxInstanceCount); + renderer.renderInstances(drawStart, drawCount, instanceCount); + } else { + renderer.render(drawStart, drawCount); + } + }; + this.compile = function(scene, camera) { + currentRenderState = renderStates.get(scene); + currentRenderState.init(); + renderStateStack.push(currentRenderState); + scene.traverseVisible(function(object) { + if (object.isLight && object.layers.test(camera.layers)) { + currentRenderState.pushLight(object); + if (object.castShadow) { + currentRenderState.pushShadow(object); + } + } + }); + currentRenderState.setupLights(_this.physicallyCorrectLights); + scene.traverse(function(object) { + const material = object.material; + if (material) { + if (Array.isArray(material)) { + for (let i = 0; i < material.length; i++) { + const material2 = material[i]; + getProgram(material2, scene, object); + } + } else { + getProgram(material, scene, object); + } + } + }); + renderStateStack.pop(); + currentRenderState = null; + }; + let onAnimationFrameCallback = null; + function onAnimationFrame(time) { + if (onAnimationFrameCallback) + onAnimationFrameCallback(time); + } + function onXRSessionStart() { + animation.stop(); + } + function onXRSessionEnd() { + animation.start(); + } + const animation = new WebGLAnimation(); + animation.setAnimationLoop(onAnimationFrame); + if (typeof self !== "undefined") + animation.setContext(self); + this.setAnimationLoop = function(callback) { + onAnimationFrameCallback = callback; + xr.setAnimationLoop(callback); + callback === null ? animation.stop() : animation.start(); + }; + xr.addEventListener("sessionstart", onXRSessionStart); + xr.addEventListener("sessionend", onXRSessionEnd); + this.render = function(scene, camera) { + if (camera !== void 0 && camera.isCamera !== true) { + console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera."); + return; + } + if (_isContextLost === true) + return; + if (scene.autoUpdate === true) + scene.updateMatrixWorld(); + if (camera.parent === null) + camera.updateMatrixWorld(); + if (xr.enabled === true && xr.isPresenting === true) { + if (xr.cameraAutoUpdate === true) + xr.updateCamera(camera); + camera = xr.getCamera(); + } + if (scene.isScene === true) + scene.onBeforeRender(_this, scene, camera, _currentRenderTarget); + currentRenderState = renderStates.get(scene, renderStateStack.length); + currentRenderState.init(); + renderStateStack.push(currentRenderState); + _projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); + _frustum.setFromProjectionMatrix(_projScreenMatrix); + _localClippingEnabled = this.localClippingEnabled; + _clippingEnabled = clipping.init(this.clippingPlanes, _localClippingEnabled, camera); + currentRenderList = renderLists.get(scene, renderListStack.length); + currentRenderList.init(); + renderListStack.push(currentRenderList); + projectObject(scene, camera, 0, _this.sortObjects); + currentRenderList.finish(); + if (_this.sortObjects === true) { + currentRenderList.sort(_opaqueSort, _transparentSort); + } + if (_clippingEnabled === true) + clipping.beginShadows(); + const shadowsArray = currentRenderState.state.shadowsArray; + shadowMap.render(shadowsArray, scene, camera); + if (_clippingEnabled === true) + clipping.endShadows(); + if (this.info.autoReset === true) + this.info.reset(); + background.render(currentRenderList, scene); + currentRenderState.setupLights(_this.physicallyCorrectLights); + if (camera.isArrayCamera) { + const cameras = camera.cameras; + for (let i = 0, l = cameras.length; i < l; i++) { + const camera2 = cameras[i]; + renderScene(currentRenderList, scene, camera2, camera2.viewport); + } + } else { + renderScene(currentRenderList, scene, camera); + } + if (_currentRenderTarget !== null) { + textures.updateMultisampleRenderTarget(_currentRenderTarget); + textures.updateRenderTargetMipmap(_currentRenderTarget); + } + if (scene.isScene === true) + scene.onAfterRender(_this, scene, camera); + bindingStates.resetDefaultState(); + _currentMaterialId = -1; + _currentCamera = null; + renderStateStack.pop(); + if (renderStateStack.length > 0) { + currentRenderState = renderStateStack[renderStateStack.length - 1]; + } else { + currentRenderState = null; + } + renderListStack.pop(); + if (renderListStack.length > 0) { + currentRenderList = renderListStack[renderListStack.length - 1]; + } else { + currentRenderList = null; + } + }; + function projectObject(object, camera, groupOrder, sortObjects) { + if (object.visible === false) + return; + const visible = object.layers.test(camera.layers); + if (visible) { + if (object.isGroup) { + groupOrder = object.renderOrder; + } else if (object.isLOD) { + if (object.autoUpdate === true) + object.update(camera); + } else if (object.isLight) { + currentRenderState.pushLight(object); + if (object.castShadow) { + currentRenderState.pushShadow(object); + } + } else if (object.isSprite) { + if (!object.frustumCulled || _frustum.intersectsSprite(object)) { + if (sortObjects) { + _vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix); + } + const geometry = objects.update(object); + const material = object.material; + if (material.visible) { + currentRenderList.push(object, geometry, material, groupOrder, _vector3.z, null); + } + } + } else if (object.isMesh || object.isLine || object.isPoints) { + if (object.isSkinnedMesh) { + if (object.skeleton.frame !== info.render.frame) { + object.skeleton.update(); + object.skeleton.frame = info.render.frame; + } + } + if (!object.frustumCulled || _frustum.intersectsObject(object)) { + if (sortObjects) { + _vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix); + } + const geometry = objects.update(object); + const material = object.material; + if (Array.isArray(material)) { + const groups = geometry.groups; + for (let i = 0, l = groups.length; i < l; i++) { + const group = groups[i]; + const groupMaterial = material[group.materialIndex]; + if (groupMaterial && groupMaterial.visible) { + currentRenderList.push(object, geometry, groupMaterial, groupOrder, _vector3.z, group); + } + } + } else if (material.visible) { + currentRenderList.push(object, geometry, material, groupOrder, _vector3.z, null); + } + } + } + } + const children2 = object.children; + for (let i = 0, l = children2.length; i < l; i++) { + projectObject(children2[i], camera, groupOrder, sortObjects); + } + } + function renderScene(currentRenderList2, scene, camera, viewport) { + const opaqueObjects = currentRenderList2.opaque; + const transmissiveObjects = currentRenderList2.transmissive; + const transparentObjects = currentRenderList2.transparent; + currentRenderState.setupLightsView(camera); + if (transmissiveObjects.length > 0) + renderTransmissionPass(opaqueObjects, scene, camera); + if (viewport) + state.viewport(_currentViewport.copy(viewport)); + if (opaqueObjects.length > 0) + renderObjects(opaqueObjects, scene, camera); + if (transmissiveObjects.length > 0) + renderObjects(transmissiveObjects, scene, camera); + if (transparentObjects.length > 0) + renderObjects(transparentObjects, scene, camera); + state.buffers.depth.setTest(true); + state.buffers.depth.setMask(true); + state.buffers.color.setMask(true); + state.setPolygonOffset(false); + } + function renderTransmissionPass(opaqueObjects, scene, camera) { + const isWebGL2 = capabilities.isWebGL2; + if (_transmissionRenderTarget === null) { + _transmissionRenderTarget = new WebGLRenderTarget(1, 1, { + generateMipmaps: true, + type: extensions.has("EXT_color_buffer_half_float") ? HalfFloatType : UnsignedByteType, + minFilter: LinearMipmapLinearFilter, + samples: isWebGL2 && _antialias === true ? 4 : 0 + }); + } + _this.getDrawingBufferSize(_vector22); + if (isWebGL2) { + _transmissionRenderTarget.setSize(_vector22.x, _vector22.y); + } else { + _transmissionRenderTarget.setSize(floorPowerOfTwo(_vector22.x), floorPowerOfTwo(_vector22.y)); + } + const currentRenderTarget = _this.getRenderTarget(); + _this.setRenderTarget(_transmissionRenderTarget); + _this.clear(); + const currentToneMapping = _this.toneMapping; + _this.toneMapping = NoToneMapping; + renderObjects(opaqueObjects, scene, camera); + _this.toneMapping = currentToneMapping; + textures.updateMultisampleRenderTarget(_transmissionRenderTarget); + textures.updateRenderTargetMipmap(_transmissionRenderTarget); + _this.setRenderTarget(currentRenderTarget); + } + function renderObjects(renderList, scene, camera) { + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; + for (let i = 0, l = renderList.length; i < l; i++) { + const renderItem = renderList[i]; + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = overrideMaterial === null ? renderItem.material : overrideMaterial; + const group = renderItem.group; + if (object.layers.test(camera.layers)) { + renderObject(object, scene, camera, geometry, material, group); + } + } + } + function renderObject(object, scene, camera, geometry, material, group) { + object.onBeforeRender(_this, scene, camera, geometry, material, group); + object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, object.matrixWorld); + object.normalMatrix.getNormalMatrix(object.modelViewMatrix); + material.onBeforeRender(_this, scene, camera, geometry, object, group); + if (material.transparent === true && material.side === DoubleSide) { + material.side = BackSide; + material.needsUpdate = true; + _this.renderBufferDirect(camera, scene, geometry, material, object, group); + material.side = FrontSide; + material.needsUpdate = true; + _this.renderBufferDirect(camera, scene, geometry, material, object, group); + material.side = DoubleSide; + } else { + _this.renderBufferDirect(camera, scene, geometry, material, object, group); + } + object.onAfterRender(_this, scene, camera, geometry, material, group); + } + function getProgram(material, scene, object) { + if (scene.isScene !== true) + scene = _emptyScene; + const materialProperties = properties.get(material); + const lights = currentRenderState.state.lights; + const shadowsArray = currentRenderState.state.shadowsArray; + const lightsStateVersion = lights.state.version; + const parameters2 = programCache.getParameters(material, lights.state, shadowsArray, scene, object); + const programCacheKey = programCache.getProgramCacheKey(parameters2); + let programs = materialProperties.programs; + materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; + materialProperties.fog = scene.fog; + materialProperties.envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || materialProperties.environment); + if (programs === void 0) { + material.addEventListener("dispose", onMaterialDispose); + programs = /* @__PURE__ */ new Map(); + materialProperties.programs = programs; + } + let program = programs.get(programCacheKey); + if (program !== void 0) { + if (materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion) { + updateCommonMaterialProperties(material, parameters2); + return program; + } + } else { + parameters2.uniforms = programCache.getUniforms(material); + material.onBuild(object, parameters2, _this); + material.onBeforeCompile(parameters2, _this); + program = programCache.acquireProgram(parameters2, programCacheKey); + programs.set(programCacheKey, program); + materialProperties.uniforms = parameters2.uniforms; + } + const uniforms = materialProperties.uniforms; + if (!material.isShaderMaterial && !material.isRawShaderMaterial || material.clipping === true) { + uniforms.clippingPlanes = clipping.uniform; + } + updateCommonMaterialProperties(material, parameters2); + materialProperties.needsLights = materialNeedsLights(material); + materialProperties.lightsStateVersion = lightsStateVersion; + if (materialProperties.needsLights) { + uniforms.ambientLightColor.value = lights.state.ambient; + uniforms.lightProbe.value = lights.state.probe; + uniforms.directionalLights.value = lights.state.directional; + uniforms.directionalLightShadows.value = lights.state.directionalShadow; + uniforms.spotLights.value = lights.state.spot; + uniforms.spotLightShadows.value = lights.state.spotShadow; + uniforms.rectAreaLights.value = lights.state.rectArea; + uniforms.ltc_1.value = lights.state.rectAreaLTC1; + uniforms.ltc_2.value = lights.state.rectAreaLTC2; + uniforms.pointLights.value = lights.state.point; + uniforms.pointLightShadows.value = lights.state.pointShadow; + uniforms.hemisphereLights.value = lights.state.hemi; + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; + } + const progUniforms = program.getUniforms(); + const uniformsList = WebGLUniforms.seqWithValue(progUniforms.seq, uniforms); + materialProperties.currentProgram = program; + materialProperties.uniformsList = uniformsList; + return program; + } + function updateCommonMaterialProperties(material, parameters2) { + const materialProperties = properties.get(material); + materialProperties.outputEncoding = parameters2.outputEncoding; + materialProperties.instancing = parameters2.instancing; + materialProperties.skinning = parameters2.skinning; + materialProperties.morphTargets = parameters2.morphTargets; + materialProperties.morphNormals = parameters2.morphNormals; + materialProperties.morphColors = parameters2.morphColors; + materialProperties.morphTargetsCount = parameters2.morphTargetsCount; + materialProperties.numClippingPlanes = parameters2.numClippingPlanes; + materialProperties.numIntersection = parameters2.numClipIntersection; + materialProperties.vertexAlphas = parameters2.vertexAlphas; + materialProperties.vertexTangents = parameters2.vertexTangents; + materialProperties.toneMapping = parameters2.toneMapping; + } + function setProgram(camera, scene, geometry, material, object) { + if (scene.isScene !== true) + scene = _emptyScene; + textures.resetTextureUnits(); + const fog = scene.fog; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const encoding = _currentRenderTarget === null ? _this.outputEncoding : _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding; + const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment); + const vertexAlphas = material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4; + const vertexTangents = !!material.normalMap && !!geometry.attributes.tangent; + const morphTargets = !!geometry.morphAttributes.position; + const morphNormals = !!geometry.morphAttributes.normal; + const morphColors = !!geometry.morphAttributes.color; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = morphAttribute !== void 0 ? morphAttribute.length : 0; + const materialProperties = properties.get(material); + const lights = currentRenderState.state.lights; + if (_clippingEnabled === true) { + if (_localClippingEnabled === true || camera !== _currentCamera) { + const useCache = camera === _currentCamera && material.id === _currentMaterialId; + clipping.setState(material, camera, useCache); + } + } + let needsProgramChange = false; + if (material.version === materialProperties.__version) { + if (materialProperties.needsLights && materialProperties.lightsStateVersion !== lights.state.version) { + needsProgramChange = true; + } else if (materialProperties.outputEncoding !== encoding) { + needsProgramChange = true; + } else if (object.isInstancedMesh && materialProperties.instancing === false) { + needsProgramChange = true; + } else if (!object.isInstancedMesh && materialProperties.instancing === true) { + needsProgramChange = true; + } else if (object.isSkinnedMesh && materialProperties.skinning === false) { + needsProgramChange = true; + } else if (!object.isSkinnedMesh && materialProperties.skinning === true) { + needsProgramChange = true; + } else if (materialProperties.envMap !== envMap) { + needsProgramChange = true; + } else if (material.fog === true && materialProperties.fog !== fog) { + needsProgramChange = true; + } else if (materialProperties.numClippingPlanes !== void 0 && (materialProperties.numClippingPlanes !== clipping.numPlanes || materialProperties.numIntersection !== clipping.numIntersection)) { + needsProgramChange = true; + } else if (materialProperties.vertexAlphas !== vertexAlphas) { + needsProgramChange = true; + } else if (materialProperties.vertexTangents !== vertexTangents) { + needsProgramChange = true; + } else if (materialProperties.morphTargets !== morphTargets) { + needsProgramChange = true; + } else if (materialProperties.morphNormals !== morphNormals) { + needsProgramChange = true; + } else if (materialProperties.morphColors !== morphColors) { + needsProgramChange = true; + } else if (materialProperties.toneMapping !== toneMapping) { + needsProgramChange = true; + } else if (capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount) { + needsProgramChange = true; + } + } else { + needsProgramChange = true; + materialProperties.__version = material.version; + } + let program = materialProperties.currentProgram; + if (needsProgramChange === true) { + program = getProgram(material, scene, object); + } + let refreshProgram = false; + let refreshMaterial = false; + let refreshLights = false; + const p_uniforms = program.getUniforms(), m_uniforms = materialProperties.uniforms; + if (state.useProgram(program.program)) { + refreshProgram = true; + refreshMaterial = true; + refreshLights = true; + } + if (material.id !== _currentMaterialId) { + _currentMaterialId = material.id; + refreshMaterial = true; + } + if (refreshProgram || _currentCamera !== camera) { + p_uniforms.setValue(_gl, "projectionMatrix", camera.projectionMatrix); + if (capabilities.logarithmicDepthBuffer) { + p_uniforms.setValue(_gl, "logDepthBufFC", 2 / (Math.log(camera.far + 1) / Math.LN2)); + } + if (_currentCamera !== camera) { + _currentCamera = camera; + refreshMaterial = true; + refreshLights = true; + } + if (material.isShaderMaterial || material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshStandardMaterial || material.envMap) { + const uCamPos = p_uniforms.map.cameraPosition; + if (uCamPos !== void 0) { + uCamPos.setValue(_gl, _vector3.setFromMatrixPosition(camera.matrixWorld)); + } + } + if (material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshLambertMaterial || material.isMeshBasicMaterial || material.isMeshStandardMaterial || material.isShaderMaterial) { + p_uniforms.setValue(_gl, "isOrthographic", camera.isOrthographicCamera === true); + } + if (material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshLambertMaterial || material.isMeshBasicMaterial || material.isMeshStandardMaterial || material.isShaderMaterial || material.isShadowMaterial || object.isSkinnedMesh) { + p_uniforms.setValue(_gl, "viewMatrix", camera.matrixWorldInverse); + } + } + if (object.isSkinnedMesh) { + p_uniforms.setOptional(_gl, object, "bindMatrix"); + p_uniforms.setOptional(_gl, object, "bindMatrixInverse"); + const skeleton = object.skeleton; + if (skeleton) { + if (capabilities.floatVertexTextures) { + if (skeleton.boneTexture === null) + skeleton.computeBoneTexture(); + p_uniforms.setValue(_gl, "boneTexture", skeleton.boneTexture, textures); + p_uniforms.setValue(_gl, "boneTextureSize", skeleton.boneTextureSize); + } else { + console.warn("THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required."); + } + } + } + const morphAttributes = geometry.morphAttributes; + if (morphAttributes.position !== void 0 || morphAttributes.normal !== void 0 || morphAttributes.color !== void 0 && capabilities.isWebGL2 === true) { + morphtargets.update(object, geometry, material, program); + } + if (refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow) { + materialProperties.receiveShadow = object.receiveShadow; + p_uniforms.setValue(_gl, "receiveShadow", object.receiveShadow); + } + if (refreshMaterial) { + p_uniforms.setValue(_gl, "toneMappingExposure", _this.toneMappingExposure); + if (materialProperties.needsLights) { + markUniformsLightsNeedsUpdate(m_uniforms, refreshLights); + } + if (fog && material.fog === true) { + materials.refreshFogUniforms(m_uniforms, fog); + } + materials.refreshMaterialUniforms(m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget); + WebGLUniforms.upload(_gl, materialProperties.uniformsList, m_uniforms, textures); + } + if (material.isShaderMaterial && material.uniformsNeedUpdate === true) { + WebGLUniforms.upload(_gl, materialProperties.uniformsList, m_uniforms, textures); + material.uniformsNeedUpdate = false; + } + if (material.isSpriteMaterial) { + p_uniforms.setValue(_gl, "center", object.center); + } + p_uniforms.setValue(_gl, "modelViewMatrix", object.modelViewMatrix); + p_uniforms.setValue(_gl, "normalMatrix", object.normalMatrix); + p_uniforms.setValue(_gl, "modelMatrix", object.matrixWorld); + if (material.isShaderMaterial || material.isRawShaderMaterial) { + const groups = material.uniformsGroups; + for (let i = 0, l = groups.length; i < l; i++) { + if (capabilities.isWebGL2) { + const group = groups[i]; + uniformsGroups.update(group, program); + uniformsGroups.bind(group, program); + } else { + console.warn("THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2."); + } + } + } + return program; + } + function markUniformsLightsNeedsUpdate(uniforms, value) { + uniforms.ambientLightColor.needsUpdate = value; + uniforms.lightProbe.needsUpdate = value; + uniforms.directionalLights.needsUpdate = value; + uniforms.directionalLightShadows.needsUpdate = value; + uniforms.pointLights.needsUpdate = value; + uniforms.pointLightShadows.needsUpdate = value; + uniforms.spotLights.needsUpdate = value; + uniforms.spotLightShadows.needsUpdate = value; + uniforms.rectAreaLights.needsUpdate = value; + uniforms.hemisphereLights.needsUpdate = value; + } + function materialNeedsLights(material) { + return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial || material.isShadowMaterial || material.isShaderMaterial && material.lights === true; + } + this.getActiveCubeFace = function() { + return _currentActiveCubeFace; + }; + this.getActiveMipmapLevel = function() { + return _currentActiveMipmapLevel; + }; + this.getRenderTarget = function() { + return _currentRenderTarget; + }; + this.setRenderTargetTextures = function(renderTarget, colorTexture, depthTexture) { + properties.get(renderTarget.texture).__webglTexture = colorTexture; + properties.get(renderTarget.depthTexture).__webglTexture = depthTexture; + const renderTargetProperties = properties.get(renderTarget); + renderTargetProperties.__hasExternalTextures = true; + if (renderTargetProperties.__hasExternalTextures) { + renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === void 0; + if (!renderTargetProperties.__autoAllocateDepthBuffer) { + if (extensions.has("WEBGL_multisampled_render_to_texture") === true) { + console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"); + renderTargetProperties.__useRenderToTexture = false; + } + } + } + }; + this.setRenderTargetFramebuffer = function(renderTarget, defaultFramebuffer) { + const renderTargetProperties = properties.get(renderTarget); + renderTargetProperties.__webglFramebuffer = defaultFramebuffer; + renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === void 0; + }; + this.setRenderTarget = function(renderTarget, activeCubeFace = 0, activeMipmapLevel = 0) { + _currentRenderTarget = renderTarget; + _currentActiveCubeFace = activeCubeFace; + _currentActiveMipmapLevel = activeMipmapLevel; + let useDefaultFramebuffer = true; + if (renderTarget) { + const renderTargetProperties = properties.get(renderTarget); + if (renderTargetProperties.__useDefaultFramebuffer !== void 0) { + state.bindFramebuffer(36160, null); + useDefaultFramebuffer = false; + } else if (renderTargetProperties.__webglFramebuffer === void 0) { + textures.setupRenderTarget(renderTarget); + } else if (renderTargetProperties.__hasExternalTextures) { + textures.rebindTextures(renderTarget, properties.get(renderTarget.texture).__webglTexture, properties.get(renderTarget.depthTexture).__webglTexture); + } + } + let framebuffer = null; + let isCube = false; + let isRenderTarget3D = false; + if (renderTarget) { + const texture = renderTarget.texture; + if (texture.isData3DTexture || texture.isDataArrayTexture) { + isRenderTarget3D = true; + } + const __webglFramebuffer = properties.get(renderTarget).__webglFramebuffer; + if (renderTarget.isWebGLCubeRenderTarget) { + framebuffer = __webglFramebuffer[activeCubeFace]; + isCube = true; + } else if (capabilities.isWebGL2 && renderTarget.samples > 0 && textures.useMultisampledRTT(renderTarget) === false) { + framebuffer = properties.get(renderTarget).__webglMultisampledFramebuffer; + } else { + framebuffer = __webglFramebuffer; + } + _currentViewport.copy(renderTarget.viewport); + _currentScissor.copy(renderTarget.scissor); + _currentScissorTest = renderTarget.scissorTest; + } else { + _currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor(); + _currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor(); + _currentScissorTest = _scissorTest; + } + const framebufferBound = state.bindFramebuffer(36160, framebuffer); + if (framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer) { + state.drawBuffers(renderTarget, framebuffer); + } + state.viewport(_currentViewport); + state.scissor(_currentScissor); + state.setScissorTest(_currentScissorTest); + if (isCube) { + const textureProperties = properties.get(renderTarget.texture); + _gl.framebufferTexture2D(36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel); + } else if (isRenderTarget3D) { + const textureProperties = properties.get(renderTarget.texture); + const layer = activeCubeFace || 0; + _gl.framebufferTextureLayer(36160, 36064, textureProperties.__webglTexture, activeMipmapLevel || 0, layer); + } + _currentMaterialId = -1; + }; + this.readRenderTargetPixels = function(renderTarget, x2, y2, width, height, buffer, activeCubeFaceIndex) { + if (!(renderTarget && renderTarget.isWebGLRenderTarget)) { + console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget."); + return; + } + let framebuffer = properties.get(renderTarget).__webglFramebuffer; + if (renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== void 0) { + framebuffer = framebuffer[activeCubeFaceIndex]; + } + if (framebuffer) { + state.bindFramebuffer(36160, framebuffer); + try { + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; + if (textureFormat !== RGBAFormat && utils.convert(textureFormat) !== _gl.getParameter(35739)) { + console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format."); + return; + } + const halfFloatSupportedByExt = textureType === HalfFloatType && (extensions.has("EXT_color_buffer_half_float") || capabilities.isWebGL2 && extensions.has("EXT_color_buffer_float")); + if (textureType !== UnsignedByteType && utils.convert(textureType) !== _gl.getParameter(35738) && !(textureType === FloatType && (capabilities.isWebGL2 || extensions.has("OES_texture_float") || extensions.has("WEBGL_color_buffer_float"))) && !halfFloatSupportedByExt) { + console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type."); + return; + } + if (x2 >= 0 && x2 <= renderTarget.width - width && (y2 >= 0 && y2 <= renderTarget.height - height)) { + _gl.readPixels(x2, y2, width, height, utils.convert(textureFormat), utils.convert(textureType), buffer); + } + } finally { + const framebuffer2 = _currentRenderTarget !== null ? properties.get(_currentRenderTarget).__webglFramebuffer : null; + state.bindFramebuffer(36160, framebuffer2); + } + } + }; + this.copyFramebufferToTexture = function(position, texture, level = 0) { + const levelScale = Math.pow(2, -level); + const width = Math.floor(texture.image.width * levelScale); + const height = Math.floor(texture.image.height * levelScale); + textures.setTexture2D(texture, 0); + _gl.copyTexSubImage2D(3553, level, 0, 0, position.x, position.y, width, height); + state.unbindTexture(); + }; + this.copyTextureToTexture = function(position, srcTexture, dstTexture, level = 0) { + const width = srcTexture.image.width; + const height = srcTexture.image.height; + const glFormat = utils.convert(dstTexture.format); + const glType = utils.convert(dstTexture.type); + textures.setTexture2D(dstTexture, 0); + _gl.pixelStorei(37440, dstTexture.flipY); + _gl.pixelStorei(37441, dstTexture.premultiplyAlpha); + _gl.pixelStorei(3317, dstTexture.unpackAlignment); + if (srcTexture.isDataTexture) { + _gl.texSubImage2D(3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data); + } else { + if (srcTexture.isCompressedTexture) { + _gl.compressedTexSubImage2D(3553, level, position.x, position.y, srcTexture.mipmaps[0].width, srcTexture.mipmaps[0].height, glFormat, srcTexture.mipmaps[0].data); + } else { + _gl.texSubImage2D(3553, level, position.x, position.y, glFormat, glType, srcTexture.image); + } + } + if (level === 0 && dstTexture.generateMipmaps) + _gl.generateMipmap(3553); + state.unbindTexture(); + }; + this.copyTextureToTexture3D = function(sourceBox, position, srcTexture, dstTexture, level = 0) { + if (_this.isWebGL1Renderer) { + console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2."); + return; + } + const width = sourceBox.max.x - sourceBox.min.x + 1; + const height = sourceBox.max.y - sourceBox.min.y + 1; + const depth = sourceBox.max.z - sourceBox.min.z + 1; + const glFormat = utils.convert(dstTexture.format); + const glType = utils.convert(dstTexture.type); + let glTarget; + if (dstTexture.isData3DTexture) { + textures.setTexture3D(dstTexture, 0); + glTarget = 32879; + } else if (dstTexture.isDataArrayTexture) { + textures.setTexture2DArray(dstTexture, 0); + glTarget = 35866; + } else { + console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray."); + return; + } + _gl.pixelStorei(37440, dstTexture.flipY); + _gl.pixelStorei(37441, dstTexture.premultiplyAlpha); + _gl.pixelStorei(3317, dstTexture.unpackAlignment); + const unpackRowLen = _gl.getParameter(3314); + const unpackImageHeight = _gl.getParameter(32878); + const unpackSkipPixels = _gl.getParameter(3316); + const unpackSkipRows = _gl.getParameter(3315); + const unpackSkipImages = _gl.getParameter(32877); + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[0] : srcTexture.image; + _gl.pixelStorei(3314, image.width); + _gl.pixelStorei(32878, image.height); + _gl.pixelStorei(3316, sourceBox.min.x); + _gl.pixelStorei(3315, sourceBox.min.y); + _gl.pixelStorei(32877, sourceBox.min.z); + if (srcTexture.isDataTexture || srcTexture.isData3DTexture) { + _gl.texSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data); + } else { + if (srcTexture.isCompressedTexture) { + console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."); + _gl.compressedTexSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data); + } else { + _gl.texSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image); + } + } + _gl.pixelStorei(3314, unpackRowLen); + _gl.pixelStorei(32878, unpackImageHeight); + _gl.pixelStorei(3316, unpackSkipPixels); + _gl.pixelStorei(3315, unpackSkipRows); + _gl.pixelStorei(32877, unpackSkipImages); + if (level === 0 && dstTexture.generateMipmaps) + _gl.generateMipmap(glTarget); + state.unbindTexture(); + }; + this.initTexture = function(texture) { + if (texture.isCubeTexture) { + textures.setTextureCube(texture, 0); + } else if (texture.isData3DTexture) { + textures.setTexture3D(texture, 0); + } else if (texture.isDataArrayTexture) { + textures.setTexture2DArray(texture, 0); + } else { + textures.setTexture2D(texture, 0); + } + state.unbindTexture(); + }; + this.resetState = function() { + _currentActiveCubeFace = 0; + _currentActiveMipmapLevel = 0; + _currentRenderTarget = null; + state.reset(); + bindingStates.reset(); + }; + if (typeof __THREE_DEVTOOLS__ !== "undefined") { + __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe", { detail: this })); + } + } + var WebGL1Renderer = class extends WebGLRenderer { + }; + WebGL1Renderer.prototype.isWebGL1Renderer = true; + var Scene = class extends Object3D { + constructor() { + super(); + this.isScene = true; + this.type = "Scene"; + this.background = null; + this.environment = null; + this.fog = null; + this.overrideMaterial = null; + this.autoUpdate = true; + if (typeof __THREE_DEVTOOLS__ !== "undefined") { + __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe", { detail: this })); + } + } + copy(source, recursive) { + super.copy(source, recursive); + if (source.background !== null) + this.background = source.background.clone(); + if (source.environment !== null) + this.environment = source.environment.clone(); + if (source.fog !== null) + this.fog = source.fog.clone(); + if (source.overrideMaterial !== null) + this.overrideMaterial = source.overrideMaterial.clone(); + this.autoUpdate = source.autoUpdate; + this.matrixAutoUpdate = source.matrixAutoUpdate; + return this; + } + toJSON(meta) { + const data = super.toJSON(meta); + if (this.fog !== null) + data.object.fog = this.fog.toJSON(); + return data; + } + }; + var CanvasTexture = class extends Texture { + constructor(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy) { + super(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format2, type2, anisotropy); + this.isCanvasTexture = true; + this.needsUpdate = true; + } + }; + var SphereGeometry = class extends BufferGeometry { + constructor(radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI) { + super(); + this.type = "SphereGeometry"; + this.parameters = { + radius, + widthSegments, + heightSegments, + phiStart, + phiLength, + thetaStart, + thetaLength + }; + widthSegments = Math.max(3, Math.floor(widthSegments)); + heightSegments = Math.max(2, Math.floor(heightSegments)); + const thetaEnd = Math.min(thetaStart + thetaLength, Math.PI); + let index2 = 0; + const grid = []; + const vertex2 = new Vector3(); + const normal = new Vector3(); + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + for (let iy = 0; iy <= heightSegments; iy++) { + const verticesRow = []; + const v = iy / heightSegments; + let uOffset = 0; + if (iy == 0 && thetaStart == 0) { + uOffset = 0.5 / widthSegments; + } else if (iy == heightSegments && thetaEnd == Math.PI) { + uOffset = -0.5 / widthSegments; + } + for (let ix = 0; ix <= widthSegments; ix++) { + const u = ix / widthSegments; + vertex2.x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); + vertex2.y = radius * Math.cos(thetaStart + v * thetaLength); + vertex2.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength); + vertices.push(vertex2.x, vertex2.y, vertex2.z); + normal.copy(vertex2).normalize(); + normals.push(normal.x, normal.y, normal.z); + uvs.push(u + uOffset, 1 - v); + verticesRow.push(index2++); + } + grid.push(verticesRow); + } + for (let iy = 0; iy < heightSegments; iy++) { + for (let ix = 0; ix < widthSegments; ix++) { + const a2 = grid[iy][ix + 1]; + const b = grid[iy][ix]; + const c2 = grid[iy + 1][ix]; + const d = grid[iy + 1][ix + 1]; + if (iy !== 0 || thetaStart > 0) + indices.push(a2, b, d); + if (iy !== heightSegments - 1 || thetaEnd < Math.PI) + indices.push(b, c2, d); + } + } + this.setIndex(indices); + this.setAttribute("position", new Float32BufferAttribute(vertices, 3)); + this.setAttribute("normal", new Float32BufferAttribute(normals, 3)); + this.setAttribute("uv", new Float32BufferAttribute(uvs, 2)); + } + static fromJSON(data) { + return new SphereGeometry(data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength); + } + }; + function arraySlice(array2, from, to) { + if (isTypedArray(array2)) { + return new array2.constructor(array2.subarray(from, to !== void 0 ? to : array2.length)); + } + return array2.slice(from, to); + } + function convertArray(array2, type2, forceClone) { + if (!array2 || !forceClone && array2.constructor === type2) + return array2; + if (typeof type2.BYTES_PER_ELEMENT === "number") { + return new type2(array2); + } + return Array.prototype.slice.call(array2); + } + function isTypedArray(object) { + return ArrayBuffer.isView(object) && !(object instanceof DataView); + } + var Interpolant = class { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + this.parameterPositions = parameterPositions; + this._cachedIndex = 0; + this.resultBuffer = resultBuffer !== void 0 ? resultBuffer : new sampleValues.constructor(sampleSize); + this.sampleValues = sampleValues; + this.valueSize = sampleSize; + this.settings = null; + this.DefaultSettings_ = {}; + } + evaluate(t) { + const pp = this.parameterPositions; + let i1 = this._cachedIndex, t1 = pp[i1], t0 = pp[i1 - 1]; + validate_interval: { + seek: { + let right; + linear_scan: { + forward_scan: + if (!(t < t1)) { + for (let giveUpAt = i1 + 2; ; ) { + if (t1 === void 0) { + if (t < t0) + break forward_scan; + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_(i1 - 1); + } + if (i1 === giveUpAt) + break; + t0 = t1; + t1 = pp[++i1]; + if (t < t1) { + break seek; + } + } + right = pp.length; + break linear_scan; + } + if (!(t >= t0)) { + const t1global = pp[1]; + if (t < t1global) { + i1 = 2; + t0 = t1global; + } + for (let giveUpAt = i1 - 2; ; ) { + if (t0 === void 0) { + this._cachedIndex = 0; + return this.copySampleValue_(0); + } + if (i1 === giveUpAt) + break; + t1 = t0; + t0 = pp[--i1 - 1]; + if (t >= t0) { + break seek; + } + } + right = i1; + i1 = 0; + break linear_scan; + } + break validate_interval; + } + while (i1 < right) { + const mid = i1 + right >>> 1; + if (t < pp[mid]) { + right = mid; + } else { + i1 = mid + 1; + } + } + t1 = pp[i1]; + t0 = pp[i1 - 1]; + if (t0 === void 0) { + this._cachedIndex = 0; + return this.copySampleValue_(0); + } + if (t1 === void 0) { + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_(i1 - 1); + } + } + this._cachedIndex = i1; + this.intervalChanged_(i1, t0, t1); + } + return this.interpolate_(i1, t0, t, t1); + } + getSettings_() { + return this.settings || this.DefaultSettings_; + } + copySampleValue_(index2) { + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, offset = index2 * stride; + for (let i = 0; i !== stride; ++i) { + result[i] = values[offset + i]; + } + return result; + } + interpolate_() { + throw new Error("call to abstract method"); + } + intervalChanged_() { + } + }; + var CubicInterpolant = class extends Interpolant { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + this._weightPrev = -0; + this._offsetPrev = -0; + this._weightNext = -0; + this._offsetNext = -0; + this.DefaultSettings_ = { + endingStart: ZeroCurvatureEnding, + endingEnd: ZeroCurvatureEnding + }; + } + intervalChanged_(i1, t0, t1) { + const pp = this.parameterPositions; + let iPrev = i1 - 2, iNext = i1 + 1, tPrev = pp[iPrev], tNext = pp[iNext]; + if (tPrev === void 0) { + switch (this.getSettings_().endingStart) { + case ZeroSlopeEnding: + iPrev = i1; + tPrev = 2 * t0 - t1; + break; + case WrapAroundEnding: + iPrev = pp.length - 2; + tPrev = t0 + pp[iPrev] - pp[iPrev + 1]; + break; + default: + iPrev = i1; + tPrev = t1; + } + } + if (tNext === void 0) { + switch (this.getSettings_().endingEnd) { + case ZeroSlopeEnding: + iNext = i1; + tNext = 2 * t1 - t0; + break; + case WrapAroundEnding: + iNext = 1; + tNext = t1 + pp[1] - pp[0]; + break; + default: + iNext = i1 - 1; + tNext = t0; + } + } + const halfDt = (t1 - t0) * 0.5, stride = this.valueSize; + this._weightPrev = halfDt / (t0 - tPrev); + this._weightNext = halfDt / (tNext - t1); + this._offsetPrev = iPrev * stride; + this._offsetNext = iNext * stride; + } + interpolate_(i1, t0, t, t1) { + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, o1 = i1 * stride, o0 = o1 - stride, oP = this._offsetPrev, oN = this._offsetNext, wP = this._weightPrev, wN = this._weightNext, p = (t - t0) / (t1 - t0), pp = p * p, ppp = pp * p; + const sP = -wP * ppp + 2 * wP * pp - wP * p; + const s0 = (1 + wP) * ppp + (-1.5 - 2 * wP) * pp + (-0.5 + wP) * p + 1; + const s1 = (-1 - wN) * ppp + (1.5 + wN) * pp + 0.5 * p; + const sN = wN * ppp - wN * pp; + for (let i = 0; i !== stride; ++i) { + result[i] = sP * values[oP + i] + s0 * values[o0 + i] + s1 * values[o1 + i] + sN * values[oN + i]; + } + return result; + } + }; + var LinearInterpolant = class extends Interpolant { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + } + interpolate_(i1, t0, t, t1) { + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, offset1 = i1 * stride, offset0 = offset1 - stride, weight1 = (t - t0) / (t1 - t0), weight0 = 1 - weight1; + for (let i = 0; i !== stride; ++i) { + result[i] = values[offset0 + i] * weight0 + values[offset1 + i] * weight1; + } + return result; + } + }; + var DiscreteInterpolant = class extends Interpolant { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + } + interpolate_(i1) { + return this.copySampleValue_(i1 - 1); + } + }; + var KeyframeTrack = class { + constructor(name, times, values, interpolation) { + if (name === void 0) + throw new Error("THREE.KeyframeTrack: track name is undefined"); + if (times === void 0 || times.length === 0) + throw new Error("THREE.KeyframeTrack: no keyframes in track named " + name); + this.name = name; + this.times = convertArray(times, this.TimeBufferType); + this.values = convertArray(values, this.ValueBufferType); + this.setInterpolation(interpolation || this.DefaultInterpolation); + } + static toJSON(track) { + const trackType = track.constructor; + let json; + if (trackType.toJSON !== this.toJSON) { + json = trackType.toJSON(track); + } else { + json = { + "name": track.name, + "times": convertArray(track.times, Array), + "values": convertArray(track.values, Array) + }; + const interpolation = track.getInterpolation(); + if (interpolation !== track.DefaultInterpolation) { + json.interpolation = interpolation; + } + } + json.type = track.ValueTypeName; + return json; + } + InterpolantFactoryMethodDiscrete(result) { + return new DiscreteInterpolant(this.times, this.values, this.getValueSize(), result); + } + InterpolantFactoryMethodLinear(result) { + return new LinearInterpolant(this.times, this.values, this.getValueSize(), result); + } + InterpolantFactoryMethodSmooth(result) { + return new CubicInterpolant(this.times, this.values, this.getValueSize(), result); + } + setInterpolation(interpolation) { + let factoryMethod; + switch (interpolation) { + case InterpolateDiscrete: + factoryMethod = this.InterpolantFactoryMethodDiscrete; + break; + case InterpolateLinear: + factoryMethod = this.InterpolantFactoryMethodLinear; + break; + case InterpolateSmooth: + factoryMethod = this.InterpolantFactoryMethodSmooth; + break; + } + if (factoryMethod === void 0) { + const message = "unsupported interpolation for " + this.ValueTypeName + " keyframe track named " + this.name; + if (this.createInterpolant === void 0) { + if (interpolation !== this.DefaultInterpolation) { + this.setInterpolation(this.DefaultInterpolation); + } else { + throw new Error(message); + } + } + console.warn("THREE.KeyframeTrack:", message); + return this; + } + this.createInterpolant = factoryMethod; + return this; + } + getInterpolation() { + switch (this.createInterpolant) { + case this.InterpolantFactoryMethodDiscrete: + return InterpolateDiscrete; + case this.InterpolantFactoryMethodLinear: + return InterpolateLinear; + case this.InterpolantFactoryMethodSmooth: + return InterpolateSmooth; + } + } + getValueSize() { + return this.values.length / this.times.length; + } + shift(timeOffset) { + if (timeOffset !== 0) { + const times = this.times; + for (let i = 0, n = times.length; i !== n; ++i) { + times[i] += timeOffset; + } + } + return this; + } + scale(timeScale) { + if (timeScale !== 1) { + const times = this.times; + for (let i = 0, n = times.length; i !== n; ++i) { + times[i] *= timeScale; + } + } + return this; + } + trim(startTime, endTime) { + const times = this.times, nKeys = times.length; + let from = 0, to = nKeys - 1; + while (from !== nKeys && times[from] < startTime) { + ++from; + } + while (to !== -1 && times[to] > endTime) { + --to; + } + ++to; + if (from !== 0 || to !== nKeys) { + if (from >= to) { + to = Math.max(to, 1); + from = to - 1; + } + const stride = this.getValueSize(); + this.times = arraySlice(times, from, to); + this.values = arraySlice(this.values, from * stride, to * stride); + } + return this; + } + validate() { + let valid = true; + const valueSize = this.getValueSize(); + if (valueSize - Math.floor(valueSize) !== 0) { + console.error("THREE.KeyframeTrack: Invalid value size in track.", this); + valid = false; + } + const times = this.times, values = this.values, nKeys = times.length; + if (nKeys === 0) { + console.error("THREE.KeyframeTrack: Track is empty.", this); + valid = false; + } + let prevTime = null; + for (let i = 0; i !== nKeys; i++) { + const currTime = times[i]; + if (typeof currTime === "number" && isNaN(currTime)) { + console.error("THREE.KeyframeTrack: Time is not a valid number.", this, i, currTime); + valid = false; + break; + } + if (prevTime !== null && prevTime > currTime) { + console.error("THREE.KeyframeTrack: Out of order keys.", this, i, currTime, prevTime); + valid = false; + break; + } + prevTime = currTime; + } + if (values !== void 0) { + if (isTypedArray(values)) { + for (let i = 0, n = values.length; i !== n; ++i) { + const value = values[i]; + if (isNaN(value)) { + console.error("THREE.KeyframeTrack: Value is not a valid number.", this, i, value); + valid = false; + break; + } + } + } + } + return valid; + } + optimize() { + const times = arraySlice(this.times), values = arraySlice(this.values), stride = this.getValueSize(), smoothInterpolation = this.getInterpolation() === InterpolateSmooth, lastIndex = times.length - 1; + let writeIndex = 1; + for (let i = 1; i < lastIndex; ++i) { + let keep = false; + const time = times[i]; + const timeNext = times[i + 1]; + if (time !== timeNext && (i !== 1 || time !== times[0])) { + if (!smoothInterpolation) { + const offset = i * stride, offsetP = offset - stride, offsetN = offset + stride; + for (let j = 0; j !== stride; ++j) { + const value = values[offset + j]; + if (value !== values[offsetP + j] || value !== values[offsetN + j]) { + keep = true; + break; + } + } + } else { + keep = true; + } + } + if (keep) { + if (i !== writeIndex) { + times[writeIndex] = times[i]; + const readOffset = i * stride, writeOffset = writeIndex * stride; + for (let j = 0; j !== stride; ++j) { + values[writeOffset + j] = values[readOffset + j]; + } + } + ++writeIndex; + } + } + if (lastIndex > 0) { + times[writeIndex] = times[lastIndex]; + for (let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++j) { + values[writeOffset + j] = values[readOffset + j]; + } + ++writeIndex; + } + if (writeIndex !== times.length) { + this.times = arraySlice(times, 0, writeIndex); + this.values = arraySlice(values, 0, writeIndex * stride); + } else { + this.times = times; + this.values = values; + } + return this; + } + clone() { + const times = arraySlice(this.times, 0); + const values = arraySlice(this.values, 0); + const TypedKeyframeTrack = this.constructor; + const track = new TypedKeyframeTrack(this.name, times, values); + track.createInterpolant = this.createInterpolant; + return track; + } + }; + KeyframeTrack.prototype.TimeBufferType = Float32Array; + KeyframeTrack.prototype.ValueBufferType = Float32Array; + KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; + var BooleanKeyframeTrack = class extends KeyframeTrack { + }; + BooleanKeyframeTrack.prototype.ValueTypeName = "bool"; + BooleanKeyframeTrack.prototype.ValueBufferType = Array; + BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; + BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = void 0; + BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = void 0; + var ColorKeyframeTrack = class extends KeyframeTrack { + }; + ColorKeyframeTrack.prototype.ValueTypeName = "color"; + var NumberKeyframeTrack = class extends KeyframeTrack { + }; + NumberKeyframeTrack.prototype.ValueTypeName = "number"; + var QuaternionLinearInterpolant = class extends Interpolant { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + } + interpolate_(i1, t0, t, t1) { + const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, alpha = (t - t0) / (t1 - t0); + let offset = i1 * stride; + for (let end = offset + stride; offset !== end; offset += 4) { + Quaternion.slerpFlat(result, 0, values, offset - stride, values, offset, alpha); + } + return result; + } + }; + var QuaternionKeyframeTrack = class extends KeyframeTrack { + InterpolantFactoryMethodLinear(result) { + return new QuaternionLinearInterpolant(this.times, this.values, this.getValueSize(), result); + } + }; + QuaternionKeyframeTrack.prototype.ValueTypeName = "quaternion"; + QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; + QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = void 0; + var StringKeyframeTrack = class extends KeyframeTrack { + }; + StringKeyframeTrack.prototype.ValueTypeName = "string"; + StringKeyframeTrack.prototype.ValueBufferType = Array; + StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; + StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = void 0; + StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = void 0; + var VectorKeyframeTrack = class extends KeyframeTrack { + }; + VectorKeyframeTrack.prototype.ValueTypeName = "vector"; + var _RESERVED_CHARS_RE = "\\[\\]\\.:\\/"; + var _reservedRe = new RegExp("[" + _RESERVED_CHARS_RE + "]", "g"); + var _wordChar = "[^" + _RESERVED_CHARS_RE + "]"; + var _wordCharOrDot = "[^" + _RESERVED_CHARS_RE.replace("\\.", "") + "]"; + var _directoryRe = /* @__PURE__ */ /((?:WC+[\/:])*)/.source.replace("WC", _wordChar); + var _nodeRe = /* @__PURE__ */ /(WCOD+)?/.source.replace("WCOD", _wordCharOrDot); + var _objectRe = /* @__PURE__ */ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC", _wordChar); + var _propertyRe = /* @__PURE__ */ /\.(WC+)(?:\[(.+)\])?/.source.replace("WC", _wordChar); + var _trackRe = new RegExp("^" + _directoryRe + _nodeRe + _objectRe + _propertyRe + "$"); + var _supportedObjectNames = ["material", "materials", "bones"]; + var Composite = class { + constructor(targetGroup, path, optionalParsedPath) { + const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName(path); + this._targetGroup = targetGroup; + this._bindings = targetGroup.subscribe_(path, parsedPath); + } + getValue(array2, offset) { + this.bind(); + const firstValidIndex = this._targetGroup.nCachedObjects_, binding = this._bindings[firstValidIndex]; + if (binding !== void 0) + binding.getValue(array2, offset); + } + setValue(array2, offset) { + const bindings = this._bindings; + for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) { + bindings[i].setValue(array2, offset); + } + } + bind() { + const bindings = this._bindings; + for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) { + bindings[i].bind(); + } + } + unbind() { + const bindings = this._bindings; + for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) { + bindings[i].unbind(); + } + } + }; + var PropertyBinding = class { + constructor(rootNode, path, parsedPath) { + this.path = path; + this.parsedPath = parsedPath || PropertyBinding.parseTrackName(path); + this.node = PropertyBinding.findNode(rootNode, this.parsedPath.nodeName) || rootNode; + this.rootNode = rootNode; + this.getValue = this._getValue_unbound; + this.setValue = this._setValue_unbound; + } + static create(root2, path, parsedPath) { + if (!(root2 && root2.isAnimationObjectGroup)) { + return new PropertyBinding(root2, path, parsedPath); + } else { + return new PropertyBinding.Composite(root2, path, parsedPath); + } + } + static sanitizeNodeName(name) { + return name.replace(/\s/g, "_").replace(_reservedRe, ""); + } + static parseTrackName(trackName) { + const matches = _trackRe.exec(trackName); + if (matches === null) { + throw new Error("PropertyBinding: Cannot parse trackName: " + trackName); + } + const results = { + nodeName: matches[2], + objectName: matches[3], + objectIndex: matches[4], + propertyName: matches[5], + propertyIndex: matches[6] + }; + const lastDot = results.nodeName && results.nodeName.lastIndexOf("."); + if (lastDot !== void 0 && lastDot !== -1) { + const objectName = results.nodeName.substring(lastDot + 1); + if (_supportedObjectNames.indexOf(objectName) !== -1) { + results.nodeName = results.nodeName.substring(0, lastDot); + results.objectName = objectName; + } + } + if (results.propertyName === null || results.propertyName.length === 0) { + throw new Error("PropertyBinding: can not parse propertyName from trackName: " + trackName); + } + return results; + } + static findNode(root2, nodeName) { + if (nodeName === void 0 || nodeName === "" || nodeName === "." || nodeName === -1 || nodeName === root2.name || nodeName === root2.uuid) { + return root2; + } + if (root2.skeleton) { + const bone = root2.skeleton.getBoneByName(nodeName); + if (bone !== void 0) { + return bone; + } + } + if (root2.children) { + const searchNodeSubtree = function(children2) { + for (let i = 0; i < children2.length; i++) { + const childNode = children2[i]; + if (childNode.name === nodeName || childNode.uuid === nodeName) { + return childNode; + } + const result = searchNodeSubtree(childNode.children); + if (result) + return result; + } + return null; + }; + const subTreeNode = searchNodeSubtree(root2.children); + if (subTreeNode) { + return subTreeNode; + } + } + return null; + } + _getValue_unavailable() { + } + _setValue_unavailable() { + } + _getValue_direct(buffer, offset) { + buffer[offset] = this.targetObject[this.propertyName]; + } + _getValue_array(buffer, offset) { + const source = this.resolvedProperty; + for (let i = 0, n = source.length; i !== n; ++i) { + buffer[offset++] = source[i]; + } + } + _getValue_arrayElement(buffer, offset) { + buffer[offset] = this.resolvedProperty[this.propertyIndex]; + } + _getValue_toArray(buffer, offset) { + this.resolvedProperty.toArray(buffer, offset); + } + _setValue_direct(buffer, offset) { + this.targetObject[this.propertyName] = buffer[offset]; + } + _setValue_direct_setNeedsUpdate(buffer, offset) { + this.targetObject[this.propertyName] = buffer[offset]; + this.targetObject.needsUpdate = true; + } + _setValue_direct_setMatrixWorldNeedsUpdate(buffer, offset) { + this.targetObject[this.propertyName] = buffer[offset]; + this.targetObject.matrixWorldNeedsUpdate = true; + } + _setValue_array(buffer, offset) { + const dest = this.resolvedProperty; + for (let i = 0, n = dest.length; i !== n; ++i) { + dest[i] = buffer[offset++]; + } + } + _setValue_array_setNeedsUpdate(buffer, offset) { + const dest = this.resolvedProperty; + for (let i = 0, n = dest.length; i !== n; ++i) { + dest[i] = buffer[offset++]; + } + this.targetObject.needsUpdate = true; + } + _setValue_array_setMatrixWorldNeedsUpdate(buffer, offset) { + const dest = this.resolvedProperty; + for (let i = 0, n = dest.length; i !== n; ++i) { + dest[i] = buffer[offset++]; + } + this.targetObject.matrixWorldNeedsUpdate = true; + } + _setValue_arrayElement(buffer, offset) { + this.resolvedProperty[this.propertyIndex] = buffer[offset]; + } + _setValue_arrayElement_setNeedsUpdate(buffer, offset) { + this.resolvedProperty[this.propertyIndex] = buffer[offset]; + this.targetObject.needsUpdate = true; + } + _setValue_arrayElement_setMatrixWorldNeedsUpdate(buffer, offset) { + this.resolvedProperty[this.propertyIndex] = buffer[offset]; + this.targetObject.matrixWorldNeedsUpdate = true; + } + _setValue_fromArray(buffer, offset) { + this.resolvedProperty.fromArray(buffer, offset); + } + _setValue_fromArray_setNeedsUpdate(buffer, offset) { + this.resolvedProperty.fromArray(buffer, offset); + this.targetObject.needsUpdate = true; + } + _setValue_fromArray_setMatrixWorldNeedsUpdate(buffer, offset) { + this.resolvedProperty.fromArray(buffer, offset); + this.targetObject.matrixWorldNeedsUpdate = true; + } + _getValue_unbound(targetArray, offset) { + this.bind(); + this.getValue(targetArray, offset); + } + _setValue_unbound(sourceArray, offset) { + this.bind(); + this.setValue(sourceArray, offset); + } + bind() { + let targetObject = this.node; + const parsedPath = this.parsedPath; + const objectName = parsedPath.objectName; + const propertyName = parsedPath.propertyName; + let propertyIndex = parsedPath.propertyIndex; + if (!targetObject) { + targetObject = PropertyBinding.findNode(this.rootNode, parsedPath.nodeName) || this.rootNode; + this.node = targetObject; + } + this.getValue = this._getValue_unavailable; + this.setValue = this._setValue_unavailable; + if (!targetObject) { + console.error("THREE.PropertyBinding: Trying to update node for track: " + this.path + " but it wasn't found."); + return; + } + if (objectName) { + let objectIndex = parsedPath.objectIndex; + switch (objectName) { + case "materials": + if (!targetObject.material) { + console.error("THREE.PropertyBinding: Can not bind to material as node does not have a material.", this); + return; + } + if (!targetObject.material.materials) { + console.error("THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.", this); + return; + } + targetObject = targetObject.material.materials; + break; + case "bones": + if (!targetObject.skeleton) { + console.error("THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.", this); + return; + } + targetObject = targetObject.skeleton.bones; + for (let i = 0; i < targetObject.length; i++) { + if (targetObject[i].name === objectIndex) { + objectIndex = i; + break; + } + } + break; + default: + if (targetObject[objectName] === void 0) { + console.error("THREE.PropertyBinding: Can not bind to objectName of node undefined.", this); + return; + } + targetObject = targetObject[objectName]; + } + if (objectIndex !== void 0) { + if (targetObject[objectIndex] === void 0) { + console.error("THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.", this, targetObject); + return; + } + targetObject = targetObject[objectIndex]; + } + } + const nodeProperty = targetObject[propertyName]; + if (nodeProperty === void 0) { + const nodeName = parsedPath.nodeName; + console.error("THREE.PropertyBinding: Trying to update property for track: " + nodeName + "." + propertyName + " but it wasn't found.", targetObject); + return; + } + let versioning = this.Versioning.None; + this.targetObject = targetObject; + if (targetObject.needsUpdate !== void 0) { + versioning = this.Versioning.NeedsUpdate; + } else if (targetObject.matrixWorldNeedsUpdate !== void 0) { + versioning = this.Versioning.MatrixWorldNeedsUpdate; + } + let bindingType = this.BindingType.Direct; + if (propertyIndex !== void 0) { + if (propertyName === "morphTargetInfluences") { + if (!targetObject.geometry) { + console.error("THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.", this); + return; + } + if (!targetObject.geometry.morphAttributes) { + console.error("THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.", this); + return; + } + if (targetObject.morphTargetDictionary[propertyIndex] !== void 0) { + propertyIndex = targetObject.morphTargetDictionary[propertyIndex]; + } + } + bindingType = this.BindingType.ArrayElement; + this.resolvedProperty = nodeProperty; + this.propertyIndex = propertyIndex; + } else if (nodeProperty.fromArray !== void 0 && nodeProperty.toArray !== void 0) { + bindingType = this.BindingType.HasFromToArray; + this.resolvedProperty = nodeProperty; + } else if (Array.isArray(nodeProperty)) { + bindingType = this.BindingType.EntireArray; + this.resolvedProperty = nodeProperty; + } else { + this.propertyName = propertyName; + } + this.getValue = this.GetterByBindingType[bindingType]; + this.setValue = this.SetterByBindingTypeAndVersioning[bindingType][versioning]; + } + unbind() { + this.node = null; + this.getValue = this._getValue_unbound; + this.setValue = this._setValue_unbound; + } + }; + PropertyBinding.Composite = Composite; + PropertyBinding.prototype.BindingType = { + Direct: 0, + EntireArray: 1, + ArrayElement: 2, + HasFromToArray: 3 + }; + PropertyBinding.prototype.Versioning = { + None: 0, + NeedsUpdate: 1, + MatrixWorldNeedsUpdate: 2 + }; + PropertyBinding.prototype.GetterByBindingType = [ + PropertyBinding.prototype._getValue_direct, + PropertyBinding.prototype._getValue_array, + PropertyBinding.prototype._getValue_arrayElement, + PropertyBinding.prototype._getValue_toArray + ]; + PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [ + [ + PropertyBinding.prototype._setValue_direct, + PropertyBinding.prototype._setValue_direct_setNeedsUpdate, + PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate + ], + [ + PropertyBinding.prototype._setValue_array, + PropertyBinding.prototype._setValue_array_setNeedsUpdate, + PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate + ], + [ + PropertyBinding.prototype._setValue_arrayElement, + PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate, + PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate + ], + [ + PropertyBinding.prototype._setValue_fromArray, + PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate, + PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate + ] + ]; + var _controlInterpolantsResultBuffer = new Float32Array(1); + var Spherical = class { + constructor(radius = 1, phi = 0, theta = 0) { + this.radius = radius; + this.phi = phi; + this.theta = theta; + return this; + } + set(radius, phi, theta) { + this.radius = radius; + this.phi = phi; + this.theta = theta; + return this; + } + copy(other) { + this.radius = other.radius; + this.phi = other.phi; + this.theta = other.theta; + return this; + } + makeSafe() { + const EPS = 1e-6; + this.phi = Math.max(EPS, Math.min(Math.PI - EPS, this.phi)); + return this; + } + setFromVector3(v) { + return this.setFromCartesianCoords(v.x, v.y, v.z); + } + setFromCartesianCoords(x2, y2, z) { + this.radius = Math.sqrt(x2 * x2 + y2 * y2 + z * z); + if (this.radius === 0) { + this.theta = 0; + this.phi = 0; + } else { + this.theta = Math.atan2(x2, z); + this.phi = Math.acos(clamp(y2 / this.radius, -1, 1)); + } + return this; + } + clone() { + return new this.constructor().copy(this); + } + }; + if (typeof __THREE_DEVTOOLS__ !== "undefined") { + __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register", { detail: { + revision: REVISION + } })); + } + if (typeof window !== "undefined") { + if (window.__THREE__) { + console.warn("WARNING: Multiple instances of Three.js being imported."); + } else { + window.__THREE__ = REVISION; + } + } + + // node_modules/three/examples/jsm/controls/OrbitControls.js + var _changeEvent = { type: "change" }; + var _startEvent = { type: "start" }; + var _endEvent = { type: "end" }; + var OrbitControls = class extends EventDispatcher { + constructor(object, domElement) { + super(); + if (domElement === void 0) + console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.'); + if (domElement === document) + console.error('THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.'); + this.object = object; + this.domElement = domElement; + this.domElement.style.touchAction = "none"; + this.enabled = true; + this.target = new Vector3(); + this.minDistance = 0; + this.maxDistance = Infinity; + this.minZoom = 0; + this.maxZoom = Infinity; + this.minPolarAngle = 0; + this.maxPolarAngle = Math.PI; + this.minAzimuthAngle = -Infinity; + this.maxAzimuthAngle = Infinity; + this.enableDamping = false; + this.dampingFactor = 0.05; + this.enableZoom = true; + this.zoomSpeed = 1; + this.enableRotate = true; + this.rotateSpeed = 1; + this.enablePan = true; + this.panSpeed = 1; + this.screenSpacePanning = true; + this.keyPanSpeed = 7; + this.autoRotate = false; + this.autoRotateSpeed = 2; + this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" }; + this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN }; + this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN }; + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.zoom0 = this.object.zoom; + this._domElementKeyEvents = null; + this.getPolarAngle = function() { + return spherical.phi; + }; + this.getAzimuthalAngle = function() { + return spherical.theta; + }; + this.getDistance = function() { + return this.object.position.distanceTo(this.target); + }; + this.listenToKeyEvents = function(domElement2) { + domElement2.addEventListener("keydown", onKeyDown); + this._domElementKeyEvents = domElement2; + }; + this.saveState = function() { + scope.target0.copy(scope.target); + scope.position0.copy(scope.object.position); + scope.zoom0 = scope.object.zoom; + }; + this.reset = function() { + scope.target.copy(scope.target0); + scope.object.position.copy(scope.position0); + scope.object.zoom = scope.zoom0; + scope.object.updateProjectionMatrix(); + scope.dispatchEvent(_changeEvent); + scope.update(); + state = STATE.NONE; + }; + this.update = function() { + const offset = new Vector3(); + const quat = new Quaternion().setFromUnitVectors(object.up, new Vector3(0, 1, 0)); + const quatInverse = quat.clone().invert(); + const lastPosition = new Vector3(); + const lastQuaternion = new Quaternion(); + const twoPI = 2 * Math.PI; + return function update() { + const position = scope.object.position; + offset.copy(position).sub(scope.target); + offset.applyQuaternion(quat); + spherical.setFromVector3(offset); + if (scope.autoRotate && state === STATE.NONE) { + rotateLeft(getAutoRotationAngle()); + } + if (scope.enableDamping) { + spherical.theta += sphericalDelta.theta * scope.dampingFactor; + spherical.phi += sphericalDelta.phi * scope.dampingFactor; + } else { + spherical.theta += sphericalDelta.theta; + spherical.phi += sphericalDelta.phi; + } + let min2 = scope.minAzimuthAngle; + let max2 = scope.maxAzimuthAngle; + if (isFinite(min2) && isFinite(max2)) { + if (min2 < -Math.PI) + min2 += twoPI; + else if (min2 > Math.PI) + min2 -= twoPI; + if (max2 < -Math.PI) + max2 += twoPI; + else if (max2 > Math.PI) + max2 -= twoPI; + if (min2 <= max2) { + spherical.theta = Math.max(min2, Math.min(max2, spherical.theta)); + } else { + spherical.theta = spherical.theta > (min2 + max2) / 2 ? Math.max(min2, spherical.theta) : Math.min(max2, spherical.theta); + } + } + spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi)); + spherical.makeSafe(); + spherical.radius *= scale; + spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius)); + if (scope.enableDamping === true) { + scope.target.addScaledVector(panOffset, scope.dampingFactor); + } else { + scope.target.add(panOffset); + } + offset.setFromSpherical(spherical); + offset.applyQuaternion(quatInverse); + position.copy(scope.target).add(offset); + scope.object.lookAt(scope.target); + if (scope.enableDamping === true) { + sphericalDelta.theta *= 1 - scope.dampingFactor; + sphericalDelta.phi *= 1 - scope.dampingFactor; + panOffset.multiplyScalar(1 - scope.dampingFactor); + } else { + sphericalDelta.set(0, 0, 0); + panOffset.set(0, 0, 0); + } + scale = 1; + if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) { + scope.dispatchEvent(_changeEvent); + lastPosition.copy(scope.object.position); + lastQuaternion.copy(scope.object.quaternion); + zoomChanged = false; + return true; + } + return false; + }; + }(); + this.dispose = function() { + scope.domElement.removeEventListener("contextmenu", onContextMenu); + scope.domElement.removeEventListener("pointerdown", onPointerDown); + scope.domElement.removeEventListener("pointercancel", onPointerCancel); + scope.domElement.removeEventListener("wheel", onMouseWheel); + scope.domElement.removeEventListener("pointermove", onPointerMove); + scope.domElement.removeEventListener("pointerup", onPointerUp); + if (scope._domElementKeyEvents !== null) { + scope._domElementKeyEvents.removeEventListener("keydown", onKeyDown); + } + }; + const scope = this; + const STATE = { + NONE: -1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_PAN: 4, + TOUCH_DOLLY_PAN: 5, + TOUCH_DOLLY_ROTATE: 6 + }; + let state = STATE.NONE; + const EPS = 1e-6; + const spherical = new Spherical(); + const sphericalDelta = new Spherical(); + let scale = 1; + const panOffset = new Vector3(); + let zoomChanged = false; + const rotateStart = new Vector2(); + const rotateEnd = new Vector2(); + const rotateDelta = new Vector2(); + const panStart = new Vector2(); + const panEnd = new Vector2(); + const panDelta = new Vector2(); + const dollyStart = new Vector2(); + const dollyEnd = new Vector2(); + const dollyDelta = new Vector2(); + const pointers = []; + const pointerPositions = {}; + function getAutoRotationAngle() { + return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; + } + function getZoomScale() { + return Math.pow(0.95, scope.zoomSpeed); + } + function rotateLeft(angle) { + sphericalDelta.theta -= angle; + } + function rotateUp(angle) { + sphericalDelta.phi -= angle; + } + const panLeft = function() { + const v = new Vector3(); + return function panLeft2(distance, objectMatrix) { + v.setFromMatrixColumn(objectMatrix, 0); + v.multiplyScalar(-distance); + panOffset.add(v); + }; + }(); + const panUp = function() { + const v = new Vector3(); + return function panUp2(distance, objectMatrix) { + if (scope.screenSpacePanning === true) { + v.setFromMatrixColumn(objectMatrix, 1); + } else { + v.setFromMatrixColumn(objectMatrix, 0); + v.crossVectors(scope.object.up, v); + } + v.multiplyScalar(distance); + panOffset.add(v); + }; + }(); + const pan = function() { + const offset = new Vector3(); + return function pan2(deltaX, deltaY) { + const element = scope.domElement; + if (scope.object.isPerspectiveCamera) { + const position = scope.object.position; + offset.copy(position).sub(scope.target); + let targetDistance = offset.length(); + targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180); + panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix); + panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix); + } else if (scope.object.isOrthographicCamera) { + panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix); + panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix); + } else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."); + scope.enablePan = false; + } + }; + }(); + function dollyOut(dollyScale) { + if (scope.object.isPerspectiveCamera) { + scale /= dollyScale; + } else if (scope.object.isOrthographicCamera) { + scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale)); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + } else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); + scope.enableZoom = false; + } + } + function dollyIn(dollyScale) { + if (scope.object.isPerspectiveCamera) { + scale *= dollyScale; + } else if (scope.object.isOrthographicCamera) { + scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale)); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + } else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); + scope.enableZoom = false; + } + } + function handleMouseDownRotate(event) { + rotateStart.set(event.clientX, event.clientY); + } + function handleMouseDownDolly(event) { + dollyStart.set(event.clientX, event.clientY); + } + function handleMouseDownPan(event) { + panStart.set(event.clientX, event.clientY); + } + function handleMouseMoveRotate(event) { + rotateEnd.set(event.clientX, event.clientY); + rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed); + const element = scope.domElement; + rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight); + rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight); + rotateStart.copy(rotateEnd); + scope.update(); + } + function handleMouseMoveDolly(event) { + dollyEnd.set(event.clientX, event.clientY); + dollyDelta.subVectors(dollyEnd, dollyStart); + if (dollyDelta.y > 0) { + dollyOut(getZoomScale()); + } else if (dollyDelta.y < 0) { + dollyIn(getZoomScale()); + } + dollyStart.copy(dollyEnd); + scope.update(); + } + function handleMouseMovePan(event) { + panEnd.set(event.clientX, event.clientY); + panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); + pan(panDelta.x, panDelta.y); + panStart.copy(panEnd); + scope.update(); + } + function handleMouseWheel(event) { + if (event.deltaY < 0) { + dollyIn(getZoomScale()); + } else if (event.deltaY > 0) { + dollyOut(getZoomScale()); + } + scope.update(); + } + function handleKeyDown(event) { + let needsUpdate = false; + switch (event.code) { + case scope.keys.UP: + pan(0, scope.keyPanSpeed); + needsUpdate = true; + break; + case scope.keys.BOTTOM: + pan(0, -scope.keyPanSpeed); + needsUpdate = true; + break; + case scope.keys.LEFT: + pan(scope.keyPanSpeed, 0); + needsUpdate = true; + break; + case scope.keys.RIGHT: + pan(-scope.keyPanSpeed, 0); + needsUpdate = true; + break; + } + if (needsUpdate) { + event.preventDefault(); + scope.update(); + } + } + function handleTouchStartRotate() { + if (pointers.length === 1) { + rotateStart.set(pointers[0].pageX, pointers[0].pageY); + } else { + const x2 = 0.5 * (pointers[0].pageX + pointers[1].pageX); + const y2 = 0.5 * (pointers[0].pageY + pointers[1].pageY); + rotateStart.set(x2, y2); + } + } + function handleTouchStartPan() { + if (pointers.length === 1) { + panStart.set(pointers[0].pageX, pointers[0].pageY); + } else { + const x2 = 0.5 * (pointers[0].pageX + pointers[1].pageX); + const y2 = 0.5 * (pointers[0].pageY + pointers[1].pageY); + panStart.set(x2, y2); + } + } + function handleTouchStartDolly() { + const dx = pointers[0].pageX - pointers[1].pageX; + const dy = pointers[0].pageY - pointers[1].pageY; + const distance = Math.sqrt(dx * dx + dy * dy); + dollyStart.set(0, distance); + } + function handleTouchStartDollyPan() { + if (scope.enableZoom) + handleTouchStartDolly(); + if (scope.enablePan) + handleTouchStartPan(); + } + function handleTouchStartDollyRotate() { + if (scope.enableZoom) + handleTouchStartDolly(); + if (scope.enableRotate) + handleTouchStartRotate(); + } + function handleTouchMoveRotate(event) { + if (pointers.length == 1) { + rotateEnd.set(event.pageX, event.pageY); + } else { + const position = getSecondPointerPosition(event); + const x2 = 0.5 * (event.pageX + position.x); + const y2 = 0.5 * (event.pageY + position.y); + rotateEnd.set(x2, y2); + } + rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed); + const element = scope.domElement; + rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight); + rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight); + rotateStart.copy(rotateEnd); + } + function handleTouchMovePan(event) { + if (pointers.length === 1) { + panEnd.set(event.pageX, event.pageY); + } else { + const position = getSecondPointerPosition(event); + const x2 = 0.5 * (event.pageX + position.x); + const y2 = 0.5 * (event.pageY + position.y); + panEnd.set(x2, y2); + } + panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); + pan(panDelta.x, panDelta.y); + panStart.copy(panEnd); + } + function handleTouchMoveDolly(event) { + const position = getSecondPointerPosition(event); + const dx = event.pageX - position.x; + const dy = event.pageY - position.y; + const distance = Math.sqrt(dx * dx + dy * dy); + dollyEnd.set(0, distance); + dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed)); + dollyOut(dollyDelta.y); + dollyStart.copy(dollyEnd); + } + function handleTouchMoveDollyPan(event) { + if (scope.enableZoom) + handleTouchMoveDolly(event); + if (scope.enablePan) + handleTouchMovePan(event); + } + function handleTouchMoveDollyRotate(event) { + if (scope.enableZoom) + handleTouchMoveDolly(event); + if (scope.enableRotate) + handleTouchMoveRotate(event); + } + function onPointerDown(event) { + if (scope.enabled === false) + return; + if (pointers.length === 0) { + scope.domElement.setPointerCapture(event.pointerId); + scope.domElement.addEventListener("pointermove", onPointerMove); + scope.domElement.addEventListener("pointerup", onPointerUp); + } + addPointer(event); + if (event.pointerType === "touch") { + onTouchStart(event); + } else { + onMouseDown(event); + } + } + function onPointerMove(event) { + if (scope.enabled === false) + return; + if (event.pointerType === "touch") { + onTouchMove(event); + } else { + onMouseMove(event); + } + } + function onPointerUp(event) { + removePointer(event); + if (pointers.length === 0) { + scope.domElement.releasePointerCapture(event.pointerId); + scope.domElement.removeEventListener("pointermove", onPointerMove); + scope.domElement.removeEventListener("pointerup", onPointerUp); + } + scope.dispatchEvent(_endEvent); + state = STATE.NONE; + } + function onPointerCancel(event) { + removePointer(event); + } + function onMouseDown(event) { + let mouseAction; + switch (event.button) { + case 0: + mouseAction = scope.mouseButtons.LEFT; + break; + case 1: + mouseAction = scope.mouseButtons.MIDDLE; + break; + case 2: + mouseAction = scope.mouseButtons.RIGHT; + break; + default: + mouseAction = -1; + } + switch (mouseAction) { + case MOUSE.DOLLY: + if (scope.enableZoom === false) + return; + handleMouseDownDolly(event); + state = STATE.DOLLY; + break; + case MOUSE.ROTATE: + if (event.ctrlKey || event.metaKey || event.shiftKey) { + if (scope.enablePan === false) + return; + handleMouseDownPan(event); + state = STATE.PAN; + } else { + if (scope.enableRotate === false) + return; + handleMouseDownRotate(event); + state = STATE.ROTATE; + } + break; + case MOUSE.PAN: + if (event.ctrlKey || event.metaKey || event.shiftKey) { + if (scope.enableRotate === false) + return; + handleMouseDownRotate(event); + state = STATE.ROTATE; + } else { + if (scope.enablePan === false) + return; + handleMouseDownPan(event); + state = STATE.PAN; + } + break; + default: + state = STATE.NONE; + } + if (state !== STATE.NONE) { + scope.dispatchEvent(_startEvent); + } + } + function onMouseMove(event) { + switch (state) { + case STATE.ROTATE: + if (scope.enableRotate === false) + return; + handleMouseMoveRotate(event); + break; + case STATE.DOLLY: + if (scope.enableZoom === false) + return; + handleMouseMoveDolly(event); + break; + case STATE.PAN: + if (scope.enablePan === false) + return; + handleMouseMovePan(event); + break; + } + } + function onMouseWheel(event) { + if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE) + return; + event.preventDefault(); + scope.dispatchEvent(_startEvent); + handleMouseWheel(event); + scope.dispatchEvent(_endEvent); + } + function onKeyDown(event) { + if (scope.enabled === false || scope.enablePan === false) + return; + handleKeyDown(event); + } + function onTouchStart(event) { + trackPointer(event); + switch (pointers.length) { + case 1: + switch (scope.touches.ONE) { + case TOUCH.ROTATE: + if (scope.enableRotate === false) + return; + handleTouchStartRotate(); + state = STATE.TOUCH_ROTATE; + break; + case TOUCH.PAN: + if (scope.enablePan === false) + return; + handleTouchStartPan(); + state = STATE.TOUCH_PAN; + break; + default: + state = STATE.NONE; + } + break; + case 2: + switch (scope.touches.TWO) { + case TOUCH.DOLLY_PAN: + if (scope.enableZoom === false && scope.enablePan === false) + return; + handleTouchStartDollyPan(); + state = STATE.TOUCH_DOLLY_PAN; + break; + case TOUCH.DOLLY_ROTATE: + if (scope.enableZoom === false && scope.enableRotate === false) + return; + handleTouchStartDollyRotate(); + state = STATE.TOUCH_DOLLY_ROTATE; + break; + default: + state = STATE.NONE; + } + break; + default: + state = STATE.NONE; + } + if (state !== STATE.NONE) { + scope.dispatchEvent(_startEvent); + } + } + function onTouchMove(event) { + trackPointer(event); + switch (state) { + case STATE.TOUCH_ROTATE: + if (scope.enableRotate === false) + return; + handleTouchMoveRotate(event); + scope.update(); + break; + case STATE.TOUCH_PAN: + if (scope.enablePan === false) + return; + handleTouchMovePan(event); + scope.update(); + break; + case STATE.TOUCH_DOLLY_PAN: + if (scope.enableZoom === false && scope.enablePan === false) + return; + handleTouchMoveDollyPan(event); + scope.update(); + break; + case STATE.TOUCH_DOLLY_ROTATE: + if (scope.enableZoom === false && scope.enableRotate === false) + return; + handleTouchMoveDollyRotate(event); + scope.update(); + break; + default: + state = STATE.NONE; + } + } + function onContextMenu(event) { + if (scope.enabled === false) + return; + event.preventDefault(); + } + function addPointer(event) { + pointers.push(event); + } + function removePointer(event) { + delete pointerPositions[event.pointerId]; + for (let i = 0; i < pointers.length; i++) { + if (pointers[i].pointerId == event.pointerId) { + pointers.splice(i, 1); + return; + } + } + } + function trackPointer(event) { + let position = pointerPositions[event.pointerId]; + if (position === void 0) { + position = new Vector2(); + pointerPositions[event.pointerId] = position; + } + position.set(event.pageX, event.pageY); + } + function getSecondPointerPosition(event) { + const pointer = event.pointerId === pointers[0].pointerId ? pointers[1] : pointers[0]; + return pointerPositions[pointer.pointerId]; + } + scope.domElement.addEventListener("contextmenu", onContextMenu); + scope.domElement.addEventListener("pointerdown", onPointerDown); + scope.domElement.addEventListener("pointercancel", onPointerCancel); + scope.domElement.addEventListener("wheel", onMouseWheel, { passive: false }); + this.update(); + } + }; + + // federjs/FederView/hnswView/HnswSearchHnsw3dView.ts + var import_three2 = __toESM(require_THREE_MeshLine(), 1); + + // node_modules/animejs/lib/anime.es.js + var defaultInstanceSettings = { + update: null, + begin: null, + loopBegin: null, + changeBegin: null, + change: null, + changeComplete: null, + loopComplete: null, + complete: null, + loop: 1, + direction: "normal", + autoplay: true, + timelineOffset: 0 + }; + var defaultTweenSettings = { + duration: 1e3, + delay: 0, + endDelay: 0, + easing: "easeOutElastic(1, .5)", + round: 0 + }; + var validTransforms = ["translateX", "translateY", "translateZ", "rotate", "rotateX", "rotateY", "rotateZ", "scale", "scaleX", "scaleY", "scaleZ", "skew", "skewX", "skewY", "perspective", "matrix", "matrix3d"]; + var cache = { + CSS: {}, + springs: {} + }; + function minMax(val, min2, max2) { + return Math.min(Math.max(val, min2), max2); + } + function stringContains(str, text) { + return str.indexOf(text) > -1; + } + function applyArguments(func, args) { + return func.apply(null, args); + } + var is = { + arr: function(a2) { + return Array.isArray(a2); + }, + obj: function(a2) { + return stringContains(Object.prototype.toString.call(a2), "Object"); + }, + pth: function(a2) { + return is.obj(a2) && a2.hasOwnProperty("totalLength"); + }, + svg: function(a2) { + return a2 instanceof SVGElement; + }, + inp: function(a2) { + return a2 instanceof HTMLInputElement; + }, + dom: function(a2) { + return a2.nodeType || is.svg(a2); + }, + str: function(a2) { + return typeof a2 === "string"; + }, + fnc: function(a2) { + return typeof a2 === "function"; + }, + und: function(a2) { + return typeof a2 === "undefined"; + }, + nil: function(a2) { + return is.und(a2) || a2 === null; + }, + hex: function(a2) { + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(a2); + }, + rgb: function(a2) { + return /^rgb/.test(a2); + }, + hsl: function(a2) { + return /^hsl/.test(a2); + }, + col: function(a2) { + return is.hex(a2) || is.rgb(a2) || is.hsl(a2); + }, + key: function(a2) { + return !defaultInstanceSettings.hasOwnProperty(a2) && !defaultTweenSettings.hasOwnProperty(a2) && a2 !== "targets" && a2 !== "keyframes"; + } + }; + function parseEasingParameters(string) { + var match = /\(([^)]+)\)/.exec(string); + return match ? match[1].split(",").map(function(p) { + return parseFloat(p); + }) : []; + } + function spring(string, duration) { + var params = parseEasingParameters(string); + var mass = minMax(is.und(params[0]) ? 1 : params[0], 0.1, 100); + var stiffness = minMax(is.und(params[1]) ? 100 : params[1], 0.1, 100); + var damping = minMax(is.und(params[2]) ? 10 : params[2], 0.1, 100); + var velocity = minMax(is.und(params[3]) ? 0 : params[3], 0.1, 100); + var w0 = Math.sqrt(stiffness / mass); + var zeta = damping / (2 * Math.sqrt(stiffness * mass)); + var wd = zeta < 1 ? w0 * Math.sqrt(1 - zeta * zeta) : 0; + var a2 = 1; + var b = zeta < 1 ? (zeta * w0 + -velocity) / wd : -velocity + w0; + function solver(t) { + var progress = duration ? duration * t / 1e3 : t; + if (zeta < 1) { + progress = Math.exp(-progress * zeta * w0) * (a2 * Math.cos(wd * progress) + b * Math.sin(wd * progress)); + } else { + progress = (a2 + b * progress) * Math.exp(-progress * w0); + } + if (t === 0 || t === 1) { + return t; + } + return 1 - progress; + } + function getDuration() { + var cached = cache.springs[string]; + if (cached) { + return cached; + } + var frame2 = 1 / 6; + var elapsed = 0; + var rest = 0; + while (true) { + elapsed += frame2; + if (solver(elapsed) === 1) { + rest++; + if (rest >= 16) { + break; + } + } else { + rest = 0; + } + } + var duration2 = elapsed * frame2 * 1e3; + cache.springs[string] = duration2; + return duration2; + } + return duration ? solver : getDuration; + } + function steps(steps2) { + if (steps2 === void 0) + steps2 = 10; + return function(t) { + return Math.ceil(minMax(t, 1e-6, 1) * steps2) * (1 / steps2); + }; + } + var bezier = function() { + var kSplineTableSize = 11; + var kSampleStepSize = 1 / (kSplineTableSize - 1); + function A(aA1, aA2) { + return 1 - 3 * aA2 + 3 * aA1; + } + function B(aA1, aA2) { + return 3 * aA2 - 6 * aA1; + } + function C(aA1) { + return 3 * aA1; + } + function calcBezier(aT, aA1, aA2) { + return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; + } + function getSlope(aT, aA1, aA2) { + return 3 * A(aA1, aA2) * aT * aT + 2 * B(aA1, aA2) * aT + C(aA1); + } + function binarySubdivide(aX, aA, aB, mX1, mX2) { + var currentX, currentT, i = 0; + do { + currentT = aA + (aB - aA) / 2; + currentX = calcBezier(currentT, mX1, mX2) - aX; + if (currentX > 0) { + aB = currentT; + } else { + aA = currentT; + } + } while (Math.abs(currentX) > 1e-7 && ++i < 10); + return currentT; + } + function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) { + for (var i = 0; i < 4; ++i) { + var currentSlope = getSlope(aGuessT, mX1, mX2); + if (currentSlope === 0) { + return aGuessT; + } + var currentX = calcBezier(aGuessT, mX1, mX2) - aX; + aGuessT -= currentX / currentSlope; + } + return aGuessT; + } + function bezier2(mX1, mY1, mX2, mY2) { + if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) { + return; + } + var sampleValues = new Float32Array(kSplineTableSize); + if (mX1 !== mY1 || mX2 !== mY2) { + for (var i = 0; i < kSplineTableSize; ++i) { + sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2); + } + } + function getTForX(aX) { + var intervalStart = 0; + var currentSample = 1; + var lastSample = kSplineTableSize - 1; + for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) { + intervalStart += kSampleStepSize; + } + --currentSample; + var dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]); + var guessForT = intervalStart + dist * kSampleStepSize; + var initialSlope = getSlope(guessForT, mX1, mX2); + if (initialSlope >= 1e-3) { + return newtonRaphsonIterate(aX, guessForT, mX1, mX2); + } else if (initialSlope === 0) { + return guessForT; + } else { + return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2); + } + } + return function(x2) { + if (mX1 === mY1 && mX2 === mY2) { + return x2; + } + if (x2 === 0 || x2 === 1) { + return x2; + } + return calcBezier(getTForX(x2), mY1, mY2); + }; + } + return bezier2; + }(); + var penner = function() { + var eases = { linear: function() { + return function(t) { + return t; + }; + } }; + var functionEasings = { + Sine: function() { + return function(t) { + return 1 - Math.cos(t * Math.PI / 2); + }; + }, + Circ: function() { + return function(t) { + return 1 - Math.sqrt(1 - t * t); + }; + }, + Back: function() { + return function(t) { + return t * t * (3 * t - 2); + }; + }, + Bounce: function() { + return function(t) { + var pow2, b = 4; + while (t < ((pow2 = Math.pow(2, --b)) - 1) / 11) { + } + return 1 / Math.pow(4, 3 - b) - 7.5625 * Math.pow((pow2 * 3 - 2) / 22 - t, 2); + }; + }, + Elastic: function(amplitude, period) { + if (amplitude === void 0) + amplitude = 1; + if (period === void 0) + period = 0.5; + var a2 = minMax(amplitude, 1, 10); + var p = minMax(period, 0.1, 2); + return function(t) { + return t === 0 || t === 1 ? t : -a2 * Math.pow(2, 10 * (t - 1)) * Math.sin((t - 1 - p / (Math.PI * 2) * Math.asin(1 / a2)) * (Math.PI * 2) / p); + }; + } + }; + var baseEasings = ["Quad", "Cubic", "Quart", "Quint", "Expo"]; + baseEasings.forEach(function(name, i) { + functionEasings[name] = function() { + return function(t) { + return Math.pow(t, i + 2); + }; + }; + }); + Object.keys(functionEasings).forEach(function(name) { + var easeIn = functionEasings[name]; + eases["easeIn" + name] = easeIn; + eases["easeOut" + name] = function(a2, b) { + return function(t) { + return 1 - easeIn(a2, b)(1 - t); + }; + }; + eases["easeInOut" + name] = function(a2, b) { + return function(t) { + return t < 0.5 ? easeIn(a2, b)(t * 2) / 2 : 1 - easeIn(a2, b)(t * -2 + 2) / 2; + }; + }; + eases["easeOutIn" + name] = function(a2, b) { + return function(t) { + return t < 0.5 ? (1 - easeIn(a2, b)(1 - t * 2)) / 2 : (easeIn(a2, b)(t * 2 - 1) + 1) / 2; + }; + }; + }); + return eases; + }(); + function parseEasings(easing, duration) { + if (is.fnc(easing)) { + return easing; + } + var name = easing.split("(")[0]; + var ease = penner[name]; + var args = parseEasingParameters(easing); + switch (name) { + case "spring": + return spring(easing, duration); + case "cubicBezier": + return applyArguments(bezier, args); + case "steps": + return applyArguments(steps, args); + default: + return applyArguments(ease, args); + } + } + function selectString(str) { + try { + var nodes = document.querySelectorAll(str); + return nodes; + } catch (e) { + return; + } + } + function filterArray(arr, callback) { + var len = arr.length; + var thisArg = arguments.length >= 2 ? arguments[1] : void 0; + var result = []; + for (var i = 0; i < len; i++) { + if (i in arr) { + var val = arr[i]; + if (callback.call(thisArg, val, i, arr)) { + result.push(val); + } + } + } + return result; + } + function flattenArray(arr) { + return arr.reduce(function(a2, b) { + return a2.concat(is.arr(b) ? flattenArray(b) : b); + }, []); + } + function toArray(o) { + if (is.arr(o)) { + return o; + } + if (is.str(o)) { + o = selectString(o) || o; + } + if (o instanceof NodeList || o instanceof HTMLCollection) { + return [].slice.call(o); + } + return [o]; + } + function arrayContains(arr, val) { + return arr.some(function(a2) { + return a2 === val; + }); + } + function cloneObject(o) { + var clone = {}; + for (var p in o) { + clone[p] = o[p]; + } + return clone; + } + function replaceObjectProps(o1, o2) { + var o = cloneObject(o1); + for (var p in o1) { + o[p] = o2.hasOwnProperty(p) ? o2[p] : o1[p]; + } + return o; + } + function mergeObjects(o1, o2) { + var o = cloneObject(o1); + for (var p in o2) { + o[p] = is.und(o1[p]) ? o2[p] : o1[p]; + } + return o; + } + function rgbToRgba(rgbValue) { + var rgb2 = /rgb\((\d+,\s*[\d]+,\s*[\d]+)\)/g.exec(rgbValue); + return rgb2 ? "rgba(" + rgb2[1] + ",1)" : rgbValue; + } + function hexToRgba(hexValue) { + var rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + var hex2 = hexValue.replace(rgx, function(m2, r2, g2, b2) { + return r2 + r2 + g2 + g2 + b2 + b2; + }); + var rgb2 = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex2); + var r = parseInt(rgb2[1], 16); + var g = parseInt(rgb2[2], 16); + var b = parseInt(rgb2[3], 16); + return "rgba(" + r + "," + g + "," + b + ",1)"; + } + function hslToRgba(hslValue) { + var hsl2 = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(hslValue) || /hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(hslValue); + var h = parseInt(hsl2[1], 10) / 360; + var s = parseInt(hsl2[2], 10) / 100; + var l = parseInt(hsl2[3], 10) / 100; + var a2 = hsl2[4] || 1; + function hue2rgb2(p2, q2, t) { + if (t < 0) { + t += 1; + } + if (t > 1) { + t -= 1; + } + if (t < 1 / 6) { + return p2 + (q2 - p2) * 6 * t; + } + if (t < 1 / 2) { + return q2; + } + if (t < 2 / 3) { + return p2 + (q2 - p2) * (2 / 3 - t) * 6; + } + return p2; + } + var r, g, b; + if (s == 0) { + r = g = b = l; + } else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb2(p, q, h + 1 / 3); + g = hue2rgb2(p, q, h); + b = hue2rgb2(p, q, h - 1 / 3); + } + return "rgba(" + r * 255 + "," + g * 255 + "," + b * 255 + "," + a2 + ")"; + } + function colorToRgb(val) { + if (is.rgb(val)) { + return rgbToRgba(val); + } + if (is.hex(val)) { + return hexToRgba(val); + } + if (is.hsl(val)) { + return hslToRgba(val); + } + } + function getUnit(val) { + var split = /[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(val); + if (split) { + return split[1]; + } + } + function getTransformUnit(propName) { + if (stringContains(propName, "translate") || propName === "perspective") { + return "px"; + } + if (stringContains(propName, "rotate") || stringContains(propName, "skew")) { + return "deg"; + } + } + function getFunctionValue(val, animatable) { + if (!is.fnc(val)) { + return val; + } + return val(animatable.target, animatable.id, animatable.total); + } + function getAttribute(el, prop) { + return el.getAttribute(prop); + } + function convertPxToUnit(el, value, unit2) { + var valueUnit = getUnit(value); + if (arrayContains([unit2, "deg", "rad", "turn"], valueUnit)) { + return value; + } + var cached = cache.CSS[value + unit2]; + if (!is.und(cached)) { + return cached; + } + var baseline = 100; + var tempEl = document.createElement(el.tagName); + var parentEl = el.parentNode && el.parentNode !== document ? el.parentNode : document.body; + parentEl.appendChild(tempEl); + tempEl.style.position = "absolute"; + tempEl.style.width = baseline + unit2; + var factor = baseline / tempEl.offsetWidth; + parentEl.removeChild(tempEl); + var convertedUnit = factor * parseFloat(value); + cache.CSS[value + unit2] = convertedUnit; + return convertedUnit; + } + function getCSSValue(el, prop, unit2) { + if (prop in el.style) { + var uppercasePropName = prop.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(); + var value = el.style[prop] || getComputedStyle(el).getPropertyValue(uppercasePropName) || "0"; + return unit2 ? convertPxToUnit(el, value, unit2) : value; + } + } + function getAnimationType(el, prop) { + if (is.dom(el) && !is.inp(el) && (!is.nil(getAttribute(el, prop)) || is.svg(el) && el[prop])) { + return "attribute"; + } + if (is.dom(el) && arrayContains(validTransforms, prop)) { + return "transform"; + } + if (is.dom(el) && (prop !== "transform" && getCSSValue(el, prop))) { + return "css"; + } + if (el[prop] != null) { + return "object"; + } + } + function getElementTransforms(el) { + if (!is.dom(el)) { + return; + } + var str = el.style.transform || ""; + var reg = /(\w+)\(([^)]*)\)/g; + var transforms = /* @__PURE__ */ new Map(); + var m2; + while (m2 = reg.exec(str)) { + transforms.set(m2[1], m2[2]); + } + return transforms; + } + function getTransformValue(el, propName, animatable, unit2) { + var defaultVal = stringContains(propName, "scale") ? 1 : 0 + getTransformUnit(propName); + var value = getElementTransforms(el).get(propName) || defaultVal; + if (animatable) { + animatable.transforms.list.set(propName, value); + animatable.transforms["last"] = propName; + } + return unit2 ? convertPxToUnit(el, value, unit2) : value; + } + function getOriginalTargetValue(target, propName, unit2, animatable) { + switch (getAnimationType(target, propName)) { + case "transform": + return getTransformValue(target, propName, animatable, unit2); + case "css": + return getCSSValue(target, propName, unit2); + case "attribute": + return getAttribute(target, propName); + default: + return target[propName] || 0; + } + } + function getRelativeValue(to, from) { + var operator = /^(\*=|\+=|-=)/.exec(to); + if (!operator) { + return to; + } + var u = getUnit(to) || 0; + var x2 = parseFloat(from); + var y2 = parseFloat(to.replace(operator[0], "")); + switch (operator[0][0]) { + case "+": + return x2 + y2 + u; + case "-": + return x2 - y2 + u; + case "*": + return x2 * y2 + u; + } + } + function validateValue(val, unit2) { + if (is.col(val)) { + return colorToRgb(val); + } + if (/\s/g.test(val)) { + return val; + } + var originalUnit = getUnit(val); + var unitLess = originalUnit ? val.substr(0, val.length - originalUnit.length) : val; + if (unit2) { + return unitLess + unit2; + } + return unitLess; + } + function getDistance(p1, p2) { + return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)); + } + function getCircleLength(el) { + return Math.PI * 2 * getAttribute(el, "r"); + } + function getRectLength(el) { + return getAttribute(el, "width") * 2 + getAttribute(el, "height") * 2; + } + function getLineLength(el) { + return getDistance({ x: getAttribute(el, "x1"), y: getAttribute(el, "y1") }, { x: getAttribute(el, "x2"), y: getAttribute(el, "y2") }); + } + function getPolylineLength(el) { + var points = el.points; + var totalLength = 0; + var previousPos; + for (var i = 0; i < points.numberOfItems; i++) { + var currentPos = points.getItem(i); + if (i > 0) { + totalLength += getDistance(previousPos, currentPos); + } + previousPos = currentPos; + } + return totalLength; + } + function getPolygonLength(el) { + var points = el.points; + return getPolylineLength(el) + getDistance(points.getItem(points.numberOfItems - 1), points.getItem(0)); + } + function getTotalLength(el) { + if (el.getTotalLength) { + return el.getTotalLength(); + } + switch (el.tagName.toLowerCase()) { + case "circle": + return getCircleLength(el); + case "rect": + return getRectLength(el); + case "line": + return getLineLength(el); + case "polyline": + return getPolylineLength(el); + case "polygon": + return getPolygonLength(el); + } + } + function setDashoffset(el) { + var pathLength = getTotalLength(el); + el.setAttribute("stroke-dasharray", pathLength); + return pathLength; + } + function getParentSvgEl(el) { + var parentEl = el.parentNode; + while (is.svg(parentEl)) { + if (!is.svg(parentEl.parentNode)) { + break; + } + parentEl = parentEl.parentNode; + } + return parentEl; + } + function getParentSvg(pathEl, svgData) { + var svg = svgData || {}; + var parentSvgEl = svg.el || getParentSvgEl(pathEl); + var rect = parentSvgEl.getBoundingClientRect(); + var viewBoxAttr = getAttribute(parentSvgEl, "viewBox"); + var width = rect.width; + var height = rect.height; + var viewBox = svg.viewBox || (viewBoxAttr ? viewBoxAttr.split(" ") : [0, 0, width, height]); + return { + el: parentSvgEl, + viewBox, + x: viewBox[0] / 1, + y: viewBox[1] / 1, + w: width, + h: height, + vW: viewBox[2], + vH: viewBox[3] + }; + } + function getPath(path, percent) { + var pathEl = is.str(path) ? selectString(path)[0] : path; + var p = percent || 100; + return function(property) { + return { + property, + el: pathEl, + svg: getParentSvg(pathEl), + totalLength: getTotalLength(pathEl) * (p / 100) + }; + }; + } + function getPathProgress(path, progress, isPathTargetInsideSVG) { + function point(offset) { + if (offset === void 0) + offset = 0; + var l = progress + offset >= 1 ? progress + offset : 0; + return path.el.getPointAtLength(l); + } + var svg = getParentSvg(path.el, path.svg); + var p = point(); + var p0 = point(-1); + var p1 = point(1); + var scaleX = isPathTargetInsideSVG ? 1 : svg.w / svg.vW; + var scaleY = isPathTargetInsideSVG ? 1 : svg.h / svg.vH; + switch (path.property) { + case "x": + return (p.x - svg.x) * scaleX; + case "y": + return (p.y - svg.y) * scaleY; + case "angle": + return Math.atan2(p1.y - p0.y, p1.x - p0.x) * 180 / Math.PI; + } + } + function decomposeValue(val, unit2) { + var rgx = /[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g; + var value = validateValue(is.pth(val) ? val.totalLength : val, unit2) + ""; + return { + original: value, + numbers: value.match(rgx) ? value.match(rgx).map(Number) : [0], + strings: is.str(val) || unit2 ? value.split(rgx) : [] + }; + } + function parseTargets(targets) { + var targetsArray = targets ? flattenArray(is.arr(targets) ? targets.map(toArray) : toArray(targets)) : []; + return filterArray(targetsArray, function(item, pos, self2) { + return self2.indexOf(item) === pos; + }); + } + function getAnimatables(targets) { + var parsed = parseTargets(targets); + return parsed.map(function(t, i) { + return { target: t, id: i, total: parsed.length, transforms: { list: getElementTransforms(t) } }; + }); + } + function normalizePropertyTweens(prop, tweenSettings) { + var settings = cloneObject(tweenSettings); + if (/^spring/.test(settings.easing)) { + settings.duration = spring(settings.easing); + } + if (is.arr(prop)) { + var l = prop.length; + var isFromTo = l === 2 && !is.obj(prop[0]); + if (!isFromTo) { + if (!is.fnc(tweenSettings.duration)) { + settings.duration = tweenSettings.duration / l; + } + } else { + prop = { value: prop }; + } + } + var propArray = is.arr(prop) ? prop : [prop]; + return propArray.map(function(v, i) { + var obj = is.obj(v) && !is.pth(v) ? v : { value: v }; + if (is.und(obj.delay)) { + obj.delay = !i ? tweenSettings.delay : 0; + } + if (is.und(obj.endDelay)) { + obj.endDelay = i === propArray.length - 1 ? tweenSettings.endDelay : 0; + } + return obj; + }).map(function(k) { + return mergeObjects(k, settings); + }); + } + function flattenKeyframes(keyframes) { + var propertyNames = filterArray(flattenArray(keyframes.map(function(key) { + return Object.keys(key); + })), function(p) { + return is.key(p); + }).reduce(function(a2, b) { + if (a2.indexOf(b) < 0) { + a2.push(b); + } + return a2; + }, []); + var properties = {}; + var loop = function(i2) { + var propName = propertyNames[i2]; + properties[propName] = keyframes.map(function(key) { + var newKey = {}; + for (var p in key) { + if (is.key(p)) { + if (p == propName) { + newKey.value = key[p]; + } + } else { + newKey[p] = key[p]; + } + } + return newKey; + }); + }; + for (var i = 0; i < propertyNames.length; i++) + loop(i); + return properties; + } + function getProperties(tweenSettings, params) { + var properties = []; + var keyframes = params.keyframes; + if (keyframes) { + params = mergeObjects(flattenKeyframes(keyframes), params); + } + for (var p in params) { + if (is.key(p)) { + properties.push({ + name: p, + tweens: normalizePropertyTweens(params[p], tweenSettings) + }); + } + } + return properties; + } + function normalizeTweenValues(tween, animatable) { + var t = {}; + for (var p in tween) { + var value = getFunctionValue(tween[p], animatable); + if (is.arr(value)) { + value = value.map(function(v) { + return getFunctionValue(v, animatable); + }); + if (value.length === 1) { + value = value[0]; + } + } + t[p] = value; + } + t.duration = parseFloat(t.duration); + t.delay = parseFloat(t.delay); + return t; + } + function normalizeTweens(prop, animatable) { + var previousTween; + return prop.tweens.map(function(t) { + var tween = normalizeTweenValues(t, animatable); + var tweenValue2 = tween.value; + var to = is.arr(tweenValue2) ? tweenValue2[1] : tweenValue2; + var toUnit = getUnit(to); + var originalValue = getOriginalTargetValue(animatable.target, prop.name, toUnit, animatable); + var previousValue = previousTween ? previousTween.to.original : originalValue; + var from = is.arr(tweenValue2) ? tweenValue2[0] : previousValue; + var fromUnit = getUnit(from) || getUnit(originalValue); + var unit2 = toUnit || fromUnit; + if (is.und(to)) { + to = previousValue; + } + tween.from = decomposeValue(from, unit2); + tween.to = decomposeValue(getRelativeValue(to, from), unit2); + tween.start = previousTween ? previousTween.end : 0; + tween.end = tween.start + tween.delay + tween.duration + tween.endDelay; + tween.easing = parseEasings(tween.easing, tween.duration); + tween.isPath = is.pth(tweenValue2); + tween.isPathTargetInsideSVG = tween.isPath && is.svg(animatable.target); + tween.isColor = is.col(tween.from.original); + if (tween.isColor) { + tween.round = 1; + } + previousTween = tween; + return tween; + }); + } + var setProgressValue = { + css: function(t, p, v) { + return t.style[p] = v; + }, + attribute: function(t, p, v) { + return t.setAttribute(p, v); + }, + object: function(t, p, v) { + return t[p] = v; + }, + transform: function(t, p, v, transforms, manual) { + transforms.list.set(p, v); + if (p === transforms.last || manual) { + var str = ""; + transforms.list.forEach(function(value, prop) { + str += prop + "(" + value + ") "; + }); + t.style.transform = str; + } + } + }; + function setTargetsValue(targets, properties) { + var animatables = getAnimatables(targets); + animatables.forEach(function(animatable) { + for (var property in properties) { + var value = getFunctionValue(properties[property], animatable); + var target = animatable.target; + var valueUnit = getUnit(value); + var originalValue = getOriginalTargetValue(target, property, valueUnit, animatable); + var unit2 = valueUnit || getUnit(originalValue); + var to = getRelativeValue(validateValue(value, unit2), originalValue); + var animType = getAnimationType(target, property); + setProgressValue[animType](target, property, to, animatable.transforms, true); + } + }); + } + function createAnimation(animatable, prop) { + var animType = getAnimationType(animatable.target, prop.name); + if (animType) { + var tweens = normalizeTweens(prop, animatable); + var lastTween = tweens[tweens.length - 1]; + return { + type: animType, + property: prop.name, + animatable, + tweens, + duration: lastTween.end, + delay: tweens[0].delay, + endDelay: lastTween.endDelay + }; + } + } + function getAnimations(animatables, properties) { + return filterArray(flattenArray(animatables.map(function(animatable) { + return properties.map(function(prop) { + return createAnimation(animatable, prop); + }); + })), function(a2) { + return !is.und(a2); + }); + } + function getInstanceTimings(animations, tweenSettings) { + var animLength = animations.length; + var getTlOffset = function(anim) { + return anim.timelineOffset ? anim.timelineOffset : 0; + }; + var timings = {}; + timings.duration = animLength ? Math.max.apply(Math, animations.map(function(anim) { + return getTlOffset(anim) + anim.duration; + })) : tweenSettings.duration; + timings.delay = animLength ? Math.min.apply(Math, animations.map(function(anim) { + return getTlOffset(anim) + anim.delay; + })) : tweenSettings.delay; + timings.endDelay = animLength ? timings.duration - Math.max.apply(Math, animations.map(function(anim) { + return getTlOffset(anim) + anim.duration - anim.endDelay; + })) : tweenSettings.endDelay; + return timings; + } + var instanceID = 0; + function createNewInstance(params) { + var instanceSettings = replaceObjectProps(defaultInstanceSettings, params); + var tweenSettings = replaceObjectProps(defaultTweenSettings, params); + var properties = getProperties(tweenSettings, params); + var animatables = getAnimatables(params.targets); + var animations = getAnimations(animatables, properties); + var timings = getInstanceTimings(animations, tweenSettings); + var id2 = instanceID; + instanceID++; + return mergeObjects(instanceSettings, { + id: id2, + children: [], + animatables, + animations, + duration: timings.duration, + delay: timings.delay, + endDelay: timings.endDelay + }); + } + var activeInstances = []; + var engine = function() { + var raf; + function play() { + if (!raf && (!isDocumentHidden() || !anime.suspendWhenDocumentHidden) && activeInstances.length > 0) { + raf = requestAnimationFrame(step); + } + } + function step(t) { + var activeInstancesLength = activeInstances.length; + var i = 0; + while (i < activeInstancesLength) { + var activeInstance = activeInstances[i]; + if (!activeInstance.paused) { + activeInstance.tick(t); + i++; + } else { + activeInstances.splice(i, 1); + activeInstancesLength--; + } + } + raf = i > 0 ? requestAnimationFrame(step) : void 0; + } + function handleVisibilityChange() { + if (!anime.suspendWhenDocumentHidden) { + return; + } + if (isDocumentHidden()) { + raf = cancelAnimationFrame(raf); + } else { + activeInstances.forEach(function(instance) { + return instance._onDocumentVisibility(); + }); + engine(); + } + } + if (typeof document !== "undefined") { + document.addEventListener("visibilitychange", handleVisibilityChange); + } + return play; + }(); + function isDocumentHidden() { + return !!document && document.hidden; + } + function anime(params) { + if (params === void 0) + params = {}; + var startTime = 0, lastTime = 0, now2 = 0; + var children2, childrenLength = 0; + var resolve = null; + function makePromise(instance2) { + var promise2 = window.Promise && new Promise(function(_resolve) { + return resolve = _resolve; + }); + instance2.finished = promise2; + return promise2; + } + var instance = createNewInstance(params); + var promise = makePromise(instance); + function toggleInstanceDirection() { + var direction = instance.direction; + if (direction !== "alternate") { + instance.direction = direction !== "normal" ? "normal" : "reverse"; + } + instance.reversed = !instance.reversed; + children2.forEach(function(child) { + return child.reversed = instance.reversed; + }); + } + function adjustTime(time) { + return instance.reversed ? instance.duration - time : time; + } + function resetTime() { + startTime = 0; + lastTime = adjustTime(instance.currentTime) * (1 / anime.speed); + } + function seekChild(time, child) { + if (child) { + child.seek(time - child.timelineOffset); + } + } + function syncInstanceChildren(time) { + if (!instance.reversePlayback) { + for (var i = 0; i < childrenLength; i++) { + seekChild(time, children2[i]); + } + } else { + for (var i$1 = childrenLength; i$1--; ) { + seekChild(time, children2[i$1]); + } + } + } + function setAnimationsProgress(insTime) { + var i = 0; + var animations = instance.animations; + var animationsLength = animations.length; + while (i < animationsLength) { + var anim = animations[i]; + var animatable = anim.animatable; + var tweens = anim.tweens; + var tweenLength = tweens.length - 1; + var tween = tweens[tweenLength]; + if (tweenLength) { + tween = filterArray(tweens, function(t) { + return insTime < t.end; + })[0] || tween; + } + var elapsed = minMax(insTime - tween.start - tween.delay, 0, tween.duration) / tween.duration; + var eased = isNaN(elapsed) ? 1 : tween.easing(elapsed); + var strings = tween.to.strings; + var round = tween.round; + var numbers = []; + var toNumbersLength = tween.to.numbers.length; + var progress = void 0; + for (var n = 0; n < toNumbersLength; n++) { + var value = void 0; + var toNumber = tween.to.numbers[n]; + var fromNumber = tween.from.numbers[n] || 0; + if (!tween.isPath) { + value = fromNumber + eased * (toNumber - fromNumber); + } else { + value = getPathProgress(tween.value, eased * toNumber, tween.isPathTargetInsideSVG); + } + if (round) { + if (!(tween.isColor && n > 2)) { + value = Math.round(value * round) / round; + } + } + numbers.push(value); + } + var stringsLength = strings.length; + if (!stringsLength) { + progress = numbers[0]; + } else { + progress = strings[0]; + for (var s = 0; s < stringsLength; s++) { + var a2 = strings[s]; + var b = strings[s + 1]; + var n$1 = numbers[s]; + if (!isNaN(n$1)) { + if (!b) { + progress += n$1 + " "; + } else { + progress += n$1 + b; + } + } + } + } + setProgressValue[anim.type](animatable.target, anim.property, progress, animatable.transforms); + anim.currentValue = progress; + i++; + } + } + function setCallback(cb) { + if (instance[cb] && !instance.passThrough) { + instance[cb](instance); + } + } + function countIteration() { + if (instance.remaining && instance.remaining !== true) { + instance.remaining--; + } + } + function setInstanceProgress(engineTime) { + var insDuration = instance.duration; + var insDelay = instance.delay; + var insEndDelay = insDuration - instance.endDelay; + var insTime = adjustTime(engineTime); + instance.progress = minMax(insTime / insDuration * 100, 0, 100); + instance.reversePlayback = insTime < instance.currentTime; + if (children2) { + syncInstanceChildren(insTime); + } + if (!instance.began && instance.currentTime > 0) { + instance.began = true; + setCallback("begin"); + } + if (!instance.loopBegan && instance.currentTime > 0) { + instance.loopBegan = true; + setCallback("loopBegin"); + } + if (insTime <= insDelay && instance.currentTime !== 0) { + setAnimationsProgress(0); + } + if (insTime >= insEndDelay && instance.currentTime !== insDuration || !insDuration) { + setAnimationsProgress(insDuration); + } + if (insTime > insDelay && insTime < insEndDelay) { + if (!instance.changeBegan) { + instance.changeBegan = true; + instance.changeCompleted = false; + setCallback("changeBegin"); + } + setCallback("change"); + setAnimationsProgress(insTime); + } else { + if (instance.changeBegan) { + instance.changeCompleted = true; + instance.changeBegan = false; + setCallback("changeComplete"); + } + } + instance.currentTime = minMax(insTime, 0, insDuration); + if (instance.began) { + setCallback("update"); + } + if (engineTime >= insDuration) { + lastTime = 0; + countIteration(); + if (!instance.remaining) { + instance.paused = true; + if (!instance.completed) { + instance.completed = true; + setCallback("loopComplete"); + setCallback("complete"); + if (!instance.passThrough && "Promise" in window) { + resolve(); + promise = makePromise(instance); + } + } + } else { + startTime = now2; + setCallback("loopComplete"); + instance.loopBegan = false; + if (instance.direction === "alternate") { + toggleInstanceDirection(); + } + } + } + } + instance.reset = function() { + var direction = instance.direction; + instance.passThrough = false; + instance.currentTime = 0; + instance.progress = 0; + instance.paused = true; + instance.began = false; + instance.loopBegan = false; + instance.changeBegan = false; + instance.completed = false; + instance.changeCompleted = false; + instance.reversePlayback = false; + instance.reversed = direction === "reverse"; + instance.remaining = instance.loop; + children2 = instance.children; + childrenLength = children2.length; + for (var i = childrenLength; i--; ) { + instance.children[i].reset(); + } + if (instance.reversed && instance.loop !== true || direction === "alternate" && instance.loop === 1) { + instance.remaining++; + } + setAnimationsProgress(instance.reversed ? instance.duration : 0); + }; + instance._onDocumentVisibility = resetTime; + instance.set = function(targets, properties) { + setTargetsValue(targets, properties); + return instance; + }; + instance.tick = function(t) { + now2 = t; + if (!startTime) { + startTime = now2; + } + setInstanceProgress((now2 + (lastTime - startTime)) * anime.speed); + }; + instance.seek = function(time) { + setInstanceProgress(adjustTime(time)); + }; + instance.pause = function() { + instance.paused = true; + resetTime(); + }; + instance.play = function() { + if (!instance.paused) { + return; + } + if (instance.completed) { + instance.reset(); + } + instance.paused = false; + activeInstances.push(instance); + resetTime(); + engine(); + }; + instance.reverse = function() { + toggleInstanceDirection(); + instance.completed = instance.reversed ? false : true; + resetTime(); + }; + instance.restart = function() { + instance.reset(); + instance.play(); + }; + instance.remove = function(targets) { + var targetsArray = parseTargets(targets); + removeTargetsFromInstance(targetsArray, instance); + }; + instance.reset(); + if (instance.autoplay) { + instance.play(); + } + return instance; + } + function removeTargetsFromAnimations(targetsArray, animations) { + for (var a2 = animations.length; a2--; ) { + if (arrayContains(targetsArray, animations[a2].animatable.target)) { + animations.splice(a2, 1); + } + } + } + function removeTargetsFromInstance(targetsArray, instance) { + var animations = instance.animations; + var children2 = instance.children; + removeTargetsFromAnimations(targetsArray, animations); + for (var c2 = children2.length; c2--; ) { + var child = children2[c2]; + var childAnimations = child.animations; + removeTargetsFromAnimations(targetsArray, childAnimations); + if (!childAnimations.length && !child.children.length) { + children2.splice(c2, 1); + } + } + if (!animations.length && !children2.length) { + instance.pause(); + } + } + function removeTargetsFromActiveInstances(targets) { + var targetsArray = parseTargets(targets); + for (var i = activeInstances.length; i--; ) { + var instance = activeInstances[i]; + removeTargetsFromInstance(targetsArray, instance); + } + } + function stagger(val, params) { + if (params === void 0) + params = {}; + var direction = params.direction || "normal"; + var easing = params.easing ? parseEasings(params.easing) : null; + var grid = params.grid; + var axis = params.axis; + var fromIndex = params.from || 0; + var fromFirst = fromIndex === "first"; + var fromCenter = fromIndex === "center"; + var fromLast = fromIndex === "last"; + var isRange = is.arr(val); + var val1 = isRange ? parseFloat(val[0]) : parseFloat(val); + var val2 = isRange ? parseFloat(val[1]) : 0; + var unit2 = getUnit(isRange ? val[1] : val) || 0; + var start2 = params.start || 0 + (isRange ? val1 : 0); + var values = []; + var maxValue = 0; + return function(el, i, t) { + if (fromFirst) { + fromIndex = 0; + } + if (fromCenter) { + fromIndex = (t - 1) / 2; + } + if (fromLast) { + fromIndex = t - 1; + } + if (!values.length) { + for (var index2 = 0; index2 < t; index2++) { + if (!grid) { + values.push(Math.abs(fromIndex - index2)); + } else { + var fromX = !fromCenter ? fromIndex % grid[0] : (grid[0] - 1) / 2; + var fromY = !fromCenter ? Math.floor(fromIndex / grid[0]) : (grid[1] - 1) / 2; + var toX = index2 % grid[0]; + var toY = Math.floor(index2 / grid[0]); + var distanceX = fromX - toX; + var distanceY = fromY - toY; + var value = Math.sqrt(distanceX * distanceX + distanceY * distanceY); + if (axis === "x") { + value = -distanceX; + } + if (axis === "y") { + value = -distanceY; + } + values.push(value); + } + maxValue = Math.max.apply(Math, values); + } + if (easing) { + values = values.map(function(val3) { + return easing(val3 / maxValue) * maxValue; + }); + } + if (direction === "reverse") { + values = values.map(function(val3) { + return axis ? val3 < 0 ? val3 * -1 : -val3 : Math.abs(maxValue - val3); + }); + } + } + var spacing = isRange ? (val2 - val1) / maxValue : val1; + return start2 + spacing * (Math.round(values[i] * 100) / 100) + unit2; + }; + } + function timeline(params) { + if (params === void 0) + params = {}; + var tl = anime(params); + tl.duration = 0; + tl.add = function(instanceParams, timelineOffset) { + var tlIndex = activeInstances.indexOf(tl); + var children2 = tl.children; + if (tlIndex > -1) { + activeInstances.splice(tlIndex, 1); + } + function passThrough(ins2) { + ins2.passThrough = true; + } + for (var i = 0; i < children2.length; i++) { + passThrough(children2[i]); + } + var insParams = mergeObjects(instanceParams, replaceObjectProps(defaultTweenSettings, params)); + insParams.targets = insParams.targets || params.targets; + var tlDuration = tl.duration; + insParams.autoplay = false; + insParams.direction = tl.direction; + insParams.timelineOffset = is.und(timelineOffset) ? tlDuration : getRelativeValue(timelineOffset, tlDuration); + passThrough(tl); + tl.seek(insParams.timelineOffset); + var ins = anime(insParams); + passThrough(ins); + children2.push(ins); + var timings = getInstanceTimings(children2, params); + tl.delay = timings.delay; + tl.endDelay = timings.endDelay; + tl.duration = timings.duration; + tl.seek(0); + tl.reset(); + if (tl.autoplay) { + tl.play(); + } + return tl; + }; + return tl; + } + anime.version = "3.2.1"; + anime.speed = 1; + anime.suspendWhenDocumentHidden = true; + anime.running = activeInstances; + anime.remove = removeTargetsFromActiveInstances; + anime.get = getOriginalTargetValue; + anime.set = setTargetsValue; + anime.convertPx = convertPxToUnit; + anime.path = getPath; + anime.setDashoffset = setDashoffset; + anime.stagger = stagger; + anime.timeline = timeline; + anime.easing = parseEasings; + anime.penner = penner; + anime.random = function(min2, max2) { + return Math.floor(Math.random() * (max2 - min2 + 1)) + min2; + }; + var anime_es_default = anime; + + // federjs/FederView/hnswView/HnswSearchHnsw3dView.ts + var defaultViewParams = { + width: 800, + height: 600 + }; + var _HnswSearchHnsw3dView = class { + constructor(visData, viewParams) { + this.selectedLayer = -1; + this.lastSelectedLayer = -1; + this.longerLineMap = /* @__PURE__ */ new Map(); + this.longerDashedLineMap = /* @__PURE__ */ new Map(); + this.spheres = []; + this.targetSpheres = []; + this.planes = []; + this.lines = []; + this.minX = Infinity; + this.minY = Infinity; + this.maxX = -Infinity; + this.maxY = -Infinity; + this.scenes = []; + this.sphere2id = /* @__PURE__ */ new Map(); + this.dashedLines = []; + this.orangeLines = []; + this.objectsPerLayer = /* @__PURE__ */ new Map(); + this.moveObjects = []; + this.staticPanel = new infoPanel(); + this.clickedPanel = new infoPanel(); + this.hoveredPanel = new infoPanel(); + this.init(visData, viewParams); + } + get k() { + return this.visData.searchRecords.searchParams.k; + } + addCss() { + this.layerUi = document.createElement("div"); + this.layerUi.style.display = "flex"; + this.layerUi.style.flexDirection = "column"; + this.layerUi.style.position = "absolute"; + this.layerUi.style.top = "0"; + this.layerUi.style.right = "0"; + this.layerUi.style.height = "100%"; + this.layerUi.style.justifyContent = "center"; + this.node.style.position = "relative"; + const style = document.createElement("style"); + style.innerHTML = ` + .layer-ui{ + position: absolute; + top: 0; + right: 0; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: center; + pointer-events: none; + } + .layer-ui-item{ + justify-content: center; + align-items: center; + display: flex; + transition: transform 0.3s; + } + + .layer-ui-item-inner-circle{ + width:12px; + height:12px; + border-radius: 50%; + background-color: #fff; + position: relative; + + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + .layer-ui-item-outer-circle{ + width:32px; + height:32px; + border-radius: 50%; + border: 1px dashed #fff; + opacity: 0.3; + } + .layer-ui-item-outer-circle:hover{ + boxShadow: 0 0 10px white; + opacity: 1; + border: 1px solid #fff; + } + .hnsw-search-hnsw3d-view-player-ui{ + position: absolute; + bottom: -128; + flex-direction: column; + display: flex; + height:128px; + } + .hnsw-search-hnsw3d-view-player-ui-row{ + display: flex; + flex-direction: row; + justify-content: space-between; + flex: 1; + } + .hnsw-search-hnsw3d-view-player-ui-row-item{ + display: flex; + flex-direction: row; + justify-content:left; + align-items: center; + flex: 1; + } + .hnsw-search-hnsw3d-view-player-ui-row-item > .icon{ + margin-right: 15px; + } + .hnsw-search-hnsw3d-view-player-ui-row-item > .icon:hover{ + cursor: pointer; + } + .hnsw-search-hnsw3d-view-player-ui-row > input{ + width: 100%; + background: rgba(255,255,255,0.3); + } + .hnsw-search-hnsw3d-view-player-ui-row > input::-webkit-slider-thumb{ + -webkit-appearance: none; + appearance: none; + visibility: hidden; + } + .hnsw-search-hnsw3d-view-player-ui-row > input::-moz-range-thumb{ + visibility: hidden; + } + //focus style + .hnsw-search-hnsw3d-view-player-ui-row > input:focus{ + outline: none; + } + //track style + .hnsw-search-hnsw3d-view-player-ui-row > input::-webkit-slider-runnable-track{ + width: 100%; + background: rgba(255,255,255); + } + .hnsw-search-hnsw3d-view-player-ui-row > input::-moz-range-track{ + width: 100%; + background: rgba(255,255,255,0.3); + } + .hnsw-search-hnsw3d-view-player-ui-row > input::-ms-track{ + width: 100%; + background: rgba(255,255,255,0.3); + } + `; + document.head.appendChild(style); + } + createCircleDom() { + const circleDom = document.createElement("div"); + circleDom.classList.add("layer-ui-item"); + const parentDiv = document.createElement("div"); + parentDiv.classList.add("layer-ui-item-outer-circle"); + parentDiv.style.cursor = "pointer"; + parentDiv.style.marginBottom = "16px"; + parentDiv.style.transition = "box-shadow 0.3s"; + parentDiv.style.transition = "opacity 0.3s"; + const childDiv = document.createElement("div"); + childDiv.classList.add("layer-ui-item-inner-circle"); + parentDiv.appendChild(childDiv); + circleDom.appendChild(parentDiv); + return circleDom; + } + setUpLayerUi() { + this.addCss(); + this.layerUi = document.createElement("div"); + this.layerUi.style.display = "flex"; + this.layerUi.style.flexDirection = "column"; + this.layerUi.style.position = "absolute"; + this.layerUi.style.top = "0"; + this.layerUi.style.right = "0"; + this.node.style.width = "1200px"; + this.layerUi.style.height = "100%"; + this.layerUi.style.justifyContent = "center"; + this.node.style.position = "relative"; + const adjustLayout = () => { + const children2 = this.layerUi.children; + for (let i = 0; i < children2.length; i++) { + const child = children2[i]; + if (this.selectedLayer <= i) { + child.style.transform = "translateY(0)"; + } else { + child.style.transform = "translateY(-100%)"; + } + } + }; + const highlightLayer = () => { + const children2 = this.layerUi.children; + for (let i = 0; i < children2.length; i++) { + const child = children2[i]; + if (this.selectedLayer === i) { + child.children[0].style.boxShadow = "0 0 10px white"; + child.children[0].style.opacity = "1"; + child.children[0].style.border = "1px solid #fff"; + } else { + child.children[0].style.boxShadow = "none"; + child.children[0].style.opacity = "0.3"; + child.children[0].style.border = "1px dashed #fff"; + } + } + }; + for (let i = 0; i < this.visData.searchRecords.searchRecords.length; i++) { + const circleDom = this.createCircleDom(); + let toggled = false; + circleDom.children[0].addEventListener("click", () => { + if (this.played) { + return; + } + if (this.selectedLayer !== i) { + this.selectedLayer = i; + } else { + this.selectedLayer = -1; + } + adjustLayout(); + this.startTransition(); + highlightLayer(); + this.lastSelectedLayer = this.selectedLayer; + }); + this.layerUi.appendChild(circleDom); + } + this.node.appendChild(this.layerUi); + } + startTransition() { + debugger; + if (this.lastSelectedLayer !== this.selectedLayer) { + for (let i = 0; i < this.scene.children.length; i++) { + const child = this.scene.children[i]; + if (child.userData.longer) { + debugger; + const layer = parseInt(child.userData.layer.split("-")[1]); + if (this.selectedLayer === layer) { + child.visible = true; + } else { + child.visible = false; + } + } else if (typeof child.userData.layer === "string") { + const layer = parseInt(child.userData.layer.split("-")[1]); + if (this.selectedLayer === layer) { + child.visible = false; + } else { + child.visible = true; + } + } + } + const lastOffsets = new Array(this.visData.searchRecords.searchRecords.length).fill(void 0).map((v, idx) => { + return idx < this.lastSelectedLayer ? 1200 : 0; + }); + const offsets = new Array(this.visData.searchRecords.searchRecords.length).fill(void 0).map((v, idx) => { + return idx < this.selectedLayer ? 1200 : 0; + }); + const diff = offsets.map((v, idx) => v - lastOffsets[idx]); + this.scene.children.forEach((obj, idx) => { + if (obj instanceof Mesh && obj.userData.layer !== void 0 && !obj.userData.longer) { + let layer = obj.userData.layer; + if (typeof layer === "string") { + layer = parseInt(layer.split("-")[0]); + } + const offset = diff[layer]; + anime_es_default({ + targets: obj.position, + y: obj.position.y + offset, + duration: 200, + easing: "easeInOutQuad" + }); + } + }); + this.pickingScene.children.forEach((pickingObj) => { + if (pickingObj instanceof Mesh && pickingObj.userData.layer !== void 0) { + let layer = pickingObj.userData.layer; + if (typeof layer === "string") { + layer = parseInt(layer.split("-")[0]); + } + const offset = diff[layer]; + pickingObj.position.y += offset; + } + }); + } + } + init(visData, viewParams) { + this.visData = visData; + console.log(visData); + const searchRecords = this.visData.searchRecords; + console.log(searchRecords); + this.node = document.createElement("div"); + this.setUpLayerUi(); + this.node.className = "hnsw-search-hnsw3d-view"; + viewParams = Object.assign({}, defaultViewParams, viewParams); + this.canvasWidth = viewParams.width; + this.canvasHeight = viewParams.height; + this.node.style.width = `${this.canvasWidth}px`; + this.node.style.height = `${this.canvasHeight}px`; + this.setupCanvas(); + this.setupRenderer(); + this.setupScene(); + this.parseSearchRecords(); + this.setupPickingScene(); + this.setupEventListeners(); + this.setupCamera(); + this.setupController(); + this.setupPlayerUi(); + } + setupPlayerUi() { + this.playerUi = document.createElement("div"); + this.playerUi.className = "hnsw-search-hnsw3d-view-player-ui"; + this.node.appendChild(this.playerUi); + this.playerUi.style.width = `${this.canvasWidth}px`; + this.playerUi.style.border = "1px solid white"; + const row1 = document.createElement("div"); + row1.className = "hnsw-search-hnsw3d-view-player-ui-row"; + this.playerUi.appendChild(row1); + row1.innerHTML = ` +
+
+ + + + +
+
+ + + + + + + + + + + +
+
+
+ + +
+
+
+ + + + + + + + + + +
+
+ `; + this.playBtn = this.playerUi.querySelector(".play"); + this.resetBtn = this.playerUi.querySelector(".replay"); + this.prevBtn = this.playerUi.querySelector(".prev"); + this.nextBtn = this.playerUi.querySelector(".next"); + this.originCamBtn = this.playerUi.querySelector(".origin-cam"); + this.playBtn.addEventListener("click", () => { + console.log("play"); + this.play(); + }); + this.resetBtn.addEventListener("click", () => { + this.currentSceneIndex = 0; + this.slider.value = "0"; + }); + this.prevBtn.addEventListener("click", () => { + console.log("prev"); + this.currentSceneIndex = Math.max(0, this.currentSceneIndex - 1); + this.slider.value = this.currentSceneIndex.toString(); + }); + this.nextBtn.addEventListener("click", () => { + console.log("next"); + this.currentSceneIndex = Math.min(this.currentSceneIndex + 1, this.scenes.length - 1); + this.slider.value = `${this.currentSceneIndex}`; + }); + this.originCamBtn.addEventListener("click", () => { + console.log("origin cam"); + this.resetCamera(); + }); + const row2 = document.createElement("div"); + row2.className = "hnsw-search-hnsw3d-view-player-ui-row"; + this.playerUi.appendChild(row2); + const slider = document.createElement("input"); + slider.type = "range"; + slider.min = "0"; + slider.max = (this.scenes.length - 1).toString(); + slider.value = slider.max; + this.currentSceneIndex = this.scenes.length - 1; + slider.className = "hnsw-search-hnsw3d-view-player-ui-slider"; + slider.addEventListener("input", () => { + this.currentSceneIndex = parseInt(slider.value); + this.played = false; + this.playBtn.innerHTML = _HnswSearchHnsw3dView.playHtml; + }); + row2.appendChild(slider); + this.slider = slider; + } + play() { + this.played = !this.played; + if (this.played) { + this.playBtn.innerHTML = _HnswSearchHnsw3dView.stopHtml; + this.intervalId = window.setInterval(() => { + if (this.played) { + this.currentSceneIndex++; + if (this.currentSceneIndex >= this.scenes.length) { + this.currentSceneIndex = 0; + } + this.slider.value = this.currentSceneIndex.toString(); + } + }, 300); + } else { + this.playBtn.innerHTML = _HnswSearchHnsw3dView.playHtml; + window.clearInterval(this.intervalId); + } + } + createLine(from, to, color2, width = 10) { + const line = new import_three2.MeshLine(); + line.setPoints([from.x, from.y, from.z, to.x, to.y, to.z]); + let material; + if (color2 instanceof Texture) { + material = new import_three2.MeshLineMaterial({ + useMap: true, + transparent: true, + map: color2, + opacity: 1, + lineWidth: width + }); + } else { + material = new import_three2.MeshLineMaterial({ + color: new Color2(color2), + lineWidth: width + }); + } + const mesh = new Mesh(line, material); + return mesh; + } + createSphere(x2, y2, z, color2) { + const geometry = new SphereGeometry(20); + const material = new MeshBasicMaterial({ + color: new Color2(color2) + }); + const sphere = new Mesh(geometry, material); + sphere.position.set(x2, y2, z); + return sphere; + } + stepTo(steps2) { + } + getPositionXZ(id2) { + const { id2forcePos } = this.visData; + const pos = id2forcePos[id2]; + return { x: pos[0], z: pos[1] }; + } + changeSphereColor(sphere, color2) { + const material = new MeshBasicMaterial({ + color: new Color2(color2) + }); + const geometry = sphere.geometry.clone(); + const newSphere = new Mesh(geometry, material); + newSphere.name = sphere.name; + newSphere.position.copy(sphere.position); + newSphere.userData = sphere.userData; + this.scene.remove(sphere); + this.scene.add(newSphere); + } + wait(ms) { + return __async(this, null, function* () { + return new Promise((resolve) => setTimeout(resolve, ms)); + }); + } + createGradientTexture(color1, color2) { + const canvas = document.createElement("canvas"); + canvas.width = 256; + canvas.height = 256; + const ctx = canvas.getContext("2d"); + const gradient = ctx.createLinearGradient(0, 0, 256, 0); + gradient.addColorStop(0, "#" + color1.toString(16)); + gradient.addColorStop(1, "#" + color2.toString(16)); + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, 256, 256); + const texture = new CanvasTexture(canvas); + return texture; + } + parseSearchRecords() { + let y0 = 0; + const { searchRecords } = this.visData.searchRecords; + let sphere2idArray = []; + let id2sphereArray = []; + let id2lineArray = []; + for (let i = 0; i < searchRecords.length; i++) { + let records = searchRecords[i]; + const sphere2id = /* @__PURE__ */ new Map(); + const id2sphere = /* @__PURE__ */ new Map(); + const id2line = /* @__PURE__ */ new Map(); + for (let j = 0; j < records.length; j++) { + const record = records[j]; + const startNode = record[0]; + const endNode = record[1]; + const { x: x0, z: z0 } = this.getPositionXZ(startNode); + const { x: x1, z: z1 } = this.getPositionXZ(endNode); + if (!id2line.has(`${startNode}-${endNode}`)) { + const line = this.createLine(new Vector3(x0, y0, z0), new Vector3(x1, y0, z1), 0); + line.userData = { + layer: i + }; + this.scene.add(line); + line.visible = false; + line.name = `${startNode}-${endNode}`; + id2line.set(`${startNode}-${endNode}`, line); + } + if (!id2sphere.has(startNode)) { + const startNodeSphere = this.createSphere(x0, y0, z0, _HnswSearchHnsw3dView.colors.searchedYellow); + startNodeSphere.visible = false; + startNodeSphere.name = `${startNode}`; + startNodeSphere.userData = { + layer: i + }; + this.scene.add(startNodeSphere); + id2sphere.set(startNode, startNodeSphere); + sphere2id.set(startNodeSphere, startNode); + } + if (!id2sphere.has(endNode)) { + const endNodeSphere = this.createSphere(x1, y0, z1, _HnswSearchHnsw3dView.colors.searchedYellow); + endNodeSphere.visible = false; + endNodeSphere.name = `${endNode}`; + endNodeSphere.userData = { + layer: i + }; + this.scene.add(endNodeSphere); + id2sphere.set(endNode, endNodeSphere); + sphere2id.set(endNodeSphere, endNode); + } + } + y0 += -400; + sphere2idArray.push(sphere2id); + id2sphereArray.push(id2sphere); + id2lineArray.push(id2line); + } + y0 = 0; + const topVisitedNodes = []; + for (let i = 0; i < searchRecords.length; i++) { + const records = searchRecords[i]; + const visited = /* @__PURE__ */ new Set(); + const firstRecord = records[0]; + let lastVisited = firstRecord[0]; + if (i === 0) { + const targetSphere = this.createSphere(0, 0, 0, _HnswSearchHnsw3dView.colors.targetWhite); + targetSphere.userData = { + layer: i + }; + this.scene.add(targetSphere); + this.targetSpheres.push(targetSphere); + } + for (let j = 0; j < records.length; j++) { + const record = records[j]; + const startNode = record[0]; + const endNode = record[1]; + const distance = record[2]; + const { x: x0, z: z0 } = this.getPositionXZ(startNode); + const { x: x1, z: z1 } = this.getPositionXZ(endNode); + const startNodeSphere = id2sphereArray[i].get(startNode); + const endNodeSphere = id2sphereArray[i].get(endNode); + const line = id2lineArray[i].get(`${startNode}-${endNode}`); + if (startNodeSphere) { + if (i === searchRecords.length - 1 && !topVisitedNodes.find((v) => v.id === endNode)) { + topVisitedNodes.push({ id: endNode, distance }); + } + startNodeSphere.visible = true; + this.changeSphereColor(startNodeSphere, _HnswSearchHnsw3dView.colors.searchedYellow); + visited.add(startNode); + if (lastVisited !== startNode) { + const line2 = id2lineArray[i].get(`${lastVisited}-${startNode}`); + if (line2) { + const texture = this.createGradientTexture(4294967040, _HnswSearchHnsw3dView.colors.searchedYellow); + this.scene.remove(line2); + const { x: x2, z: z2 } = this.getPositionXZ(lastVisited); + const line22 = this.createLine(new Vector3(x2, y0, z2), new Vector3(x0, y0, z0), texture); + line22.userData = { + layer: i + }; + this.scene.add(line22); + id2lineArray[i].set(`${lastVisited}-${startNode}`, line22); + } else if (i === searchRecords.length - 1) { + const id2line = id2lineArray[i]; + const key = Array.from(id2line.keys()).find((key2) => key2.includes(`-${startNode}`)); + const line3 = id2line.get(key); + if (line3) { + const texture = this.createGradientTexture(4294967040, _HnswSearchHnsw3dView.colors.searchedYellow); + this.scene.remove(line3); + const [start2, end] = key.split("-").map((v) => parseInt(v)); + const { x: x02, z: z02 } = this.getPositionXZ(start2); + const { x: x12, z: z12 } = this.getPositionXZ(end); + const line22 = this.createLine(new Vector3(x02, y0, z02), new Vector3(x12, y0, z12), texture); + line22.userData = { + layer: i + }; + this.scene.add(line22); + line22.name = `${start2}-${end}`; + id2lineArray[i].set(`${start2}-${end}`, line22); + } + } + } + } + if (endNodeSphere && !visited.has(endNode)) { + endNodeSphere.visible = true; + this.changeSphereColor(endNodeSphere, _HnswSearchHnsw3dView.colors.candidateBlue); + } + if (line && !visited.has(endNode)) { + let texture = null; + texture = this.createGradientTexture(4294967040, _HnswSearchHnsw3dView.colors.candidateBlue); + const newLine = this.createLine(new Vector3(x0, y0, z0), new Vector3(x1, y0, z1), texture); + newLine.userData = { + layer: i + }; + this.scene.remove(line); + this.scene.add(newLine); + id2lineArray[i].set(`${startNode}-${endNode}`, newLine); + } + lastVisited = startNode; + this.scenes.push(this.scene.clone()); + } + let nextLevelMap = id2sphereArray[i + 1]; + if (nextLevelMap) { + const nextLevelSphere = nextLevelMap.get(lastVisited); + if (nextLevelSphere) { + this.changeSphereColor(nextLevelSphere, _HnswSearchHnsw3dView.colors.searchedYellow); + nextLevelSphere.visible = true; + const currentLevelSphere = id2sphereArray[i].get(lastVisited); + if (currentLevelSphere) { + this.changeSphereColor(currentLevelSphere, _HnswSearchHnsw3dView.colors.fineOrange); + } + const orangeYellowTexture = this.createGradientTexture(_HnswSearchHnsw3dView.colors.fineOrange, _HnswSearchHnsw3dView.colors.searchedYellow); + const { x: x0, z: z0 } = this.getPositionXZ(lastVisited); + const { x: x1, z: z1 } = this.getPositionXZ(lastVisited); + const line = this.createLine(new Vector3(x0, y0, z0), new Vector3(x1, y0 - 400, z1), orangeYellowTexture); + line.userData = { + layer: `${i}-${i + 1}` + }; + this.orangeLines.push(line); + const longerLine = this.createLine(new Vector3(x0, y0 + 1200, z0), new Vector3(x1, y0 - 400, z1), orangeYellowTexture); + longerLine.userData = { + layer: `${i}-${i + 1}`, + longer: true + }; + longerLine.visible = false; + this.longerLineMap.set(`${i}-${i + 1}`, longerLine); + this.scene.add(longerLine); + this.scene.add(line); + } + } + if (i === searchRecords.length - 1) { + topVisitedNodes.sort((a2, b) => a2.distance - b.distance); + const k = this.k; + const topEfNodes = topVisitedNodes.slice(0, k); + for (let j = 0; j < topEfNodes.length; j++) { + const { id: id2 } = topEfNodes[j]; + const sphere = id2sphereArray[i].get(id2); + if (sphere) { + this.changeSphereColor(sphere, _HnswSearchHnsw3dView.colors.fineOrange); + } + } + this.scenes.push(this.scene.clone()); + } + if (i < searchRecords.length - 1) { + const targetSphere = this.createSphere(0, y0 - 400, 0, _HnswSearchHnsw3dView.colors.targetWhite); + targetSphere.userData = { + layer: i + 1 + }; + this.targetSpheres.push(targetSphere); + this.scene.add(targetSphere); + const dashedMaterial = new import_three2.MeshLineMaterial({ + color: new Color2(_HnswSearchHnsw3dView.colors.targetWhite), + lineWidth: 10, + dashed: true, + dashArray: 0.1, + dashRatio: 0.5, + transparent: true + }); + const line = new import_three2.MeshLine(); + line.setPoints([0, y0, 0, 0, y0 - 400, 0]); + const mesh = new Mesh(line.geometry, dashedMaterial); + mesh.userData = { + layer: `${i}-${i + 1}` + }; + this.dashedLines.push(mesh); + const dashedMaterial2 = new import_three2.MeshLineMaterial({ + color: new Color2(_HnswSearchHnsw3dView.colors.targetWhite), + lineWidth: 10, + dashed: true, + dashArray: 0.025, + dashRatio: 0.5, + transparent: true + }); + const longerDashedLineGeometry = new import_three2.MeshLine(); + longerDashedLineGeometry.setPoints([0, y0 + 1200, 0, 0, y0 - 400, 0]); + const longerDashedLine = new Mesh(longerDashedLineGeometry, dashedMaterial2); + longerDashedLine.userData = { + layer: `${i}-${i + 1}`, + longer: true + }; + longerDashedLine.visible = false; + this.scene.add(longerDashedLine); + this.longerDashedLineMap.set(`${i}-${i + 1}`, longerDashedLine); + this.scene.add(mesh); + if (i === searchRecords.length - 2) { + const targetSphere2 = this.createSphere(0, y0 - 400, 0, _HnswSearchHnsw3dView.colors.targetWhite); + targetSphere2.userData = { + layer: i + 1 + }; + this.targetSpheres.push(targetSphere2); + this.scene.add(targetSphere2); + } + } + y0 += -400; + } + } + createDashedLineTexture(backgroundColor = 0, color2 = 4294967040, dashSize = 20, gapSize = 10) { + const canvas = document.createElement("canvas"); + canvas.width = 128; + canvas.height = 1; + const context = canvas.getContext("2d"); + context.fillStyle = `#${backgroundColor.toString(16)}`; + context.fillRect(0, 0, canvas.width, canvas.height); + context.strokeStyle = `#${color2.toString(16)}`; + context.lineWidth = 10; + context.beginPath(); + context.setLineDash([dashSize, gapSize]); + context.moveTo(0, 0); + context.lineTo(canvas.width, canvas.height); + context.stroke(); + const texture = new Texture(canvas); + texture.needsUpdate = true; + return texture; + } + setupPickingScene() { + this.pickingScene = new Scene(); + this.pickingTarget = new WebGLRenderTarget(this.renderer.domElement.width, this.renderer.domElement.height); + this.pickingScene.background = new Color2(0); + let count = 1; + this.pickingMap = /* @__PURE__ */ new Map(); + const pickingMaterial = new MeshBasicMaterial({ + vertexColors: true + }); + this.scene.traverse((obj) => { + if (obj instanceof Mesh) { + if (obj.geometry.type === "SphereGeometry") { + const geometry = obj.geometry.clone(); + let color2 = new Color2(); + applyVertexColors(geometry, color2.setHex(count)); + const pickingMesh = new Mesh(geometry, pickingMaterial); + pickingMesh.position.copy(obj.position); + pickingMesh.rotation.copy(obj.rotation); + pickingMesh.scale.copy(obj.scale); + pickingMesh.userData = obj.userData; + pickingMesh.name = obj.name; + this.pickingScene.add(pickingMesh); + this.pickingMap.set(count, pickingMesh); + count++; + } + } + }); + const pickingPlaneMaterial = new MeshBasicMaterial({ + vertexColors: true + }); + for (let i = 0; i < this.visData.searchRecords.searchRecords.length; i++) { + let geometry = this.planes[i].clone().geometry.clone(); + let color2 = new Color2(); + applyVertexColors(geometry, color2.setHex(count)); + const plane = new Mesh(geometry, pickingPlaneMaterial); + const { x: x2, y: y2, z } = this.planes[i].position; + const scale = this.planes[i].scale; + plane.scale.set(scale.x, scale.y, scale.z); + plane.position.set(x2, y2, z); + plane.rotation.x = -Math.PI / 2; + plane.scale.set(1.2, 1.2, 1.2); + plane.name = `plane${i}`; + plane.userData = { layer: i }; + this.pickingScene.add(plane); + this.pickingMap.set(count, plane); + count += 66; + } + } + setupEventListeners() { + this.renderer.domElement.addEventListener("click", (event) => { + var _a; + let id2 = this.pick(event.offsetX, event.offsetY); + const obj = this.pickingMap.get(id2); + console.log("picked", obj.userData, obj.name); + if ((_a = obj == null ? void 0 : obj.name) == null ? void 0 : _a.startsWith("plane")) { + const layer = obj.userData.layer; + console.log(layer); + } + }); + } + pick(x2, y2) { + if (x2 < 0 || y2 < 0) + return -1; + const pixelRatio = this.renderer.getPixelRatio(); + this.camera.setViewOffset(this.canvas.clientWidth, this.canvas.clientHeight, x2 * pixelRatio, y2 * pixelRatio, 1, 1); + this.renderer.setRenderTarget(this.pickingTarget); + this.renderer.render(this.pickingScene, this.camera); + this.renderer.setRenderTarget(null); + this.camera.clearViewOffset(); + const pixelBuffer = new Uint8Array(4); + this.renderer.readRenderTargetPixels(this.pickingTarget, 0, 0, 1, 1, pixelBuffer); + const id2 = pixelBuffer[0] << 16 | pixelBuffer[1] << 8 | pixelBuffer[2]; + return id2; + } + createPlaneGradientTexture() { + const canvas = document.createElement("canvas"); + canvas.width = 256; + canvas.height = 256; + const ctx = canvas.getContext("2d"); + const gradient = ctx.createLinearGradient(0, 0, 0, 256); + gradient.addColorStop(0, "rgba(30, 100, 255, 1)"); + gradient.addColorStop(1, "rgba(0, 35, 77, 0)"); + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, 256, 256); + ctx.fillStyle = "#D9EAFF"; + ctx.fillRect(0, 0, 1, 256); + ctx.fillRect(0, 0, 256, 1); + ctx.fillRect(0, 255, 256, 1); + ctx.fillRect(255, 0, 1, 256); + const texture = new Texture(canvas); + texture.needsUpdate = true; + return texture; + } + drawBorderLine(from, to, color2) { + const line = new import_three2.MeshLine(); + line.setPoints([from.x, from.y, from.z, to.x, to.y, to.z]); + const material = new import_three2.MeshLineMaterial({ + color: new Color2(color2), + lineWidth: 0.01, + sizeAttenuation: false + }); + const mesh = new Mesh(line, material); + this.scene.add(mesh); + } + setupPlanes() { + let z0 = -30; + const { visData } = this.visData; + for (let i = visData.length - 1; i >= 0; i--) { + const width = this.maxX - this.minX; + const height = this.maxY - this.minY; + const planeGeometry = new PlaneGeometry(width, height); + const texture = this.createPlaneGradientTexture(); + const planeMaterial = new MeshBasicMaterial({ + map: texture, + side: DoubleSide, + transparent: true, + opacity: 0.5, + depthWrite: false + }); + const plane = new Mesh(planeGeometry, planeMaterial); + plane.rotation.x = Math.PI / 2; + plane.position.z = (this.maxY + this.minY) / 2; + plane.position.x = (this.maxX + this.minX) / 2; + plane.scale.set(1.2, 1.2, 1.2); + plane.position.y = z0; + plane.name = `plane${i}`; + plane.userData = { layer: visData.length - 1 - i }; + z0 += -400; + this.planes.push(plane); + } + console.log(this.planes); + } + computeBoundries() { + const { visData } = this.visData; + console.log(visData); + for (let i = visData.length - 1; i >= 0; i--) { + const { nodes } = visData[i]; + for (let j = 0; j < nodes.length; j++) { + const node = nodes[j]; + const { id: id2, x: x2, y: y2, type: type2 } = node; + this.maxX = Math.max(this.maxX, x2); + this.maxY = Math.max(this.maxY, y2); + this.minX = Math.min(this.minX, x2); + this.minY = Math.min(this.minY, y2); + } + } + } + render() { + const render = (t) => { + if (this.dashedLines.length > 0) { + this.dashedLines.forEach((line) => { + line.material.uniforms.dashOffset.value -= 0.01; + }); + this.longerDashedLineMap.forEach((line) => { + line.material.uniforms.dashOffset.value -= 25e-4; + }); + } + this.controller.update(); + if (this.currentSceneIndex !== void 0) { + this.scene = this.scenes[this.currentSceneIndex]; + } + this.renderer.render(this.scene, this.camera); + requestAnimationFrame(render); + }; + requestAnimationFrame(render); + } + setupController() { + this.controller = new OrbitControls(this.camera, this.canvas); + this.controller.enableZoom = true; + this.controller.enablePan = true; + this.controller.enableDamping = true; + this.controller.enableRotate = true; + } + setupCamera() { + this.camera = new OrthographicCamera(-this.canvas.width / 2, this.canvas.width / 2, this.canvas.height / 2, -this.canvas.height / 2, -4e3, 4e3); + this.camera.position.set(_HnswSearchHnsw3dView.defaultCamera.position.x, _HnswSearchHnsw3dView.defaultCamera.position.y, _HnswSearchHnsw3dView.defaultCamera.position.z); + this.camera.rotation.set(_HnswSearchHnsw3dView.defaultCamera.rotation.x, _HnswSearchHnsw3dView.defaultCamera.rotation.y, _HnswSearchHnsw3dView.defaultCamera.rotation.z); + this.camera.zoom = _HnswSearchHnsw3dView.defaultCamera.zoom; + this.camera.updateProjectionMatrix(); + } + resetCamera() { + this.camera.position.set(_HnswSearchHnsw3dView.defaultCamera.position.x, _HnswSearchHnsw3dView.defaultCamera.position.y, _HnswSearchHnsw3dView.defaultCamera.position.z); + this.camera.rotation.set(_HnswSearchHnsw3dView.defaultCamera.rotation.x, _HnswSearchHnsw3dView.defaultCamera.rotation.y, _HnswSearchHnsw3dView.defaultCamera.rotation.z); + this.camera.zoom = _HnswSearchHnsw3dView.defaultCamera.zoom; + this.camera.updateProjectionMatrix(); + } + setupScene() { + this.scene = new Scene(); + this.computeBoundries(); + this.setupPlanes(); + this.scene.add(...this.planes); + } + setupRenderer() { + this.renderer = new WebGLRenderer({ + canvas: this.canvas, + antialias: true + }); + this.renderer.setSize(this.canvas.width, this.canvas.height); + } + setupCanvas() { + this.canvas = document.createElement("canvas"); + this.node.appendChild(this.canvas); + this.canvas.width = this.canvasWidth; + this.canvas.height = this.canvasHeight; + } + }; + var HnswSearchHnsw3dView = _HnswSearchHnsw3dView; + HnswSearchHnsw3dView.colors = { + candidateBlue: 1531903, + searchedYellow: 16776325, + fineOrange: 15953483, + targetWhite: 16777215, + labelGreen: 8388476 + }; + HnswSearchHnsw3dView.defaultCamera = { + position: { + isVector3: true, + x: 85.73523132349014, + y: 21.163507502655282, + z: 46.92095544735611 + }, + rotation: { + isEuler: true, + x: -0.42372340871438785, + y: 1.0301035872063589, + z: 0.36899315353677475, + order: "XYZ" + }, + zoom: 0.14239574134637464 + }; + HnswSearchHnsw3dView.stopHtml = ` + + + + + + `; + HnswSearchHnsw3dView.playHtml = ` + + + + + `; + function applyVertexColors(geometry, color2) { + const positions = geometry.getAttribute("position"); + const colors = []; + for (let i = 0; i < positions.count; i++) { + colors.push(color2.r, color2.g, color2.b); + } + geometry.setAttribute("color", new Float32BufferAttribute(colors, 3)); + } + + // federjs/FederView/hnswView/HnswSearchView.ts + var HnswSearchView = class { + constructor(visData, viewParams) { + this.staticPanel = new infoPanel(); + this.clickedPanel = new infoPanel(); + this.hoveredPanel = new infoPanel(); + this.init(visData, viewParams); + } + init(visData, viewParams) { + } + render() { + } + }; + + // federjs/FederView/index.ts + var viewMap = { + ["hnsw" /* hnsw */ + "search" /* search */ + "hnsw3d" /* hnsw3d */]: HnswSearchHnsw3dView, + ["hnsw" /* hnsw */ + "search" /* search */ + "default" /* default */]: HnswSearchView + }; + var FederView = class { + constructor({ indexType, actionType, viewType, visData }, viewParams) { + this.view = new viewMap[indexType + actionType + viewType](visData, viewParams); + } + render() { + this.view.render(); + } + }; + + // test/index.js + var hnswIndexFile = "hnswlib_hnsw_voc_17k_1f1dfd63a9.index"; + var testVector = Array(512).fill(0).map((_) => Math.random()); + var testSearchParams = { + k: 4, + ef: 6, + nprobe: 4 + }; + window.addEventListener("DOMContentLoaded", () => __async(void 0, null, function* () { + const arrayBuffer = yield fetch(hnswIndexFile).then((res) => res.arrayBuffer()); + const federIndex = new FederIndex("hnswlib"); + federIndex.initByArrayBuffer(arrayBuffer); + const federLayout = new FederLayout(federIndex); + const visDataAll = yield federLayout.getVisData({ + actionType: "search", + actionData: { + target: testVector, + searchParams: testSearchParams + }, + viewType: "hnsw3d", + layoutParams: {} + }); + console.log("visDataAll", visDataAll); + const viewParams = {}; + const federView = new FederView(visDataAll, viewParams); + document.querySelector("#container").appendChild(federView.view.node); + federView.view.render(); + })); +})(); +/** + * @license + * Copyright 2010-2022 Three.js Authors + * SPDX-License-Identifier: MIT + */ diff --git a/test/index.html b/test/index.html new file mode 100644 index 0000000..10ab134 --- /dev/null +++ b/test/index.html @@ -0,0 +1,20 @@ + + + + + + + + Feder2 view test + + + + +
+ +
+ + + + + \ No newline at end of file diff --git a/test/index.js b/test/index.js index 22353ad..1506c3e 100644 --- a/test/index.js +++ b/test/index.js @@ -1,23 +1,52 @@ -import { Feder } from '../esm/index.js'; +import { FederIndex, FederLayout, FederView } from ''; -let feder = new Feder(); +const hnswIndexFile = 'hnswlib_hnsw_voc_17k_1f1dfd63a9.index'; -console.assert(feder instanceof Feder, { - errorMsg: 'should be instanceof Feder', -}); +const testVector = Array(512) + .fill(0) + .map((_) => Math.random()); -console.assert(typeof feder.update === 'function', { - errorMsg: 'feder should have an update method', -}); +const testSearchParams = { + k: 4, + ef: 6, + nprobe: 4, +}; -console.assert(typeof feder.update === 'function', { - errorMsg: 'feder should have an update method', -}); +window.addEventListener('DOMContentLoaded', async () => { + const arrayBuffer = await fetch(hnswIndexFile).then((res) => + res.arrayBuffer() + ); -console.assert(typeof feder.search === 'function', { - errorMsg: 'feder should have an search method', -}); + const federIndex = new FederIndex('hnswlib'); + + federIndex.initByArrayBuffer(arrayBuffer); + + // console.log('federIndex', federIndex); + + const federLayout = new FederLayout(federIndex); + + // const visData = await federLayout.getVisData({ + // actionType: 'overview', + // viewType: "normal", + // }) + + const visDataAll = await federLayout.getVisData({ + actionType: 'search', // 'overview' + actionData: { + target: testVector, + searchParams: testSearchParams, + }, + // viewType: 'default', + viewType: 'hnsw3d', + layoutParams: {}, + }); + + console.log('visDataAll', visDataAll); -console.assert(typeof feder.reset === 'function', { - errorMsg: 'feder should have an reset method', + const viewParams = {}; + const federView = new FederView(visDataAll, viewParams); + document.querySelector('#container').appendChild(federView.view.node); + + federView.view.render(); + // federView.view.test(); }); diff --git a/test_old/bundle.js b/test_old/bundle.js new file mode 100644 index 0000000..d2f739d --- /dev/null +++ b/test_old/bundle.js @@ -0,0 +1,18025 @@ +(() => { + var __create = Object.create; + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __getOwnPropSymbols = Object.getOwnPropertySymbols; + var __getProtoOf = Object.getPrototypeOf; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __propIsEnum = Object.prototype.propertyIsEnumerable; + var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; + var __spreadValues = (a2, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp.call(b, prop)) + __defNormalProp(a2, prop, b[prop]); + if (__getOwnPropSymbols) + for (var prop of __getOwnPropSymbols(b)) { + if (__propIsEnum.call(b, prop)) + __defNormalProp(a2, prop, b[prop]); + } + return a2; + }; + var __objRest = (source, exclude) => { + var target = {}; + for (var prop in source) + if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) + target[prop] = source[prop]; + if (source != null && __getOwnPropSymbols) + for (var prop of __getOwnPropSymbols(source)) { + if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) + target[prop] = source[prop]; + } + return target; + }; + var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); + var __async = (__this, __arguments, generator) => { + return new Promise((resolve, reject) => { + var fulfilled = (value) => { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + }; + var rejected = (value) => { + try { + step(generator.throw(value)); + } catch (e) { + reject(e); + } + }; + var step = (x3) => x3.done ? resolve(x3.value) : Promise.resolve(x3.value).then(fulfilled, rejected); + step((generator = generator.apply(__this, __arguments)).next()); + }); + }; + + // node_modules/umap-js/dist/utils.js + var require_utils = __commonJS({ + "node_modules/umap-js/dist/utils.js"(exports) { + "use strict"; + var __values = exports && exports.__values || function(o) { + var m2 = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m2) + return m2.call(o); + return { + next: function() { + if (o && i >= o.length) + o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + function tauRandInt(n, random) { + return Math.floor(random() * n); + } + exports.tauRandInt = tauRandInt; + function tauRand(random) { + return random(); + } + exports.tauRand = tauRand; + function norm(vec2) { + var e_1, _a; + var result = 0; + try { + for (var vec_1 = __values(vec2), vec_1_1 = vec_1.next(); !vec_1_1.done; vec_1_1 = vec_1.next()) { + var item = vec_1_1.value; + result += Math.pow(item, 2); + } + } catch (e_1_1) { + e_1 = { error: e_1_1 }; + } finally { + try { + if (vec_1_1 && !vec_1_1.done && (_a = vec_1.return)) + _a.call(vec_1); + } finally { + if (e_1) + throw e_1.error; + } + } + return Math.sqrt(result); + } + exports.norm = norm; + function empty2(n) { + var output = []; + for (var i = 0; i < n; i++) { + output.push(void 0); + } + return output; + } + exports.empty = empty2; + function range2(n) { + return empty2(n).map(function(_, i) { + return i; + }); + } + exports.range = range2; + function filled(n, v2) { + return empty2(n).map(function() { + return v2; + }); + } + exports.filled = filled; + function zeros(n) { + return filled(n, 0); + } + exports.zeros = zeros; + function ones(n) { + return filled(n, 1); + } + exports.ones = ones; + function linear3(a2, b, len) { + return empty2(len).map(function(_, i) { + return a2 + i * ((b - a2) / (len - 1)); + }); + } + exports.linear = linear3; + function sum2(input) { + return input.reduce(function(sum3, val) { + return sum3 + val; + }); + } + exports.sum = sum2; + function mean(input) { + return sum2(input) / input.length; + } + exports.mean = mean; + function max3(input) { + var max4 = 0; + for (var i = 0; i < input.length; i++) { + max4 = input[i] > max4 ? input[i] : max4; + } + return max4; + } + exports.max = max3; + function max2d(input) { + var max4 = 0; + for (var i = 0; i < input.length; i++) { + for (var j = 0; j < input[i].length; j++) { + max4 = input[i][j] > max4 ? input[i][j] : max4; + } + } + return max4; + } + exports.max2d = max2d; + function rejectionSample(nSamples, poolSize, random) { + var result = zeros(nSamples); + for (var i = 0; i < nSamples; i++) { + var rejectSample = true; + while (rejectSample) { + var j = tauRandInt(poolSize, random); + var broken = false; + for (var k = 0; k < i; k++) { + if (j === result[k]) { + broken = true; + break; + } + } + if (!broken) { + rejectSample = false; + } + result[i] = j; + } + } + return result; + } + exports.rejectionSample = rejectionSample; + function reshape2d(x3, a2, b) { + var rows = []; + var count = 0; + var index2 = 0; + if (x3.length !== a2 * b) { + throw new Error("Array dimensions must match input length."); + } + for (var i = 0; i < a2; i++) { + var col = []; + for (var j = 0; j < b; j++) { + col.push(x3[index2]); + index2 += 1; + } + rows.push(col); + count += 1; + } + return rows; + } + exports.reshape2d = reshape2d; + } + }); + + // node_modules/umap-js/dist/heap.js + var require_heap = __commonJS({ + "node_modules/umap-js/dist/heap.js"(exports) { + "use strict"; + var __importStar = exports && exports.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (Object.hasOwnProperty.call(mod, k)) + result[k] = mod[k]; + } + result["default"] = mod; + return result; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + var utils = __importStar(require_utils()); + function makeHeap(nPoints, size) { + var makeArrays = function(fillValue) { + return utils.empty(nPoints).map(function() { + return utils.filled(size, fillValue); + }); + }; + var heap = []; + heap.push(makeArrays(-1)); + heap.push(makeArrays(Infinity)); + heap.push(makeArrays(0)); + return heap; + } + exports.makeHeap = makeHeap; + function rejectionSample(nSamples, poolSize, random) { + var result = utils.zeros(nSamples); + for (var i = 0; i < nSamples; i++) { + var rejectSample = true; + var j = 0; + while (rejectSample) { + j = utils.tauRandInt(poolSize, random); + var broken = false; + for (var k = 0; k < i; k++) { + if (j === result[k]) { + broken = true; + break; + } + } + if (!broken) + rejectSample = false; + } + result[i] = j; + } + return result; + } + exports.rejectionSample = rejectionSample; + function heapPush(heap, row, weight, index2, flag) { + row = Math.floor(row); + var indices = heap[0][row]; + var weights = heap[1][row]; + var isNew = heap[2][row]; + if (weight >= weights[0]) { + return 0; + } + for (var i = 0; i < indices.length; i++) { + if (index2 === indices[i]) { + return 0; + } + } + return uncheckedHeapPush(heap, row, weight, index2, flag); + } + exports.heapPush = heapPush; + function uncheckedHeapPush(heap, row, weight, index2, flag) { + var indices = heap[0][row]; + var weights = heap[1][row]; + var isNew = heap[2][row]; + if (weight >= weights[0]) { + return 0; + } + weights[0] = weight; + indices[0] = index2; + isNew[0] = flag; + var i = 0; + var iSwap = 0; + while (true) { + var ic1 = 2 * i + 1; + var ic2 = ic1 + 1; + var heapShape2 = heap[0][0].length; + if (ic1 >= heapShape2) { + break; + } else if (ic2 >= heapShape2) { + if (weights[ic1] > weight) { + iSwap = ic1; + } else { + break; + } + } else if (weights[ic1] >= weights[ic2]) { + if (weight < weights[ic1]) { + iSwap = ic1; + } else { + break; + } + } else { + if (weight < weights[ic2]) { + iSwap = ic2; + } else { + break; + } + } + weights[i] = weights[iSwap]; + indices[i] = indices[iSwap]; + isNew[i] = isNew[iSwap]; + i = iSwap; + } + weights[i] = weight; + indices[i] = index2; + isNew[i] = flag; + return 1; + } + exports.uncheckedHeapPush = uncheckedHeapPush; + function buildCandidates(currentGraph, nVertices, nNeighbors, maxCandidates, random) { + var candidateNeighbors = makeHeap(nVertices, maxCandidates); + for (var i = 0; i < nVertices; i++) { + for (var j = 0; j < nNeighbors; j++) { + if (currentGraph[0][i][j] < 0) { + continue; + } + var idx = currentGraph[0][i][j]; + var isn = currentGraph[2][i][j]; + var d = utils.tauRand(random); + heapPush(candidateNeighbors, i, d, idx, isn); + heapPush(candidateNeighbors, idx, d, i, isn); + currentGraph[2][i][j] = 0; + } + } + return candidateNeighbors; + } + exports.buildCandidates = buildCandidates; + function deheapSort(heap) { + var indices = heap[0]; + var weights = heap[1]; + for (var i = 0; i < indices.length; i++) { + var indHeap = indices[i]; + var distHeap = weights[i]; + for (var j = 0; j < indHeap.length - 1; j++) { + var indHeapIndex = indHeap.length - j - 1; + var distHeapIndex = distHeap.length - j - 1; + var temp1 = indHeap[0]; + indHeap[0] = indHeap[indHeapIndex]; + indHeap[indHeapIndex] = temp1; + var temp2 = distHeap[0]; + distHeap[0] = distHeap[distHeapIndex]; + distHeap[distHeapIndex] = temp2; + siftDown(distHeap, indHeap, distHeapIndex, 0); + } + } + return { indices, weights }; + } + exports.deheapSort = deheapSort; + function siftDown(heap1, heap2, ceiling, elt) { + while (elt * 2 + 1 < ceiling) { + var leftChild = elt * 2 + 1; + var rightChild = leftChild + 1; + var swap2 = elt; + if (heap1[swap2] < heap1[leftChild]) { + swap2 = leftChild; + } + if (rightChild < ceiling && heap1[swap2] < heap1[rightChild]) { + swap2 = rightChild; + } + if (swap2 === elt) { + break; + } else { + var temp1 = heap1[elt]; + heap1[elt] = heap1[swap2]; + heap1[swap2] = temp1; + var temp2 = heap2[elt]; + heap2[elt] = heap2[swap2]; + heap2[swap2] = temp2; + elt = swap2; + } + } + } + function smallestFlagged(heap, row) { + var ind = heap[0][row]; + var dist4 = heap[1][row]; + var flag = heap[2][row]; + var minDist = Infinity; + var resultIndex = -1; + for (var i = 0; i > ind.length; i++) { + if (flag[i] === 1 && dist4[i] < minDist) { + minDist = dist4[i]; + resultIndex = i; + } + } + if (resultIndex >= 0) { + flag[resultIndex] = 0; + return Math.floor(ind[resultIndex]); + } else { + return -1; + } + } + exports.smallestFlagged = smallestFlagged; + } + }); + + // node_modules/umap-js/dist/matrix.js + var require_matrix = __commonJS({ + "node_modules/umap-js/dist/matrix.js"(exports) { + "use strict"; + var __read = exports && exports.__read || function(o, n) { + var m2 = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m2) + return o; + var i = m2.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) + ar.push(r.value); + } catch (error) { + e = { error }; + } finally { + try { + if (r && !r.done && (m2 = i["return"])) + m2.call(i); + } finally { + if (e) + throw e.error; + } + } + return ar; + }; + var __values = exports && exports.__values || function(o) { + var m2 = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m2) + return m2.call(o); + return { + next: function() { + if (o && i >= o.length) + o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + }; + var __importStar = exports && exports.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (Object.hasOwnProperty.call(mod, k)) + result[k] = mod[k]; + } + result["default"] = mod; + return result; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + var _a; + var utils = __importStar(require_utils()); + var SparseMatrix = function() { + function SparseMatrix2(rows, cols, values, dims) { + this.entries = /* @__PURE__ */ new Map(); + this.nRows = 0; + this.nCols = 0; + if (rows.length !== cols.length || rows.length !== values.length) { + throw new Error("rows, cols and values arrays must all have the same length"); + } + this.nRows = dims[0]; + this.nCols = dims[1]; + for (var i = 0; i < values.length; i++) { + var row = rows[i]; + var col = cols[i]; + this.checkDims(row, col); + var key = this.makeKey(row, col); + this.entries.set(key, { value: values[i], row, col }); + } + } + SparseMatrix2.prototype.makeKey = function(row, col) { + return row + ":" + col; + }; + SparseMatrix2.prototype.checkDims = function(row, col) { + var withinBounds = row < this.nRows && col < this.nCols; + if (!withinBounds) { + throw new Error("row and/or col specified outside of matrix dimensions"); + } + }; + SparseMatrix2.prototype.set = function(row, col, value) { + this.checkDims(row, col); + var key = this.makeKey(row, col); + if (!this.entries.has(key)) { + this.entries.set(key, { value, row, col }); + } else { + this.entries.get(key).value = value; + } + }; + SparseMatrix2.prototype.get = function(row, col, defaultValue) { + if (defaultValue === void 0) { + defaultValue = 0; + } + this.checkDims(row, col); + var key = this.makeKey(row, col); + if (this.entries.has(key)) { + return this.entries.get(key).value; + } else { + return defaultValue; + } + }; + SparseMatrix2.prototype.getAll = function(ordered) { + if (ordered === void 0) { + ordered = true; + } + var rowColValues = []; + this.entries.forEach(function(value) { + rowColValues.push(value); + }); + if (ordered) { + rowColValues.sort(function(a2, b) { + if (a2.row === b.row) { + return a2.col - b.col; + } else { + return a2.row - b.row; + } + }); + } + return rowColValues; + }; + SparseMatrix2.prototype.getDims = function() { + return [this.nRows, this.nCols]; + }; + SparseMatrix2.prototype.getRows = function() { + return Array.from(this.entries, function(_a2) { + var _b = __read(_a2, 2), key = _b[0], value = _b[1]; + return value.row; + }); + }; + SparseMatrix2.prototype.getCols = function() { + return Array.from(this.entries, function(_a2) { + var _b = __read(_a2, 2), key = _b[0], value = _b[1]; + return value.col; + }); + }; + SparseMatrix2.prototype.getValues = function() { + return Array.from(this.entries, function(_a2) { + var _b = __read(_a2, 2), key = _b[0], value = _b[1]; + return value.value; + }); + }; + SparseMatrix2.prototype.forEach = function(fn) { + this.entries.forEach(function(value) { + return fn(value.value, value.row, value.col); + }); + }; + SparseMatrix2.prototype.map = function(fn) { + var vals = []; + this.entries.forEach(function(value) { + vals.push(fn(value.value, value.row, value.col)); + }); + var dims = [this.nRows, this.nCols]; + return new SparseMatrix2(this.getRows(), this.getCols(), vals, dims); + }; + SparseMatrix2.prototype.toArray = function() { + var _this = this; + var rows = utils.empty(this.nRows); + var output = rows.map(function() { + return utils.zeros(_this.nCols); + }); + this.entries.forEach(function(value) { + output[value.row][value.col] = value.value; + }); + return output; + }; + return SparseMatrix2; + }(); + exports.SparseMatrix = SparseMatrix; + function transpose(matrix) { + var cols = []; + var rows = []; + var vals = []; + matrix.forEach(function(value, row, col) { + cols.push(row); + rows.push(col); + vals.push(value); + }); + var dims = [matrix.nCols, matrix.nRows]; + return new SparseMatrix(rows, cols, vals, dims); + } + exports.transpose = transpose; + function identity4(size) { + var _a2 = __read(size, 1), rows = _a2[0]; + var matrix = new SparseMatrix([], [], [], size); + for (var i = 0; i < rows; i++) { + matrix.set(i, i, 1); + } + return matrix; + } + exports.identity = identity4; + function pairwiseMultiply(a2, b) { + return elementWise(a2, b, function(x3, y4) { + return x3 * y4; + }); + } + exports.pairwiseMultiply = pairwiseMultiply; + function add2(a2, b) { + return elementWise(a2, b, function(x3, y4) { + return x3 + y4; + }); + } + exports.add = add2; + function subtract(a2, b) { + return elementWise(a2, b, function(x3, y4) { + return x3 - y4; + }); + } + exports.subtract = subtract; + function maximum(a2, b) { + return elementWise(a2, b, function(x3, y4) { + return x3 > y4 ? x3 : y4; + }); + } + exports.maximum = maximum; + function multiplyScalar(a2, scalar) { + return a2.map(function(value) { + return value * scalar; + }); + } + exports.multiplyScalar = multiplyScalar; + function eliminateZeros(m2) { + var zeroIndices = /* @__PURE__ */ new Set(); + var values = m2.getValues(); + var rows = m2.getRows(); + var cols = m2.getCols(); + for (var i = 0; i < values.length; i++) { + if (values[i] === 0) { + zeroIndices.add(i); + } + } + var removeByZeroIndex = function(_, index2) { + return !zeroIndices.has(index2); + }; + var nextValues = values.filter(removeByZeroIndex); + var nextRows = rows.filter(removeByZeroIndex); + var nextCols = cols.filter(removeByZeroIndex); + return new SparseMatrix(nextRows, nextCols, nextValues, m2.getDims()); + } + exports.eliminateZeros = eliminateZeros; + function normalize2(m2, normType) { + if (normType === void 0) { + normType = "l2"; + } + var e_1, _a2; + var normFn = normFns[normType]; + var colsByRow = /* @__PURE__ */ new Map(); + m2.forEach(function(_, row2, col) { + var cols = colsByRow.get(row2) || []; + cols.push(col); + colsByRow.set(row2, cols); + }); + var nextMatrix = new SparseMatrix([], [], [], m2.getDims()); + var _loop_1 = function(row2) { + var cols = colsByRow.get(row2).sort(); + var vals = cols.map(function(col) { + return m2.get(row2, col); + }); + var norm = normFn(vals); + for (var i = 0; i < norm.length; i++) { + nextMatrix.set(row2, cols[i], norm[i]); + } + }; + try { + for (var _b = __values(colsByRow.keys()), _c = _b.next(); !_c.done; _c = _b.next()) { + var row = _c.value; + _loop_1(row); + } + } catch (e_1_1) { + e_1 = { error: e_1_1 }; + } finally { + try { + if (_c && !_c.done && (_a2 = _b.return)) + _a2.call(_b); + } finally { + if (e_1) + throw e_1.error; + } + } + return nextMatrix; + } + exports.normalize = normalize2; + var normFns = (_a = {}, _a["max"] = function(xs) { + var max3 = -Infinity; + for (var i = 0; i < xs.length; i++) { + max3 = xs[i] > max3 ? xs[i] : max3; + } + return xs.map(function(x3) { + return x3 / max3; + }); + }, _a["l1"] = function(xs) { + var sum2 = 0; + for (var i = 0; i < xs.length; i++) { + sum2 += xs[i]; + } + return xs.map(function(x3) { + return x3 / sum2; + }); + }, _a["l2"] = function(xs) { + var sum2 = 0; + for (var i = 0; i < xs.length; i++) { + sum2 += Math.pow(xs[i], 2); + } + return xs.map(function(x3) { + return Math.sqrt(Math.pow(x3, 2) / sum2); + }); + }, _a); + function elementWise(a2, b, op) { + var visited = /* @__PURE__ */ new Set(); + var rows = []; + var cols = []; + var vals = []; + var operate = function(row2, col2) { + rows.push(row2); + cols.push(col2); + var nextValue = op(a2.get(row2, col2), b.get(row2, col2)); + vals.push(nextValue); + }; + var valuesA = a2.getValues(); + var rowsA = a2.getRows(); + var colsA = a2.getCols(); + for (var i = 0; i < valuesA.length; i++) { + var row = rowsA[i]; + var col = colsA[i]; + var key = row + ":" + col; + visited.add(key); + operate(row, col); + } + var valuesB = b.getValues(); + var rowsB = b.getRows(); + var colsB = b.getCols(); + for (var i = 0; i < valuesB.length; i++) { + var row = rowsB[i]; + var col = colsB[i]; + var key = row + ":" + col; + if (visited.has(key)) + continue; + operate(row, col); + } + var dims = [a2.nRows, a2.nCols]; + return new SparseMatrix(rows, cols, vals, dims); + } + function getCSR(x3) { + var entries = []; + x3.forEach(function(value2, row2, col2) { + entries.push({ value: value2, row: row2, col: col2 }); + }); + entries.sort(function(a2, b) { + if (a2.row === b.row) { + return a2.col - b.col; + } else { + return a2.row - b.row; + } + }); + var indices = []; + var values = []; + var indptr = []; + var currentRow = -1; + for (var i = 0; i < entries.length; i++) { + var _a2 = entries[i], row = _a2.row, col = _a2.col, value = _a2.value; + if (row !== currentRow) { + currentRow = row; + indptr.push(i); + } + indices.push(col); + values.push(value); + } + return { indices, values, indptr }; + } + exports.getCSR = getCSR; + } + }); + + // node_modules/umap-js/dist/tree.js + var require_tree = __commonJS({ + "node_modules/umap-js/dist/tree.js"(exports) { + "use strict"; + var __read = exports && exports.__read || function(o, n) { + var m2 = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m2) + return o; + var i = m2.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) + ar.push(r.value); + } catch (error) { + e = { error }; + } finally { + try { + if (r && !r.done && (m2 = i["return"])) + m2.call(i); + } finally { + if (e) + throw e.error; + } + } + return ar; + }; + var __spread = exports && exports.__spread || function() { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; + }; + var __values = exports && exports.__values || function(o) { + var m2 = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m2) + return m2.call(o); + return { + next: function() { + if (o && i >= o.length) + o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + }; + var __importStar = exports && exports.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (Object.hasOwnProperty.call(mod, k)) + result[k] = mod[k]; + } + result["default"] = mod; + return result; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + var utils = __importStar(require_utils()); + var FlatTree = function() { + function FlatTree2(hyperplanes, offsets, children2, indices) { + this.hyperplanes = hyperplanes; + this.offsets = offsets; + this.children = children2; + this.indices = indices; + } + return FlatTree2; + }(); + exports.FlatTree = FlatTree; + function makeForest(data, nNeighbors, nTrees, random) { + var leafSize = Math.max(10, nNeighbors); + var trees = utils.range(nTrees).map(function(_, i) { + return makeTree(data, leafSize, i, random); + }); + var forest = trees.map(function(tree) { + return flattenTree(tree, leafSize); + }); + return forest; + } + exports.makeForest = makeForest; + function makeTree(data, leafSize, n, random) { + if (leafSize === void 0) { + leafSize = 30; + } + var indices = utils.range(data.length); + var tree = makeEuclideanTree(data, indices, leafSize, n, random); + return tree; + } + function makeEuclideanTree(data, indices, leafSize, q, random) { + if (leafSize === void 0) { + leafSize = 30; + } + if (indices.length > leafSize) { + var splitResults = euclideanRandomProjectionSplit(data, indices, random); + var indicesLeft = splitResults.indicesLeft, indicesRight = splitResults.indicesRight, hyperplane = splitResults.hyperplane, offset = splitResults.offset; + var leftChild = makeEuclideanTree(data, indicesLeft, leafSize, q + 1, random); + var rightChild = makeEuclideanTree(data, indicesRight, leafSize, q + 1, random); + var node = { leftChild, rightChild, isLeaf: false, hyperplane, offset }; + return node; + } else { + var node = { indices, isLeaf: true }; + return node; + } + } + function euclideanRandomProjectionSplit(data, indices, random) { + var dim = data[0].length; + var leftIndex = utils.tauRandInt(indices.length, random); + var rightIndex = utils.tauRandInt(indices.length, random); + rightIndex += leftIndex === rightIndex ? 1 : 0; + rightIndex = rightIndex % indices.length; + var left = indices[leftIndex]; + var right = indices[rightIndex]; + var hyperplaneOffset = 0; + var hyperplaneVector = utils.zeros(dim); + for (var i = 0; i < hyperplaneVector.length; i++) { + hyperplaneVector[i] = data[left][i] - data[right][i]; + hyperplaneOffset -= hyperplaneVector[i] * (data[left][i] + data[right][i]) / 2; + } + var nLeft = 0; + var nRight = 0; + var side = utils.zeros(indices.length); + for (var i = 0; i < indices.length; i++) { + var margin = hyperplaneOffset; + for (var d = 0; d < dim; d++) { + margin += hyperplaneVector[d] * data[indices[i]][d]; + } + if (margin === 0) { + side[i] = utils.tauRandInt(2, random); + if (side[i] === 0) { + nLeft += 1; + } else { + nRight += 1; + } + } else if (margin > 0) { + side[i] = 0; + nLeft += 1; + } else { + side[i] = 1; + nRight += 1; + } + } + var indicesLeft = utils.zeros(nLeft); + var indicesRight = utils.zeros(nRight); + nLeft = 0; + nRight = 0; + for (var i = 0; i < side.length; i++) { + if (side[i] === 0) { + indicesLeft[nLeft] = indices[i]; + nLeft += 1; + } else { + indicesRight[nRight] = indices[i]; + nRight += 1; + } + } + return { + indicesLeft, + indicesRight, + hyperplane: hyperplaneVector, + offset: hyperplaneOffset + }; + } + function flattenTree(tree, leafSize) { + var nNodes = numNodes(tree); + var nLeaves = numLeaves(tree); + var hyperplanes = utils.range(nNodes).map(function() { + return utils.zeros(tree.hyperplane ? tree.hyperplane.length : 0); + }); + var offsets = utils.zeros(nNodes); + var children2 = utils.range(nNodes).map(function() { + return [-1, -1]; + }); + var indices = utils.range(nLeaves).map(function() { + return utils.range(leafSize).map(function() { + return -1; + }); + }); + recursiveFlatten(tree, hyperplanes, offsets, children2, indices, 0, 0); + return new FlatTree(hyperplanes, offsets, children2, indices); + } + function recursiveFlatten(tree, hyperplanes, offsets, children2, indices, nodeNum, leafNum) { + var _a; + if (tree.isLeaf) { + children2[nodeNum][0] = -leafNum; + (_a = indices[leafNum]).splice.apply(_a, __spread([0, tree.indices.length], tree.indices)); + leafNum += 1; + return { nodeNum, leafNum }; + } else { + hyperplanes[nodeNum] = tree.hyperplane; + offsets[nodeNum] = tree.offset; + children2[nodeNum][0] = nodeNum + 1; + var oldNodeNum = nodeNum; + var res = recursiveFlatten(tree.leftChild, hyperplanes, offsets, children2, indices, nodeNum + 1, leafNum); + nodeNum = res.nodeNum; + leafNum = res.leafNum; + children2[oldNodeNum][1] = nodeNum + 1; + res = recursiveFlatten(tree.rightChild, hyperplanes, offsets, children2, indices, nodeNum + 1, leafNum); + return { nodeNum: res.nodeNum, leafNum: res.leafNum }; + } + } + function numNodes(tree) { + if (tree.isLeaf) { + return 1; + } else { + return 1 + numNodes(tree.leftChild) + numNodes(tree.rightChild); + } + } + function numLeaves(tree) { + if (tree.isLeaf) { + return 1; + } else { + return numLeaves(tree.leftChild) + numLeaves(tree.rightChild); + } + } + function makeLeafArray(rpForest) { + var e_1, _a; + if (rpForest.length > 0) { + var output = []; + try { + for (var rpForest_1 = __values(rpForest), rpForest_1_1 = rpForest_1.next(); !rpForest_1_1.done; rpForest_1_1 = rpForest_1.next()) { + var tree = rpForest_1_1.value; + output.push.apply(output, __spread(tree.indices)); + } + } catch (e_1_1) { + e_1 = { error: e_1_1 }; + } finally { + try { + if (rpForest_1_1 && !rpForest_1_1.done && (_a = rpForest_1.return)) + _a.call(rpForest_1); + } finally { + if (e_1) + throw e_1.error; + } + } + return output; + } else { + return [[-1]]; + } + } + exports.makeLeafArray = makeLeafArray; + function selectSide(hyperplane, offset, point, random) { + var margin = offset; + for (var d = 0; d < point.length; d++) { + margin += hyperplane[d] * point[d]; + } + if (margin === 0) { + var side = utils.tauRandInt(2, random); + return side; + } else if (margin > 0) { + return 0; + } else { + return 1; + } + } + function searchFlatTree(point, tree, random) { + var node = 0; + while (tree.children[node][0] > 0) { + var side = selectSide(tree.hyperplanes[node], tree.offsets[node], point, random); + if (side === 0) { + node = tree.children[node][0]; + } else { + node = tree.children[node][1]; + } + } + var index2 = -1 * tree.children[node][0]; + return tree.indices[index2]; + } + exports.searchFlatTree = searchFlatTree; + } + }); + + // node_modules/umap-js/dist/nn_descent.js + var require_nn_descent = __commonJS({ + "node_modules/umap-js/dist/nn_descent.js"(exports) { + "use strict"; + var __values = exports && exports.__values || function(o) { + var m2 = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m2) + return m2.call(o); + return { + next: function() { + if (o && i >= o.length) + o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + }; + var __importStar = exports && exports.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (Object.hasOwnProperty.call(mod, k)) + result[k] = mod[k]; + } + result["default"] = mod; + return result; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + var heap = __importStar(require_heap()); + var matrix = __importStar(require_matrix()); + var tree = __importStar(require_tree()); + var utils = __importStar(require_utils()); + function makeNNDescent(distanceFn, random) { + return function nNDescent(data, leafArray, nNeighbors, nIters, maxCandidates, delta, rho, rpTreeInit) { + if (nIters === void 0) { + nIters = 10; + } + if (maxCandidates === void 0) { + maxCandidates = 50; + } + if (delta === void 0) { + delta = 1e-3; + } + if (rho === void 0) { + rho = 0.5; + } + if (rpTreeInit === void 0) { + rpTreeInit = true; + } + var nVertices = data.length; + var currentGraph = heap.makeHeap(data.length, nNeighbors); + for (var i = 0; i < data.length; i++) { + var indices = heap.rejectionSample(nNeighbors, data.length, random); + for (var j = 0; j < indices.length; j++) { + var d = distanceFn(data[i], data[indices[j]]); + heap.heapPush(currentGraph, i, d, indices[j], 1); + heap.heapPush(currentGraph, indices[j], d, i, 1); + } + } + if (rpTreeInit) { + for (var n = 0; n < leafArray.length; n++) { + for (var i = 0; i < leafArray[n].length; i++) { + if (leafArray[n][i] < 0) { + break; + } + for (var j = i + 1; j < leafArray[n].length; j++) { + if (leafArray[n][j] < 0) { + break; + } + var d = distanceFn(data[leafArray[n][i]], data[leafArray[n][j]]); + heap.heapPush(currentGraph, leafArray[n][i], d, leafArray[n][j], 1); + heap.heapPush(currentGraph, leafArray[n][j], d, leafArray[n][i], 1); + } + } + } + } + for (var n = 0; n < nIters; n++) { + var candidateNeighbors = heap.buildCandidates(currentGraph, nVertices, nNeighbors, maxCandidates, random); + var c2 = 0; + for (var i = 0; i < nVertices; i++) { + for (var j = 0; j < maxCandidates; j++) { + var p = Math.floor(candidateNeighbors[0][i][j]); + if (p < 0 || utils.tauRand(random) < rho) { + continue; + } + for (var k = 0; k < maxCandidates; k++) { + var q = Math.floor(candidateNeighbors[0][i][k]); + var cj = candidateNeighbors[2][i][j]; + var ck = candidateNeighbors[2][i][k]; + if (q < 0 || !cj && !ck) { + continue; + } + var d = distanceFn(data[p], data[q]); + c2 += heap.heapPush(currentGraph, p, d, q, 1); + c2 += heap.heapPush(currentGraph, q, d, p, 1); + } + } + } + if (c2 <= delta * nNeighbors * data.length) { + break; + } + } + var sorted = heap.deheapSort(currentGraph); + return sorted; + }; + } + exports.makeNNDescent = makeNNDescent; + function makeInitializations(distanceFn) { + function initFromRandom(nNeighbors, data, queryPoints, _heap, random) { + for (var i = 0; i < queryPoints.length; i++) { + var indices = utils.rejectionSample(nNeighbors, data.length, random); + for (var j = 0; j < indices.length; j++) { + if (indices[j] < 0) { + continue; + } + var d = distanceFn(data[indices[j]], queryPoints[i]); + heap.heapPush(_heap, i, d, indices[j], 1); + } + } + } + function initFromTree(_tree, data, queryPoints, _heap, random) { + for (var i = 0; i < queryPoints.length; i++) { + var indices = tree.searchFlatTree(queryPoints[i], _tree, random); + for (var j = 0; j < indices.length; j++) { + if (indices[j] < 0) { + return; + } + var d = distanceFn(data[indices[j]], queryPoints[i]); + heap.heapPush(_heap, i, d, indices[j], 1); + } + } + return; + } + return { initFromRandom, initFromTree }; + } + exports.makeInitializations = makeInitializations; + function makeInitializedNNSearch(distanceFn) { + return function nnSearchFn(data, graph, initialization, queryPoints) { + var e_1, _a; + var _b = matrix.getCSR(graph), indices = _b.indices, indptr = _b.indptr; + for (var i = 0; i < queryPoints.length; i++) { + var tried = new Set(initialization[0][i]); + while (true) { + var vertex = heap.smallestFlagged(initialization, i); + if (vertex === -1) { + break; + } + var candidates = indices.slice(indptr[vertex], indptr[vertex + 1]); + try { + for (var candidates_1 = __values(candidates), candidates_1_1 = candidates_1.next(); !candidates_1_1.done; candidates_1_1 = candidates_1.next()) { + var candidate = candidates_1_1.value; + if (candidate === vertex || candidate === -1 || tried.has(candidate)) { + continue; + } + var d = distanceFn(data[candidate], queryPoints[i]); + heap.uncheckedHeapPush(initialization, i, d, candidate, 1); + tried.add(candidate); + } + } catch (e_1_1) { + e_1 = { error: e_1_1 }; + } finally { + try { + if (candidates_1_1 && !candidates_1_1.done && (_a = candidates_1.return)) + _a.call(candidates_1); + } finally { + if (e_1) + throw e_1.error; + } + } + } + } + return initialization; + }; + } + exports.makeInitializedNNSearch = makeInitializedNNSearch; + function initializeSearch(forest, data, queryPoints, nNeighbors, initFromRandom, initFromTree, random) { + var e_2, _a; + var results = heap.makeHeap(queryPoints.length, nNeighbors); + initFromRandom(nNeighbors, data, queryPoints, results, random); + if (forest) { + try { + for (var forest_1 = __values(forest), forest_1_1 = forest_1.next(); !forest_1_1.done; forest_1_1 = forest_1.next()) { + var tree_1 = forest_1_1.value; + initFromTree(tree_1, data, queryPoints, results, random); + } + } catch (e_2_1) { + e_2 = { error: e_2_1 }; + } finally { + try { + if (forest_1_1 && !forest_1_1.done && (_a = forest_1.return)) + _a.call(forest_1); + } finally { + if (e_2) + throw e_2.error; + } + } + } + return results; + } + exports.initializeSearch = initializeSearch; + } + }); + + // node_modules/ml-levenberg-marquardt/node_modules/is-any-array/lib/index.js + var require_lib = __commonJS({ + "node_modules/ml-levenberg-marquardt/node_modules/is-any-array/lib/index.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var toString = Object.prototype.toString; + function isAnyArray(object) { + return toString.call(object).endsWith("Array]"); + } + exports.default = isAnyArray; + } + }); + + // node_modules/is-any-array/lib/index.js + var require_lib2 = __commonJS({ + "node_modules/is-any-array/lib/index.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.isAnyArray = void 0; + var toString = Object.prototype.toString; + function isAnyArray(value) { + return toString.call(value).endsWith("Array]"); + } + exports.isAnyArray = isAnyArray; + } + }); + + // node_modules/ml-array-max/lib/index.js + var require_lib3 = __commonJS({ + "node_modules/ml-array-max/lib/index.js"(exports, module) { + "use strict"; + var isAnyArray = require_lib2(); + function max3(input, options = {}) { + if (!isAnyArray.isAnyArray(input)) { + throw new TypeError("input must be an array"); + } + if (input.length === 0) { + throw new TypeError("input must not be empty"); + } + const { fromIndex = 0, toIndex = input.length } = options; + if (fromIndex < 0 || fromIndex >= input.length || !Number.isInteger(fromIndex)) { + throw new Error("fromIndex must be a positive integer smaller than length"); + } + if (toIndex <= fromIndex || toIndex > input.length || !Number.isInteger(toIndex)) { + throw new Error("toIndex must be an integer greater than fromIndex and at most equal to length"); + } + let maxValue = input[fromIndex]; + for (let i = fromIndex + 1; i < toIndex; i++) { + if (input[i] > maxValue) + maxValue = input[i]; + } + return maxValue; + } + module.exports = max3; + } + }); + + // node_modules/ml-array-min/lib/index.js + var require_lib4 = __commonJS({ + "node_modules/ml-array-min/lib/index.js"(exports, module) { + "use strict"; + var isAnyArray = require_lib2(); + function min3(input, options = {}) { + if (!isAnyArray.isAnyArray(input)) { + throw new TypeError("input must be an array"); + } + if (input.length === 0) { + throw new TypeError("input must not be empty"); + } + const { fromIndex = 0, toIndex = input.length } = options; + if (fromIndex < 0 || fromIndex >= input.length || !Number.isInteger(fromIndex)) { + throw new Error("fromIndex must be a positive integer smaller than length"); + } + if (toIndex <= fromIndex || toIndex > input.length || !Number.isInteger(toIndex)) { + throw new Error("toIndex must be an integer greater than fromIndex and at most equal to length"); + } + let minValue = input[fromIndex]; + for (let i = fromIndex + 1; i < toIndex; i++) { + if (input[i] < minValue) + minValue = input[i]; + } + return minValue; + } + module.exports = min3; + } + }); + + // node_modules/ml-array-rescale/lib/index.js + var require_lib5 = __commonJS({ + "node_modules/ml-array-rescale/lib/index.js"(exports, module) { + "use strict"; + var isAnyArray = require_lib2(); + var max3 = require_lib3(); + var min3 = require_lib4(); + function _interopDefaultLegacy(e) { + return e && typeof e === "object" && "default" in e ? e : { "default": e }; + } + var max__default = /* @__PURE__ */ _interopDefaultLegacy(max3); + var min__default = /* @__PURE__ */ _interopDefaultLegacy(min3); + function rescale(input, options = {}) { + if (!isAnyArray.isAnyArray(input)) { + throw new TypeError("input must be an array"); + } else if (input.length === 0) { + throw new TypeError("input must not be empty"); + } + let output; + if (options.output !== void 0) { + if (!isAnyArray.isAnyArray(options.output)) { + throw new TypeError("output option must be an array if specified"); + } + output = options.output; + } else { + output = new Array(input.length); + } + const currentMin = min__default["default"](input); + const currentMax = max__default["default"](input); + if (currentMin === currentMax) { + throw new RangeError("minimum and maximum input values are equal. Cannot rescale a constant array"); + } + const { + min: minValue = options.autoMinMax ? currentMin : 0, + max: maxValue = options.autoMinMax ? currentMax : 1 + } = options; + if (minValue >= maxValue) { + throw new RangeError("min option must be smaller than max option"); + } + const factor = (maxValue - minValue) / (currentMax - currentMin); + for (let i = 0; i < input.length; i++) { + output[i] = (input[i] - currentMin) * factor + minValue; + } + return output; + } + module.exports = rescale; + } + }); + + // node_modules/ml-matrix/matrix.js + var require_matrix2 = __commonJS({ + "node_modules/ml-matrix/matrix.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var isAnyArray = require_lib2(); + var rescale = require_lib5(); + function _interopDefaultLegacy(e) { + return e && typeof e === "object" && "default" in e ? e : { "default": e }; + } + var rescale__default = /* @__PURE__ */ _interopDefaultLegacy(rescale); + var indent = " ".repeat(2); + var indentData = " ".repeat(4); + function inspectMatrix() { + return inspectMatrixWithOptions(this); + } + function inspectMatrixWithOptions(matrix, options = {}) { + const { maxRows = 15, maxColumns = 10, maxNumSize = 8 } = options; + return `${matrix.constructor.name} { +${indent}[ +${indentData}${inspectData(matrix, maxRows, maxColumns, maxNumSize)} +${indent}] +${indent}rows: ${matrix.rows} +${indent}columns: ${matrix.columns} +}`; + } + function inspectData(matrix, maxRows, maxColumns, maxNumSize) { + const { rows, columns } = matrix; + const maxI = Math.min(rows, maxRows); + const maxJ = Math.min(columns, maxColumns); + const result = []; + for (let i = 0; i < maxI; i++) { + let line = []; + for (let j = 0; j < maxJ; j++) { + line.push(formatNumber(matrix.get(i, j), maxNumSize)); + } + result.push(`${line.join(" ")}`); + } + if (maxJ !== columns) { + result[result.length - 1] += ` ... ${columns - maxColumns} more columns`; + } + if (maxI !== rows) { + result.push(`... ${rows - maxRows} more rows`); + } + return result.join(` +${indentData}`); + } + function formatNumber(num, maxNumSize) { + const numStr = String(num); + if (numStr.length <= maxNumSize) { + return numStr.padEnd(maxNumSize, " "); + } + const precise = num.toPrecision(maxNumSize - 2); + if (precise.length <= maxNumSize) { + return precise; + } + const exponential2 = num.toExponential(maxNumSize - 2); + const eIndex = exponential2.indexOf("e"); + const e = exponential2.slice(eIndex); + return exponential2.slice(0, maxNumSize - e.length) + e; + } + function installMathOperations(AbstractMatrix2, Matrix2) { + AbstractMatrix2.prototype.add = function add2(value) { + if (typeof value === "number") + return this.addS(value); + return this.addM(value); + }; + AbstractMatrix2.prototype.addS = function addS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) + value); + } + } + return this; + }; + AbstractMatrix2.prototype.addM = function addM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) + matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.add = function add2(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.add(value); + }; + AbstractMatrix2.prototype.sub = function sub(value) { + if (typeof value === "number") + return this.subS(value); + return this.subM(value); + }; + AbstractMatrix2.prototype.subS = function subS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) - value); + } + } + return this; + }; + AbstractMatrix2.prototype.subM = function subM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) - matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.sub = function sub(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.sub(value); + }; + AbstractMatrix2.prototype.subtract = AbstractMatrix2.prototype.sub; + AbstractMatrix2.prototype.subtractS = AbstractMatrix2.prototype.subS; + AbstractMatrix2.prototype.subtractM = AbstractMatrix2.prototype.subM; + AbstractMatrix2.subtract = AbstractMatrix2.sub; + AbstractMatrix2.prototype.mul = function mul(value) { + if (typeof value === "number") + return this.mulS(value); + return this.mulM(value); + }; + AbstractMatrix2.prototype.mulS = function mulS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) * value); + } + } + return this; + }; + AbstractMatrix2.prototype.mulM = function mulM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) * matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.mul = function mul(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.mul(value); + }; + AbstractMatrix2.prototype.multiply = AbstractMatrix2.prototype.mul; + AbstractMatrix2.prototype.multiplyS = AbstractMatrix2.prototype.mulS; + AbstractMatrix2.prototype.multiplyM = AbstractMatrix2.prototype.mulM; + AbstractMatrix2.multiply = AbstractMatrix2.mul; + AbstractMatrix2.prototype.div = function div(value) { + if (typeof value === "number") + return this.divS(value); + return this.divM(value); + }; + AbstractMatrix2.prototype.divS = function divS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) / value); + } + } + return this; + }; + AbstractMatrix2.prototype.divM = function divM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) / matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.div = function div(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.div(value); + }; + AbstractMatrix2.prototype.divide = AbstractMatrix2.prototype.div; + AbstractMatrix2.prototype.divideS = AbstractMatrix2.prototype.divS; + AbstractMatrix2.prototype.divideM = AbstractMatrix2.prototype.divM; + AbstractMatrix2.divide = AbstractMatrix2.div; + AbstractMatrix2.prototype.mod = function mod(value) { + if (typeof value === "number") + return this.modS(value); + return this.modM(value); + }; + AbstractMatrix2.prototype.modS = function modS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) % value); + } + } + return this; + }; + AbstractMatrix2.prototype.modM = function modM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) % matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.mod = function mod(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.mod(value); + }; + AbstractMatrix2.prototype.modulus = AbstractMatrix2.prototype.mod; + AbstractMatrix2.prototype.modulusS = AbstractMatrix2.prototype.modS; + AbstractMatrix2.prototype.modulusM = AbstractMatrix2.prototype.modM; + AbstractMatrix2.modulus = AbstractMatrix2.mod; + AbstractMatrix2.prototype.and = function and(value) { + if (typeof value === "number") + return this.andS(value); + return this.andM(value); + }; + AbstractMatrix2.prototype.andS = function andS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) & value); + } + } + return this; + }; + AbstractMatrix2.prototype.andM = function andM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) & matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.and = function and(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.and(value); + }; + AbstractMatrix2.prototype.or = function or(value) { + if (typeof value === "number") + return this.orS(value); + return this.orM(value); + }; + AbstractMatrix2.prototype.orS = function orS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) | value); + } + } + return this; + }; + AbstractMatrix2.prototype.orM = function orM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) | matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.or = function or(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.or(value); + }; + AbstractMatrix2.prototype.xor = function xor(value) { + if (typeof value === "number") + return this.xorS(value); + return this.xorM(value); + }; + AbstractMatrix2.prototype.xorS = function xorS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) ^ value); + } + } + return this; + }; + AbstractMatrix2.prototype.xorM = function xorM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) ^ matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.xor = function xor(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.xor(value); + }; + AbstractMatrix2.prototype.leftShift = function leftShift(value) { + if (typeof value === "number") + return this.leftShiftS(value); + return this.leftShiftM(value); + }; + AbstractMatrix2.prototype.leftShiftS = function leftShiftS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) << value); + } + } + return this; + }; + AbstractMatrix2.prototype.leftShiftM = function leftShiftM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) << matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.leftShift = function leftShift(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.leftShift(value); + }; + AbstractMatrix2.prototype.signPropagatingRightShift = function signPropagatingRightShift(value) { + if (typeof value === "number") + return this.signPropagatingRightShiftS(value); + return this.signPropagatingRightShiftM(value); + }; + AbstractMatrix2.prototype.signPropagatingRightShiftS = function signPropagatingRightShiftS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) >> value); + } + } + return this; + }; + AbstractMatrix2.prototype.signPropagatingRightShiftM = function signPropagatingRightShiftM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) >> matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.signPropagatingRightShift = function signPropagatingRightShift(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.signPropagatingRightShift(value); + }; + AbstractMatrix2.prototype.rightShift = function rightShift(value) { + if (typeof value === "number") + return this.rightShiftS(value); + return this.rightShiftM(value); + }; + AbstractMatrix2.prototype.rightShiftS = function rightShiftS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) >>> value); + } + } + return this; + }; + AbstractMatrix2.prototype.rightShiftM = function rightShiftM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) >>> matrix.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.rightShift = function rightShift(matrix, value) { + const newMatrix = new Matrix2(matrix); + return newMatrix.rightShift(value); + }; + AbstractMatrix2.prototype.zeroFillRightShift = AbstractMatrix2.prototype.rightShift; + AbstractMatrix2.prototype.zeroFillRightShiftS = AbstractMatrix2.prototype.rightShiftS; + AbstractMatrix2.prototype.zeroFillRightShiftM = AbstractMatrix2.prototype.rightShiftM; + AbstractMatrix2.zeroFillRightShift = AbstractMatrix2.rightShift; + AbstractMatrix2.prototype.not = function not() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, ~this.get(i, j)); + } + } + return this; + }; + AbstractMatrix2.not = function not(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.not(); + }; + AbstractMatrix2.prototype.abs = function abs2() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.abs(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.abs = function abs2(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.abs(); + }; + AbstractMatrix2.prototype.acos = function acos() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.acos(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.acos = function acos(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.acos(); + }; + AbstractMatrix2.prototype.acosh = function acosh() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.acosh(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.acosh = function acosh(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.acosh(); + }; + AbstractMatrix2.prototype.asin = function asin() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.asin(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.asin = function asin(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.asin(); + }; + AbstractMatrix2.prototype.asinh = function asinh() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.asinh(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.asinh = function asinh(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.asinh(); + }; + AbstractMatrix2.prototype.atan = function atan() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.atan(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.atan = function atan(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.atan(); + }; + AbstractMatrix2.prototype.atanh = function atanh() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.atanh(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.atanh = function atanh(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.atanh(); + }; + AbstractMatrix2.prototype.cbrt = function cbrt() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.cbrt(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.cbrt = function cbrt(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.cbrt(); + }; + AbstractMatrix2.prototype.ceil = function ceil() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.ceil(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.ceil = function ceil(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.ceil(); + }; + AbstractMatrix2.prototype.clz32 = function clz32() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.clz32(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.clz32 = function clz32(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.clz32(); + }; + AbstractMatrix2.prototype.cos = function cos() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.cos(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.cos = function cos(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.cos(); + }; + AbstractMatrix2.prototype.cosh = function cosh() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.cosh(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.cosh = function cosh(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.cosh(); + }; + AbstractMatrix2.prototype.exp = function exp() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.exp(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.exp = function exp(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.exp(); + }; + AbstractMatrix2.prototype.expm1 = function expm1() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.expm1(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.expm1 = function expm1(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.expm1(); + }; + AbstractMatrix2.prototype.floor = function floor() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.floor(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.floor = function floor(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.floor(); + }; + AbstractMatrix2.prototype.fround = function fround() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.fround(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.fround = function fround(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.fround(); + }; + AbstractMatrix2.prototype.log = function log() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.log(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.log = function log(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.log(); + }; + AbstractMatrix2.prototype.log1p = function log1p() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.log1p(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.log1p = function log1p(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.log1p(); + }; + AbstractMatrix2.prototype.log10 = function log10() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.log10(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.log10 = function log10(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.log10(); + }; + AbstractMatrix2.prototype.log2 = function log2() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.log2(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.log2 = function log2(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.log2(); + }; + AbstractMatrix2.prototype.round = function round() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.round(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.round = function round(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.round(); + }; + AbstractMatrix2.prototype.sign = function sign() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.sign(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.sign = function sign(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.sign(); + }; + AbstractMatrix2.prototype.sin = function sin() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.sin(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.sin = function sin(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.sin(); + }; + AbstractMatrix2.prototype.sinh = function sinh() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.sinh(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.sinh = function sinh(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.sinh(); + }; + AbstractMatrix2.prototype.sqrt = function sqrt() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.sqrt(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.sqrt = function sqrt(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.sqrt(); + }; + AbstractMatrix2.prototype.tan = function tan() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.tan(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.tan = function tan(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.tan(); + }; + AbstractMatrix2.prototype.tanh = function tanh() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.tanh(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.tanh = function tanh(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.tanh(); + }; + AbstractMatrix2.prototype.trunc = function trunc() { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.trunc(this.get(i, j))); + } + } + return this; + }; + AbstractMatrix2.trunc = function trunc(matrix) { + const newMatrix = new Matrix2(matrix); + return newMatrix.trunc(); + }; + AbstractMatrix2.pow = function pow2(matrix, arg0) { + const newMatrix = new Matrix2(matrix); + return newMatrix.pow(arg0); + }; + AbstractMatrix2.prototype.pow = function pow2(value) { + if (typeof value === "number") + return this.powS(value); + return this.powM(value); + }; + AbstractMatrix2.prototype.powS = function powS(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.pow(this.get(i, j), value)); + } + } + return this; + }; + AbstractMatrix2.prototype.powM = function powM(matrix) { + matrix = Matrix2.checkMatrix(matrix); + if (this.rows !== matrix.rows || this.columns !== matrix.columns) { + throw new RangeError("Matrices dimensions must be equal"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, Math.pow(this.get(i, j), matrix.get(i, j))); + } + } + return this; + }; + } + function checkRowIndex(matrix, index2, outer) { + let max3 = outer ? matrix.rows : matrix.rows - 1; + if (index2 < 0 || index2 > max3) { + throw new RangeError("Row index out of range"); + } + } + function checkColumnIndex(matrix, index2, outer) { + let max3 = outer ? matrix.columns : matrix.columns - 1; + if (index2 < 0 || index2 > max3) { + throw new RangeError("Column index out of range"); + } + } + function checkRowVector(matrix, vector) { + if (vector.to1DArray) { + vector = vector.to1DArray(); + } + if (vector.length !== matrix.columns) { + throw new RangeError("vector size must be the same as the number of columns"); + } + return vector; + } + function checkColumnVector(matrix, vector) { + if (vector.to1DArray) { + vector = vector.to1DArray(); + } + if (vector.length !== matrix.rows) { + throw new RangeError("vector size must be the same as the number of rows"); + } + return vector; + } + function checkRowIndices(matrix, rowIndices) { + if (!isAnyArray.isAnyArray(rowIndices)) { + throw new TypeError("row indices must be an array"); + } + for (let i = 0; i < rowIndices.length; i++) { + if (rowIndices[i] < 0 || rowIndices[i] >= matrix.rows) { + throw new RangeError("row indices are out of range"); + } + } + } + function checkColumnIndices(matrix, columnIndices) { + if (!isAnyArray.isAnyArray(columnIndices)) { + throw new TypeError("column indices must be an array"); + } + for (let i = 0; i < columnIndices.length; i++) { + if (columnIndices[i] < 0 || columnIndices[i] >= matrix.columns) { + throw new RangeError("column indices are out of range"); + } + } + } + function checkRange(matrix, startRow, endRow, startColumn, endColumn) { + if (arguments.length !== 5) { + throw new RangeError("expected 4 arguments"); + } + checkNumber("startRow", startRow); + checkNumber("endRow", endRow); + checkNumber("startColumn", startColumn); + checkNumber("endColumn", endColumn); + if (startRow > endRow || startColumn > endColumn || startRow < 0 || startRow >= matrix.rows || endRow < 0 || endRow >= matrix.rows || startColumn < 0 || startColumn >= matrix.columns || endColumn < 0 || endColumn >= matrix.columns) { + throw new RangeError("Submatrix indices are out of range"); + } + } + function newArray(length, value = 0) { + let array2 = []; + for (let i = 0; i < length; i++) { + array2.push(value); + } + return array2; + } + function checkNumber(name, value) { + if (typeof value !== "number") { + throw new TypeError(`${name} must be a number`); + } + } + function checkNonEmpty(matrix) { + if (matrix.isEmpty()) { + throw new Error("Empty matrix has no elements to index"); + } + } + function sumByRow(matrix) { + let sum2 = newArray(matrix.rows); + for (let i = 0; i < matrix.rows; ++i) { + for (let j = 0; j < matrix.columns; ++j) { + sum2[i] += matrix.get(i, j); + } + } + return sum2; + } + function sumByColumn(matrix) { + let sum2 = newArray(matrix.columns); + for (let i = 0; i < matrix.rows; ++i) { + for (let j = 0; j < matrix.columns; ++j) { + sum2[j] += matrix.get(i, j); + } + } + return sum2; + } + function sumAll(matrix) { + let v2 = 0; + for (let i = 0; i < matrix.rows; i++) { + for (let j = 0; j < matrix.columns; j++) { + v2 += matrix.get(i, j); + } + } + return v2; + } + function productByRow(matrix) { + let sum2 = newArray(matrix.rows, 1); + for (let i = 0; i < matrix.rows; ++i) { + for (let j = 0; j < matrix.columns; ++j) { + sum2[i] *= matrix.get(i, j); + } + } + return sum2; + } + function productByColumn(matrix) { + let sum2 = newArray(matrix.columns, 1); + for (let i = 0; i < matrix.rows; ++i) { + for (let j = 0; j < matrix.columns; ++j) { + sum2[j] *= matrix.get(i, j); + } + } + return sum2; + } + function productAll(matrix) { + let v2 = 1; + for (let i = 0; i < matrix.rows; i++) { + for (let j = 0; j < matrix.columns; j++) { + v2 *= matrix.get(i, j); + } + } + return v2; + } + function varianceByRow(matrix, unbiased, mean) { + const rows = matrix.rows; + const cols = matrix.columns; + const variance = []; + for (let i = 0; i < rows; i++) { + let sum1 = 0; + let sum2 = 0; + let x3 = 0; + for (let j = 0; j < cols; j++) { + x3 = matrix.get(i, j) - mean[i]; + sum1 += x3; + sum2 += x3 * x3; + } + if (unbiased) { + variance.push((sum2 - sum1 * sum1 / cols) / (cols - 1)); + } else { + variance.push((sum2 - sum1 * sum1 / cols) / cols); + } + } + return variance; + } + function varianceByColumn(matrix, unbiased, mean) { + const rows = matrix.rows; + const cols = matrix.columns; + const variance = []; + for (let j = 0; j < cols; j++) { + let sum1 = 0; + let sum2 = 0; + let x3 = 0; + for (let i = 0; i < rows; i++) { + x3 = matrix.get(i, j) - mean[j]; + sum1 += x3; + sum2 += x3 * x3; + } + if (unbiased) { + variance.push((sum2 - sum1 * sum1 / rows) / (rows - 1)); + } else { + variance.push((sum2 - sum1 * sum1 / rows) / rows); + } + } + return variance; + } + function varianceAll(matrix, unbiased, mean) { + const rows = matrix.rows; + const cols = matrix.columns; + const size = rows * cols; + let sum1 = 0; + let sum2 = 0; + let x3 = 0; + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + x3 = matrix.get(i, j) - mean; + sum1 += x3; + sum2 += x3 * x3; + } + } + if (unbiased) { + return (sum2 - sum1 * sum1 / size) / (size - 1); + } else { + return (sum2 - sum1 * sum1 / size) / size; + } + } + function centerByRow(matrix, mean) { + for (let i = 0; i < matrix.rows; i++) { + for (let j = 0; j < matrix.columns; j++) { + matrix.set(i, j, matrix.get(i, j) - mean[i]); + } + } + } + function centerByColumn(matrix, mean) { + for (let i = 0; i < matrix.rows; i++) { + for (let j = 0; j < matrix.columns; j++) { + matrix.set(i, j, matrix.get(i, j) - mean[j]); + } + } + } + function centerAll(matrix, mean) { + for (let i = 0; i < matrix.rows; i++) { + for (let j = 0; j < matrix.columns; j++) { + matrix.set(i, j, matrix.get(i, j) - mean); + } + } + } + function getScaleByRow(matrix) { + const scale2 = []; + for (let i = 0; i < matrix.rows; i++) { + let sum2 = 0; + for (let j = 0; j < matrix.columns; j++) { + sum2 += Math.pow(matrix.get(i, j), 2) / (matrix.columns - 1); + } + scale2.push(Math.sqrt(sum2)); + } + return scale2; + } + function scaleByRow(matrix, scale2) { + for (let i = 0; i < matrix.rows; i++) { + for (let j = 0; j < matrix.columns; j++) { + matrix.set(i, j, matrix.get(i, j) / scale2[i]); + } + } + } + function getScaleByColumn(matrix) { + const scale2 = []; + for (let j = 0; j < matrix.columns; j++) { + let sum2 = 0; + for (let i = 0; i < matrix.rows; i++) { + sum2 += Math.pow(matrix.get(i, j), 2) / (matrix.rows - 1); + } + scale2.push(Math.sqrt(sum2)); + } + return scale2; + } + function scaleByColumn(matrix, scale2) { + for (let i = 0; i < matrix.rows; i++) { + for (let j = 0; j < matrix.columns; j++) { + matrix.set(i, j, matrix.get(i, j) / scale2[j]); + } + } + } + function getScaleAll(matrix) { + const divider = matrix.size - 1; + let sum2 = 0; + for (let j = 0; j < matrix.columns; j++) { + for (let i = 0; i < matrix.rows; i++) { + sum2 += Math.pow(matrix.get(i, j), 2) / divider; + } + } + return Math.sqrt(sum2); + } + function scaleAll(matrix, scale2) { + for (let i = 0; i < matrix.rows; i++) { + for (let j = 0; j < matrix.columns; j++) { + matrix.set(i, j, matrix.get(i, j) / scale2); + } + } + } + var AbstractMatrix = class { + static from1DArray(newRows, newColumns, newData) { + let length = newRows * newColumns; + if (length !== newData.length) { + throw new RangeError("data length does not match given dimensions"); + } + let newMatrix = new Matrix(newRows, newColumns); + for (let row = 0; row < newRows; row++) { + for (let column = 0; column < newColumns; column++) { + newMatrix.set(row, column, newData[row * newColumns + column]); + } + } + return newMatrix; + } + static rowVector(newData) { + let vector = new Matrix(1, newData.length); + for (let i = 0; i < newData.length; i++) { + vector.set(0, i, newData[i]); + } + return vector; + } + static columnVector(newData) { + let vector = new Matrix(newData.length, 1); + for (let i = 0; i < newData.length; i++) { + vector.set(i, 0, newData[i]); + } + return vector; + } + static zeros(rows, columns) { + return new Matrix(rows, columns); + } + static ones(rows, columns) { + return new Matrix(rows, columns).fill(1); + } + static rand(rows, columns, options = {}) { + if (typeof options !== "object") { + throw new TypeError("options must be an object"); + } + const { random = Math.random } = options; + let matrix = new Matrix(rows, columns); + for (let i = 0; i < rows; i++) { + for (let j = 0; j < columns; j++) { + matrix.set(i, j, random()); + } + } + return matrix; + } + static randInt(rows, columns, options = {}) { + if (typeof options !== "object") { + throw new TypeError("options must be an object"); + } + const { min: min3 = 0, max: max3 = 1e3, random = Math.random } = options; + if (!Number.isInteger(min3)) + throw new TypeError("min must be an integer"); + if (!Number.isInteger(max3)) + throw new TypeError("max must be an integer"); + if (min3 >= max3) + throw new RangeError("min must be smaller than max"); + let interval2 = max3 - min3; + let matrix = new Matrix(rows, columns); + for (let i = 0; i < rows; i++) { + for (let j = 0; j < columns; j++) { + let value = min3 + Math.round(random() * interval2); + matrix.set(i, j, value); + } + } + return matrix; + } + static eye(rows, columns, value) { + if (columns === void 0) + columns = rows; + if (value === void 0) + value = 1; + let min3 = Math.min(rows, columns); + let matrix = this.zeros(rows, columns); + for (let i = 0; i < min3; i++) { + matrix.set(i, i, value); + } + return matrix; + } + static diag(data, rows, columns) { + let l = data.length; + if (rows === void 0) + rows = l; + if (columns === void 0) + columns = rows; + let min3 = Math.min(l, rows, columns); + let matrix = this.zeros(rows, columns); + for (let i = 0; i < min3; i++) { + matrix.set(i, i, data[i]); + } + return matrix; + } + static min(matrix1, matrix2) { + matrix1 = this.checkMatrix(matrix1); + matrix2 = this.checkMatrix(matrix2); + let rows = matrix1.rows; + let columns = matrix1.columns; + let result = new Matrix(rows, columns); + for (let i = 0; i < rows; i++) { + for (let j = 0; j < columns; j++) { + result.set(i, j, Math.min(matrix1.get(i, j), matrix2.get(i, j))); + } + } + return result; + } + static max(matrix1, matrix2) { + matrix1 = this.checkMatrix(matrix1); + matrix2 = this.checkMatrix(matrix2); + let rows = matrix1.rows; + let columns = matrix1.columns; + let result = new this(rows, columns); + for (let i = 0; i < rows; i++) { + for (let j = 0; j < columns; j++) { + result.set(i, j, Math.max(matrix1.get(i, j), matrix2.get(i, j))); + } + } + return result; + } + static checkMatrix(value) { + return AbstractMatrix.isMatrix(value) ? value : new Matrix(value); + } + static isMatrix(value) { + return value != null && value.klass === "Matrix"; + } + get size() { + return this.rows * this.columns; + } + apply(callback) { + if (typeof callback !== "function") { + throw new TypeError("callback must be a function"); + } + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + callback.call(this, i, j); + } + } + return this; + } + to1DArray() { + let array2 = []; + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + array2.push(this.get(i, j)); + } + } + return array2; + } + to2DArray() { + let copy2 = []; + for (let i = 0; i < this.rows; i++) { + copy2.push([]); + for (let j = 0; j < this.columns; j++) { + copy2[i].push(this.get(i, j)); + } + } + return copy2; + } + toJSON() { + return this.to2DArray(); + } + isRowVector() { + return this.rows === 1; + } + isColumnVector() { + return this.columns === 1; + } + isVector() { + return this.rows === 1 || this.columns === 1; + } + isSquare() { + return this.rows === this.columns; + } + isEmpty() { + return this.rows === 0 || this.columns === 0; + } + isSymmetric() { + if (this.isSquare()) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j <= i; j++) { + if (this.get(i, j) !== this.get(j, i)) { + return false; + } + } + } + return true; + } + return false; + } + isEchelonForm() { + let i = 0; + let j = 0; + let previousColumn = -1; + let isEchelonForm = true; + let checked = false; + while (i < this.rows && isEchelonForm) { + j = 0; + checked = false; + while (j < this.columns && checked === false) { + if (this.get(i, j) === 0) { + j++; + } else if (this.get(i, j) === 1 && j > previousColumn) { + checked = true; + previousColumn = j; + } else { + isEchelonForm = false; + checked = true; + } + } + i++; + } + return isEchelonForm; + } + isReducedEchelonForm() { + let i = 0; + let j = 0; + let previousColumn = -1; + let isReducedEchelonForm = true; + let checked = false; + while (i < this.rows && isReducedEchelonForm) { + j = 0; + checked = false; + while (j < this.columns && checked === false) { + if (this.get(i, j) === 0) { + j++; + } else if (this.get(i, j) === 1 && j > previousColumn) { + checked = true; + previousColumn = j; + } else { + isReducedEchelonForm = false; + checked = true; + } + } + for (let k = j + 1; k < this.rows; k++) { + if (this.get(i, k) !== 0) { + isReducedEchelonForm = false; + } + } + i++; + } + return isReducedEchelonForm; + } + echelonForm() { + let result = this.clone(); + let h = 0; + let k = 0; + while (h < result.rows && k < result.columns) { + let iMax = h; + for (let i = h; i < result.rows; i++) { + if (result.get(i, k) > result.get(iMax, k)) { + iMax = i; + } + } + if (result.get(iMax, k) === 0) { + k++; + } else { + result.swapRows(h, iMax); + let tmp = result.get(h, k); + for (let j = k; j < result.columns; j++) { + result.set(h, j, result.get(h, j) / tmp); + } + for (let i = h + 1; i < result.rows; i++) { + let factor = result.get(i, k) / result.get(h, k); + result.set(i, k, 0); + for (let j = k + 1; j < result.columns; j++) { + result.set(i, j, result.get(i, j) - result.get(h, j) * factor); + } + } + h++; + k++; + } + } + return result; + } + reducedEchelonForm() { + let result = this.echelonForm(); + let m2 = result.columns; + let n = result.rows; + let h = n - 1; + while (h >= 0) { + if (result.maxRow(h) === 0) { + h--; + } else { + let p = 0; + let pivot = false; + while (p < n && pivot === false) { + if (result.get(h, p) === 1) { + pivot = true; + } else { + p++; + } + } + for (let i = 0; i < h; i++) { + let factor = result.get(i, p); + for (let j = p; j < m2; j++) { + let tmp = result.get(i, j) - factor * result.get(h, j); + result.set(i, j, tmp); + } + } + h--; + } + } + return result; + } + set() { + throw new Error("set method is unimplemented"); + } + get() { + throw new Error("get method is unimplemented"); + } + repeat(options = {}) { + if (typeof options !== "object") { + throw new TypeError("options must be an object"); + } + const { rows = 1, columns = 1 } = options; + if (!Number.isInteger(rows) || rows <= 0) { + throw new TypeError("rows must be a positive integer"); + } + if (!Number.isInteger(columns) || columns <= 0) { + throw new TypeError("columns must be a positive integer"); + } + let matrix = new Matrix(this.rows * rows, this.columns * columns); + for (let i = 0; i < rows; i++) { + for (let j = 0; j < columns; j++) { + matrix.setSubMatrix(this, this.rows * i, this.columns * j); + } + } + return matrix; + } + fill(value) { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, value); + } + } + return this; + } + neg() { + return this.mulS(-1); + } + getRow(index2) { + checkRowIndex(this, index2); + let row = []; + for (let i = 0; i < this.columns; i++) { + row.push(this.get(index2, i)); + } + return row; + } + getRowVector(index2) { + return Matrix.rowVector(this.getRow(index2)); + } + setRow(index2, array2) { + checkRowIndex(this, index2); + array2 = checkRowVector(this, array2); + for (let i = 0; i < this.columns; i++) { + this.set(index2, i, array2[i]); + } + return this; + } + swapRows(row1, row2) { + checkRowIndex(this, row1); + checkRowIndex(this, row2); + for (let i = 0; i < this.columns; i++) { + let temp = this.get(row1, i); + this.set(row1, i, this.get(row2, i)); + this.set(row2, i, temp); + } + return this; + } + getColumn(index2) { + checkColumnIndex(this, index2); + let column = []; + for (let i = 0; i < this.rows; i++) { + column.push(this.get(i, index2)); + } + return column; + } + getColumnVector(index2) { + return Matrix.columnVector(this.getColumn(index2)); + } + setColumn(index2, array2) { + checkColumnIndex(this, index2); + array2 = checkColumnVector(this, array2); + for (let i = 0; i < this.rows; i++) { + this.set(i, index2, array2[i]); + } + return this; + } + swapColumns(column1, column2) { + checkColumnIndex(this, column1); + checkColumnIndex(this, column2); + for (let i = 0; i < this.rows; i++) { + let temp = this.get(i, column1); + this.set(i, column1, this.get(i, column2)); + this.set(i, column2, temp); + } + return this; + } + addRowVector(vector) { + vector = checkRowVector(this, vector); + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) + vector[j]); + } + } + return this; + } + subRowVector(vector) { + vector = checkRowVector(this, vector); + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) - vector[j]); + } + } + return this; + } + mulRowVector(vector) { + vector = checkRowVector(this, vector); + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) * vector[j]); + } + } + return this; + } + divRowVector(vector) { + vector = checkRowVector(this, vector); + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) / vector[j]); + } + } + return this; + } + addColumnVector(vector) { + vector = checkColumnVector(this, vector); + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) + vector[i]); + } + } + return this; + } + subColumnVector(vector) { + vector = checkColumnVector(this, vector); + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) - vector[i]); + } + } + return this; + } + mulColumnVector(vector) { + vector = checkColumnVector(this, vector); + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) * vector[i]); + } + } + return this; + } + divColumnVector(vector) { + vector = checkColumnVector(this, vector); + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + this.set(i, j, this.get(i, j) / vector[i]); + } + } + return this; + } + mulRow(index2, value) { + checkRowIndex(this, index2); + for (let i = 0; i < this.columns; i++) { + this.set(index2, i, this.get(index2, i) * value); + } + return this; + } + mulColumn(index2, value) { + checkColumnIndex(this, index2); + for (let i = 0; i < this.rows; i++) { + this.set(i, index2, this.get(i, index2) * value); + } + return this; + } + max(by) { + if (this.isEmpty()) { + return NaN; + } + switch (by) { + case "row": { + const max3 = new Array(this.rows).fill(Number.NEGATIVE_INFINITY); + for (let row = 0; row < this.rows; row++) { + for (let column = 0; column < this.columns; column++) { + if (this.get(row, column) > max3[row]) { + max3[row] = this.get(row, column); + } + } + } + return max3; + } + case "column": { + const max3 = new Array(this.columns).fill(Number.NEGATIVE_INFINITY); + for (let row = 0; row < this.rows; row++) { + for (let column = 0; column < this.columns; column++) { + if (this.get(row, column) > max3[column]) { + max3[column] = this.get(row, column); + } + } + } + return max3; + } + case void 0: { + let max3 = this.get(0, 0); + for (let row = 0; row < this.rows; row++) { + for (let column = 0; column < this.columns; column++) { + if (this.get(row, column) > max3) { + max3 = this.get(row, column); + } + } + } + return max3; + } + default: + throw new Error(`invalid option: ${by}`); + } + } + maxIndex() { + checkNonEmpty(this); + let v2 = this.get(0, 0); + let idx = [0, 0]; + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + if (this.get(i, j) > v2) { + v2 = this.get(i, j); + idx[0] = i; + idx[1] = j; + } + } + } + return idx; + } + min(by) { + if (this.isEmpty()) { + return NaN; + } + switch (by) { + case "row": { + const min3 = new Array(this.rows).fill(Number.POSITIVE_INFINITY); + for (let row = 0; row < this.rows; row++) { + for (let column = 0; column < this.columns; column++) { + if (this.get(row, column) < min3[row]) { + min3[row] = this.get(row, column); + } + } + } + return min3; + } + case "column": { + const min3 = new Array(this.columns).fill(Number.POSITIVE_INFINITY); + for (let row = 0; row < this.rows; row++) { + for (let column = 0; column < this.columns; column++) { + if (this.get(row, column) < min3[column]) { + min3[column] = this.get(row, column); + } + } + } + return min3; + } + case void 0: { + let min3 = this.get(0, 0); + for (let row = 0; row < this.rows; row++) { + for (let column = 0; column < this.columns; column++) { + if (this.get(row, column) < min3) { + min3 = this.get(row, column); + } + } + } + return min3; + } + default: + throw new Error(`invalid option: ${by}`); + } + } + minIndex() { + checkNonEmpty(this); + let v2 = this.get(0, 0); + let idx = [0, 0]; + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + if (this.get(i, j) < v2) { + v2 = this.get(i, j); + idx[0] = i; + idx[1] = j; + } + } + } + return idx; + } + maxRow(row) { + checkRowIndex(this, row); + if (this.isEmpty()) { + return NaN; + } + let v2 = this.get(row, 0); + for (let i = 1; i < this.columns; i++) { + if (this.get(row, i) > v2) { + v2 = this.get(row, i); + } + } + return v2; + } + maxRowIndex(row) { + checkRowIndex(this, row); + checkNonEmpty(this); + let v2 = this.get(row, 0); + let idx = [row, 0]; + for (let i = 1; i < this.columns; i++) { + if (this.get(row, i) > v2) { + v2 = this.get(row, i); + idx[1] = i; + } + } + return idx; + } + minRow(row) { + checkRowIndex(this, row); + if (this.isEmpty()) { + return NaN; + } + let v2 = this.get(row, 0); + for (let i = 1; i < this.columns; i++) { + if (this.get(row, i) < v2) { + v2 = this.get(row, i); + } + } + return v2; + } + minRowIndex(row) { + checkRowIndex(this, row); + checkNonEmpty(this); + let v2 = this.get(row, 0); + let idx = [row, 0]; + for (let i = 1; i < this.columns; i++) { + if (this.get(row, i) < v2) { + v2 = this.get(row, i); + idx[1] = i; + } + } + return idx; + } + maxColumn(column) { + checkColumnIndex(this, column); + if (this.isEmpty()) { + return NaN; + } + let v2 = this.get(0, column); + for (let i = 1; i < this.rows; i++) { + if (this.get(i, column) > v2) { + v2 = this.get(i, column); + } + } + return v2; + } + maxColumnIndex(column) { + checkColumnIndex(this, column); + checkNonEmpty(this); + let v2 = this.get(0, column); + let idx = [0, column]; + for (let i = 1; i < this.rows; i++) { + if (this.get(i, column) > v2) { + v2 = this.get(i, column); + idx[0] = i; + } + } + return idx; + } + minColumn(column) { + checkColumnIndex(this, column); + if (this.isEmpty()) { + return NaN; + } + let v2 = this.get(0, column); + for (let i = 1; i < this.rows; i++) { + if (this.get(i, column) < v2) { + v2 = this.get(i, column); + } + } + return v2; + } + minColumnIndex(column) { + checkColumnIndex(this, column); + checkNonEmpty(this); + let v2 = this.get(0, column); + let idx = [0, column]; + for (let i = 1; i < this.rows; i++) { + if (this.get(i, column) < v2) { + v2 = this.get(i, column); + idx[0] = i; + } + } + return idx; + } + diag() { + let min3 = Math.min(this.rows, this.columns); + let diag = []; + for (let i = 0; i < min3; i++) { + diag.push(this.get(i, i)); + } + return diag; + } + norm(type2 = "frobenius") { + let result = 0; + if (type2 === "max") { + return this.max(); + } else if (type2 === "frobenius") { + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + result = result + this.get(i, j) * this.get(i, j); + } + } + return Math.sqrt(result); + } else { + throw new RangeError(`unknown norm type: ${type2}`); + } + } + cumulativeSum() { + let sum2 = 0; + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + sum2 += this.get(i, j); + this.set(i, j, sum2); + } + } + return this; + } + dot(vector2) { + if (AbstractMatrix.isMatrix(vector2)) + vector2 = vector2.to1DArray(); + let vector1 = this.to1DArray(); + if (vector1.length !== vector2.length) { + throw new RangeError("vectors do not have the same size"); + } + let dot = 0; + for (let i = 0; i < vector1.length; i++) { + dot += vector1[i] * vector2[i]; + } + return dot; + } + mmul(other) { + other = Matrix.checkMatrix(other); + let m2 = this.rows; + let n = this.columns; + let p = other.columns; + let result = new Matrix(m2, p); + let Bcolj = new Float64Array(n); + for (let j = 0; j < p; j++) { + for (let k = 0; k < n; k++) { + Bcolj[k] = other.get(k, j); + } + for (let i = 0; i < m2; i++) { + let s = 0; + for (let k = 0; k < n; k++) { + s += this.get(i, k) * Bcolj[k]; + } + result.set(i, j, s); + } + } + return result; + } + strassen2x2(other) { + other = Matrix.checkMatrix(other); + let result = new Matrix(2, 2); + const a11 = this.get(0, 0); + const b11 = other.get(0, 0); + const a12 = this.get(0, 1); + const b12 = other.get(0, 1); + const a21 = this.get(1, 0); + const b21 = other.get(1, 0); + const a22 = this.get(1, 1); + const b22 = other.get(1, 1); + const m1 = (a11 + a22) * (b11 + b22); + const m2 = (a21 + a22) * b11; + const m3 = a11 * (b12 - b22); + const m4 = a22 * (b21 - b11); + const m5 = (a11 + a12) * b22; + const m6 = (a21 - a11) * (b11 + b12); + const m7 = (a12 - a22) * (b21 + b22); + const c00 = m1 + m4 - m5 + m7; + const c01 = m3 + m5; + const c10 = m2 + m4; + const c11 = m1 - m2 + m3 + m6; + result.set(0, 0, c00); + result.set(0, 1, c01); + result.set(1, 0, c10); + result.set(1, 1, c11); + return result; + } + strassen3x3(other) { + other = Matrix.checkMatrix(other); + let result = new Matrix(3, 3); + const a00 = this.get(0, 0); + const a01 = this.get(0, 1); + const a02 = this.get(0, 2); + const a10 = this.get(1, 0); + const a11 = this.get(1, 1); + const a12 = this.get(1, 2); + const a20 = this.get(2, 0); + const a21 = this.get(2, 1); + const a22 = this.get(2, 2); + const b00 = other.get(0, 0); + const b01 = other.get(0, 1); + const b02 = other.get(0, 2); + const b10 = other.get(1, 0); + const b11 = other.get(1, 1); + const b12 = other.get(1, 2); + const b20 = other.get(2, 0); + const b21 = other.get(2, 1); + const b22 = other.get(2, 2); + const m1 = (a00 + a01 + a02 - a10 - a11 - a21 - a22) * b11; + const m2 = (a00 - a10) * (-b01 + b11); + const m3 = a11 * (-b00 + b01 + b10 - b11 - b12 - b20 + b22); + const m4 = (-a00 + a10 + a11) * (b00 - b01 + b11); + const m5 = (a10 + a11) * (-b00 + b01); + const m6 = a00 * b00; + const m7 = (-a00 + a20 + a21) * (b00 - b02 + b12); + const m8 = (-a00 + a20) * (b02 - b12); + const m9 = (a20 + a21) * (-b00 + b02); + const m10 = (a00 + a01 + a02 - a11 - a12 - a20 - a21) * b12; + const m11 = a21 * (-b00 + b02 + b10 - b11 - b12 - b20 + b21); + const m12 = (-a02 + a21 + a22) * (b11 + b20 - b21); + const m13 = (a02 - a22) * (b11 - b21); + const m14 = a02 * b20; + const m15 = (a21 + a22) * (-b20 + b21); + const m16 = (-a02 + a11 + a12) * (b12 + b20 - b22); + const m17 = (a02 - a12) * (b12 - b22); + const m18 = (a11 + a12) * (-b20 + b22); + const m19 = a01 * b10; + const m20 = a12 * b21; + const m21 = a10 * b02; + const m22 = a20 * b01; + const m23 = a22 * b22; + const c00 = m6 + m14 + m19; + const c01 = m1 + m4 + m5 + m6 + m12 + m14 + m15; + const c02 = m6 + m7 + m9 + m10 + m14 + m16 + m18; + const c10 = m2 + m3 + m4 + m6 + m14 + m16 + m17; + const c11 = m2 + m4 + m5 + m6 + m20; + const c12 = m14 + m16 + m17 + m18 + m21; + const c20 = m6 + m7 + m8 + m11 + m12 + m13 + m14; + const c21 = m12 + m13 + m14 + m15 + m22; + const c22 = m6 + m7 + m8 + m9 + m23; + result.set(0, 0, c00); + result.set(0, 1, c01); + result.set(0, 2, c02); + result.set(1, 0, c10); + result.set(1, 1, c11); + result.set(1, 2, c12); + result.set(2, 0, c20); + result.set(2, 1, c21); + result.set(2, 2, c22); + return result; + } + mmulStrassen(y4) { + y4 = Matrix.checkMatrix(y4); + let x3 = this.clone(); + let r1 = x3.rows; + let c1 = x3.columns; + let r2 = y4.rows; + let c2 = y4.columns; + if (c1 !== r2) { + console.warn(`Multiplying ${r1} x ${c1} and ${r2} x ${c2} matrix: dimensions do not match.`); + } + function embed(mat, rows, cols) { + let r3 = mat.rows; + let c4 = mat.columns; + if (r3 === rows && c4 === cols) { + return mat; + } else { + let resultat = AbstractMatrix.zeros(rows, cols); + resultat = resultat.setSubMatrix(mat, 0, 0); + return resultat; + } + } + let r = Math.max(r1, r2); + let c3 = Math.max(c1, c2); + x3 = embed(x3, r, c3); + y4 = embed(y4, r, c3); + function blockMult(a2, b, rows, cols) { + if (rows <= 512 || cols <= 512) { + return a2.mmul(b); + } + if (rows % 2 === 1 && cols % 2 === 1) { + a2 = embed(a2, rows + 1, cols + 1); + b = embed(b, rows + 1, cols + 1); + } else if (rows % 2 === 1) { + a2 = embed(a2, rows + 1, cols); + b = embed(b, rows + 1, cols); + } else if (cols % 2 === 1) { + a2 = embed(a2, rows, cols + 1); + b = embed(b, rows, cols + 1); + } + let halfRows = parseInt(a2.rows / 2, 10); + let halfCols = parseInt(a2.columns / 2, 10); + let a11 = a2.subMatrix(0, halfRows - 1, 0, halfCols - 1); + let b11 = b.subMatrix(0, halfRows - 1, 0, halfCols - 1); + let a12 = a2.subMatrix(0, halfRows - 1, halfCols, a2.columns - 1); + let b12 = b.subMatrix(0, halfRows - 1, halfCols, b.columns - 1); + let a21 = a2.subMatrix(halfRows, a2.rows - 1, 0, halfCols - 1); + let b21 = b.subMatrix(halfRows, b.rows - 1, 0, halfCols - 1); + let a22 = a2.subMatrix(halfRows, a2.rows - 1, halfCols, a2.columns - 1); + let b22 = b.subMatrix(halfRows, b.rows - 1, halfCols, b.columns - 1); + let m1 = blockMult(AbstractMatrix.add(a11, a22), AbstractMatrix.add(b11, b22), halfRows, halfCols); + let m2 = blockMult(AbstractMatrix.add(a21, a22), b11, halfRows, halfCols); + let m3 = blockMult(a11, AbstractMatrix.sub(b12, b22), halfRows, halfCols); + let m4 = blockMult(a22, AbstractMatrix.sub(b21, b11), halfRows, halfCols); + let m5 = blockMult(AbstractMatrix.add(a11, a12), b22, halfRows, halfCols); + let m6 = blockMult(AbstractMatrix.sub(a21, a11), AbstractMatrix.add(b11, b12), halfRows, halfCols); + let m7 = blockMult(AbstractMatrix.sub(a12, a22), AbstractMatrix.add(b21, b22), halfRows, halfCols); + let c11 = AbstractMatrix.add(m1, m4); + c11.sub(m5); + c11.add(m7); + let c12 = AbstractMatrix.add(m3, m5); + let c21 = AbstractMatrix.add(m2, m4); + let c22 = AbstractMatrix.sub(m1, m2); + c22.add(m3); + c22.add(m6); + let resultat = AbstractMatrix.zeros(2 * c11.rows, 2 * c11.columns); + resultat = resultat.setSubMatrix(c11, 0, 0); + resultat = resultat.setSubMatrix(c12, c11.rows, 0); + resultat = resultat.setSubMatrix(c21, 0, c11.columns); + resultat = resultat.setSubMatrix(c22, c11.rows, c11.columns); + return resultat.subMatrix(0, rows - 1, 0, cols - 1); + } + return blockMult(x3, y4, r, c3); + } + scaleRows(options = {}) { + if (typeof options !== "object") { + throw new TypeError("options must be an object"); + } + const { min: min3 = 0, max: max3 = 1 } = options; + if (!Number.isFinite(min3)) + throw new TypeError("min must be a number"); + if (!Number.isFinite(max3)) + throw new TypeError("max must be a number"); + if (min3 >= max3) + throw new RangeError("min must be smaller than max"); + let newMatrix = new Matrix(this.rows, this.columns); + for (let i = 0; i < this.rows; i++) { + const row = this.getRow(i); + if (row.length > 0) { + rescale__default["default"](row, { min: min3, max: max3, output: row }); + } + newMatrix.setRow(i, row); + } + return newMatrix; + } + scaleColumns(options = {}) { + if (typeof options !== "object") { + throw new TypeError("options must be an object"); + } + const { min: min3 = 0, max: max3 = 1 } = options; + if (!Number.isFinite(min3)) + throw new TypeError("min must be a number"); + if (!Number.isFinite(max3)) + throw new TypeError("max must be a number"); + if (min3 >= max3) + throw new RangeError("min must be smaller than max"); + let newMatrix = new Matrix(this.rows, this.columns); + for (let i = 0; i < this.columns; i++) { + const column = this.getColumn(i); + if (column.length) { + rescale__default["default"](column, { + min: min3, + max: max3, + output: column + }); + } + newMatrix.setColumn(i, column); + } + return newMatrix; + } + flipRows() { + const middle = Math.ceil(this.columns / 2); + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < middle; j++) { + let first = this.get(i, j); + let last = this.get(i, this.columns - 1 - j); + this.set(i, j, last); + this.set(i, this.columns - 1 - j, first); + } + } + return this; + } + flipColumns() { + const middle = Math.ceil(this.rows / 2); + for (let j = 0; j < this.columns; j++) { + for (let i = 0; i < middle; i++) { + let first = this.get(i, j); + let last = this.get(this.rows - 1 - i, j); + this.set(i, j, last); + this.set(this.rows - 1 - i, j, first); + } + } + return this; + } + kroneckerProduct(other) { + other = Matrix.checkMatrix(other); + let m2 = this.rows; + let n = this.columns; + let p = other.rows; + let q = other.columns; + let result = new Matrix(m2 * p, n * q); + for (let i = 0; i < m2; i++) { + for (let j = 0; j < n; j++) { + for (let k = 0; k < p; k++) { + for (let l = 0; l < q; l++) { + result.set(p * i + k, q * j + l, this.get(i, j) * other.get(k, l)); + } + } + } + } + return result; + } + kroneckerSum(other) { + other = Matrix.checkMatrix(other); + if (!this.isSquare() || !other.isSquare()) { + throw new Error("Kronecker Sum needs two Square Matrices"); + } + let m2 = this.rows; + let n = other.rows; + let AxI = this.kroneckerProduct(Matrix.eye(n, n)); + let IxB = Matrix.eye(m2, m2).kroneckerProduct(other); + return AxI.add(IxB); + } + transpose() { + let result = new Matrix(this.columns, this.rows); + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.columns; j++) { + result.set(j, i, this.get(i, j)); + } + } + return result; + } + sortRows(compareFunction = compareNumbers) { + for (let i = 0; i < this.rows; i++) { + this.setRow(i, this.getRow(i).sort(compareFunction)); + } + return this; + } + sortColumns(compareFunction = compareNumbers) { + for (let i = 0; i < this.columns; i++) { + this.setColumn(i, this.getColumn(i).sort(compareFunction)); + } + return this; + } + subMatrix(startRow, endRow, startColumn, endColumn) { + checkRange(this, startRow, endRow, startColumn, endColumn); + let newMatrix = new Matrix(endRow - startRow + 1, endColumn - startColumn + 1); + for (let i = startRow; i <= endRow; i++) { + for (let j = startColumn; j <= endColumn; j++) { + newMatrix.set(i - startRow, j - startColumn, this.get(i, j)); + } + } + return newMatrix; + } + subMatrixRow(indices, startColumn, endColumn) { + if (startColumn === void 0) + startColumn = 0; + if (endColumn === void 0) + endColumn = this.columns - 1; + if (startColumn > endColumn || startColumn < 0 || startColumn >= this.columns || endColumn < 0 || endColumn >= this.columns) { + throw new RangeError("Argument out of range"); + } + let newMatrix = new Matrix(indices.length, endColumn - startColumn + 1); + for (let i = 0; i < indices.length; i++) { + for (let j = startColumn; j <= endColumn; j++) { + if (indices[i] < 0 || indices[i] >= this.rows) { + throw new RangeError(`Row index out of range: ${indices[i]}`); + } + newMatrix.set(i, j - startColumn, this.get(indices[i], j)); + } + } + return newMatrix; + } + subMatrixColumn(indices, startRow, endRow) { + if (startRow === void 0) + startRow = 0; + if (endRow === void 0) + endRow = this.rows - 1; + if (startRow > endRow || startRow < 0 || startRow >= this.rows || endRow < 0 || endRow >= this.rows) { + throw new RangeError("Argument out of range"); + } + let newMatrix = new Matrix(endRow - startRow + 1, indices.length); + for (let i = 0; i < indices.length; i++) { + for (let j = startRow; j <= endRow; j++) { + if (indices[i] < 0 || indices[i] >= this.columns) { + throw new RangeError(`Column index out of range: ${indices[i]}`); + } + newMatrix.set(j - startRow, i, this.get(j, indices[i])); + } + } + return newMatrix; + } + setSubMatrix(matrix, startRow, startColumn) { + matrix = Matrix.checkMatrix(matrix); + if (matrix.isEmpty()) { + return this; + } + let endRow = startRow + matrix.rows - 1; + let endColumn = startColumn + matrix.columns - 1; + checkRange(this, startRow, endRow, startColumn, endColumn); + for (let i = 0; i < matrix.rows; i++) { + for (let j = 0; j < matrix.columns; j++) { + this.set(startRow + i, startColumn + j, matrix.get(i, j)); + } + } + return this; + } + selection(rowIndices, columnIndices) { + checkRowIndices(this, rowIndices); + checkColumnIndices(this, columnIndices); + let newMatrix = new Matrix(rowIndices.length, columnIndices.length); + for (let i = 0; i < rowIndices.length; i++) { + let rowIndex = rowIndices[i]; + for (let j = 0; j < columnIndices.length; j++) { + let columnIndex = columnIndices[j]; + newMatrix.set(i, j, this.get(rowIndex, columnIndex)); + } + } + return newMatrix; + } + trace() { + let min3 = Math.min(this.rows, this.columns); + let trace = 0; + for (let i = 0; i < min3; i++) { + trace += this.get(i, i); + } + return trace; + } + clone() { + let newMatrix = new Matrix(this.rows, this.columns); + for (let row = 0; row < this.rows; row++) { + for (let column = 0; column < this.columns; column++) { + newMatrix.set(row, column, this.get(row, column)); + } + } + return newMatrix; + } + sum(by) { + switch (by) { + case "row": + return sumByRow(this); + case "column": + return sumByColumn(this); + case void 0: + return sumAll(this); + default: + throw new Error(`invalid option: ${by}`); + } + } + product(by) { + switch (by) { + case "row": + return productByRow(this); + case "column": + return productByColumn(this); + case void 0: + return productAll(this); + default: + throw new Error(`invalid option: ${by}`); + } + } + mean(by) { + const sum2 = this.sum(by); + switch (by) { + case "row": { + for (let i = 0; i < this.rows; i++) { + sum2[i] /= this.columns; + } + return sum2; + } + case "column": { + for (let i = 0; i < this.columns; i++) { + sum2[i] /= this.rows; + } + return sum2; + } + case void 0: + return sum2 / this.size; + default: + throw new Error(`invalid option: ${by}`); + } + } + variance(by, options = {}) { + if (typeof by === "object") { + options = by; + by = void 0; + } + if (typeof options !== "object") { + throw new TypeError("options must be an object"); + } + const { unbiased = true, mean = this.mean(by) } = options; + if (typeof unbiased !== "boolean") { + throw new TypeError("unbiased must be a boolean"); + } + switch (by) { + case "row": { + if (!isAnyArray.isAnyArray(mean)) { + throw new TypeError("mean must be an array"); + } + return varianceByRow(this, unbiased, mean); + } + case "column": { + if (!isAnyArray.isAnyArray(mean)) { + throw new TypeError("mean must be an array"); + } + return varianceByColumn(this, unbiased, mean); + } + case void 0: { + if (typeof mean !== "number") { + throw new TypeError("mean must be a number"); + } + return varianceAll(this, unbiased, mean); + } + default: + throw new Error(`invalid option: ${by}`); + } + } + standardDeviation(by, options) { + if (typeof by === "object") { + options = by; + by = void 0; + } + const variance = this.variance(by, options); + if (by === void 0) { + return Math.sqrt(variance); + } else { + for (let i = 0; i < variance.length; i++) { + variance[i] = Math.sqrt(variance[i]); + } + return variance; + } + } + center(by, options = {}) { + if (typeof by === "object") { + options = by; + by = void 0; + } + if (typeof options !== "object") { + throw new TypeError("options must be an object"); + } + const { center = this.mean(by) } = options; + switch (by) { + case "row": { + if (!isAnyArray.isAnyArray(center)) { + throw new TypeError("center must be an array"); + } + centerByRow(this, center); + return this; + } + case "column": { + if (!isAnyArray.isAnyArray(center)) { + throw new TypeError("center must be an array"); + } + centerByColumn(this, center); + return this; + } + case void 0: { + if (typeof center !== "number") { + throw new TypeError("center must be a number"); + } + centerAll(this, center); + return this; + } + default: + throw new Error(`invalid option: ${by}`); + } + } + scale(by, options = {}) { + if (typeof by === "object") { + options = by; + by = void 0; + } + if (typeof options !== "object") { + throw new TypeError("options must be an object"); + } + let scale2 = options.scale; + switch (by) { + case "row": { + if (scale2 === void 0) { + scale2 = getScaleByRow(this); + } else if (!isAnyArray.isAnyArray(scale2)) { + throw new TypeError("scale must be an array"); + } + scaleByRow(this, scale2); + return this; + } + case "column": { + if (scale2 === void 0) { + scale2 = getScaleByColumn(this); + } else if (!isAnyArray.isAnyArray(scale2)) { + throw new TypeError("scale must be an array"); + } + scaleByColumn(this, scale2); + return this; + } + case void 0: { + if (scale2 === void 0) { + scale2 = getScaleAll(this); + } else if (typeof scale2 !== "number") { + throw new TypeError("scale must be a number"); + } + scaleAll(this, scale2); + return this; + } + default: + throw new Error(`invalid option: ${by}`); + } + } + toString(options) { + return inspectMatrixWithOptions(this, options); + } + }; + AbstractMatrix.prototype.klass = "Matrix"; + if (typeof Symbol !== "undefined") { + AbstractMatrix.prototype[Symbol.for("nodejs.util.inspect.custom")] = inspectMatrix; + } + function compareNumbers(a2, b) { + return a2 - b; + } + AbstractMatrix.random = AbstractMatrix.rand; + AbstractMatrix.randomInt = AbstractMatrix.randInt; + AbstractMatrix.diagonal = AbstractMatrix.diag; + AbstractMatrix.prototype.diagonal = AbstractMatrix.prototype.diag; + AbstractMatrix.identity = AbstractMatrix.eye; + AbstractMatrix.prototype.negate = AbstractMatrix.prototype.neg; + AbstractMatrix.prototype.tensorProduct = AbstractMatrix.prototype.kroneckerProduct; + var Matrix = class extends AbstractMatrix { + constructor(nRows, nColumns) { + super(); + if (Matrix.isMatrix(nRows)) { + return nRows.clone(); + } else if (Number.isInteger(nRows) && nRows >= 0) { + this.data = []; + if (Number.isInteger(nColumns) && nColumns >= 0) { + for (let i = 0; i < nRows; i++) { + this.data.push(new Float64Array(nColumns)); + } + } else { + throw new TypeError("nColumns must be a positive integer"); + } + } else if (isAnyArray.isAnyArray(nRows)) { + const arrayData = nRows; + nRows = arrayData.length; + nColumns = nRows ? arrayData[0].length : 0; + if (typeof nColumns !== "number") { + throw new TypeError("Data must be a 2D array with at least one element"); + } + this.data = []; + for (let i = 0; i < nRows; i++) { + if (arrayData[i].length !== nColumns) { + throw new RangeError("Inconsistent array dimensions"); + } + this.data.push(Float64Array.from(arrayData[i])); + } + } else { + throw new TypeError("First argument must be a positive number or an array"); + } + this.rows = nRows; + this.columns = nColumns; + } + set(rowIndex, columnIndex, value) { + this.data[rowIndex][columnIndex] = value; + return this; + } + get(rowIndex, columnIndex) { + return this.data[rowIndex][columnIndex]; + } + removeRow(index2) { + checkRowIndex(this, index2); + this.data.splice(index2, 1); + this.rows -= 1; + return this; + } + addRow(index2, array2) { + if (array2 === void 0) { + array2 = index2; + index2 = this.rows; + } + checkRowIndex(this, index2, true); + array2 = Float64Array.from(checkRowVector(this, array2)); + this.data.splice(index2, 0, array2); + this.rows += 1; + return this; + } + removeColumn(index2) { + checkColumnIndex(this, index2); + for (let i = 0; i < this.rows; i++) { + const newRow = new Float64Array(this.columns - 1); + for (let j = 0; j < index2; j++) { + newRow[j] = this.data[i][j]; + } + for (let j = index2 + 1; j < this.columns; j++) { + newRow[j - 1] = this.data[i][j]; + } + this.data[i] = newRow; + } + this.columns -= 1; + return this; + } + addColumn(index2, array2) { + if (typeof array2 === "undefined") { + array2 = index2; + index2 = this.columns; + } + checkColumnIndex(this, index2, true); + array2 = checkColumnVector(this, array2); + for (let i = 0; i < this.rows; i++) { + const newRow = new Float64Array(this.columns + 1); + let j = 0; + for (; j < index2; j++) { + newRow[j] = this.data[i][j]; + } + newRow[j++] = array2[i]; + for (; j < this.columns + 1; j++) { + newRow[j] = this.data[i][j - 1]; + } + this.data[i] = newRow; + } + this.columns += 1; + return this; + } + }; + installMathOperations(AbstractMatrix, Matrix); + var BaseView2 = class extends AbstractMatrix { + constructor(matrix, rows, columns) { + super(); + this.matrix = matrix; + this.rows = rows; + this.columns = columns; + } + }; + var MatrixColumnView = class extends BaseView2 { + constructor(matrix, column) { + checkColumnIndex(matrix, column); + super(matrix, matrix.rows, 1); + this.column = column; + } + set(rowIndex, columnIndex, value) { + this.matrix.set(rowIndex, this.column, value); + return this; + } + get(rowIndex) { + return this.matrix.get(rowIndex, this.column); + } + }; + var MatrixColumnSelectionView = class extends BaseView2 { + constructor(matrix, columnIndices) { + checkColumnIndices(matrix, columnIndices); + super(matrix, matrix.rows, columnIndices.length); + this.columnIndices = columnIndices; + } + set(rowIndex, columnIndex, value) { + this.matrix.set(rowIndex, this.columnIndices[columnIndex], value); + return this; + } + get(rowIndex, columnIndex) { + return this.matrix.get(rowIndex, this.columnIndices[columnIndex]); + } + }; + var MatrixFlipColumnView = class extends BaseView2 { + constructor(matrix) { + super(matrix, matrix.rows, matrix.columns); + } + set(rowIndex, columnIndex, value) { + this.matrix.set(rowIndex, this.columns - columnIndex - 1, value); + return this; + } + get(rowIndex, columnIndex) { + return this.matrix.get(rowIndex, this.columns - columnIndex - 1); + } + }; + var MatrixFlipRowView = class extends BaseView2 { + constructor(matrix) { + super(matrix, matrix.rows, matrix.columns); + } + set(rowIndex, columnIndex, value) { + this.matrix.set(this.rows - rowIndex - 1, columnIndex, value); + return this; + } + get(rowIndex, columnIndex) { + return this.matrix.get(this.rows - rowIndex - 1, columnIndex); + } + }; + var MatrixRowView = class extends BaseView2 { + constructor(matrix, row) { + checkRowIndex(matrix, row); + super(matrix, 1, matrix.columns); + this.row = row; + } + set(rowIndex, columnIndex, value) { + this.matrix.set(this.row, columnIndex, value); + return this; + } + get(rowIndex, columnIndex) { + return this.matrix.get(this.row, columnIndex); + } + }; + var MatrixRowSelectionView = class extends BaseView2 { + constructor(matrix, rowIndices) { + checkRowIndices(matrix, rowIndices); + super(matrix, rowIndices.length, matrix.columns); + this.rowIndices = rowIndices; + } + set(rowIndex, columnIndex, value) { + this.matrix.set(this.rowIndices[rowIndex], columnIndex, value); + return this; + } + get(rowIndex, columnIndex) { + return this.matrix.get(this.rowIndices[rowIndex], columnIndex); + } + }; + var MatrixSelectionView = class extends BaseView2 { + constructor(matrix, rowIndices, columnIndices) { + checkRowIndices(matrix, rowIndices); + checkColumnIndices(matrix, columnIndices); + super(matrix, rowIndices.length, columnIndices.length); + this.rowIndices = rowIndices; + this.columnIndices = columnIndices; + } + set(rowIndex, columnIndex, value) { + this.matrix.set(this.rowIndices[rowIndex], this.columnIndices[columnIndex], value); + return this; + } + get(rowIndex, columnIndex) { + return this.matrix.get(this.rowIndices[rowIndex], this.columnIndices[columnIndex]); + } + }; + var MatrixSubView = class extends BaseView2 { + constructor(matrix, startRow, endRow, startColumn, endColumn) { + checkRange(matrix, startRow, endRow, startColumn, endColumn); + super(matrix, endRow - startRow + 1, endColumn - startColumn + 1); + this.startRow = startRow; + this.startColumn = startColumn; + } + set(rowIndex, columnIndex, value) { + this.matrix.set(this.startRow + rowIndex, this.startColumn + columnIndex, value); + return this; + } + get(rowIndex, columnIndex) { + return this.matrix.get(this.startRow + rowIndex, this.startColumn + columnIndex); + } + }; + var MatrixTransposeView = class extends BaseView2 { + constructor(matrix) { + super(matrix, matrix.columns, matrix.rows); + } + set(rowIndex, columnIndex, value) { + this.matrix.set(columnIndex, rowIndex, value); + return this; + } + get(rowIndex, columnIndex) { + return this.matrix.get(columnIndex, rowIndex); + } + }; + var WrapperMatrix1D = class extends AbstractMatrix { + constructor(data, options = {}) { + const { rows = 1 } = options; + if (data.length % rows !== 0) { + throw new Error("the data length is not divisible by the number of rows"); + } + super(); + this.rows = rows; + this.columns = data.length / rows; + this.data = data; + } + set(rowIndex, columnIndex, value) { + let index2 = this._calculateIndex(rowIndex, columnIndex); + this.data[index2] = value; + return this; + } + get(rowIndex, columnIndex) { + let index2 = this._calculateIndex(rowIndex, columnIndex); + return this.data[index2]; + } + _calculateIndex(row, column) { + return row * this.columns + column; + } + }; + var WrapperMatrix2D = class extends AbstractMatrix { + constructor(data) { + super(); + this.data = data; + this.rows = data.length; + this.columns = data[0].length; + } + set(rowIndex, columnIndex, value) { + this.data[rowIndex][columnIndex] = value; + return this; + } + get(rowIndex, columnIndex) { + return this.data[rowIndex][columnIndex]; + } + }; + function wrap(array2, options) { + if (isAnyArray.isAnyArray(array2)) { + if (array2[0] && isAnyArray.isAnyArray(array2[0])) { + return new WrapperMatrix2D(array2); + } else { + return new WrapperMatrix1D(array2, options); + } + } else { + throw new Error("the argument is not an array"); + } + } + var LuDecomposition = class { + constructor(matrix) { + matrix = WrapperMatrix2D.checkMatrix(matrix); + let lu = matrix.clone(); + let rows = lu.rows; + let columns = lu.columns; + let pivotVector = new Float64Array(rows); + let pivotSign = 1; + let i, j, k, p, s, t, v2; + let LUcolj, kmax; + for (i = 0; i < rows; i++) { + pivotVector[i] = i; + } + LUcolj = new Float64Array(rows); + for (j = 0; j < columns; j++) { + for (i = 0; i < rows; i++) { + LUcolj[i] = lu.get(i, j); + } + for (i = 0; i < rows; i++) { + kmax = Math.min(i, j); + s = 0; + for (k = 0; k < kmax; k++) { + s += lu.get(i, k) * LUcolj[k]; + } + LUcolj[i] -= s; + lu.set(i, j, LUcolj[i]); + } + p = j; + for (i = j + 1; i < rows; i++) { + if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) { + p = i; + } + } + if (p !== j) { + for (k = 0; k < columns; k++) { + t = lu.get(p, k); + lu.set(p, k, lu.get(j, k)); + lu.set(j, k, t); + } + v2 = pivotVector[p]; + pivotVector[p] = pivotVector[j]; + pivotVector[j] = v2; + pivotSign = -pivotSign; + } + if (j < rows && lu.get(j, j) !== 0) { + for (i = j + 1; i < rows; i++) { + lu.set(i, j, lu.get(i, j) / lu.get(j, j)); + } + } + } + this.LU = lu; + this.pivotVector = pivotVector; + this.pivotSign = pivotSign; + } + isSingular() { + let data = this.LU; + let col = data.columns; + for (let j = 0; j < col; j++) { + if (data.get(j, j) === 0) { + return true; + } + } + return false; + } + solve(value) { + value = Matrix.checkMatrix(value); + let lu = this.LU; + let rows = lu.rows; + if (rows !== value.rows) { + throw new Error("Invalid matrix dimensions"); + } + if (this.isSingular()) { + throw new Error("LU matrix is singular"); + } + let count = value.columns; + let X2 = value.subMatrixRow(this.pivotVector, 0, count - 1); + let columns = lu.columns; + let i, j, k; + for (k = 0; k < columns; k++) { + for (i = k + 1; i < columns; i++) { + for (j = 0; j < count; j++) { + X2.set(i, j, X2.get(i, j) - X2.get(k, j) * lu.get(i, k)); + } + } + } + for (k = columns - 1; k >= 0; k--) { + for (j = 0; j < count; j++) { + X2.set(k, j, X2.get(k, j) / lu.get(k, k)); + } + for (i = 0; i < k; i++) { + for (j = 0; j < count; j++) { + X2.set(i, j, X2.get(i, j) - X2.get(k, j) * lu.get(i, k)); + } + } + } + return X2; + } + get determinant() { + let data = this.LU; + if (!data.isSquare()) { + throw new Error("Matrix must be square"); + } + let determinant2 = this.pivotSign; + let col = data.columns; + for (let j = 0; j < col; j++) { + determinant2 *= data.get(j, j); + } + return determinant2; + } + get lowerTriangularMatrix() { + let data = this.LU; + let rows = data.rows; + let columns = data.columns; + let X2 = new Matrix(rows, columns); + for (let i = 0; i < rows; i++) { + for (let j = 0; j < columns; j++) { + if (i > j) { + X2.set(i, j, data.get(i, j)); + } else if (i === j) { + X2.set(i, j, 1); + } else { + X2.set(i, j, 0); + } + } + } + return X2; + } + get upperTriangularMatrix() { + let data = this.LU; + let rows = data.rows; + let columns = data.columns; + let X2 = new Matrix(rows, columns); + for (let i = 0; i < rows; i++) { + for (let j = 0; j < columns; j++) { + if (i <= j) { + X2.set(i, j, data.get(i, j)); + } else { + X2.set(i, j, 0); + } + } + } + return X2; + } + get pivotPermutationVector() { + return Array.from(this.pivotVector); + } + }; + function hypotenuse(a2, b) { + let r = 0; + if (Math.abs(a2) > Math.abs(b)) { + r = b / a2; + return Math.abs(a2) * Math.sqrt(1 + r * r); + } + if (b !== 0) { + r = a2 / b; + return Math.abs(b) * Math.sqrt(1 + r * r); + } + return 0; + } + var QrDecomposition = class { + constructor(value) { + value = WrapperMatrix2D.checkMatrix(value); + let qr = value.clone(); + let m2 = value.rows; + let n = value.columns; + let rdiag = new Float64Array(n); + let i, j, k, s; + for (k = 0; k < n; k++) { + let nrm = 0; + for (i = k; i < m2; i++) { + nrm = hypotenuse(nrm, qr.get(i, k)); + } + if (nrm !== 0) { + if (qr.get(k, k) < 0) { + nrm = -nrm; + } + for (i = k; i < m2; i++) { + qr.set(i, k, qr.get(i, k) / nrm); + } + qr.set(k, k, qr.get(k, k) + 1); + for (j = k + 1; j < n; j++) { + s = 0; + for (i = k; i < m2; i++) { + s += qr.get(i, k) * qr.get(i, j); + } + s = -s / qr.get(k, k); + for (i = k; i < m2; i++) { + qr.set(i, j, qr.get(i, j) + s * qr.get(i, k)); + } + } + } + rdiag[k] = -nrm; + } + this.QR = qr; + this.Rdiag = rdiag; + } + solve(value) { + value = Matrix.checkMatrix(value); + let qr = this.QR; + let m2 = qr.rows; + if (value.rows !== m2) { + throw new Error("Matrix row dimensions must agree"); + } + if (!this.isFullRank()) { + throw new Error("Matrix is rank deficient"); + } + let count = value.columns; + let X2 = value.clone(); + let n = qr.columns; + let i, j, k, s; + for (k = 0; k < n; k++) { + for (j = 0; j < count; j++) { + s = 0; + for (i = k; i < m2; i++) { + s += qr.get(i, k) * X2.get(i, j); + } + s = -s / qr.get(k, k); + for (i = k; i < m2; i++) { + X2.set(i, j, X2.get(i, j) + s * qr.get(i, k)); + } + } + } + for (k = n - 1; k >= 0; k--) { + for (j = 0; j < count; j++) { + X2.set(k, j, X2.get(k, j) / this.Rdiag[k]); + } + for (i = 0; i < k; i++) { + for (j = 0; j < count; j++) { + X2.set(i, j, X2.get(i, j) - X2.get(k, j) * qr.get(i, k)); + } + } + } + return X2.subMatrix(0, n - 1, 0, count - 1); + } + isFullRank() { + let columns = this.QR.columns; + for (let i = 0; i < columns; i++) { + if (this.Rdiag[i] === 0) { + return false; + } + } + return true; + } + get upperTriangularMatrix() { + let qr = this.QR; + let n = qr.columns; + let X2 = new Matrix(n, n); + let i, j; + for (i = 0; i < n; i++) { + for (j = 0; j < n; j++) { + if (i < j) { + X2.set(i, j, qr.get(i, j)); + } else if (i === j) { + X2.set(i, j, this.Rdiag[i]); + } else { + X2.set(i, j, 0); + } + } + } + return X2; + } + get orthogonalMatrix() { + let qr = this.QR; + let rows = qr.rows; + let columns = qr.columns; + let X2 = new Matrix(rows, columns); + let i, j, k, s; + for (k = columns - 1; k >= 0; k--) { + for (i = 0; i < rows; i++) { + X2.set(i, k, 0); + } + X2.set(k, k, 1); + for (j = k; j < columns; j++) { + if (qr.get(k, k) !== 0) { + s = 0; + for (i = k; i < rows; i++) { + s += qr.get(i, k) * X2.get(i, j); + } + s = -s / qr.get(k, k); + for (i = k; i < rows; i++) { + X2.set(i, j, X2.get(i, j) + s * qr.get(i, k)); + } + } + } + } + return X2; + } + }; + var SingularValueDecomposition = class { + constructor(value, options = {}) { + value = WrapperMatrix2D.checkMatrix(value); + if (value.isEmpty()) { + throw new Error("Matrix must be non-empty"); + } + let m2 = value.rows; + let n = value.columns; + const { + computeLeftSingularVectors = true, + computeRightSingularVectors = true, + autoTranspose = false + } = options; + let wantu = Boolean(computeLeftSingularVectors); + let wantv = Boolean(computeRightSingularVectors); + let swapped = false; + let a2; + if (m2 < n) { + if (!autoTranspose) { + a2 = value.clone(); + console.warn("Computing SVD on a matrix with more columns than rows. Consider enabling autoTranspose"); + } else { + a2 = value.transpose(); + m2 = a2.rows; + n = a2.columns; + swapped = true; + let aux = wantu; + wantu = wantv; + wantv = aux; + } + } else { + a2 = value.clone(); + } + let nu = Math.min(m2, n); + let ni = Math.min(m2 + 1, n); + let s = new Float64Array(ni); + let U = new Matrix(m2, nu); + let V = new Matrix(n, n); + let e = new Float64Array(n); + let work = new Float64Array(m2); + let si = new Float64Array(ni); + for (let i = 0; i < ni; i++) + si[i] = i; + let nct = Math.min(m2 - 1, n); + let nrt = Math.max(0, Math.min(n - 2, m2)); + let mrc = Math.max(nct, nrt); + for (let k = 0; k < mrc; k++) { + if (k < nct) { + s[k] = 0; + for (let i = k; i < m2; i++) { + s[k] = hypotenuse(s[k], a2.get(i, k)); + } + if (s[k] !== 0) { + if (a2.get(k, k) < 0) { + s[k] = -s[k]; + } + for (let i = k; i < m2; i++) { + a2.set(i, k, a2.get(i, k) / s[k]); + } + a2.set(k, k, a2.get(k, k) + 1); + } + s[k] = -s[k]; + } + for (let j = k + 1; j < n; j++) { + if (k < nct && s[k] !== 0) { + let t = 0; + for (let i = k; i < m2; i++) { + t += a2.get(i, k) * a2.get(i, j); + } + t = -t / a2.get(k, k); + for (let i = k; i < m2; i++) { + a2.set(i, j, a2.get(i, j) + t * a2.get(i, k)); + } + } + e[j] = a2.get(k, j); + } + if (wantu && k < nct) { + for (let i = k; i < m2; i++) { + U.set(i, k, a2.get(i, k)); + } + } + if (k < nrt) { + e[k] = 0; + for (let i = k + 1; i < n; i++) { + e[k] = hypotenuse(e[k], e[i]); + } + if (e[k] !== 0) { + if (e[k + 1] < 0) { + e[k] = 0 - e[k]; + } + for (let i = k + 1; i < n; i++) { + e[i] /= e[k]; + } + e[k + 1] += 1; + } + e[k] = -e[k]; + if (k + 1 < m2 && e[k] !== 0) { + for (let i = k + 1; i < m2; i++) { + work[i] = 0; + } + for (let i = k + 1; i < m2; i++) { + for (let j = k + 1; j < n; j++) { + work[i] += e[j] * a2.get(i, j); + } + } + for (let j = k + 1; j < n; j++) { + let t = -e[j] / e[k + 1]; + for (let i = k + 1; i < m2; i++) { + a2.set(i, j, a2.get(i, j) + t * work[i]); + } + } + } + if (wantv) { + for (let i = k + 1; i < n; i++) { + V.set(i, k, e[i]); + } + } + } + } + let p = Math.min(n, m2 + 1); + if (nct < n) { + s[nct] = a2.get(nct, nct); + } + if (m2 < p) { + s[p - 1] = 0; + } + if (nrt + 1 < p) { + e[nrt] = a2.get(nrt, p - 1); + } + e[p - 1] = 0; + if (wantu) { + for (let j = nct; j < nu; j++) { + for (let i = 0; i < m2; i++) { + U.set(i, j, 0); + } + U.set(j, j, 1); + } + for (let k = nct - 1; k >= 0; k--) { + if (s[k] !== 0) { + for (let j = k + 1; j < nu; j++) { + let t = 0; + for (let i = k; i < m2; i++) { + t += U.get(i, k) * U.get(i, j); + } + t = -t / U.get(k, k); + for (let i = k; i < m2; i++) { + U.set(i, j, U.get(i, j) + t * U.get(i, k)); + } + } + for (let i = k; i < m2; i++) { + U.set(i, k, -U.get(i, k)); + } + U.set(k, k, 1 + U.get(k, k)); + for (let i = 0; i < k - 1; i++) { + U.set(i, k, 0); + } + } else { + for (let i = 0; i < m2; i++) { + U.set(i, k, 0); + } + U.set(k, k, 1); + } + } + } + if (wantv) { + for (let k = n - 1; k >= 0; k--) { + if (k < nrt && e[k] !== 0) { + for (let j = k + 1; j < n; j++) { + let t = 0; + for (let i = k + 1; i < n; i++) { + t += V.get(i, k) * V.get(i, j); + } + t = -t / V.get(k + 1, k); + for (let i = k + 1; i < n; i++) { + V.set(i, j, V.get(i, j) + t * V.get(i, k)); + } + } + } + for (let i = 0; i < n; i++) { + V.set(i, k, 0); + } + V.set(k, k, 1); + } + } + let pp = p - 1; + let eps = Number.EPSILON; + while (p > 0) { + let k, kase; + for (k = p - 2; k >= -1; k--) { + if (k === -1) { + break; + } + const alpha = Number.MIN_VALUE + eps * Math.abs(s[k] + Math.abs(s[k + 1])); + if (Math.abs(e[k]) <= alpha || Number.isNaN(e[k])) { + e[k] = 0; + break; + } + } + if (k === p - 2) { + kase = 4; + } else { + let ks; + for (ks = p - 1; ks >= k; ks--) { + if (ks === k) { + break; + } + let t = (ks !== p ? Math.abs(e[ks]) : 0) + (ks !== k + 1 ? Math.abs(e[ks - 1]) : 0); + if (Math.abs(s[ks]) <= eps * t) { + s[ks] = 0; + break; + } + } + if (ks === k) { + kase = 3; + } else if (ks === p - 1) { + kase = 1; + } else { + kase = 2; + k = ks; + } + } + k++; + switch (kase) { + case 1: { + let f = e[p - 2]; + e[p - 2] = 0; + for (let j = p - 2; j >= k; j--) { + let t = hypotenuse(s[j], f); + let cs = s[j] / t; + let sn = f / t; + s[j] = t; + if (j !== k) { + f = -sn * e[j - 1]; + e[j - 1] = cs * e[j - 1]; + } + if (wantv) { + for (let i = 0; i < n; i++) { + t = cs * V.get(i, j) + sn * V.get(i, p - 1); + V.set(i, p - 1, -sn * V.get(i, j) + cs * V.get(i, p - 1)); + V.set(i, j, t); + } + } + } + break; + } + case 2: { + let f = e[k - 1]; + e[k - 1] = 0; + for (let j = k; j < p; j++) { + let t = hypotenuse(s[j], f); + let cs = s[j] / t; + let sn = f / t; + s[j] = t; + f = -sn * e[j]; + e[j] = cs * e[j]; + if (wantu) { + for (let i = 0; i < m2; i++) { + t = cs * U.get(i, j) + sn * U.get(i, k - 1); + U.set(i, k - 1, -sn * U.get(i, j) + cs * U.get(i, k - 1)); + U.set(i, j, t); + } + } + } + break; + } + case 3: { + const scale2 = Math.max(Math.abs(s[p - 1]), Math.abs(s[p - 2]), Math.abs(e[p - 2]), Math.abs(s[k]), Math.abs(e[k])); + const sp = s[p - 1] / scale2; + const spm1 = s[p - 2] / scale2; + const epm1 = e[p - 2] / scale2; + const sk = s[k] / scale2; + const ek = e[k] / scale2; + const b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2; + const c2 = sp * epm1 * (sp * epm1); + let shift = 0; + if (b !== 0 || c2 !== 0) { + if (b < 0) { + shift = 0 - Math.sqrt(b * b + c2); + } else { + shift = Math.sqrt(b * b + c2); + } + shift = c2 / (b + shift); + } + let f = (sk + sp) * (sk - sp) + shift; + let g = sk * ek; + for (let j = k; j < p - 1; j++) { + let t = hypotenuse(f, g); + if (t === 0) + t = Number.MIN_VALUE; + let cs = f / t; + let sn = g / t; + if (j !== k) { + e[j - 1] = t; + } + f = cs * s[j] + sn * e[j]; + e[j] = cs * e[j] - sn * s[j]; + g = sn * s[j + 1]; + s[j + 1] = cs * s[j + 1]; + if (wantv) { + for (let i = 0; i < n; i++) { + t = cs * V.get(i, j) + sn * V.get(i, j + 1); + V.set(i, j + 1, -sn * V.get(i, j) + cs * V.get(i, j + 1)); + V.set(i, j, t); + } + } + t = hypotenuse(f, g); + if (t === 0) + t = Number.MIN_VALUE; + cs = f / t; + sn = g / t; + s[j] = t; + f = cs * e[j] + sn * s[j + 1]; + s[j + 1] = -sn * e[j] + cs * s[j + 1]; + g = sn * e[j + 1]; + e[j + 1] = cs * e[j + 1]; + if (wantu && j < m2 - 1) { + for (let i = 0; i < m2; i++) { + t = cs * U.get(i, j) + sn * U.get(i, j + 1); + U.set(i, j + 1, -sn * U.get(i, j) + cs * U.get(i, j + 1)); + U.set(i, j, t); + } + } + } + e[p - 2] = f; + break; + } + case 4: { + if (s[k] <= 0) { + s[k] = s[k] < 0 ? -s[k] : 0; + if (wantv) { + for (let i = 0; i <= pp; i++) { + V.set(i, k, -V.get(i, k)); + } + } + } + while (k < pp) { + if (s[k] >= s[k + 1]) { + break; + } + let t = s[k]; + s[k] = s[k + 1]; + s[k + 1] = t; + if (wantv && k < n - 1) { + for (let i = 0; i < n; i++) { + t = V.get(i, k + 1); + V.set(i, k + 1, V.get(i, k)); + V.set(i, k, t); + } + } + if (wantu && k < m2 - 1) { + for (let i = 0; i < m2; i++) { + t = U.get(i, k + 1); + U.set(i, k + 1, U.get(i, k)); + U.set(i, k, t); + } + } + k++; + } + p--; + break; + } + } + } + if (swapped) { + let tmp = V; + V = U; + U = tmp; + } + this.m = m2; + this.n = n; + this.s = s; + this.U = U; + this.V = V; + } + solve(value) { + let Y2 = value; + let e = this.threshold; + let scols = this.s.length; + let Ls = Matrix.zeros(scols, scols); + for (let i = 0; i < scols; i++) { + if (Math.abs(this.s[i]) <= e) { + Ls.set(i, i, 0); + } else { + Ls.set(i, i, 1 / this.s[i]); + } + } + let U = this.U; + let V = this.rightSingularVectors; + let VL = V.mmul(Ls); + let vrows = V.rows; + let urows = U.rows; + let VLU = Matrix.zeros(vrows, urows); + for (let i = 0; i < vrows; i++) { + for (let j = 0; j < urows; j++) { + let sum2 = 0; + for (let k = 0; k < scols; k++) { + sum2 += VL.get(i, k) * U.get(j, k); + } + VLU.set(i, j, sum2); + } + } + return VLU.mmul(Y2); + } + solveForDiagonal(value) { + return this.solve(Matrix.diag(value)); + } + inverse() { + let V = this.V; + let e = this.threshold; + let vrows = V.rows; + let vcols = V.columns; + let X2 = new Matrix(vrows, this.s.length); + for (let i = 0; i < vrows; i++) { + for (let j = 0; j < vcols; j++) { + if (Math.abs(this.s[j]) > e) { + X2.set(i, j, V.get(i, j) / this.s[j]); + } + } + } + let U = this.U; + let urows = U.rows; + let ucols = U.columns; + let Y2 = new Matrix(vrows, urows); + for (let i = 0; i < vrows; i++) { + for (let j = 0; j < urows; j++) { + let sum2 = 0; + for (let k = 0; k < ucols; k++) { + sum2 += X2.get(i, k) * U.get(j, k); + } + Y2.set(i, j, sum2); + } + } + return Y2; + } + get condition() { + return this.s[0] / this.s[Math.min(this.m, this.n) - 1]; + } + get norm2() { + return this.s[0]; + } + get rank() { + let tol = Math.max(this.m, this.n) * this.s[0] * Number.EPSILON; + let r = 0; + let s = this.s; + for (let i = 0, ii = s.length; i < ii; i++) { + if (s[i] > tol) { + r++; + } + } + return r; + } + get diagonal() { + return Array.from(this.s); + } + get threshold() { + return Number.EPSILON / 2 * Math.max(this.m, this.n) * this.s[0]; + } + get leftSingularVectors() { + return this.U; + } + get rightSingularVectors() { + return this.V; + } + get diagonalMatrix() { + return Matrix.diag(this.s); + } + }; + function inverse(matrix, useSVD = false) { + matrix = WrapperMatrix2D.checkMatrix(matrix); + if (useSVD) { + return new SingularValueDecomposition(matrix).inverse(); + } else { + return solve(matrix, Matrix.eye(matrix.rows)); + } + } + function solve(leftHandSide, rightHandSide, useSVD = false) { + leftHandSide = WrapperMatrix2D.checkMatrix(leftHandSide); + rightHandSide = WrapperMatrix2D.checkMatrix(rightHandSide); + if (useSVD) { + return new SingularValueDecomposition(leftHandSide).solve(rightHandSide); + } else { + return leftHandSide.isSquare() ? new LuDecomposition(leftHandSide).solve(rightHandSide) : new QrDecomposition(leftHandSide).solve(rightHandSide); + } + } + function determinant(matrix) { + matrix = Matrix.checkMatrix(matrix); + if (matrix.isSquare()) { + if (matrix.columns === 0) { + return 1; + } + let a2, b, c2, d; + if (matrix.columns === 2) { + a2 = matrix.get(0, 0); + b = matrix.get(0, 1); + c2 = matrix.get(1, 0); + d = matrix.get(1, 1); + return a2 * d - b * c2; + } else if (matrix.columns === 3) { + let subMatrix0, subMatrix1, subMatrix2; + subMatrix0 = new MatrixSelectionView(matrix, [1, 2], [1, 2]); + subMatrix1 = new MatrixSelectionView(matrix, [1, 2], [0, 2]); + subMatrix2 = new MatrixSelectionView(matrix, [1, 2], [0, 1]); + a2 = matrix.get(0, 0); + b = matrix.get(0, 1); + c2 = matrix.get(0, 2); + return a2 * determinant(subMatrix0) - b * determinant(subMatrix1) + c2 * determinant(subMatrix2); + } else { + return new LuDecomposition(matrix).determinant; + } + } else { + throw Error("determinant can only be calculated for a square matrix"); + } + } + function xrange(n, exception) { + let range2 = []; + for (let i = 0; i < n; i++) { + if (i !== exception) { + range2.push(i); + } + } + return range2; + } + function dependenciesOneRow(error, matrix, index2, thresholdValue = 1e-9, thresholdError = 1e-9) { + if (error > thresholdError) { + return new Array(matrix.rows + 1).fill(0); + } else { + let returnArray = matrix.addRow(index2, [0]); + for (let i = 0; i < returnArray.rows; i++) { + if (Math.abs(returnArray.get(i, 0)) < thresholdValue) { + returnArray.set(i, 0, 0); + } + } + return returnArray.to1DArray(); + } + } + function linearDependencies(matrix, options = {}) { + const { thresholdValue = 1e-9, thresholdError = 1e-9 } = options; + matrix = Matrix.checkMatrix(matrix); + let n = matrix.rows; + let results = new Matrix(n, n); + for (let i = 0; i < n; i++) { + let b = Matrix.columnVector(matrix.getRow(i)); + let Abis = matrix.subMatrixRow(xrange(n, i)).transpose(); + let svd = new SingularValueDecomposition(Abis); + let x3 = svd.solve(b); + let error = Matrix.sub(b, Abis.mmul(x3)).abs().max(); + results.setRow(i, dependenciesOneRow(error, x3, i, thresholdValue, thresholdError)); + } + return results; + } + function pseudoInverse(matrix, threshold = Number.EPSILON) { + matrix = Matrix.checkMatrix(matrix); + if (matrix.isEmpty()) { + return matrix.transpose(); + } + let svdSolution = new SingularValueDecomposition(matrix, { autoTranspose: true }); + let U = svdSolution.leftSingularVectors; + let V = svdSolution.rightSingularVectors; + let s = svdSolution.diagonal; + for (let i = 0; i < s.length; i++) { + if (Math.abs(s[i]) > threshold) { + s[i] = 1 / s[i]; + } else { + s[i] = 0; + } + } + return V.mmul(Matrix.diag(s).mmul(U.transpose())); + } + function covariance(xMatrix, yMatrix = xMatrix, options = {}) { + xMatrix = new Matrix(xMatrix); + let yIsSame = false; + if (typeof yMatrix === "object" && !Matrix.isMatrix(yMatrix) && !isAnyArray.isAnyArray(yMatrix)) { + options = yMatrix; + yMatrix = xMatrix; + yIsSame = true; + } else { + yMatrix = new Matrix(yMatrix); + } + if (xMatrix.rows !== yMatrix.rows) { + throw new TypeError("Both matrices must have the same number of rows"); + } + const { center = true } = options; + if (center) { + xMatrix = xMatrix.center("column"); + if (!yIsSame) { + yMatrix = yMatrix.center("column"); + } + } + const cov = xMatrix.transpose().mmul(yMatrix); + for (let i = 0; i < cov.rows; i++) { + for (let j = 0; j < cov.columns; j++) { + cov.set(i, j, cov.get(i, j) * (1 / (xMatrix.rows - 1))); + } + } + return cov; + } + function correlation(xMatrix, yMatrix = xMatrix, options = {}) { + xMatrix = new Matrix(xMatrix); + let yIsSame = false; + if (typeof yMatrix === "object" && !Matrix.isMatrix(yMatrix) && !isAnyArray.isAnyArray(yMatrix)) { + options = yMatrix; + yMatrix = xMatrix; + yIsSame = true; + } else { + yMatrix = new Matrix(yMatrix); + } + if (xMatrix.rows !== yMatrix.rows) { + throw new TypeError("Both matrices must have the same number of rows"); + } + const { center = true, scale: scale2 = true } = options; + if (center) { + xMatrix.center("column"); + if (!yIsSame) { + yMatrix.center("column"); + } + } + if (scale2) { + xMatrix.scale("column"); + if (!yIsSame) { + yMatrix.scale("column"); + } + } + const sdx = xMatrix.standardDeviation("column", { unbiased: true }); + const sdy = yIsSame ? sdx : yMatrix.standardDeviation("column", { unbiased: true }); + const corr = xMatrix.transpose().mmul(yMatrix); + for (let i = 0; i < corr.rows; i++) { + for (let j = 0; j < corr.columns; j++) { + corr.set(i, j, corr.get(i, j) * (1 / (sdx[i] * sdy[j])) * (1 / (xMatrix.rows - 1))); + } + } + return corr; + } + var EigenvalueDecomposition = class { + constructor(matrix, options = {}) { + const { assumeSymmetric = false } = options; + matrix = WrapperMatrix2D.checkMatrix(matrix); + if (!matrix.isSquare()) { + throw new Error("Matrix is not a square matrix"); + } + if (matrix.isEmpty()) { + throw new Error("Matrix must be non-empty"); + } + let n = matrix.columns; + let V = new Matrix(n, n); + let d = new Float64Array(n); + let e = new Float64Array(n); + let value = matrix; + let i, j; + let isSymmetric = false; + if (assumeSymmetric) { + isSymmetric = true; + } else { + isSymmetric = matrix.isSymmetric(); + } + if (isSymmetric) { + for (i = 0; i < n; i++) { + for (j = 0; j < n; j++) { + V.set(i, j, value.get(i, j)); + } + } + tred2(n, e, d, V); + tql2(n, e, d, V); + } else { + let H = new Matrix(n, n); + let ort = new Float64Array(n); + for (j = 0; j < n; j++) { + for (i = 0; i < n; i++) { + H.set(i, j, value.get(i, j)); + } + } + orthes(n, H, ort, V); + hqr2(n, e, d, V, H); + } + this.n = n; + this.e = e; + this.d = d; + this.V = V; + } + get realEigenvalues() { + return Array.from(this.d); + } + get imaginaryEigenvalues() { + return Array.from(this.e); + } + get eigenvectorMatrix() { + return this.V; + } + get diagonalMatrix() { + let n = this.n; + let e = this.e; + let d = this.d; + let X2 = new Matrix(n, n); + let i, j; + for (i = 0; i < n; i++) { + for (j = 0; j < n; j++) { + X2.set(i, j, 0); + } + X2.set(i, i, d[i]); + if (e[i] > 0) { + X2.set(i, i + 1, e[i]); + } else if (e[i] < 0) { + X2.set(i, i - 1, e[i]); + } + } + return X2; + } + }; + function tred2(n, e, d, V) { + let f, g, h, i, j, k, hh, scale2; + for (j = 0; j < n; j++) { + d[j] = V.get(n - 1, j); + } + for (i = n - 1; i > 0; i--) { + scale2 = 0; + h = 0; + for (k = 0; k < i; k++) { + scale2 = scale2 + Math.abs(d[k]); + } + if (scale2 === 0) { + e[i] = d[i - 1]; + for (j = 0; j < i; j++) { + d[j] = V.get(i - 1, j); + V.set(i, j, 0); + V.set(j, i, 0); + } + } else { + for (k = 0; k < i; k++) { + d[k] /= scale2; + h += d[k] * d[k]; + } + f = d[i - 1]; + g = Math.sqrt(h); + if (f > 0) { + g = -g; + } + e[i] = scale2 * g; + h = h - f * g; + d[i - 1] = f - g; + for (j = 0; j < i; j++) { + e[j] = 0; + } + for (j = 0; j < i; j++) { + f = d[j]; + V.set(j, i, f); + g = e[j] + V.get(j, j) * f; + for (k = j + 1; k <= i - 1; k++) { + g += V.get(k, j) * d[k]; + e[k] += V.get(k, j) * f; + } + e[j] = g; + } + f = 0; + for (j = 0; j < i; j++) { + e[j] /= h; + f += e[j] * d[j]; + } + hh = f / (h + h); + for (j = 0; j < i; j++) { + e[j] -= hh * d[j]; + } + for (j = 0; j < i; j++) { + f = d[j]; + g = e[j]; + for (k = j; k <= i - 1; k++) { + V.set(k, j, V.get(k, j) - (f * e[k] + g * d[k])); + } + d[j] = V.get(i - 1, j); + V.set(i, j, 0); + } + } + d[i] = h; + } + for (i = 0; i < n - 1; i++) { + V.set(n - 1, i, V.get(i, i)); + V.set(i, i, 1); + h = d[i + 1]; + if (h !== 0) { + for (k = 0; k <= i; k++) { + d[k] = V.get(k, i + 1) / h; + } + for (j = 0; j <= i; j++) { + g = 0; + for (k = 0; k <= i; k++) { + g += V.get(k, i + 1) * V.get(k, j); + } + for (k = 0; k <= i; k++) { + V.set(k, j, V.get(k, j) - g * d[k]); + } + } + } + for (k = 0; k <= i; k++) { + V.set(k, i + 1, 0); + } + } + for (j = 0; j < n; j++) { + d[j] = V.get(n - 1, j); + V.set(n - 1, j, 0); + } + V.set(n - 1, n - 1, 1); + e[0] = 0; + } + function tql2(n, e, d, V) { + let g, h, i, j, k, l, m2, p, r, dl1, c2, c22, c3, el1, s, s2; + for (i = 1; i < n; i++) { + e[i - 1] = e[i]; + } + e[n - 1] = 0; + let f = 0; + let tst1 = 0; + let eps = Number.EPSILON; + for (l = 0; l < n; l++) { + tst1 = Math.max(tst1, Math.abs(d[l]) + Math.abs(e[l])); + m2 = l; + while (m2 < n) { + if (Math.abs(e[m2]) <= eps * tst1) { + break; + } + m2++; + } + if (m2 > l) { + do { + g = d[l]; + p = (d[l + 1] - g) / (2 * e[l]); + r = hypotenuse(p, 1); + if (p < 0) { + r = -r; + } + d[l] = e[l] / (p + r); + d[l + 1] = e[l] * (p + r); + dl1 = d[l + 1]; + h = g - d[l]; + for (i = l + 2; i < n; i++) { + d[i] -= h; + } + f = f + h; + p = d[m2]; + c2 = 1; + c22 = c2; + c3 = c2; + el1 = e[l + 1]; + s = 0; + s2 = 0; + for (i = m2 - 1; i >= l; i--) { + c3 = c22; + c22 = c2; + s2 = s; + g = c2 * e[i]; + h = c2 * p; + r = hypotenuse(p, e[i]); + e[i + 1] = s * r; + s = e[i] / r; + c2 = p / r; + p = c2 * d[i] - s * g; + d[i + 1] = h + s * (c2 * g + s * d[i]); + for (k = 0; k < n; k++) { + h = V.get(k, i + 1); + V.set(k, i + 1, s * V.get(k, i) + c2 * h); + V.set(k, i, c2 * V.get(k, i) - s * h); + } + } + p = -s * s2 * c3 * el1 * e[l] / dl1; + e[l] = s * p; + d[l] = c2 * p; + } while (Math.abs(e[l]) > eps * tst1); + } + d[l] = d[l] + f; + e[l] = 0; + } + for (i = 0; i < n - 1; i++) { + k = i; + p = d[i]; + for (j = i + 1; j < n; j++) { + if (d[j] < p) { + k = j; + p = d[j]; + } + } + if (k !== i) { + d[k] = d[i]; + d[i] = p; + for (j = 0; j < n; j++) { + p = V.get(j, i); + V.set(j, i, V.get(j, k)); + V.set(j, k, p); + } + } + } + } + function orthes(n, H, ort, V) { + let low = 0; + let high = n - 1; + let f, g, h, i, j, m2; + let scale2; + for (m2 = low + 1; m2 <= high - 1; m2++) { + scale2 = 0; + for (i = m2; i <= high; i++) { + scale2 = scale2 + Math.abs(H.get(i, m2 - 1)); + } + if (scale2 !== 0) { + h = 0; + for (i = high; i >= m2; i--) { + ort[i] = H.get(i, m2 - 1) / scale2; + h += ort[i] * ort[i]; + } + g = Math.sqrt(h); + if (ort[m2] > 0) { + g = -g; + } + h = h - ort[m2] * g; + ort[m2] = ort[m2] - g; + for (j = m2; j < n; j++) { + f = 0; + for (i = high; i >= m2; i--) { + f += ort[i] * H.get(i, j); + } + f = f / h; + for (i = m2; i <= high; i++) { + H.set(i, j, H.get(i, j) - f * ort[i]); + } + } + for (i = 0; i <= high; i++) { + f = 0; + for (j = high; j >= m2; j--) { + f += ort[j] * H.get(i, j); + } + f = f / h; + for (j = m2; j <= high; j++) { + H.set(i, j, H.get(i, j) - f * ort[j]); + } + } + ort[m2] = scale2 * ort[m2]; + H.set(m2, m2 - 1, scale2 * g); + } + } + for (i = 0; i < n; i++) { + for (j = 0; j < n; j++) { + V.set(i, j, i === j ? 1 : 0); + } + } + for (m2 = high - 1; m2 >= low + 1; m2--) { + if (H.get(m2, m2 - 1) !== 0) { + for (i = m2 + 1; i <= high; i++) { + ort[i] = H.get(i, m2 - 1); + } + for (j = m2; j <= high; j++) { + g = 0; + for (i = m2; i <= high; i++) { + g += ort[i] * V.get(i, j); + } + g = g / ort[m2] / H.get(m2, m2 - 1); + for (i = m2; i <= high; i++) { + V.set(i, j, V.get(i, j) + g * ort[i]); + } + } + } + } + } + function hqr2(nn, e, d, V, H) { + let n = nn - 1; + let low = 0; + let high = nn - 1; + let eps = Number.EPSILON; + let exshift = 0; + let norm = 0; + let p = 0; + let q = 0; + let r = 0; + let s = 0; + let z = 0; + let iter = 0; + let i, j, k, l, m2, t, w, x3, y4; + let ra, sa, vr, vi; + let notlast, cdivres; + for (i = 0; i < nn; i++) { + if (i < low || i > high) { + d[i] = H.get(i, i); + e[i] = 0; + } + for (j = Math.max(i - 1, 0); j < nn; j++) { + norm = norm + Math.abs(H.get(i, j)); + } + } + while (n >= low) { + l = n; + while (l > low) { + s = Math.abs(H.get(l - 1, l - 1)) + Math.abs(H.get(l, l)); + if (s === 0) { + s = norm; + } + if (Math.abs(H.get(l, l - 1)) < eps * s) { + break; + } + l--; + } + if (l === n) { + H.set(n, n, H.get(n, n) + exshift); + d[n] = H.get(n, n); + e[n] = 0; + n--; + iter = 0; + } else if (l === n - 1) { + w = H.get(n, n - 1) * H.get(n - 1, n); + p = (H.get(n - 1, n - 1) - H.get(n, n)) / 2; + q = p * p + w; + z = Math.sqrt(Math.abs(q)); + H.set(n, n, H.get(n, n) + exshift); + H.set(n - 1, n - 1, H.get(n - 1, n - 1) + exshift); + x3 = H.get(n, n); + if (q >= 0) { + z = p >= 0 ? p + z : p - z; + d[n - 1] = x3 + z; + d[n] = d[n - 1]; + if (z !== 0) { + d[n] = x3 - w / z; + } + e[n - 1] = 0; + e[n] = 0; + x3 = H.get(n, n - 1); + s = Math.abs(x3) + Math.abs(z); + p = x3 / s; + q = z / s; + r = Math.sqrt(p * p + q * q); + p = p / r; + q = q / r; + for (j = n - 1; j < nn; j++) { + z = H.get(n - 1, j); + H.set(n - 1, j, q * z + p * H.get(n, j)); + H.set(n, j, q * H.get(n, j) - p * z); + } + for (i = 0; i <= n; i++) { + z = H.get(i, n - 1); + H.set(i, n - 1, q * z + p * H.get(i, n)); + H.set(i, n, q * H.get(i, n) - p * z); + } + for (i = low; i <= high; i++) { + z = V.get(i, n - 1); + V.set(i, n - 1, q * z + p * V.get(i, n)); + V.set(i, n, q * V.get(i, n) - p * z); + } + } else { + d[n - 1] = x3 + p; + d[n] = x3 + p; + e[n - 1] = z; + e[n] = -z; + } + n = n - 2; + iter = 0; + } else { + x3 = H.get(n, n); + y4 = 0; + w = 0; + if (l < n) { + y4 = H.get(n - 1, n - 1); + w = H.get(n, n - 1) * H.get(n - 1, n); + } + if (iter === 10) { + exshift += x3; + for (i = low; i <= n; i++) { + H.set(i, i, H.get(i, i) - x3); + } + s = Math.abs(H.get(n, n - 1)) + Math.abs(H.get(n - 1, n - 2)); + x3 = y4 = 0.75 * s; + w = -0.4375 * s * s; + } + if (iter === 30) { + s = (y4 - x3) / 2; + s = s * s + w; + if (s > 0) { + s = Math.sqrt(s); + if (y4 < x3) { + s = -s; + } + s = x3 - w / ((y4 - x3) / 2 + s); + for (i = low; i <= n; i++) { + H.set(i, i, H.get(i, i) - s); + } + exshift += s; + x3 = y4 = w = 0.964; + } + } + iter = iter + 1; + m2 = n - 2; + while (m2 >= l) { + z = H.get(m2, m2); + r = x3 - z; + s = y4 - z; + p = (r * s - w) / H.get(m2 + 1, m2) + H.get(m2, m2 + 1); + q = H.get(m2 + 1, m2 + 1) - z - r - s; + r = H.get(m2 + 2, m2 + 1); + s = Math.abs(p) + Math.abs(q) + Math.abs(r); + p = p / s; + q = q / s; + r = r / s; + if (m2 === l) { + break; + } + if (Math.abs(H.get(m2, m2 - 1)) * (Math.abs(q) + Math.abs(r)) < eps * (Math.abs(p) * (Math.abs(H.get(m2 - 1, m2 - 1)) + Math.abs(z) + Math.abs(H.get(m2 + 1, m2 + 1))))) { + break; + } + m2--; + } + for (i = m2 + 2; i <= n; i++) { + H.set(i, i - 2, 0); + if (i > m2 + 2) { + H.set(i, i - 3, 0); + } + } + for (k = m2; k <= n - 1; k++) { + notlast = k !== n - 1; + if (k !== m2) { + p = H.get(k, k - 1); + q = H.get(k + 1, k - 1); + r = notlast ? H.get(k + 2, k - 1) : 0; + x3 = Math.abs(p) + Math.abs(q) + Math.abs(r); + if (x3 !== 0) { + p = p / x3; + q = q / x3; + r = r / x3; + } + } + if (x3 === 0) { + break; + } + s = Math.sqrt(p * p + q * q + r * r); + if (p < 0) { + s = -s; + } + if (s !== 0) { + if (k !== m2) { + H.set(k, k - 1, -s * x3); + } else if (l !== m2) { + H.set(k, k - 1, -H.get(k, k - 1)); + } + p = p + s; + x3 = p / s; + y4 = q / s; + z = r / s; + q = q / p; + r = r / p; + for (j = k; j < nn; j++) { + p = H.get(k, j) + q * H.get(k + 1, j); + if (notlast) { + p = p + r * H.get(k + 2, j); + H.set(k + 2, j, H.get(k + 2, j) - p * z); + } + H.set(k, j, H.get(k, j) - p * x3); + H.set(k + 1, j, H.get(k + 1, j) - p * y4); + } + for (i = 0; i <= Math.min(n, k + 3); i++) { + p = x3 * H.get(i, k) + y4 * H.get(i, k + 1); + if (notlast) { + p = p + z * H.get(i, k + 2); + H.set(i, k + 2, H.get(i, k + 2) - p * r); + } + H.set(i, k, H.get(i, k) - p); + H.set(i, k + 1, H.get(i, k + 1) - p * q); + } + for (i = low; i <= high; i++) { + p = x3 * V.get(i, k) + y4 * V.get(i, k + 1); + if (notlast) { + p = p + z * V.get(i, k + 2); + V.set(i, k + 2, V.get(i, k + 2) - p * r); + } + V.set(i, k, V.get(i, k) - p); + V.set(i, k + 1, V.get(i, k + 1) - p * q); + } + } + } + } + } + if (norm === 0) { + return; + } + for (n = nn - 1; n >= 0; n--) { + p = d[n]; + q = e[n]; + if (q === 0) { + l = n; + H.set(n, n, 1); + for (i = n - 1; i >= 0; i--) { + w = H.get(i, i) - p; + r = 0; + for (j = l; j <= n; j++) { + r = r + H.get(i, j) * H.get(j, n); + } + if (e[i] < 0) { + z = w; + s = r; + } else { + l = i; + if (e[i] === 0) { + H.set(i, n, w !== 0 ? -r / w : -r / (eps * norm)); + } else { + x3 = H.get(i, i + 1); + y4 = H.get(i + 1, i); + q = (d[i] - p) * (d[i] - p) + e[i] * e[i]; + t = (x3 * s - z * r) / q; + H.set(i, n, t); + H.set(i + 1, n, Math.abs(x3) > Math.abs(z) ? (-r - w * t) / x3 : (-s - y4 * t) / z); + } + t = Math.abs(H.get(i, n)); + if (eps * t * t > 1) { + for (j = i; j <= n; j++) { + H.set(j, n, H.get(j, n) / t); + } + } + } + } + } else if (q < 0) { + l = n - 1; + if (Math.abs(H.get(n, n - 1)) > Math.abs(H.get(n - 1, n))) { + H.set(n - 1, n - 1, q / H.get(n, n - 1)); + H.set(n - 1, n, -(H.get(n, n) - p) / H.get(n, n - 1)); + } else { + cdivres = cdiv(0, -H.get(n - 1, n), H.get(n - 1, n - 1) - p, q); + H.set(n - 1, n - 1, cdivres[0]); + H.set(n - 1, n, cdivres[1]); + } + H.set(n, n - 1, 0); + H.set(n, n, 1); + for (i = n - 2; i >= 0; i--) { + ra = 0; + sa = 0; + for (j = l; j <= n; j++) { + ra = ra + H.get(i, j) * H.get(j, n - 1); + sa = sa + H.get(i, j) * H.get(j, n); + } + w = H.get(i, i) - p; + if (e[i] < 0) { + z = w; + r = ra; + s = sa; + } else { + l = i; + if (e[i] === 0) { + cdivres = cdiv(-ra, -sa, w, q); + H.set(i, n - 1, cdivres[0]); + H.set(i, n, cdivres[1]); + } else { + x3 = H.get(i, i + 1); + y4 = H.get(i + 1, i); + vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q; + vi = (d[i] - p) * 2 * q; + if (vr === 0 && vi === 0) { + vr = eps * norm * (Math.abs(w) + Math.abs(q) + Math.abs(x3) + Math.abs(y4) + Math.abs(z)); + } + cdivres = cdiv(x3 * r - z * ra + q * sa, x3 * s - z * sa - q * ra, vr, vi); + H.set(i, n - 1, cdivres[0]); + H.set(i, n, cdivres[1]); + if (Math.abs(x3) > Math.abs(z) + Math.abs(q)) { + H.set(i + 1, n - 1, (-ra - w * H.get(i, n - 1) + q * H.get(i, n)) / x3); + H.set(i + 1, n, (-sa - w * H.get(i, n) - q * H.get(i, n - 1)) / x3); + } else { + cdivres = cdiv(-r - y4 * H.get(i, n - 1), -s - y4 * H.get(i, n), z, q); + H.set(i + 1, n - 1, cdivres[0]); + H.set(i + 1, n, cdivres[1]); + } + } + t = Math.max(Math.abs(H.get(i, n - 1)), Math.abs(H.get(i, n))); + if (eps * t * t > 1) { + for (j = i; j <= n; j++) { + H.set(j, n - 1, H.get(j, n - 1) / t); + H.set(j, n, H.get(j, n) / t); + } + } + } + } + } + } + for (i = 0; i < nn; i++) { + if (i < low || i > high) { + for (j = i; j < nn; j++) { + V.set(i, j, H.get(i, j)); + } + } + } + for (j = nn - 1; j >= low; j--) { + for (i = low; i <= high; i++) { + z = 0; + for (k = low; k <= Math.min(j, high); k++) { + z = z + V.get(i, k) * H.get(k, j); + } + V.set(i, j, z); + } + } + } + function cdiv(xr, xi, yr, yi) { + let r, d; + if (Math.abs(yr) > Math.abs(yi)) { + r = yi / yr; + d = yr + r * yi; + return [(xr + r * xi) / d, (xi - r * xr) / d]; + } else { + r = yr / yi; + d = yi + r * yr; + return [(r * xr + xi) / d, (r * xi - xr) / d]; + } + } + var CholeskyDecomposition = class { + constructor(value) { + value = WrapperMatrix2D.checkMatrix(value); + if (!value.isSymmetric()) { + throw new Error("Matrix is not symmetric"); + } + let a2 = value; + let dimension = a2.rows; + let l = new Matrix(dimension, dimension); + let positiveDefinite = true; + let i, j, k; + for (j = 0; j < dimension; j++) { + let d = 0; + for (k = 0; k < j; k++) { + let s = 0; + for (i = 0; i < k; i++) { + s += l.get(k, i) * l.get(j, i); + } + s = (a2.get(j, k) - s) / l.get(k, k); + l.set(j, k, s); + d = d + s * s; + } + d = a2.get(j, j) - d; + positiveDefinite &= d > 0; + l.set(j, j, Math.sqrt(Math.max(d, 0))); + for (k = j + 1; k < dimension; k++) { + l.set(j, k, 0); + } + } + this.L = l; + this.positiveDefinite = Boolean(positiveDefinite); + } + isPositiveDefinite() { + return this.positiveDefinite; + } + solve(value) { + value = WrapperMatrix2D.checkMatrix(value); + let l = this.L; + let dimension = l.rows; + if (value.rows !== dimension) { + throw new Error("Matrix dimensions do not match"); + } + if (this.isPositiveDefinite() === false) { + throw new Error("Matrix is not positive definite"); + } + let count = value.columns; + let B2 = value.clone(); + let i, j, k; + for (k = 0; k < dimension; k++) { + for (j = 0; j < count; j++) { + for (i = 0; i < k; i++) { + B2.set(k, j, B2.get(k, j) - B2.get(i, j) * l.get(k, i)); + } + B2.set(k, j, B2.get(k, j) / l.get(k, k)); + } + } + for (k = dimension - 1; k >= 0; k--) { + for (j = 0; j < count; j++) { + for (i = k + 1; i < dimension; i++) { + B2.set(k, j, B2.get(k, j) - B2.get(i, j) * l.get(i, k)); + } + B2.set(k, j, B2.get(k, j) / l.get(k, k)); + } + } + return B2; + } + get lowerTriangularMatrix() { + return this.L; + } + }; + var nipals = class { + constructor(X2, options = {}) { + X2 = WrapperMatrix2D.checkMatrix(X2); + let { Y: Y2 } = options; + const { + scaleScores = false, + maxIterations = 1e3, + terminationCriteria = 1e-10 + } = options; + let u4; + if (Y2) { + if (isAnyArray.isAnyArray(Y2) && typeof Y2[0] === "number") { + Y2 = Matrix.columnVector(Y2); + } else { + Y2 = WrapperMatrix2D.checkMatrix(Y2); + } + if (Y2.rows !== X2.rows) { + throw new Error("Y should have the same number of rows as X"); + } + u4 = Y2.getColumnVector(0); + } else { + u4 = X2.getColumnVector(0); + } + let diff = 1; + let t, q, w, tOld; + for (let counter = 0; counter < maxIterations && diff > terminationCriteria; counter++) { + w = X2.transpose().mmul(u4).div(u4.transpose().mmul(u4).get(0, 0)); + w = w.div(w.norm()); + t = X2.mmul(w).div(w.transpose().mmul(w).get(0, 0)); + if (counter > 0) { + diff = t.clone().sub(tOld).pow(2).sum(); + } + tOld = t.clone(); + if (Y2) { + q = Y2.transpose().mmul(t).div(t.transpose().mmul(t).get(0, 0)); + q = q.div(q.norm()); + u4 = Y2.mmul(q).div(q.transpose().mmul(q).get(0, 0)); + } else { + u4 = t; + } + } + if (Y2) { + let p = X2.transpose().mmul(t).div(t.transpose().mmul(t).get(0, 0)); + p = p.div(p.norm()); + let xResidual = X2.clone().sub(t.clone().mmul(p.transpose())); + let residual = u4.transpose().mmul(t).div(t.transpose().mmul(t).get(0, 0)); + let yResidual = Y2.clone().sub(t.clone().mulS(residual.get(0, 0)).mmul(q.transpose())); + this.t = t; + this.p = p.transpose(); + this.w = w.transpose(); + this.q = q; + this.u = u4; + this.s = t.transpose().mmul(t); + this.xResidual = xResidual; + this.yResidual = yResidual; + this.betas = residual; + } else { + this.w = w.transpose(); + this.s = t.transpose().mmul(t).sqrt(); + if (scaleScores) { + this.t = t.clone().div(this.s.get(0, 0)); + } else { + this.t = t; + } + this.xResidual = X2.sub(t.mmul(w.transpose())); + } + } + }; + exports.AbstractMatrix = AbstractMatrix; + exports.CHO = CholeskyDecomposition; + exports.CholeskyDecomposition = CholeskyDecomposition; + exports.EVD = EigenvalueDecomposition; + exports.EigenvalueDecomposition = EigenvalueDecomposition; + exports.LU = LuDecomposition; + exports.LuDecomposition = LuDecomposition; + exports.Matrix = Matrix; + exports.MatrixColumnSelectionView = MatrixColumnSelectionView; + exports.MatrixColumnView = MatrixColumnView; + exports.MatrixFlipColumnView = MatrixFlipColumnView; + exports.MatrixFlipRowView = MatrixFlipRowView; + exports.MatrixRowSelectionView = MatrixRowSelectionView; + exports.MatrixRowView = MatrixRowView; + exports.MatrixSelectionView = MatrixSelectionView; + exports.MatrixSubView = MatrixSubView; + exports.MatrixTransposeView = MatrixTransposeView; + exports.NIPALS = nipals; + exports.Nipals = nipals; + exports.QR = QrDecomposition; + exports.QrDecomposition = QrDecomposition; + exports.SVD = SingularValueDecomposition; + exports.SingularValueDecomposition = SingularValueDecomposition; + exports.WrapperMatrix1D = WrapperMatrix1D; + exports.WrapperMatrix2D = WrapperMatrix2D; + exports.correlation = correlation; + exports.covariance = covariance; + exports["default"] = Matrix; + exports.determinant = determinant; + exports.inverse = inverse; + exports.linearDependencies = linearDependencies; + exports.pseudoInverse = pseudoInverse; + exports.solve = solve; + exports.wrap = wrap; + } + }); + + // node_modules/ml-levenberg-marquardt/lib/index.js + var require_lib6 = __commonJS({ + "node_modules/ml-levenberg-marquardt/lib/index.js"(exports, module) { + "use strict"; + function _interopDefault(ex) { + return ex && typeof ex === "object" && "default" in ex ? ex["default"] : ex; + } + var isArray = _interopDefault(require_lib()); + var mlMatrix = require_matrix2(); + function errorCalculation(data, parameters, parameterizedFunction) { + let error = 0; + const func = parameterizedFunction(parameters); + for (let i = 0; i < data.x.length; i++) { + error += Math.abs(data.y[i] - func(data.x[i])); + } + return error; + } + function gradientFunction(data, evaluatedData, params, gradientDifference, paramFunction) { + const n = params.length; + const m2 = data.x.length; + let ans = new Array(n); + for (let param = 0; param < n; param++) { + ans[param] = new Array(m2); + let auxParams = params.slice(); + auxParams[param] += gradientDifference; + let funcParam = paramFunction(auxParams); + for (let point = 0; point < m2; point++) { + ans[param][point] = evaluatedData[point] - funcParam(data.x[point]); + } + } + return new mlMatrix.Matrix(ans); + } + function matrixFunction(data, evaluatedData) { + const m2 = data.x.length; + let ans = new Array(m2); + for (let point = 0; point < m2; point++) { + ans[point] = [data.y[point] - evaluatedData[point]]; + } + return new mlMatrix.Matrix(ans); + } + function step(data, params, damping, gradientDifference, parameterizedFunction) { + let value = damping * gradientDifference * gradientDifference; + let identity4 = mlMatrix.Matrix.eye(params.length, params.length, value); + const func = parameterizedFunction(params); + let evaluatedData = new Float64Array(data.x.length); + for (let i = 0; i < data.x.length; i++) { + evaluatedData[i] = func(data.x[i]); + } + let gradientFunc = gradientFunction(data, evaluatedData, params, gradientDifference, parameterizedFunction); + let matrixFunc = matrixFunction(data, evaluatedData); + let inverseMatrix = mlMatrix.inverse(identity4.add(gradientFunc.mmul(gradientFunc.transpose()))); + params = new mlMatrix.Matrix([params]); + params = params.sub(inverseMatrix.mmul(gradientFunc).mmul(matrixFunc).mul(gradientDifference).transpose()); + return params.to1DArray(); + } + function levenbergMarquardt(data, parameterizedFunction, options = {}) { + let { + maxIterations = 100, + gradientDifference = 0.1, + damping = 0, + errorTolerance = 0.01, + minValues, + maxValues, + initialValues + } = options; + if (damping <= 0) { + throw new Error("The damping option must be a positive number"); + } else if (!data.x || !data.y) { + throw new Error("The data parameter must have x and y elements"); + } else if (!isArray(data.x) || data.x.length < 2 || !isArray(data.y) || data.y.length < 2) { + throw new Error("The data parameter elements must be an array with more than 2 points"); + } else if (data.x.length !== data.y.length) { + throw new Error("The data parameter elements must have the same size"); + } + let parameters = initialValues || new Array(parameterizedFunction.length).fill(1); + let parLen = parameters.length; + maxValues = maxValues || new Array(parLen).fill(Number.MAX_SAFE_INTEGER); + minValues = minValues || new Array(parLen).fill(Number.MIN_SAFE_INTEGER); + if (maxValues.length !== minValues.length) { + throw new Error("minValues and maxValues must be the same size"); + } + if (!isArray(parameters)) { + throw new Error("initialValues must be an array"); + } + let error = errorCalculation(data, parameters, parameterizedFunction); + let converged = error <= errorTolerance; + let iteration; + for (iteration = 0; iteration < maxIterations && !converged; iteration++) { + parameters = step(data, parameters, damping, gradientDifference, parameterizedFunction); + for (let k = 0; k < parLen; k++) { + parameters[k] = Math.min(Math.max(minValues[k], parameters[k]), maxValues[k]); + } + error = errorCalculation(data, parameters, parameterizedFunction); + if (isNaN(error)) + break; + converged = error <= errorTolerance; + } + return { + parameterValues: parameters, + parameterError: error, + iterations: iteration + }; + } + module.exports = levenbergMarquardt; + } + }); + + // node_modules/umap-js/dist/umap.js + var require_umap = __commonJS({ + "node_modules/umap-js/dist/umap.js"(exports) { + "use strict"; + var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : new P(function(resolve2) { + resolve2(result.value); + }).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __generator = exports && exports.__generator || function(thisArg, body) { + var _ = { label: 0, sent: function() { + if (t[0] & 1) + throw t[1]; + return t[1]; + }, trys: [], ops: [] }, f, y4, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { + return this; + }), g; + function verb(n) { + return function(v2) { + return step([n, v2]); + }; + } + function step(op) { + if (f) + throw new TypeError("Generator is already executing."); + while (_) + try { + if (f = 1, y4 && (t = op[0] & 2 ? y4["return"] : op[0] ? y4["throw"] || ((t = y4["return"]) && t.call(y4), 0) : y4.next) && !(t = t.call(y4, op[1])).done) + return t; + if (y4 = 0, t) + op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: + case 1: + t = op; + break; + case 4: + _.label++; + return { value: op[1], done: false }; + case 5: + _.label++; + y4 = op[1]; + op = [0]; + continue; + case 7: + op = _.ops.pop(); + _.trys.pop(); + continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { + _ = 0; + continue; + } + if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { + _.label = op[1]; + break; + } + if (op[0] === 6 && _.label < t[1]) { + _.label = t[1]; + t = op; + break; + } + if (t && _.label < t[2]) { + _.label = t[2]; + _.ops.push(op); + break; + } + if (t[2]) + _.ops.pop(); + _.trys.pop(); + continue; + } + op = body.call(thisArg, _); + } catch (e) { + op = [6, e]; + y4 = 0; + } finally { + f = t = 0; + } + if (op[0] & 5) + throw op[1]; + return { value: op[0] ? op[1] : void 0, done: true }; + } + }; + var __read = exports && exports.__read || function(o, n) { + var m2 = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m2) + return o; + var i = m2.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) + ar.push(r.value); + } catch (error) { + e = { error }; + } finally { + try { + if (r && !r.done && (m2 = i["return"])) + m2.call(i); + } finally { + if (e) + throw e.error; + } + } + return ar; + }; + var __spread = exports && exports.__spread || function() { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; + }; + var __importStar = exports && exports.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (Object.hasOwnProperty.call(mod, k)) + result[k] = mod[k]; + } + result["default"] = mod; + return result; + }; + var __importDefault = exports && exports.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + var heap = __importStar(require_heap()); + var matrix = __importStar(require_matrix()); + var nnDescent = __importStar(require_nn_descent()); + var tree = __importStar(require_tree()); + var utils = __importStar(require_utils()); + var ml_levenberg_marquardt_1 = __importDefault(require_lib6()); + var SMOOTH_K_TOLERANCE = 1e-5; + var MIN_K_DIST_SCALE = 1e-3; + var UMAP2 = function() { + function UMAP3(params) { + if (params === void 0) { + params = {}; + } + var _this = this; + this.learningRate = 1; + this.localConnectivity = 1; + this.minDist = 0.1; + this.nComponents = 2; + this.nEpochs = 0; + this.nNeighbors = 15; + this.negativeSampleRate = 5; + this.random = Math.random; + this.repulsionStrength = 1; + this.setOpMixRatio = 1; + this.spread = 1; + this.transformQueueSize = 4; + this.targetMetric = "categorical"; + this.targetWeight = 0.5; + this.targetNNeighbors = this.nNeighbors; + this.distanceFn = euclidean; + this.isInitialized = false; + this.rpForest = []; + this.embedding = []; + this.optimizationState = new OptimizationState(); + var setParam = function(key) { + if (params[key] !== void 0) + _this[key] = params[key]; + }; + setParam("distanceFn"); + setParam("learningRate"); + setParam("localConnectivity"); + setParam("minDist"); + setParam("nComponents"); + setParam("nEpochs"); + setParam("nNeighbors"); + setParam("negativeSampleRate"); + setParam("random"); + setParam("repulsionStrength"); + setParam("setOpMixRatio"); + setParam("spread"); + setParam("transformQueueSize"); + } + UMAP3.prototype.fit = function(X2) { + this.initializeFit(X2); + this.optimizeLayout(); + return this.embedding; + }; + UMAP3.prototype.fitAsync = function(X2, callback) { + if (callback === void 0) { + callback = function() { + return true; + }; + } + return __awaiter(this, void 0, void 0, function() { + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + this.initializeFit(X2); + return [4, this.optimizeLayoutAsync(callback)]; + case 1: + _a.sent(); + return [2, this.embedding]; + } + }); + }); + }; + UMAP3.prototype.setSupervisedProjection = function(Y2, params) { + if (params === void 0) { + params = {}; + } + this.Y = Y2; + this.targetMetric = params.targetMetric || this.targetMetric; + this.targetWeight = params.targetWeight || this.targetWeight; + this.targetNNeighbors = params.targetNNeighbors || this.targetNNeighbors; + }; + UMAP3.prototype.setPrecomputedKNN = function(knnIndices, knnDistances) { + this.knnIndices = knnIndices; + this.knnDistances = knnDistances; + }; + UMAP3.prototype.initializeFit = function(X2) { + if (X2.length <= this.nNeighbors) { + throw new Error("Not enough data points (" + X2.length + ") to create nNeighbors: " + this.nNeighbors + ". Add more data points or adjust the configuration."); + } + if (this.X === X2 && this.isInitialized) { + return this.getNEpochs(); + } + this.X = X2; + if (!this.knnIndices && !this.knnDistances) { + var knnResults = this.nearestNeighbors(X2); + this.knnIndices = knnResults.knnIndices; + this.knnDistances = knnResults.knnDistances; + } + this.graph = this.fuzzySimplicialSet(X2, this.nNeighbors, this.setOpMixRatio); + this.makeSearchFns(); + this.searchGraph = this.makeSearchGraph(X2); + this.processGraphForSupervisedProjection(); + var _a = this.initializeSimplicialSetEmbedding(), head = _a.head, tail = _a.tail, epochsPerSample = _a.epochsPerSample; + this.optimizationState.head = head; + this.optimizationState.tail = tail; + this.optimizationState.epochsPerSample = epochsPerSample; + this.initializeOptimization(); + this.prepareForOptimizationLoop(); + this.isInitialized = true; + return this.getNEpochs(); + }; + UMAP3.prototype.makeSearchFns = function() { + var _a = nnDescent.makeInitializations(this.distanceFn), initFromTree = _a.initFromTree, initFromRandom = _a.initFromRandom; + this.initFromTree = initFromTree; + this.initFromRandom = initFromRandom; + this.search = nnDescent.makeInitializedNNSearch(this.distanceFn); + }; + UMAP3.prototype.makeSearchGraph = function(X2) { + var knnIndices = this.knnIndices; + var knnDistances = this.knnDistances; + var dims = [X2.length, X2.length]; + var searchGraph = new matrix.SparseMatrix([], [], [], dims); + for (var i = 0; i < knnIndices.length; i++) { + var knn = knnIndices[i]; + var distances = knnDistances[i]; + for (var j = 0; j < knn.length; j++) { + var neighbor = knn[j]; + var distance = distances[j]; + if (distance > 0) { + searchGraph.set(i, neighbor, distance); + } + } + } + var transpose = matrix.transpose(searchGraph); + return matrix.maximum(searchGraph, transpose); + }; + UMAP3.prototype.transform = function(toTransform) { + var _this = this; + var rawData = this.X; + if (rawData === void 0 || rawData.length === 0) { + throw new Error("No data has been fit."); + } + var nNeighbors = Math.floor(this.nNeighbors * this.transformQueueSize); + nNeighbors = Math.min(rawData.length, nNeighbors); + var init2 = nnDescent.initializeSearch(this.rpForest, rawData, toTransform, nNeighbors, this.initFromRandom, this.initFromTree, this.random); + var result = this.search(rawData, this.searchGraph, init2, toTransform); + var _a = heap.deheapSort(result), indices = _a.indices, distances = _a.weights; + indices = indices.map(function(x3) { + return x3.slice(0, _this.nNeighbors); + }); + distances = distances.map(function(x3) { + return x3.slice(0, _this.nNeighbors); + }); + var adjustedLocalConnectivity = Math.max(0, this.localConnectivity - 1); + var _b = this.smoothKNNDistance(distances, this.nNeighbors, adjustedLocalConnectivity), sigmas = _b.sigmas, rhos = _b.rhos; + var _c = this.computeMembershipStrengths(indices, distances, sigmas, rhos), rows = _c.rows, cols = _c.cols, vals = _c.vals; + var size = [toTransform.length, rawData.length]; + var graph = new matrix.SparseMatrix(rows, cols, vals, size); + var normed = matrix.normalize(graph, "l1"); + var csrMatrix = matrix.getCSR(normed); + var nPoints = toTransform.length; + var eIndices = utils.reshape2d(csrMatrix.indices, nPoints, this.nNeighbors); + var eWeights = utils.reshape2d(csrMatrix.values, nPoints, this.nNeighbors); + var embedding = initTransform(eIndices, eWeights, this.embedding); + var nEpochs = this.nEpochs ? this.nEpochs / 3 : graph.nRows <= 1e4 ? 100 : 30; + var graphMax = graph.getValues().reduce(function(max3, val) { + return val > max3 ? val : max3; + }, 0); + graph = graph.map(function(value) { + return value < graphMax / nEpochs ? 0 : value; + }); + graph = matrix.eliminateZeros(graph); + var epochsPerSample = this.makeEpochsPerSample(graph.getValues(), nEpochs); + var head = graph.getRows(); + var tail = graph.getCols(); + this.assignOptimizationStateParameters({ + headEmbedding: embedding, + tailEmbedding: this.embedding, + head, + tail, + currentEpoch: 0, + nEpochs, + nVertices: graph.getDims()[1], + epochsPerSample + }); + this.prepareForOptimizationLoop(); + return this.optimizeLayout(); + }; + UMAP3.prototype.processGraphForSupervisedProjection = function() { + var _a = this, Y2 = _a.Y, X2 = _a.X; + if (Y2) { + if (Y2.length !== X2.length) { + throw new Error("Length of X and y must be equal"); + } + if (this.targetMetric === "categorical") { + var lt = this.targetWeight < 1; + var farDist = lt ? 2.5 * (1 / (1 - this.targetWeight)) : 1e12; + this.graph = this.categoricalSimplicialSetIntersection(this.graph, Y2, farDist); + } + } + }; + UMAP3.prototype.step = function() { + var currentEpoch = this.optimizationState.currentEpoch; + if (currentEpoch < this.getNEpochs()) { + this.optimizeLayoutStep(currentEpoch); + } + return this.optimizationState.currentEpoch; + }; + UMAP3.prototype.getEmbedding = function() { + return this.embedding; + }; + UMAP3.prototype.nearestNeighbors = function(X2) { + var _a = this, distanceFn = _a.distanceFn, nNeighbors = _a.nNeighbors; + var log2 = function(n) { + return Math.log(n) / Math.log(2); + }; + var metricNNDescent = nnDescent.makeNNDescent(distanceFn, this.random); + var round = function(n) { + return n === 0.5 ? 0 : Math.round(n); + }; + var nTrees = 5 + Math.floor(round(Math.pow(X2.length, 0.5) / 20)); + var nIters = Math.max(5, Math.floor(Math.round(log2(X2.length)))); + this.rpForest = tree.makeForest(X2, nNeighbors, nTrees, this.random); + var leafArray = tree.makeLeafArray(this.rpForest); + var _b = metricNNDescent(X2, leafArray, nNeighbors, nIters), indices = _b.indices, weights = _b.weights; + return { knnIndices: indices, knnDistances: weights }; + }; + UMAP3.prototype.fuzzySimplicialSet = function(X2, nNeighbors, setOpMixRatio) { + if (setOpMixRatio === void 0) { + setOpMixRatio = 1; + } + var _a = this, _b = _a.knnIndices, knnIndices = _b === void 0 ? [] : _b, _c = _a.knnDistances, knnDistances = _c === void 0 ? [] : _c, localConnectivity = _a.localConnectivity; + var _d = this.smoothKNNDistance(knnDistances, nNeighbors, localConnectivity), sigmas = _d.sigmas, rhos = _d.rhos; + var _e = this.computeMembershipStrengths(knnIndices, knnDistances, sigmas, rhos), rows = _e.rows, cols = _e.cols, vals = _e.vals; + var size = [X2.length, X2.length]; + var sparseMatrix = new matrix.SparseMatrix(rows, cols, vals, size); + var transpose = matrix.transpose(sparseMatrix); + var prodMatrix = matrix.pairwiseMultiply(sparseMatrix, transpose); + var a2 = matrix.subtract(matrix.add(sparseMatrix, transpose), prodMatrix); + var b = matrix.multiplyScalar(a2, setOpMixRatio); + var c2 = matrix.multiplyScalar(prodMatrix, 1 - setOpMixRatio); + var result = matrix.add(b, c2); + return result; + }; + UMAP3.prototype.categoricalSimplicialSetIntersection = function(simplicialSet, target, farDist, unknownDist) { + if (unknownDist === void 0) { + unknownDist = 1; + } + var intersection = fastIntersection(simplicialSet, target, unknownDist, farDist); + intersection = matrix.eliminateZeros(intersection); + return resetLocalConnectivity(intersection); + }; + UMAP3.prototype.smoothKNNDistance = function(distances, k, localConnectivity, nIter, bandwidth) { + if (localConnectivity === void 0) { + localConnectivity = 1; + } + if (nIter === void 0) { + nIter = 64; + } + if (bandwidth === void 0) { + bandwidth = 1; + } + var target = Math.log(k) / Math.log(2) * bandwidth; + var rho = utils.zeros(distances.length); + var result = utils.zeros(distances.length); + for (var i = 0; i < distances.length; i++) { + var lo = 0; + var hi = Infinity; + var mid = 1; + var ithDistances = distances[i]; + var nonZeroDists = ithDistances.filter(function(d2) { + return d2 > 0; + }); + if (nonZeroDists.length >= localConnectivity) { + var index2 = Math.floor(localConnectivity); + var interpolation = localConnectivity - index2; + if (index2 > 0) { + rho[i] = nonZeroDists[index2 - 1]; + if (interpolation > SMOOTH_K_TOLERANCE) { + rho[i] += interpolation * (nonZeroDists[index2] - nonZeroDists[index2 - 1]); + } + } else { + rho[i] = interpolation * nonZeroDists[0]; + } + } else if (nonZeroDists.length > 0) { + rho[i] = utils.max(nonZeroDists); + } + for (var n = 0; n < nIter; n++) { + var psum = 0; + for (var j = 1; j < distances[i].length; j++) { + var d = distances[i][j] - rho[i]; + if (d > 0) { + psum += Math.exp(-(d / mid)); + } else { + psum += 1; + } + } + if (Math.abs(psum - target) < SMOOTH_K_TOLERANCE) { + break; + } + if (psum > target) { + hi = mid; + mid = (lo + hi) / 2; + } else { + lo = mid; + if (hi === Infinity) { + mid *= 2; + } else { + mid = (lo + hi) / 2; + } + } + } + result[i] = mid; + if (rho[i] > 0) { + var meanIthDistances = utils.mean(ithDistances); + if (result[i] < MIN_K_DIST_SCALE * meanIthDistances) { + result[i] = MIN_K_DIST_SCALE * meanIthDistances; + } + } else { + var meanDistances = utils.mean(distances.map(utils.mean)); + if (result[i] < MIN_K_DIST_SCALE * meanDistances) { + result[i] = MIN_K_DIST_SCALE * meanDistances; + } + } + } + return { sigmas: result, rhos: rho }; + }; + UMAP3.prototype.computeMembershipStrengths = function(knnIndices, knnDistances, sigmas, rhos) { + var nSamples = knnIndices.length; + var nNeighbors = knnIndices[0].length; + var rows = utils.zeros(nSamples * nNeighbors); + var cols = utils.zeros(nSamples * nNeighbors); + var vals = utils.zeros(nSamples * nNeighbors); + for (var i = 0; i < nSamples; i++) { + for (var j = 0; j < nNeighbors; j++) { + var val = 0; + if (knnIndices[i][j] === -1) { + continue; + } + if (knnIndices[i][j] === i) { + val = 0; + } else if (knnDistances[i][j] - rhos[i] <= 0) { + val = 1; + } else { + val = Math.exp(-((knnDistances[i][j] - rhos[i]) / sigmas[i])); + } + rows[i * nNeighbors + j] = i; + cols[i * nNeighbors + j] = knnIndices[i][j]; + vals[i * nNeighbors + j] = val; + } + } + return { rows, cols, vals }; + }; + UMAP3.prototype.initializeSimplicialSetEmbedding = function() { + var _this = this; + var nEpochs = this.getNEpochs(); + var nComponents = this.nComponents; + var graphValues = this.graph.getValues(); + var graphMax = 0; + for (var i = 0; i < graphValues.length; i++) { + var value = graphValues[i]; + if (graphMax < graphValues[i]) { + graphMax = value; + } + } + var graph = this.graph.map(function(value2) { + if (value2 < graphMax / nEpochs) { + return 0; + } else { + return value2; + } + }); + this.embedding = utils.zeros(graph.nRows).map(function() { + return utils.zeros(nComponents).map(function() { + return utils.tauRand(_this.random) * 20 + -10; + }); + }); + var weights = []; + var head = []; + var tail = []; + var rowColValues = graph.getAll(); + for (var i = 0; i < rowColValues.length; i++) { + var entry = rowColValues[i]; + if (entry.value) { + weights.push(entry.value); + tail.push(entry.row); + head.push(entry.col); + } + } + var epochsPerSample = this.makeEpochsPerSample(weights, nEpochs); + return { head, tail, epochsPerSample }; + }; + UMAP3.prototype.makeEpochsPerSample = function(weights, nEpochs) { + var result = utils.filled(weights.length, -1); + var max3 = utils.max(weights); + var nSamples = weights.map(function(w) { + return w / max3 * nEpochs; + }); + nSamples.forEach(function(n, i) { + if (n > 0) + result[i] = nEpochs / nSamples[i]; + }); + return result; + }; + UMAP3.prototype.assignOptimizationStateParameters = function(state) { + Object.assign(this.optimizationState, state); + }; + UMAP3.prototype.prepareForOptimizationLoop = function() { + var _a = this, repulsionStrength = _a.repulsionStrength, learningRate = _a.learningRate, negativeSampleRate = _a.negativeSampleRate; + var _b = this.optimizationState, epochsPerSample = _b.epochsPerSample, headEmbedding = _b.headEmbedding, tailEmbedding = _b.tailEmbedding; + var dim = headEmbedding[0].length; + var moveOther = headEmbedding.length === tailEmbedding.length; + var epochsPerNegativeSample = epochsPerSample.map(function(e) { + return e / negativeSampleRate; + }); + var epochOfNextNegativeSample = __spread(epochsPerNegativeSample); + var epochOfNextSample = __spread(epochsPerSample); + this.assignOptimizationStateParameters({ + epochOfNextSample, + epochOfNextNegativeSample, + epochsPerNegativeSample, + moveOther, + initialAlpha: learningRate, + alpha: learningRate, + gamma: repulsionStrength, + dim + }); + }; + UMAP3.prototype.initializeOptimization = function() { + var headEmbedding = this.embedding; + var tailEmbedding = this.embedding; + var _a = this.optimizationState, head = _a.head, tail = _a.tail, epochsPerSample = _a.epochsPerSample; + var nEpochs = this.getNEpochs(); + var nVertices = this.graph.nCols; + var _b = findABParams(this.spread, this.minDist), a2 = _b.a, b = _b.b; + this.assignOptimizationStateParameters({ + headEmbedding, + tailEmbedding, + head, + tail, + epochsPerSample, + a: a2, + b, + nEpochs, + nVertices + }); + }; + UMAP3.prototype.optimizeLayoutStep = function(n) { + var optimizationState = this.optimizationState; + var head = optimizationState.head, tail = optimizationState.tail, headEmbedding = optimizationState.headEmbedding, tailEmbedding = optimizationState.tailEmbedding, epochsPerSample = optimizationState.epochsPerSample, epochOfNextSample = optimizationState.epochOfNextSample, epochOfNextNegativeSample = optimizationState.epochOfNextNegativeSample, epochsPerNegativeSample = optimizationState.epochsPerNegativeSample, moveOther = optimizationState.moveOther, initialAlpha = optimizationState.initialAlpha, alpha = optimizationState.alpha, gamma2 = optimizationState.gamma, a2 = optimizationState.a, b = optimizationState.b, dim = optimizationState.dim, nEpochs = optimizationState.nEpochs, nVertices = optimizationState.nVertices; + var clipValue = 4; + for (var i = 0; i < epochsPerSample.length; i++) { + if (epochOfNextSample[i] > n) { + continue; + } + var j = head[i]; + var k = tail[i]; + var current = headEmbedding[j]; + var other = tailEmbedding[k]; + var distSquared = rDist(current, other); + var gradCoeff = 0; + if (distSquared > 0) { + gradCoeff = -2 * a2 * b * Math.pow(distSquared, b - 1); + gradCoeff /= a2 * Math.pow(distSquared, b) + 1; + } + for (var d = 0; d < dim; d++) { + var gradD = clip(gradCoeff * (current[d] - other[d]), clipValue); + current[d] += gradD * alpha; + if (moveOther) { + other[d] += -gradD * alpha; + } + } + epochOfNextSample[i] += epochsPerSample[i]; + var nNegSamples = Math.floor((n - epochOfNextNegativeSample[i]) / epochsPerNegativeSample[i]); + for (var p = 0; p < nNegSamples; p++) { + var k_1 = utils.tauRandInt(nVertices, this.random); + var other_1 = tailEmbedding[k_1]; + var distSquared_1 = rDist(current, other_1); + var gradCoeff_1 = 0; + if (distSquared_1 > 0) { + gradCoeff_1 = 2 * gamma2 * b; + gradCoeff_1 /= (1e-3 + distSquared_1) * (a2 * Math.pow(distSquared_1, b) + 1); + } else if (j === k_1) { + continue; + } + for (var d = 0; d < dim; d++) { + var gradD = 4; + if (gradCoeff_1 > 0) { + gradD = clip(gradCoeff_1 * (current[d] - other_1[d]), clipValue); + } + current[d] += gradD * alpha; + } + } + epochOfNextNegativeSample[i] += nNegSamples * epochsPerNegativeSample[i]; + } + optimizationState.alpha = initialAlpha * (1 - n / nEpochs); + optimizationState.currentEpoch += 1; + return headEmbedding; + }; + UMAP3.prototype.optimizeLayoutAsync = function(epochCallback) { + var _this = this; + if (epochCallback === void 0) { + epochCallback = function() { + return true; + }; + } + return new Promise(function(resolve, reject) { + var step = function() { + return __awaiter(_this, void 0, void 0, function() { + var _a, nEpochs, currentEpoch, epochCompleted, shouldStop, isFinished; + return __generator(this, function(_b) { + try { + _a = this.optimizationState, nEpochs = _a.nEpochs, currentEpoch = _a.currentEpoch; + this.embedding = this.optimizeLayoutStep(currentEpoch); + epochCompleted = this.optimizationState.currentEpoch; + shouldStop = epochCallback(epochCompleted) === false; + isFinished = epochCompleted === nEpochs; + if (!shouldStop && !isFinished) { + setTimeout(function() { + return step(); + }, 0); + } else { + return [2, resolve(isFinished)]; + } + } catch (err) { + reject(err); + } + return [2]; + }); + }); + }; + setTimeout(function() { + return step(); + }, 0); + }); + }; + UMAP3.prototype.optimizeLayout = function(epochCallback) { + if (epochCallback === void 0) { + epochCallback = function() { + return true; + }; + } + var isFinished = false; + var embedding = []; + while (!isFinished) { + var _a = this.optimizationState, nEpochs = _a.nEpochs, currentEpoch = _a.currentEpoch; + embedding = this.optimizeLayoutStep(currentEpoch); + var epochCompleted = this.optimizationState.currentEpoch; + var shouldStop = epochCallback(epochCompleted) === false; + isFinished = epochCompleted === nEpochs || shouldStop; + } + return embedding; + }; + UMAP3.prototype.getNEpochs = function() { + var graph = this.graph; + if (this.nEpochs > 0) { + return this.nEpochs; + } + var length = graph.nRows; + if (length <= 2500) { + return 500; + } else if (length <= 5e3) { + return 400; + } else if (length <= 7500) { + return 300; + } else { + return 200; + } + }; + return UMAP3; + }(); + exports.UMAP = UMAP2; + function euclidean(x3, y4) { + var result = 0; + for (var i = 0; i < x3.length; i++) { + result += Math.pow(x3[i] - y4[i], 2); + } + return Math.sqrt(result); + } + exports.euclidean = euclidean; + function cosine(x3, y4) { + var result = 0; + var normX = 0; + var normY = 0; + for (var i = 0; i < x3.length; i++) { + result += x3[i] * y4[i]; + normX += Math.pow(x3[i], 2); + normY += Math.pow(y4[i], 2); + } + if (normX === 0 && normY === 0) { + return 0; + } else if (normX === 0 || normY === 0) { + return 1; + } else { + return 1 - result / Math.sqrt(normX * normY); + } + } + exports.cosine = cosine; + var OptimizationState = function() { + function OptimizationState2() { + this.currentEpoch = 0; + this.headEmbedding = []; + this.tailEmbedding = []; + this.head = []; + this.tail = []; + this.epochsPerSample = []; + this.epochOfNextSample = []; + this.epochOfNextNegativeSample = []; + this.epochsPerNegativeSample = []; + this.moveOther = true; + this.initialAlpha = 1; + this.alpha = 1; + this.gamma = 1; + this.a = 1.5769434603113077; + this.b = 0.8950608779109733; + this.dim = 2; + this.nEpochs = 500; + this.nVertices = 0; + } + return OptimizationState2; + }(); + function clip(x3, clipValue) { + if (x3 > clipValue) + return clipValue; + else if (x3 < -clipValue) + return -clipValue; + else + return x3; + } + function rDist(x3, y4) { + var result = 0; + for (var i = 0; i < x3.length; i++) { + result += Math.pow(x3[i] - y4[i], 2); + } + return result; + } + function findABParams(spread, minDist) { + var curve = function(_a2) { + var _b = __read(_a2, 2), a3 = _b[0], b2 = _b[1]; + return function(x3) { + return 1 / (1 + a3 * Math.pow(x3, 2 * b2)); + }; + }; + var xv = utils.linear(0, spread * 3, 300).map(function(val) { + return val < minDist ? 1 : val; + }); + var yv = utils.zeros(xv.length).map(function(val, index2) { + var gte = xv[index2] >= minDist; + return gte ? Math.exp(-(xv[index2] - minDist) / spread) : val; + }); + var initialValues = [0.5, 0.5]; + var data = { x: xv, y: yv }; + var options = { + damping: 1.5, + initialValues, + gradientDifference: 0.1, + maxIterations: 100, + errorTolerance: 0.01 + }; + var parameterValues = ml_levenberg_marquardt_1.default(data, curve, options).parameterValues; + var _a = __read(parameterValues, 2), a2 = _a[0], b = _a[1]; + return { a: a2, b }; + } + exports.findABParams = findABParams; + function fastIntersection(graph, target, unknownDist, farDist) { + if (unknownDist === void 0) { + unknownDist = 1; + } + if (farDist === void 0) { + farDist = 5; + } + return graph.map(function(value, row, col) { + if (target[row] === -1 || target[col] === -1) { + return value * Math.exp(-unknownDist); + } else if (target[row] !== target[col]) { + return value * Math.exp(-farDist); + } else { + return value; + } + }); + } + exports.fastIntersection = fastIntersection; + function resetLocalConnectivity(simplicialSet) { + simplicialSet = matrix.normalize(simplicialSet, "max"); + var transpose = matrix.transpose(simplicialSet); + var prodMatrix = matrix.pairwiseMultiply(transpose, simplicialSet); + simplicialSet = matrix.add(simplicialSet, matrix.subtract(transpose, prodMatrix)); + return matrix.eliminateZeros(simplicialSet); + } + exports.resetLocalConnectivity = resetLocalConnectivity; + function initTransform(indices, weights, embedding) { + var result = utils.zeros(indices.length).map(function(z) { + return utils.zeros(embedding[0].length); + }); + for (var i = 0; i < indices.length; i++) { + for (var j = 0; j < indices[0].length; j++) { + for (var d = 0; d < embedding[0].length; d++) { + var a2 = indices[i][j]; + result[i][d] += weights[i][j] * embedding[a2][d]; + } + } + } + return result; + } + exports.initTransform = initTransform; + } + }); + + // node_modules/umap-js/dist/index.js + var require_dist = __commonJS({ + "node_modules/umap-js/dist/index.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + var umap_1 = require_umap(); + exports.UMAP = umap_1.UMAP; + } + }); + + // node_modules/seedrandom/lib/alea.js + var require_alea = __commonJS({ + "node_modules/seedrandom/lib/alea.js"(exports, module) { + (function(global, module2, define2) { + function Alea(seed) { + var me = this, mash = Mash(); + me.next = function() { + var t = 2091639 * me.s0 + me.c * 23283064365386963e-26; + me.s0 = me.s1; + me.s1 = me.s2; + return me.s2 = t - (me.c = t | 0); + }; + me.c = 1; + me.s0 = mash(" "); + me.s1 = mash(" "); + me.s2 = mash(" "); + me.s0 -= mash(seed); + if (me.s0 < 0) { + me.s0 += 1; + } + me.s1 -= mash(seed); + if (me.s1 < 0) { + me.s1 += 1; + } + me.s2 -= mash(seed); + if (me.s2 < 0) { + me.s2 += 1; + } + mash = null; + } + function copy2(f, t) { + t.c = f.c; + t.s0 = f.s0; + t.s1 = f.s1; + t.s2 = f.s2; + return t; + } + function impl(seed, opts) { + var xg = new Alea(seed), state = opts && opts.state, prng = xg.next; + prng.int32 = function() { + return xg.next() * 4294967296 | 0; + }; + prng.double = function() { + return prng() + (prng() * 2097152 | 0) * 11102230246251565e-32; + }; + prng.quick = prng; + if (state) { + if (typeof state == "object") + copy2(state, xg); + prng.state = function() { + return copy2(xg, {}); + }; + } + return prng; + } + function Mash() { + var n = 4022871197; + var mash = function(data) { + data = String(data); + for (var i = 0; i < data.length; i++) { + n += data.charCodeAt(i); + var h = 0.02519603282416938 * n; + n = h >>> 0; + h -= n; + h *= n; + n = h >>> 0; + h -= n; + n += h * 4294967296; + } + return (n >>> 0) * 23283064365386963e-26; + }; + return mash; + } + if (module2 && module2.exports) { + module2.exports = impl; + } else if (define2 && define2.amd) { + define2(function() { + return impl; + }); + } else { + this.alea = impl; + } + })(exports, typeof module == "object" && module, typeof define == "function" && define); + } + }); + + // node_modules/seedrandom/lib/xor128.js + var require_xor128 = __commonJS({ + "node_modules/seedrandom/lib/xor128.js"(exports, module) { + (function(global, module2, define2) { + function XorGen(seed) { + var me = this, strseed = ""; + me.x = 0; + me.y = 0; + me.z = 0; + me.w = 0; + me.next = function() { + var t = me.x ^ me.x << 11; + me.x = me.y; + me.y = me.z; + me.z = me.w; + return me.w ^= me.w >>> 19 ^ t ^ t >>> 8; + }; + if (seed === (seed | 0)) { + me.x = seed; + } else { + strseed += seed; + } + for (var k = 0; k < strseed.length + 64; k++) { + me.x ^= strseed.charCodeAt(k) | 0; + me.next(); + } + } + function copy2(f, t) { + t.x = f.x; + t.y = f.y; + t.z = f.z; + t.w = f.w; + return t; + } + function impl(seed, opts) { + var xg = new XorGen(seed), state = opts && opts.state, prng = function() { + return (xg.next() >>> 0) / 4294967296; + }; + prng.double = function() { + do { + var top = xg.next() >>> 11, bot = (xg.next() >>> 0) / 4294967296, result = (top + bot) / (1 << 21); + } while (result === 0); + return result; + }; + prng.int32 = xg.next; + prng.quick = prng; + if (state) { + if (typeof state == "object") + copy2(state, xg); + prng.state = function() { + return copy2(xg, {}); + }; + } + return prng; + } + if (module2 && module2.exports) { + module2.exports = impl; + } else if (define2 && define2.amd) { + define2(function() { + return impl; + }); + } else { + this.xor128 = impl; + } + })(exports, typeof module == "object" && module, typeof define == "function" && define); + } + }); + + // node_modules/seedrandom/lib/xorwow.js + var require_xorwow = __commonJS({ + "node_modules/seedrandom/lib/xorwow.js"(exports, module) { + (function(global, module2, define2) { + function XorGen(seed) { + var me = this, strseed = ""; + me.next = function() { + var t = me.x ^ me.x >>> 2; + me.x = me.y; + me.y = me.z; + me.z = me.w; + me.w = me.v; + return (me.d = me.d + 362437 | 0) + (me.v = me.v ^ me.v << 4 ^ (t ^ t << 1)) | 0; + }; + me.x = 0; + me.y = 0; + me.z = 0; + me.w = 0; + me.v = 0; + if (seed === (seed | 0)) { + me.x = seed; + } else { + strseed += seed; + } + for (var k = 0; k < strseed.length + 64; k++) { + me.x ^= strseed.charCodeAt(k) | 0; + if (k == strseed.length) { + me.d = me.x << 10 ^ me.x >>> 4; + } + me.next(); + } + } + function copy2(f, t) { + t.x = f.x; + t.y = f.y; + t.z = f.z; + t.w = f.w; + t.v = f.v; + t.d = f.d; + return t; + } + function impl(seed, opts) { + var xg = new XorGen(seed), state = opts && opts.state, prng = function() { + return (xg.next() >>> 0) / 4294967296; + }; + prng.double = function() { + do { + var top = xg.next() >>> 11, bot = (xg.next() >>> 0) / 4294967296, result = (top + bot) / (1 << 21); + } while (result === 0); + return result; + }; + prng.int32 = xg.next; + prng.quick = prng; + if (state) { + if (typeof state == "object") + copy2(state, xg); + prng.state = function() { + return copy2(xg, {}); + }; + } + return prng; + } + if (module2 && module2.exports) { + module2.exports = impl; + } else if (define2 && define2.amd) { + define2(function() { + return impl; + }); + } else { + this.xorwow = impl; + } + })(exports, typeof module == "object" && module, typeof define == "function" && define); + } + }); + + // node_modules/seedrandom/lib/xorshift7.js + var require_xorshift7 = __commonJS({ + "node_modules/seedrandom/lib/xorshift7.js"(exports, module) { + (function(global, module2, define2) { + function XorGen(seed) { + var me = this; + me.next = function() { + var X2 = me.x, i = me.i, t, v2, w; + t = X2[i]; + t ^= t >>> 7; + v2 = t ^ t << 24; + t = X2[i + 1 & 7]; + v2 ^= t ^ t >>> 10; + t = X2[i + 3 & 7]; + v2 ^= t ^ t >>> 3; + t = X2[i + 4 & 7]; + v2 ^= t ^ t << 7; + t = X2[i + 7 & 7]; + t = t ^ t << 13; + v2 ^= t ^ t << 9; + X2[i] = v2; + me.i = i + 1 & 7; + return v2; + }; + function init2(me2, seed2) { + var j, w, X2 = []; + if (seed2 === (seed2 | 0)) { + w = X2[0] = seed2; + } else { + seed2 = "" + seed2; + for (j = 0; j < seed2.length; ++j) { + X2[j & 7] = X2[j & 7] << 15 ^ seed2.charCodeAt(j) + X2[j + 1 & 7] << 13; + } + } + while (X2.length < 8) + X2.push(0); + for (j = 0; j < 8 && X2[j] === 0; ++j) + ; + if (j == 8) + w = X2[7] = -1; + else + w = X2[j]; + me2.x = X2; + me2.i = 0; + for (j = 256; j > 0; --j) { + me2.next(); + } + } + init2(me, seed); + } + function copy2(f, t) { + t.x = f.x.slice(); + t.i = f.i; + return t; + } + function impl(seed, opts) { + if (seed == null) + seed = +new Date(); + var xg = new XorGen(seed), state = opts && opts.state, prng = function() { + return (xg.next() >>> 0) / 4294967296; + }; + prng.double = function() { + do { + var top = xg.next() >>> 11, bot = (xg.next() >>> 0) / 4294967296, result = (top + bot) / (1 << 21); + } while (result === 0); + return result; + }; + prng.int32 = xg.next; + prng.quick = prng; + if (state) { + if (state.x) + copy2(state, xg); + prng.state = function() { + return copy2(xg, {}); + }; + } + return prng; + } + if (module2 && module2.exports) { + module2.exports = impl; + } else if (define2 && define2.amd) { + define2(function() { + return impl; + }); + } else { + this.xorshift7 = impl; + } + })(exports, typeof module == "object" && module, typeof define == "function" && define); + } + }); + + // node_modules/seedrandom/lib/xor4096.js + var require_xor4096 = __commonJS({ + "node_modules/seedrandom/lib/xor4096.js"(exports, module) { + (function(global, module2, define2) { + function XorGen(seed) { + var me = this; + me.next = function() { + var w = me.w, X2 = me.X, i = me.i, t, v2; + me.w = w = w + 1640531527 | 0; + v2 = X2[i + 34 & 127]; + t = X2[i = i + 1 & 127]; + v2 ^= v2 << 13; + t ^= t << 17; + v2 ^= v2 >>> 15; + t ^= t >>> 12; + v2 = X2[i] = v2 ^ t; + me.i = i; + return v2 + (w ^ w >>> 16) | 0; + }; + function init2(me2, seed2) { + var t, v2, i, j, w, X2 = [], limit = 128; + if (seed2 === (seed2 | 0)) { + v2 = seed2; + seed2 = null; + } else { + seed2 = seed2 + "\0"; + v2 = 0; + limit = Math.max(limit, seed2.length); + } + for (i = 0, j = -32; j < limit; ++j) { + if (seed2) + v2 ^= seed2.charCodeAt((j + 32) % seed2.length); + if (j === 0) + w = v2; + v2 ^= v2 << 10; + v2 ^= v2 >>> 15; + v2 ^= v2 << 4; + v2 ^= v2 >>> 13; + if (j >= 0) { + w = w + 1640531527 | 0; + t = X2[j & 127] ^= v2 + w; + i = t == 0 ? i + 1 : 0; + } + } + if (i >= 128) { + X2[(seed2 && seed2.length || 0) & 127] = -1; + } + i = 127; + for (j = 4 * 128; j > 0; --j) { + v2 = X2[i + 34 & 127]; + t = X2[i = i + 1 & 127]; + v2 ^= v2 << 13; + t ^= t << 17; + v2 ^= v2 >>> 15; + t ^= t >>> 12; + X2[i] = v2 ^ t; + } + me2.w = w; + me2.X = X2; + me2.i = i; + } + init2(me, seed); + } + function copy2(f, t) { + t.i = f.i; + t.w = f.w; + t.X = f.X.slice(); + return t; + } + ; + function impl(seed, opts) { + if (seed == null) + seed = +new Date(); + var xg = new XorGen(seed), state = opts && opts.state, prng = function() { + return (xg.next() >>> 0) / 4294967296; + }; + prng.double = function() { + do { + var top = xg.next() >>> 11, bot = (xg.next() >>> 0) / 4294967296, result = (top + bot) / (1 << 21); + } while (result === 0); + return result; + }; + prng.int32 = xg.next; + prng.quick = prng; + if (state) { + if (state.X) + copy2(state, xg); + prng.state = function() { + return copy2(xg, {}); + }; + } + return prng; + } + if (module2 && module2.exports) { + module2.exports = impl; + } else if (define2 && define2.amd) { + define2(function() { + return impl; + }); + } else { + this.xor4096 = impl; + } + })(exports, typeof module == "object" && module, typeof define == "function" && define); + } + }); + + // node_modules/seedrandom/lib/tychei.js + var require_tychei = __commonJS({ + "node_modules/seedrandom/lib/tychei.js"(exports, module) { + (function(global, module2, define2) { + function XorGen(seed) { + var me = this, strseed = ""; + me.next = function() { + var b = me.b, c2 = me.c, d = me.d, a2 = me.a; + b = b << 25 ^ b >>> 7 ^ c2; + c2 = c2 - d | 0; + d = d << 24 ^ d >>> 8 ^ a2; + a2 = a2 - b | 0; + me.b = b = b << 20 ^ b >>> 12 ^ c2; + me.c = c2 = c2 - d | 0; + me.d = d << 16 ^ c2 >>> 16 ^ a2; + return me.a = a2 - b | 0; + }; + me.a = 0; + me.b = 0; + me.c = 2654435769 | 0; + me.d = 1367130551; + if (seed === Math.floor(seed)) { + me.a = seed / 4294967296 | 0; + me.b = seed | 0; + } else { + strseed += seed; + } + for (var k = 0; k < strseed.length + 20; k++) { + me.b ^= strseed.charCodeAt(k) | 0; + me.next(); + } + } + function copy2(f, t) { + t.a = f.a; + t.b = f.b; + t.c = f.c; + t.d = f.d; + return t; + } + ; + function impl(seed, opts) { + var xg = new XorGen(seed), state = opts && opts.state, prng = function() { + return (xg.next() >>> 0) / 4294967296; + }; + prng.double = function() { + do { + var top = xg.next() >>> 11, bot = (xg.next() >>> 0) / 4294967296, result = (top + bot) / (1 << 21); + } while (result === 0); + return result; + }; + prng.int32 = xg.next; + prng.quick = prng; + if (state) { + if (typeof state == "object") + copy2(state, xg); + prng.state = function() { + return copy2(xg, {}); + }; + } + return prng; + } + if (module2 && module2.exports) { + module2.exports = impl; + } else if (define2 && define2.amd) { + define2(function() { + return impl; + }); + } else { + this.tychei = impl; + } + })(exports, typeof module == "object" && module, typeof define == "function" && define); + } + }); + + // (disabled):crypto + var require_crypto = __commonJS({ + "(disabled):crypto"() { + } + }); + + // node_modules/seedrandom/seedrandom.js + var require_seedrandom = __commonJS({ + "node_modules/seedrandom/seedrandom.js"(exports, module) { + (function(global, pool, math) { + var width = 256, chunks = 6, digits = 52, rngname = "random", startdenom = math.pow(width, chunks), significance = math.pow(2, digits), overflow = significance * 2, mask = width - 1, nodecrypto; + function seedrandom3(seed, options, callback) { + var key = []; + options = options == true ? { entropy: true } : options || {}; + var shortseed = mixkey(flatten(options.entropy ? [seed, tostring(pool)] : seed == null ? autoseed() : seed, 3), key); + var arc4 = new ARC4(key); + var prng = function() { + var n = arc4.g(chunks), d = startdenom, x3 = 0; + while (n < significance) { + n = (n + x3) * width; + d *= width; + x3 = arc4.g(1); + } + while (n >= overflow) { + n /= 2; + d /= 2; + x3 >>>= 1; + } + return (n + x3) / d; + }; + prng.int32 = function() { + return arc4.g(4) | 0; + }; + prng.quick = function() { + return arc4.g(4) / 4294967296; + }; + prng.double = prng; + mixkey(tostring(arc4.S), pool); + return (options.pass || callback || function(prng2, seed2, is_math_call, state) { + if (state) { + if (state.S) { + copy2(state, arc4); + } + prng2.state = function() { + return copy2(arc4, {}); + }; + } + if (is_math_call) { + math[rngname] = prng2; + return seed2; + } else + return prng2; + })(prng, shortseed, "global" in options ? options.global : this == math, options.state); + } + function ARC4(key) { + var t, keylen = key.length, me = this, i = 0, j = me.i = me.j = 0, s = me.S = []; + if (!keylen) { + key = [keylen++]; + } + while (i < width) { + s[i] = i++; + } + for (i = 0; i < width; i++) { + s[i] = s[j = mask & j + key[i % keylen] + (t = s[i])]; + s[j] = t; + } + (me.g = function(count) { + var t2, r = 0, i2 = me.i, j2 = me.j, s2 = me.S; + while (count--) { + t2 = s2[i2 = mask & i2 + 1]; + r = r * width + s2[mask & (s2[i2] = s2[j2 = mask & j2 + t2]) + (s2[j2] = t2)]; + } + me.i = i2; + me.j = j2; + return r; + })(width); + } + function copy2(f, t) { + t.i = f.i; + t.j = f.j; + t.S = f.S.slice(); + return t; + } + ; + function flatten(obj, depth) { + var result = [], typ = typeof obj, prop; + if (depth && typ == "object") { + for (prop in obj) { + try { + result.push(flatten(obj[prop], depth - 1)); + } catch (e) { + } + } + } + return result.length ? result : typ == "string" ? obj : obj + "\0"; + } + function mixkey(seed, key) { + var stringseed = seed + "", smear, j = 0; + while (j < stringseed.length) { + key[mask & j] = mask & (smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++); + } + return tostring(key); + } + function autoseed() { + try { + var out; + if (nodecrypto && (out = nodecrypto.randomBytes)) { + out = out(width); + } else { + out = new Uint8Array(width); + (global.crypto || global.msCrypto).getRandomValues(out); + } + return tostring(out); + } catch (e) { + var browser = global.navigator, plugins = browser && browser.plugins; + return [+new Date(), global, plugins, global.screen, tostring(pool)]; + } + } + function tostring(a2) { + return String.fromCharCode.apply(0, a2); + } + mixkey(math.random(), pool); + if (typeof module == "object" && module.exports) { + module.exports = seedrandom3; + try { + nodecrypto = require_crypto(); + } catch (ex) { + } + } else if (typeof define == "function" && define.amd) { + define(function() { + return seedrandom3; + }); + } else { + math["seed" + rngname] = seedrandom3; + } + })(typeof self !== "undefined" ? self : exports, [], Math); + } + }); + + // node_modules/seedrandom/index.js + var require_seedrandom2 = __commonJS({ + "node_modules/seedrandom/index.js"(exports, module) { + var alea = require_alea(); + var xor128 = require_xor128(); + var xorwow = require_xorwow(); + var xorshift7 = require_xorshift7(); + var xor4096 = require_xor4096(); + var tychei = require_tychei(); + var sr = require_seedrandom(); + sr.alea = alea; + sr.xor128 = xor128; + sr.xorwow = xorwow; + sr.xorshift7 = xorshift7; + sr.xor4096 = xor4096; + sr.tychei = tychei; + module.exports = sr; + } + }); + + // node_modules/d3-array/src/ascending.js + function ascending(a2, b) { + return a2 == null || b == null ? NaN : a2 < b ? -1 : a2 > b ? 1 : a2 >= b ? 0 : NaN; + } + + // node_modules/d3-array/src/descending.js + function descending(a2, b) { + return a2 == null || b == null ? NaN : b < a2 ? -1 : b > a2 ? 1 : b >= a2 ? 0 : NaN; + } + + // node_modules/d3-array/src/bisector.js + function bisector(f) { + let compare1, compare2, delta; + if (f.length !== 2) { + compare1 = ascending; + compare2 = (d, x3) => ascending(f(d), x3); + delta = (d, x3) => f(d) - x3; + } else { + compare1 = f === ascending || f === descending ? f : zero; + compare2 = f; + delta = f; + } + function left(a2, x3, lo = 0, hi = a2.length) { + if (lo < hi) { + if (compare1(x3, x3) !== 0) + return hi; + do { + const mid = lo + hi >>> 1; + if (compare2(a2[mid], x3) < 0) + lo = mid + 1; + else + hi = mid; + } while (lo < hi); + } + return lo; + } + function right(a2, x3, lo = 0, hi = a2.length) { + if (lo < hi) { + if (compare1(x3, x3) !== 0) + return hi; + do { + const mid = lo + hi >>> 1; + if (compare2(a2[mid], x3) <= 0) + lo = mid + 1; + else + hi = mid; + } while (lo < hi); + } + return lo; + } + function center(a2, x3, lo = 0, hi = a2.length) { + const i = left(a2, x3, lo, hi - 1); + return i > lo && delta(a2[i - 1], x3) > -delta(a2[i], x3) ? i - 1 : i; + } + return { left, center, right }; + } + function zero() { + return 0; + } + + // node_modules/d3-array/src/number.js + function number(x3) { + return x3 === null ? NaN : +x3; + } + + // node_modules/d3-array/src/bisect.js + var ascendingBisect = bisector(ascending); + var bisectRight = ascendingBisect.right; + var bisectLeft = ascendingBisect.left; + var bisectCenter = bisector(number).center; + var bisect_default = bisectRight; + + // node_modules/d3-array/src/extent.js + function extent(values, valueof) { + let min3; + let max3; + if (valueof === void 0) { + for (const value of values) { + if (value != null) { + if (min3 === void 0) { + if (value >= value) + min3 = max3 = value; + } else { + if (min3 > value) + min3 = value; + if (max3 < value) + max3 = value; + } + } + } + } else { + let index2 = -1; + for (let value of values) { + if ((value = valueof(value, ++index2, values)) != null) { + if (min3 === void 0) { + if (value >= value) + min3 = max3 = value; + } else { + if (min3 > value) + min3 = value; + if (max3 < value) + max3 = value; + } + } + } + } + return [min3, max3]; + } + + // node_modules/d3-array/src/ticks.js + var e10 = Math.sqrt(50); + var e5 = Math.sqrt(10); + var e2 = Math.sqrt(2); + function ticks(start2, stop, count) { + var reverse, i = -1, n, ticks2, step; + stop = +stop, start2 = +start2, count = +count; + if (start2 === stop && count > 0) + return [start2]; + if (reverse = stop < start2) + n = start2, start2 = stop, stop = n; + if ((step = tickIncrement(start2, stop, count)) === 0 || !isFinite(step)) + return []; + if (step > 0) { + let r0 = Math.round(start2 / step), r1 = Math.round(stop / step); + if (r0 * step < start2) + ++r0; + if (r1 * step > stop) + --r1; + ticks2 = new Array(n = r1 - r0 + 1); + while (++i < n) + ticks2[i] = (r0 + i) * step; + } else { + step = -step; + let r0 = Math.round(start2 * step), r1 = Math.round(stop * step); + if (r0 / step < start2) + ++r0; + if (r1 / step > stop) + --r1; + ticks2 = new Array(n = r1 - r0 + 1); + while (++i < n) + ticks2[i] = (r0 + i) / step; + } + if (reverse) + ticks2.reverse(); + return ticks2; + } + function tickIncrement(start2, stop, count) { + var step = (stop - start2) / Math.max(0, count), power = Math.floor(Math.log(step) / Math.LN10), error = step / Math.pow(10, power); + return power >= 0 ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); + } + function tickStep(start2, stop, count) { + var step0 = Math.abs(stop - start2) / Math.max(0, count), step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), error = step0 / step1; + if (error >= e10) + step1 *= 10; + else if (error >= e5) + step1 *= 5; + else if (error >= e2) + step1 *= 2; + return stop < start2 ? -step1 : step1; + } + + // node_modules/d3-array/src/max.js + function max(values, valueof) { + let max3; + if (valueof === void 0) { + for (const value of values) { + if (value != null && (max3 < value || max3 === void 0 && value >= value)) { + max3 = value; + } + } + } else { + let index2 = -1; + for (let value of values) { + if ((value = valueof(value, ++index2, values)) != null && (max3 < value || max3 === void 0 && value >= value)) { + max3 = value; + } + } + } + return max3; + } + + // node_modules/d3-array/src/min.js + function min(values, valueof) { + let min3; + if (valueof === void 0) { + for (const value of values) { + if (value != null && (min3 > value || min3 === void 0 && value >= value)) { + min3 = value; + } + } + } else { + let index2 = -1; + for (let value of values) { + if ((value = valueof(value, ++index2, values)) != null && (min3 > value || min3 === void 0 && value >= value)) { + min3 = value; + } + } + } + return min3; + } + + // node_modules/d3-array/src/minIndex.js + function minIndex(values, valueof) { + let min3; + let minIndex2 = -1; + let index2 = -1; + if (valueof === void 0) { + for (const value of values) { + ++index2; + if (value != null && (min3 > value || min3 === void 0 && value >= value)) { + min3 = value, minIndex2 = index2; + } + } + } else { + for (let value of values) { + if ((value = valueof(value, ++index2, values)) != null && (min3 > value || min3 === void 0 && value >= value)) { + min3 = value, minIndex2 = index2; + } + } + } + return minIndex2; + } + + // node_modules/d3-array/src/range.js + function range(start2, stop, step) { + start2 = +start2, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start2, start2 = 0, 1) : n < 3 ? 1 : +step; + var i = -1, n = Math.max(0, Math.ceil((stop - start2) / step)) | 0, range2 = new Array(n); + while (++i < n) { + range2[i] = start2 + i * step; + } + return range2; + } + + // node_modules/d3-dispatch/src/dispatch.js + var noop = { value: () => { + } }; + function dispatch() { + for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { + if (!(t = arguments[i] + "") || t in _ || /[\s.]/.test(t)) + throw new Error("illegal type: " + t); + _[t] = []; + } + return new Dispatch(_); + } + function Dispatch(_) { + this._ = _; + } + function parseTypenames(typenames, types) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) + name = t.slice(i + 1), t = t.slice(0, i); + if (t && !types.hasOwnProperty(t)) + throw new Error("unknown type: " + t); + return { type: t, name }; + }); + } + Dispatch.prototype = dispatch.prototype = { + constructor: Dispatch, + on: function(typename, callback) { + var _ = this._, T = parseTypenames(typename + "", _), t, i = -1, n = T.length; + if (arguments.length < 2) { + while (++i < n) + if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) + return t; + return; + } + if (callback != null && typeof callback !== "function") + throw new Error("invalid callback: " + callback); + while (++i < n) { + if (t = (typename = T[i]).type) + _[t] = set(_[t], typename.name, callback); + else if (callback == null) + for (t in _) + _[t] = set(_[t], typename.name, null); + } + return this; + }, + copy: function() { + var copy2 = {}, _ = this._; + for (var t in _) + copy2[t] = _[t].slice(); + return new Dispatch(copy2); + }, + call: function(type2, that) { + if ((n = arguments.length - 2) > 0) + for (var args = new Array(n), i = 0, n, t; i < n; ++i) + args[i] = arguments[i + 2]; + if (!this._.hasOwnProperty(type2)) + throw new Error("unknown type: " + type2); + for (t = this._[type2], i = 0, n = t.length; i < n; ++i) + t[i].value.apply(that, args); + }, + apply: function(type2, that, args) { + if (!this._.hasOwnProperty(type2)) + throw new Error("unknown type: " + type2); + for (var t = this._[type2], i = 0, n = t.length; i < n; ++i) + t[i].value.apply(that, args); + } + }; + function get(type2, name) { + for (var i = 0, n = type2.length, c2; i < n; ++i) { + if ((c2 = type2[i]).name === name) { + return c2.value; + } + } + } + function set(type2, name, callback) { + for (var i = 0, n = type2.length; i < n; ++i) { + if (type2[i].name === name) { + type2[i] = noop, type2 = type2.slice(0, i).concat(type2.slice(i + 1)); + break; + } + } + if (callback != null) + type2.push({ name, value: callback }); + return type2; + } + var dispatch_default = dispatch; + + // node_modules/d3-selection/src/namespaces.js + var xhtml = "http://www.w3.org/1999/xhtml"; + var namespaces_default = { + svg: "http://www.w3.org/2000/svg", + xhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + + // node_modules/d3-selection/src/namespace.js + function namespace_default(name) { + var prefix = name += "", i = prefix.indexOf(":"); + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") + name = name.slice(i + 1); + return namespaces_default.hasOwnProperty(prefix) ? { space: namespaces_default[prefix], local: name } : name; + } + + // node_modules/d3-selection/src/creator.js + function creatorInherit(name) { + return function() { + var document2 = this.ownerDocument, uri = this.namespaceURI; + return uri === xhtml && document2.documentElement.namespaceURI === xhtml ? document2.createElement(name) : document2.createElementNS(uri, name); + }; + } + function creatorFixed(fullname) { + return function() { + return this.ownerDocument.createElementNS(fullname.space, fullname.local); + }; + } + function creator_default(name) { + var fullname = namespace_default(name); + return (fullname.local ? creatorFixed : creatorInherit)(fullname); + } + + // node_modules/d3-selection/src/selector.js + function none() { + } + function selector_default(selector) { + return selector == null ? none : function() { + return this.querySelector(selector); + }; + } + + // node_modules/d3-selection/src/selection/select.js + function select_default(select) { + if (typeof select !== "function") + select = selector_default(select); + for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) + subnode.__data__ = node.__data__; + subgroup[i] = subnode; + } + } + } + return new Selection(subgroups, this._parents); + } + + // node_modules/d3-selection/src/array.js + function array(x3) { + return x3 == null ? [] : Array.isArray(x3) ? x3 : Array.from(x3); + } + + // node_modules/d3-selection/src/selectorAll.js + function empty() { + return []; + } + function selectorAll_default(selector) { + return selector == null ? empty : function() { + return this.querySelectorAll(selector); + }; + } + + // node_modules/d3-selection/src/selection/selectAll.js + function arrayAll(select) { + return function() { + return array(select.apply(this, arguments)); + }; + } + function selectAll_default(select) { + if (typeof select === "function") + select = arrayAll(select); + else + select = selectorAll_default(select); + for (var groups = this._groups, m2 = groups.length, subgroups = [], parents = [], j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + subgroups.push(select.call(node, node.__data__, i, group)); + parents.push(node); + } + } + } + return new Selection(subgroups, parents); + } + + // node_modules/d3-selection/src/matcher.js + function matcher_default(selector) { + return function() { + return this.matches(selector); + }; + } + function childMatcher(selector) { + return function(node) { + return node.matches(selector); + }; + } + + // node_modules/d3-selection/src/selection/selectChild.js + var find = Array.prototype.find; + function childFind(match) { + return function() { + return find.call(this.children, match); + }; + } + function childFirst() { + return this.firstElementChild; + } + function selectChild_default(match) { + return this.select(match == null ? childFirst : childFind(typeof match === "function" ? match : childMatcher(match))); + } + + // node_modules/d3-selection/src/selection/selectChildren.js + var filter = Array.prototype.filter; + function children() { + return Array.from(this.children); + } + function childrenFilter(match) { + return function() { + return filter.call(this.children, match); + }; + } + function selectChildren_default(match) { + return this.selectAll(match == null ? children : childrenFilter(typeof match === "function" ? match : childMatcher(match))); + } + + // node_modules/d3-selection/src/selection/filter.js + function filter_default(match) { + if (typeof match !== "function") + match = matcher_default(match); + for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + return new Selection(subgroups, this._parents); + } + + // node_modules/d3-selection/src/selection/sparse.js + function sparse_default(update) { + return new Array(update.length); + } + + // node_modules/d3-selection/src/selection/enter.js + function enter_default() { + return new Selection(this._enter || this._groups.map(sparse_default), this._parents); + } + function EnterNode(parent, datum2) { + this.ownerDocument = parent.ownerDocument; + this.namespaceURI = parent.namespaceURI; + this._next = null; + this._parent = parent; + this.__data__ = datum2; + } + EnterNode.prototype = { + constructor: EnterNode, + appendChild: function(child) { + return this._parent.insertBefore(child, this._next); + }, + insertBefore: function(child, next) { + return this._parent.insertBefore(child, next); + }, + querySelector: function(selector) { + return this._parent.querySelector(selector); + }, + querySelectorAll: function(selector) { + return this._parent.querySelectorAll(selector); + } + }; + + // node_modules/d3-selection/src/constant.js + function constant_default(x3) { + return function() { + return x3; + }; + } + + // node_modules/d3-selection/src/selection/data.js + function bindIndex(parent, group, enter, update, exit, data) { + var i = 0, node, groupLength = group.length, dataLength = data.length; + for (; i < dataLength; ++i) { + if (node = group[i]) { + node.__data__ = data[i]; + update[i] = node; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + for (; i < groupLength; ++i) { + if (node = group[i]) { + exit[i] = node; + } + } + } + function bindKey(parent, group, enter, update, exit, data, key) { + var i, node, nodeByKeyValue = /* @__PURE__ */ new Map(), groupLength = group.length, dataLength = data.length, keyValues = new Array(groupLength), keyValue; + for (i = 0; i < groupLength; ++i) { + if (node = group[i]) { + keyValues[i] = keyValue = key.call(node, node.__data__, i, group) + ""; + if (nodeByKeyValue.has(keyValue)) { + exit[i] = node; + } else { + nodeByKeyValue.set(keyValue, node); + } + } + } + for (i = 0; i < dataLength; ++i) { + keyValue = key.call(parent, data[i], i, data) + ""; + if (node = nodeByKeyValue.get(keyValue)) { + update[i] = node; + node.__data__ = data[i]; + nodeByKeyValue.delete(keyValue); + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + for (i = 0; i < groupLength; ++i) { + if ((node = group[i]) && nodeByKeyValue.get(keyValues[i]) === node) { + exit[i] = node; + } + } + } + function datum(node) { + return node.__data__; + } + function data_default(value, key) { + if (!arguments.length) + return Array.from(this, datum); + var bind = key ? bindKey : bindIndex, parents = this._parents, groups = this._groups; + if (typeof value !== "function") + value = constant_default(value); + for (var m2 = groups.length, update = new Array(m2), enter = new Array(m2), exit = new Array(m2), j = 0; j < m2; ++j) { + var parent = parents[j], group = groups[j], groupLength = group.length, data = arraylike(value.call(parent, parent && parent.__data__, j, parents)), dataLength = data.length, enterGroup = enter[j] = new Array(dataLength), updateGroup = update[j] = new Array(dataLength), exitGroup = exit[j] = new Array(groupLength); + bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); + for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { + if (previous = enterGroup[i0]) { + if (i0 >= i1) + i1 = i0 + 1; + while (!(next = updateGroup[i1]) && ++i1 < dataLength) + ; + previous._next = next || null; + } + } + } + update = new Selection(update, parents); + update._enter = enter; + update._exit = exit; + return update; + } + function arraylike(data) { + return typeof data === "object" && "length" in data ? data : Array.from(data); + } + + // node_modules/d3-selection/src/selection/exit.js + function exit_default() { + return new Selection(this._exit || this._groups.map(sparse_default), this._parents); + } + + // node_modules/d3-selection/src/selection/join.js + function join_default(onenter, onupdate, onexit) { + var enter = this.enter(), update = this, exit = this.exit(); + if (typeof onenter === "function") { + enter = onenter(enter); + if (enter) + enter = enter.selection(); + } else { + enter = enter.append(onenter + ""); + } + if (onupdate != null) { + update = onupdate(update); + if (update) + update = update.selection(); + } + if (onexit == null) + exit.remove(); + else + onexit(exit); + return enter && update ? enter.merge(update).order() : update; + } + + // node_modules/d3-selection/src/selection/merge.js + function merge_default(context) { + var selection2 = context.selection ? context.selection() : context; + for (var groups0 = this._groups, groups1 = selection2._groups, m0 = groups0.length, m1 = groups1.length, m2 = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m2; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + return new Selection(merges, this._parents); + } + + // node_modules/d3-selection/src/selection/order.js + function order_default() { + for (var groups = this._groups, j = -1, m2 = groups.length; ++j < m2; ) { + for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { + if (node = group[i]) { + if (next && node.compareDocumentPosition(next) ^ 4) + next.parentNode.insertBefore(node, next); + next = node; + } + } + } + return this; + } + + // node_modules/d3-selection/src/selection/sort.js + function sort_default(compare) { + if (!compare) + compare = ascending2; + function compareNode(a2, b) { + return a2 && b ? compare(a2.__data__, b.__data__) : !a2 - !b; + } + for (var groups = this._groups, m2 = groups.length, sortgroups = new Array(m2), j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group[i]) { + sortgroup[i] = node; + } + } + sortgroup.sort(compareNode); + } + return new Selection(sortgroups, this._parents).order(); + } + function ascending2(a2, b) { + return a2 < b ? -1 : a2 > b ? 1 : a2 >= b ? 0 : NaN; + } + + // node_modules/d3-selection/src/selection/call.js + function call_default() { + var callback = arguments[0]; + arguments[0] = this; + callback.apply(null, arguments); + return this; + } + + // node_modules/d3-selection/src/selection/nodes.js + function nodes_default() { + return Array.from(this); + } + + // node_modules/d3-selection/src/selection/node.js + function node_default() { + for (var groups = this._groups, j = 0, m2 = groups.length; j < m2; ++j) { + for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { + var node = group[i]; + if (node) + return node; + } + } + return null; + } + + // node_modules/d3-selection/src/selection/size.js + function size_default() { + let size = 0; + for (const node of this) + ++size; + return size; + } + + // node_modules/d3-selection/src/selection/empty.js + function empty_default() { + return !this.node(); + } + + // node_modules/d3-selection/src/selection/each.js + function each_default(callback) { + for (var groups = this._groups, j = 0, m2 = groups.length; j < m2; ++j) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { + if (node = group[i]) + callback.call(node, node.__data__, i, group); + } + } + return this; + } + + // node_modules/d3-selection/src/selection/attr.js + function attrRemove(name) { + return function() { + this.removeAttribute(name); + }; + } + function attrRemoveNS(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; + } + function attrConstant(name, value) { + return function() { + this.setAttribute(name, value); + }; + } + function attrConstantNS(fullname, value) { + return function() { + this.setAttributeNS(fullname.space, fullname.local, value); + }; + } + function attrFunction(name, value) { + return function() { + var v2 = value.apply(this, arguments); + if (v2 == null) + this.removeAttribute(name); + else + this.setAttribute(name, v2); + }; + } + function attrFunctionNS(fullname, value) { + return function() { + var v2 = value.apply(this, arguments); + if (v2 == null) + this.removeAttributeNS(fullname.space, fullname.local); + else + this.setAttributeNS(fullname.space, fullname.local, v2); + }; + } + function attr_default(name, value) { + var fullname = namespace_default(name); + if (arguments.length < 2) { + var node = this.node(); + return fullname.local ? node.getAttributeNS(fullname.space, fullname.local) : node.getAttribute(fullname); + } + return this.each((value == null ? fullname.local ? attrRemoveNS : attrRemove : typeof value === "function" ? fullname.local ? attrFunctionNS : attrFunction : fullname.local ? attrConstantNS : attrConstant)(fullname, value)); + } + + // node_modules/d3-selection/src/window.js + function window_default(node) { + return node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView; + } + + // node_modules/d3-selection/src/selection/style.js + function styleRemove(name) { + return function() { + this.style.removeProperty(name); + }; + } + function styleConstant(name, value, priority) { + return function() { + this.style.setProperty(name, value, priority); + }; + } + function styleFunction(name, value, priority) { + return function() { + var v2 = value.apply(this, arguments); + if (v2 == null) + this.style.removeProperty(name); + else + this.style.setProperty(name, v2, priority); + }; + } + function style_default(name, value, priority) { + return arguments.length > 1 ? this.each((value == null ? styleRemove : typeof value === "function" ? styleFunction : styleConstant)(name, value, priority == null ? "" : priority)) : styleValue(this.node(), name); + } + function styleValue(node, name) { + return node.style.getPropertyValue(name) || window_default(node).getComputedStyle(node, null).getPropertyValue(name); + } + + // node_modules/d3-selection/src/selection/property.js + function propertyRemove(name) { + return function() { + delete this[name]; + }; + } + function propertyConstant(name, value) { + return function() { + this[name] = value; + }; + } + function propertyFunction(name, value) { + return function() { + var v2 = value.apply(this, arguments); + if (v2 == null) + delete this[name]; + else + this[name] = v2; + }; + } + function property_default(name, value) { + return arguments.length > 1 ? this.each((value == null ? propertyRemove : typeof value === "function" ? propertyFunction : propertyConstant)(name, value)) : this.node()[name]; + } + + // node_modules/d3-selection/src/selection/classed.js + function classArray(string) { + return string.trim().split(/^|\s+/); + } + function classList(node) { + return node.classList || new ClassList(node); + } + function ClassList(node) { + this._node = node; + this._names = classArray(node.getAttribute("class") || ""); + } + ClassList.prototype = { + add: function(name) { + var i = this._names.indexOf(name); + if (i < 0) { + this._names.push(name); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + remove: function(name) { + var i = this._names.indexOf(name); + if (i >= 0) { + this._names.splice(i, 1); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + contains: function(name) { + return this._names.indexOf(name) >= 0; + } + }; + function classedAdd(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) + list.add(names[i]); + } + function classedRemove(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) + list.remove(names[i]); + } + function classedTrue(names) { + return function() { + classedAdd(this, names); + }; + } + function classedFalse(names) { + return function() { + classedRemove(this, names); + }; + } + function classedFunction(names, value) { + return function() { + (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); + }; + } + function classed_default(name, value) { + var names = classArray(name + ""); + if (arguments.length < 2) { + var list = classList(this.node()), i = -1, n = names.length; + while (++i < n) + if (!list.contains(names[i])) + return false; + return true; + } + return this.each((typeof value === "function" ? classedFunction : value ? classedTrue : classedFalse)(names, value)); + } + + // node_modules/d3-selection/src/selection/text.js + function textRemove() { + this.textContent = ""; + } + function textConstant(value) { + return function() { + this.textContent = value; + }; + } + function textFunction(value) { + return function() { + var v2 = value.apply(this, arguments); + this.textContent = v2 == null ? "" : v2; + }; + } + function text_default(value) { + return arguments.length ? this.each(value == null ? textRemove : (typeof value === "function" ? textFunction : textConstant)(value)) : this.node().textContent; + } + + // node_modules/d3-selection/src/selection/html.js + function htmlRemove() { + this.innerHTML = ""; + } + function htmlConstant(value) { + return function() { + this.innerHTML = value; + }; + } + function htmlFunction(value) { + return function() { + var v2 = value.apply(this, arguments); + this.innerHTML = v2 == null ? "" : v2; + }; + } + function html_default(value) { + return arguments.length ? this.each(value == null ? htmlRemove : (typeof value === "function" ? htmlFunction : htmlConstant)(value)) : this.node().innerHTML; + } + + // node_modules/d3-selection/src/selection/raise.js + function raise() { + if (this.nextSibling) + this.parentNode.appendChild(this); + } + function raise_default() { + return this.each(raise); + } + + // node_modules/d3-selection/src/selection/lower.js + function lower() { + if (this.previousSibling) + this.parentNode.insertBefore(this, this.parentNode.firstChild); + } + function lower_default() { + return this.each(lower); + } + + // node_modules/d3-selection/src/selection/append.js + function append_default(name) { + var create2 = typeof name === "function" ? name : creator_default(name); + return this.select(function() { + return this.appendChild(create2.apply(this, arguments)); + }); + } + + // node_modules/d3-selection/src/selection/insert.js + function constantNull() { + return null; + } + function insert_default(name, before) { + var create2 = typeof name === "function" ? name : creator_default(name), select = before == null ? constantNull : typeof before === "function" ? before : selector_default(before); + return this.select(function() { + return this.insertBefore(create2.apply(this, arguments), select.apply(this, arguments) || null); + }); + } + + // node_modules/d3-selection/src/selection/remove.js + function remove() { + var parent = this.parentNode; + if (parent) + parent.removeChild(this); + } + function remove_default() { + return this.each(remove); + } + + // node_modules/d3-selection/src/selection/clone.js + function selection_cloneShallow() { + var clone = this.cloneNode(false), parent = this.parentNode; + return parent ? parent.insertBefore(clone, this.nextSibling) : clone; + } + function selection_cloneDeep() { + var clone = this.cloneNode(true), parent = this.parentNode; + return parent ? parent.insertBefore(clone, this.nextSibling) : clone; + } + function clone_default(deep) { + return this.select(deep ? selection_cloneDeep : selection_cloneShallow); + } + + // node_modules/d3-selection/src/selection/datum.js + function datum_default(value) { + return arguments.length ? this.property("__data__", value) : this.node().__data__; + } + + // node_modules/d3-selection/src/selection/on.js + function contextListener(listener) { + return function(event) { + listener.call(this, event, this.__data__); + }; + } + function parseTypenames2(typenames) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) + name = t.slice(i + 1), t = t.slice(0, i); + return { type: t, name }; + }); + } + function onRemove(typename) { + return function() { + var on = this.__on; + if (!on) + return; + for (var j = 0, i = -1, m2 = on.length, o; j < m2; ++j) { + if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.options); + } else { + on[++i] = o; + } + } + if (++i) + on.length = i; + else + delete this.__on; + }; + } + function onAdd(typename, value, options) { + return function() { + var on = this.__on, o, listener = contextListener(value); + if (on) + for (var j = 0, m2 = on.length; j < m2; ++j) { + if ((o = on[j]).type === typename.type && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.options); + this.addEventListener(o.type, o.listener = listener, o.options = options); + o.value = value; + return; + } + } + this.addEventListener(typename.type, listener, options); + o = { type: typename.type, name: typename.name, value, listener, options }; + if (!on) + this.__on = [o]; + else + on.push(o); + }; + } + function on_default(typename, value, options) { + var typenames = parseTypenames2(typename + ""), i, n = typenames.length, t; + if (arguments.length < 2) { + var on = this.node().__on; + if (on) + for (var j = 0, m2 = on.length, o; j < m2; ++j) { + for (i = 0, o = on[j]; i < n; ++i) { + if ((t = typenames[i]).type === o.type && t.name === o.name) { + return o.value; + } + } + } + return; + } + on = value ? onAdd : onRemove; + for (i = 0; i < n; ++i) + this.each(on(typenames[i], value, options)); + return this; + } + + // node_modules/d3-selection/src/selection/dispatch.js + function dispatchEvent(node, type2, params) { + var window2 = window_default(node), event = window2.CustomEvent; + if (typeof event === "function") { + event = new event(type2, params); + } else { + event = window2.document.createEvent("Event"); + if (params) + event.initEvent(type2, params.bubbles, params.cancelable), event.detail = params.detail; + else + event.initEvent(type2, false, false); + } + node.dispatchEvent(event); + } + function dispatchConstant(type2, params) { + return function() { + return dispatchEvent(this, type2, params); + }; + } + function dispatchFunction(type2, params) { + return function() { + return dispatchEvent(this, type2, params.apply(this, arguments)); + }; + } + function dispatch_default2(type2, params) { + return this.each((typeof params === "function" ? dispatchFunction : dispatchConstant)(type2, params)); + } + + // node_modules/d3-selection/src/selection/iterator.js + function* iterator_default() { + for (var groups = this._groups, j = 0, m2 = groups.length; j < m2; ++j) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { + if (node = group[i]) + yield node; + } + } + } + + // node_modules/d3-selection/src/selection/index.js + var root = [null]; + function Selection(groups, parents) { + this._groups = groups; + this._parents = parents; + } + function selection() { + return new Selection([[document.documentElement]], root); + } + function selection_selection() { + return this; + } + Selection.prototype = selection.prototype = { + constructor: Selection, + select: select_default, + selectAll: selectAll_default, + selectChild: selectChild_default, + selectChildren: selectChildren_default, + filter: filter_default, + data: data_default, + enter: enter_default, + exit: exit_default, + join: join_default, + merge: merge_default, + selection: selection_selection, + order: order_default, + sort: sort_default, + call: call_default, + nodes: nodes_default, + node: node_default, + size: size_default, + empty: empty_default, + each: each_default, + attr: attr_default, + style: style_default, + property: property_default, + classed: classed_default, + text: text_default, + html: html_default, + raise: raise_default, + lower: lower_default, + append: append_default, + insert: insert_default, + remove: remove_default, + clone: clone_default, + datum: datum_default, + on: on_default, + dispatch: dispatch_default2, + [Symbol.iterator]: iterator_default + }; + var selection_default = selection; + + // node_modules/d3-selection/src/select.js + function select_default2(selector) { + return typeof selector === "string" ? new Selection([[document.querySelector(selector)]], [document.documentElement]) : new Selection([[selector]], root); + } + + // node_modules/d3-selection/src/sourceEvent.js + function sourceEvent_default(event) { + let sourceEvent; + while (sourceEvent = event.sourceEvent) + event = sourceEvent; + return event; + } + + // node_modules/d3-selection/src/pointer.js + function pointer_default(event, node) { + event = sourceEvent_default(event); + if (node === void 0) + node = event.currentTarget; + if (node) { + var svg = node.ownerSVGElement || node; + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + point.x = event.clientX, point.y = event.clientY; + point = point.matrixTransform(node.getScreenCTM().inverse()); + return [point.x, point.y]; + } + if (node.getBoundingClientRect) { + var rect = node.getBoundingClientRect(); + return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; + } + } + return [event.pageX, event.pageY]; + } + + // node_modules/d3-drag/src/noevent.js + var nonpassive = { passive: false }; + var nonpassivecapture = { capture: true, passive: false }; + function nopropagation(event) { + event.stopImmediatePropagation(); + } + function noevent_default(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + + // node_modules/d3-drag/src/nodrag.js + function nodrag_default(view) { + var root2 = view.document.documentElement, selection2 = select_default2(view).on("dragstart.drag", noevent_default, nonpassivecapture); + if ("onselectstart" in root2) { + selection2.on("selectstart.drag", noevent_default, nonpassivecapture); + } else { + root2.__noselect = root2.style.MozUserSelect; + root2.style.MozUserSelect = "none"; + } + } + function yesdrag(view, noclick) { + var root2 = view.document.documentElement, selection2 = select_default2(view).on("dragstart.drag", null); + if (noclick) { + selection2.on("click.drag", noevent_default, nonpassivecapture); + setTimeout(function() { + selection2.on("click.drag", null); + }, 0); + } + if ("onselectstart" in root2) { + selection2.on("selectstart.drag", null); + } else { + root2.style.MozUserSelect = root2.__noselect; + delete root2.__noselect; + } + } + + // node_modules/d3-drag/src/constant.js + var constant_default2 = (x3) => () => x3; + + // node_modules/d3-drag/src/event.js + function DragEvent(type2, { + sourceEvent, + subject, + target, + identifier, + active, + x: x3, + y: y4, + dx, + dy, + dispatch: dispatch2 + }) { + Object.defineProperties(this, { + type: { value: type2, enumerable: true, configurable: true }, + sourceEvent: { value: sourceEvent, enumerable: true, configurable: true }, + subject: { value: subject, enumerable: true, configurable: true }, + target: { value: target, enumerable: true, configurable: true }, + identifier: { value: identifier, enumerable: true, configurable: true }, + active: { value: active, enumerable: true, configurable: true }, + x: { value: x3, enumerable: true, configurable: true }, + y: { value: y4, enumerable: true, configurable: true }, + dx: { value: dx, enumerable: true, configurable: true }, + dy: { value: dy, enumerable: true, configurable: true }, + _: { value: dispatch2 } + }); + } + DragEvent.prototype.on = function() { + var value = this._.on.apply(this._, arguments); + return value === this._ ? this : value; + }; + + // node_modules/d3-drag/src/drag.js + function defaultFilter(event) { + return !event.ctrlKey && !event.button; + } + function defaultContainer() { + return this.parentNode; + } + function defaultSubject(event, d) { + return d == null ? { x: event.x, y: event.y } : d; + } + function defaultTouchable() { + return navigator.maxTouchPoints || "ontouchstart" in this; + } + function drag_default() { + var filter2 = defaultFilter, container = defaultContainer, subject = defaultSubject, touchable = defaultTouchable, gestures = {}, listeners = dispatch_default("start", "drag", "end"), active = 0, mousedownx, mousedowny, mousemoving, touchending, clickDistance2 = 0; + function drag(selection2) { + selection2.on("mousedown.drag", mousedowned).filter(touchable).on("touchstart.drag", touchstarted).on("touchmove.drag", touchmoved, nonpassive).on("touchend.drag touchcancel.drag", touchended).style("touch-action", "none").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + function mousedowned(event, d) { + if (touchending || !filter2.call(this, event, d)) + return; + var gesture = beforestart(this, container.call(this, event, d), event, d, "mouse"); + if (!gesture) + return; + select_default2(event.view).on("mousemove.drag", mousemoved, nonpassivecapture).on("mouseup.drag", mouseupped, nonpassivecapture); + nodrag_default(event.view); + nopropagation(event); + mousemoving = false; + mousedownx = event.clientX; + mousedowny = event.clientY; + gesture("start", event); + } + function mousemoved(event) { + noevent_default(event); + if (!mousemoving) { + var dx = event.clientX - mousedownx, dy = event.clientY - mousedowny; + mousemoving = dx * dx + dy * dy > clickDistance2; + } + gestures.mouse("drag", event); + } + function mouseupped(event) { + select_default2(event.view).on("mousemove.drag mouseup.drag", null); + yesdrag(event.view, mousemoving); + noevent_default(event); + gestures.mouse("end", event); + } + function touchstarted(event, d) { + if (!filter2.call(this, event, d)) + return; + var touches = event.changedTouches, c2 = container.call(this, event, d), n = touches.length, i, gesture; + for (i = 0; i < n; ++i) { + if (gesture = beforestart(this, c2, event, d, touches[i].identifier, touches[i])) { + nopropagation(event); + gesture("start", event, touches[i]); + } + } + } + function touchmoved(event) { + var touches = event.changedTouches, n = touches.length, i, gesture; + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches[i].identifier]) { + noevent_default(event); + gesture("drag", event, touches[i]); + } + } + } + function touchended(event) { + var touches = event.changedTouches, n = touches.length, i, gesture; + if (touchending) + clearTimeout(touchending); + touchending = setTimeout(function() { + touchending = null; + }, 500); + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches[i].identifier]) { + nopropagation(event); + gesture("end", event, touches[i]); + } + } + } + function beforestart(that, container2, event, d, identifier, touch) { + var dispatch2 = listeners.copy(), p = pointer_default(touch || event, container2), dx, dy, s; + if ((s = subject.call(that, new DragEvent("beforestart", { + sourceEvent: event, + target: drag, + identifier, + active, + x: p[0], + y: p[1], + dx: 0, + dy: 0, + dispatch: dispatch2 + }), d)) == null) + return; + dx = s.x - p[0] || 0; + dy = s.y - p[1] || 0; + return function gesture(type2, event2, touch2) { + var p0 = p, n; + switch (type2) { + case "start": + gestures[identifier] = gesture, n = active++; + break; + case "end": + delete gestures[identifier], --active; + case "drag": + p = pointer_default(touch2 || event2, container2), n = active; + break; + } + dispatch2.call(type2, that, new DragEvent(type2, { + sourceEvent: event2, + subject: s, + target: drag, + identifier, + active: n, + x: p[0] + dx, + y: p[1] + dy, + dx: p[0] - p0[0], + dy: p[1] - p0[1], + dispatch: dispatch2 + }), d); + }; + } + drag.filter = function(_) { + return arguments.length ? (filter2 = typeof _ === "function" ? _ : constant_default2(!!_), drag) : filter2; + }; + drag.container = function(_) { + return arguments.length ? (container = typeof _ === "function" ? _ : constant_default2(_), drag) : container; + }; + drag.subject = function(_) { + return arguments.length ? (subject = typeof _ === "function" ? _ : constant_default2(_), drag) : subject; + }; + drag.touchable = function(_) { + return arguments.length ? (touchable = typeof _ === "function" ? _ : constant_default2(!!_), drag) : touchable; + }; + drag.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? drag : value; + }; + drag.clickDistance = function(_) { + return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2); + }; + return drag; + } + + // node_modules/d3-color/src/define.js + function define_default(constructor, factory, prototype) { + constructor.prototype = factory.prototype = prototype; + prototype.constructor = constructor; + } + function extend(parent, definition) { + var prototype = Object.create(parent.prototype); + for (var key in definition) + prototype[key] = definition[key]; + return prototype; + } + + // node_modules/d3-color/src/color.js + function Color() { + } + var darker = 0.7; + var brighter = 1 / darker; + var reI = "\\s*([+-]?\\d+)\\s*"; + var reN = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*"; + var reP = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*"; + var reHex = /^#([0-9a-f]{3,8})$/; + var reRgbInteger = new RegExp(`^rgb\\(${reI},${reI},${reI}\\)$`); + var reRgbPercent = new RegExp(`^rgb\\(${reP},${reP},${reP}\\)$`); + var reRgbaInteger = new RegExp(`^rgba\\(${reI},${reI},${reI},${reN}\\)$`); + var reRgbaPercent = new RegExp(`^rgba\\(${reP},${reP},${reP},${reN}\\)$`); + var reHslPercent = new RegExp(`^hsl\\(${reN},${reP},${reP}\\)$`); + var reHslaPercent = new RegExp(`^hsla\\(${reN},${reP},${reP},${reN}\\)$`); + var named = { + aliceblue: 15792383, + antiquewhite: 16444375, + aqua: 65535, + aquamarine: 8388564, + azure: 15794175, + beige: 16119260, + bisque: 16770244, + black: 0, + blanchedalmond: 16772045, + blue: 255, + blueviolet: 9055202, + brown: 10824234, + burlywood: 14596231, + cadetblue: 6266528, + chartreuse: 8388352, + chocolate: 13789470, + coral: 16744272, + cornflowerblue: 6591981, + cornsilk: 16775388, + crimson: 14423100, + cyan: 65535, + darkblue: 139, + darkcyan: 35723, + darkgoldenrod: 12092939, + darkgray: 11119017, + darkgreen: 25600, + darkgrey: 11119017, + darkkhaki: 12433259, + darkmagenta: 9109643, + darkolivegreen: 5597999, + darkorange: 16747520, + darkorchid: 10040012, + darkred: 9109504, + darksalmon: 15308410, + darkseagreen: 9419919, + darkslateblue: 4734347, + darkslategray: 3100495, + darkslategrey: 3100495, + darkturquoise: 52945, + darkviolet: 9699539, + deeppink: 16716947, + deepskyblue: 49151, + dimgray: 6908265, + dimgrey: 6908265, + dodgerblue: 2003199, + firebrick: 11674146, + floralwhite: 16775920, + forestgreen: 2263842, + fuchsia: 16711935, + gainsboro: 14474460, + ghostwhite: 16316671, + gold: 16766720, + goldenrod: 14329120, + gray: 8421504, + green: 32768, + greenyellow: 11403055, + grey: 8421504, + honeydew: 15794160, + hotpink: 16738740, + indianred: 13458524, + indigo: 4915330, + ivory: 16777200, + khaki: 15787660, + lavender: 15132410, + lavenderblush: 16773365, + lawngreen: 8190976, + lemonchiffon: 16775885, + lightblue: 11393254, + lightcoral: 15761536, + lightcyan: 14745599, + lightgoldenrodyellow: 16448210, + lightgray: 13882323, + lightgreen: 9498256, + lightgrey: 13882323, + lightpink: 16758465, + lightsalmon: 16752762, + lightseagreen: 2142890, + lightskyblue: 8900346, + lightslategray: 7833753, + lightslategrey: 7833753, + lightsteelblue: 11584734, + lightyellow: 16777184, + lime: 65280, + limegreen: 3329330, + linen: 16445670, + magenta: 16711935, + maroon: 8388608, + mediumaquamarine: 6737322, + mediumblue: 205, + mediumorchid: 12211667, + mediumpurple: 9662683, + mediumseagreen: 3978097, + mediumslateblue: 8087790, + mediumspringgreen: 64154, + mediumturquoise: 4772300, + mediumvioletred: 13047173, + midnightblue: 1644912, + mintcream: 16121850, + mistyrose: 16770273, + moccasin: 16770229, + navajowhite: 16768685, + navy: 128, + oldlace: 16643558, + olive: 8421376, + olivedrab: 7048739, + orange: 16753920, + orangered: 16729344, + orchid: 14315734, + palegoldenrod: 15657130, + palegreen: 10025880, + paleturquoise: 11529966, + palevioletred: 14381203, + papayawhip: 16773077, + peachpuff: 16767673, + peru: 13468991, + pink: 16761035, + plum: 14524637, + powderblue: 11591910, + purple: 8388736, + rebeccapurple: 6697881, + red: 16711680, + rosybrown: 12357519, + royalblue: 4286945, + saddlebrown: 9127187, + salmon: 16416882, + sandybrown: 16032864, + seagreen: 3050327, + seashell: 16774638, + sienna: 10506797, + silver: 12632256, + skyblue: 8900331, + slateblue: 6970061, + slategray: 7372944, + slategrey: 7372944, + snow: 16775930, + springgreen: 65407, + steelblue: 4620980, + tan: 13808780, + teal: 32896, + thistle: 14204888, + tomato: 16737095, + turquoise: 4251856, + violet: 15631086, + wheat: 16113331, + white: 16777215, + whitesmoke: 16119285, + yellow: 16776960, + yellowgreen: 10145074 + }; + define_default(Color, color, { + copy(channels) { + return Object.assign(new this.constructor(), this, channels); + }, + displayable() { + return this.rgb().displayable(); + }, + hex: color_formatHex, + formatHex: color_formatHex, + formatHex8: color_formatHex8, + formatHsl: color_formatHsl, + formatRgb: color_formatRgb, + toString: color_formatRgb + }); + function color_formatHex() { + return this.rgb().formatHex(); + } + function color_formatHex8() { + return this.rgb().formatHex8(); + } + function color_formatHsl() { + return hslConvert(this).formatHsl(); + } + function color_formatRgb() { + return this.rgb().formatRgb(); + } + function color(format2) { + var m2, l; + format2 = (format2 + "").trim().toLowerCase(); + return (m2 = reHex.exec(format2)) ? (l = m2[1].length, m2 = parseInt(m2[1], 16), l === 6 ? rgbn(m2) : l === 3 ? new Rgb(m2 >> 8 & 15 | m2 >> 4 & 240, m2 >> 4 & 15 | m2 & 240, (m2 & 15) << 4 | m2 & 15, 1) : l === 8 ? rgba(m2 >> 24 & 255, m2 >> 16 & 255, m2 >> 8 & 255, (m2 & 255) / 255) : l === 4 ? rgba(m2 >> 12 & 15 | m2 >> 8 & 240, m2 >> 8 & 15 | m2 >> 4 & 240, m2 >> 4 & 15 | m2 & 240, ((m2 & 15) << 4 | m2 & 15) / 255) : null) : (m2 = reRgbInteger.exec(format2)) ? new Rgb(m2[1], m2[2], m2[3], 1) : (m2 = reRgbPercent.exec(format2)) ? new Rgb(m2[1] * 255 / 100, m2[2] * 255 / 100, m2[3] * 255 / 100, 1) : (m2 = reRgbaInteger.exec(format2)) ? rgba(m2[1], m2[2], m2[3], m2[4]) : (m2 = reRgbaPercent.exec(format2)) ? rgba(m2[1] * 255 / 100, m2[2] * 255 / 100, m2[3] * 255 / 100, m2[4]) : (m2 = reHslPercent.exec(format2)) ? hsla(m2[1], m2[2] / 100, m2[3] / 100, 1) : (m2 = reHslaPercent.exec(format2)) ? hsla(m2[1], m2[2] / 100, m2[3] / 100, m2[4]) : named.hasOwnProperty(format2) ? rgbn(named[format2]) : format2 === "transparent" ? new Rgb(NaN, NaN, NaN, 0) : null; + } + function rgbn(n) { + return new Rgb(n >> 16 & 255, n >> 8 & 255, n & 255, 1); + } + function rgba(r, g, b, a2) { + if (a2 <= 0) + r = g = b = NaN; + return new Rgb(r, g, b, a2); + } + function rgbConvert(o) { + if (!(o instanceof Color)) + o = color(o); + if (!o) + return new Rgb(); + o = o.rgb(); + return new Rgb(o.r, o.g, o.b, o.opacity); + } + function rgb(r, g, b, opacity) { + return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); + } + function Rgb(r, g, b, opacity) { + this.r = +r; + this.g = +g; + this.b = +b; + this.opacity = +opacity; + } + define_default(Rgb, rgb, extend(Color, { + brighter(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + darker(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + rgb() { + return this; + }, + clamp() { + return new Rgb(clampi(this.r), clampi(this.g), clampi(this.b), clampa(this.opacity)); + }, + displayable() { + return -0.5 <= this.r && this.r < 255.5 && (-0.5 <= this.g && this.g < 255.5) && (-0.5 <= this.b && this.b < 255.5) && (0 <= this.opacity && this.opacity <= 1); + }, + hex: rgb_formatHex, + formatHex: rgb_formatHex, + formatHex8: rgb_formatHex8, + formatRgb: rgb_formatRgb, + toString: rgb_formatRgb + })); + function rgb_formatHex() { + return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`; + } + function rgb_formatHex8() { + return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`; + } + function rgb_formatRgb() { + const a2 = clampa(this.opacity); + return `${a2 === 1 ? "rgb(" : "rgba("}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a2 === 1 ? ")" : `, ${a2})`}`; + } + function clampa(opacity) { + return isNaN(opacity) ? 1 : Math.max(0, Math.min(1, opacity)); + } + function clampi(value) { + return Math.max(0, Math.min(255, Math.round(value) || 0)); + } + function hex(value) { + value = clampi(value); + return (value < 16 ? "0" : "") + value.toString(16); + } + function hsla(h, s, l, a2) { + if (a2 <= 0) + h = s = l = NaN; + else if (l <= 0 || l >= 1) + h = s = NaN; + else if (s <= 0) + h = NaN; + return new Hsl(h, s, l, a2); + } + function hslConvert(o) { + if (o instanceof Hsl) + return new Hsl(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Color)) + o = color(o); + if (!o) + return new Hsl(); + if (o instanceof Hsl) + return o; + o = o.rgb(); + var r = o.r / 255, g = o.g / 255, b = o.b / 255, min3 = Math.min(r, g, b), max3 = Math.max(r, g, b), h = NaN, s = max3 - min3, l = (max3 + min3) / 2; + if (s) { + if (r === max3) + h = (g - b) / s + (g < b) * 6; + else if (g === max3) + h = (b - r) / s + 2; + else + h = (r - g) / s + 4; + s /= l < 0.5 ? max3 + min3 : 2 - max3 - min3; + h *= 60; + } else { + s = l > 0 && l < 1 ? 0 : h; + } + return new Hsl(h, s, l, o.opacity); + } + function hsl(h, s, l, opacity) { + return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); + } + function Hsl(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; + } + define_default(Hsl, hsl, extend(Color, { + brighter(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + darker(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + rgb() { + var h = this.h % 360 + (this.h < 0) * 360, s = isNaN(h) || isNaN(this.s) ? 0 : this.s, l = this.l, m2 = l + (l < 0.5 ? l : 1 - l) * s, m1 = 2 * l - m2; + return new Rgb(hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb(h, m1, m2), hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity); + }, + clamp() { + return new Hsl(clamph(this.h), clampt(this.s), clampt(this.l), clampa(this.opacity)); + }, + displayable() { + return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && (0 <= this.l && this.l <= 1) && (0 <= this.opacity && this.opacity <= 1); + }, + formatHsl() { + const a2 = clampa(this.opacity); + return `${a2 === 1 ? "hsl(" : "hsla("}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a2 === 1 ? ")" : `, ${a2})`}`; + } + })); + function clamph(value) { + value = (value || 0) % 360; + return value < 0 ? value + 360 : value; + } + function clampt(value) { + return Math.max(0, Math.min(1, value || 0)); + } + function hsl2rgb(h, m1, m2) { + return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255; + } + + // node_modules/d3-interpolate/src/basis.js + function basis(t1, v0, v1, v2, v3) { + var t2 = t1 * t1, t3 = t2 * t1; + return ((1 - 3 * t1 + 3 * t2 - t3) * v0 + (4 - 6 * t2 + 3 * t3) * v1 + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 + t3 * v3) / 6; + } + function basis_default(values) { + var n = values.length - 1; + return function(t) { + var i = t <= 0 ? t = 0 : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), v1 = values[i], v2 = values[i + 1], v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; + } + + // node_modules/d3-interpolate/src/basisClosed.js + function basisClosed_default(values) { + var n = values.length; + return function(t) { + var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), v0 = values[(i + n - 1) % n], v1 = values[i % n], v2 = values[(i + 1) % n], v3 = values[(i + 2) % n]; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; + } + + // node_modules/d3-interpolate/src/constant.js + var constant_default3 = (x3) => () => x3; + + // node_modules/d3-interpolate/src/color.js + function linear(a2, d) { + return function(t) { + return a2 + t * d; + }; + } + function exponential(a2, b, y4) { + return a2 = Math.pow(a2, y4), b = Math.pow(b, y4) - a2, y4 = 1 / y4, function(t) { + return Math.pow(a2 + t * b, y4); + }; + } + function gamma(y4) { + return (y4 = +y4) === 1 ? nogamma : function(a2, b) { + return b - a2 ? exponential(a2, b, y4) : constant_default3(isNaN(a2) ? b : a2); + }; + } + function nogamma(a2, b) { + var d = b - a2; + return d ? linear(a2, d) : constant_default3(isNaN(a2) ? b : a2); + } + + // node_modules/d3-interpolate/src/rgb.js + var rgb_default = function rgbGamma(y4) { + var color2 = gamma(y4); + function rgb2(start2, end) { + var r = color2((start2 = rgb(start2)).r, (end = rgb(end)).r), g = color2(start2.g, end.g), b = color2(start2.b, end.b), opacity = nogamma(start2.opacity, end.opacity); + return function(t) { + start2.r = r(t); + start2.g = g(t); + start2.b = b(t); + start2.opacity = opacity(t); + return start2 + ""; + }; + } + rgb2.gamma = rgbGamma; + return rgb2; + }(1); + function rgbSpline(spline) { + return function(colors) { + var n = colors.length, r = new Array(n), g = new Array(n), b = new Array(n), i, color2; + for (i = 0; i < n; ++i) { + color2 = rgb(colors[i]); + r[i] = color2.r || 0; + g[i] = color2.g || 0; + b[i] = color2.b || 0; + } + r = spline(r); + g = spline(g); + b = spline(b); + color2.opacity = 1; + return function(t) { + color2.r = r(t); + color2.g = g(t); + color2.b = b(t); + return color2 + ""; + }; + }; + } + var rgbBasis = rgbSpline(basis_default); + var rgbBasisClosed = rgbSpline(basisClosed_default); + + // node_modules/d3-interpolate/src/numberArray.js + function numberArray_default(a2, b) { + if (!b) + b = []; + var n = a2 ? Math.min(b.length, a2.length) : 0, c2 = b.slice(), i; + return function(t) { + for (i = 0; i < n; ++i) + c2[i] = a2[i] * (1 - t) + b[i] * t; + return c2; + }; + } + function isNumberArray(x3) { + return ArrayBuffer.isView(x3) && !(x3 instanceof DataView); + } + + // node_modules/d3-interpolate/src/array.js + function genericArray(a2, b) { + var nb = b ? b.length : 0, na = a2 ? Math.min(nb, a2.length) : 0, x3 = new Array(na), c2 = new Array(nb), i; + for (i = 0; i < na; ++i) + x3[i] = value_default(a2[i], b[i]); + for (; i < nb; ++i) + c2[i] = b[i]; + return function(t) { + for (i = 0; i < na; ++i) + c2[i] = x3[i](t); + return c2; + }; + } + + // node_modules/d3-interpolate/src/date.js + function date_default(a2, b) { + var d = new Date(); + return a2 = +a2, b = +b, function(t) { + return d.setTime(a2 * (1 - t) + b * t), d; + }; + } + + // node_modules/d3-interpolate/src/number.js + function number_default(a2, b) { + return a2 = +a2, b = +b, function(t) { + return a2 * (1 - t) + b * t; + }; + } + + // node_modules/d3-interpolate/src/object.js + function object_default(a2, b) { + var i = {}, c2 = {}, k; + if (a2 === null || typeof a2 !== "object") + a2 = {}; + if (b === null || typeof b !== "object") + b = {}; + for (k in b) { + if (k in a2) { + i[k] = value_default(a2[k], b[k]); + } else { + c2[k] = b[k]; + } + } + return function(t) { + for (k in i) + c2[k] = i[k](t); + return c2; + }; + } + + // node_modules/d3-interpolate/src/string.js + var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; + var reB = new RegExp(reA.source, "g"); + function zero2(b) { + return function() { + return b; + }; + } + function one(b) { + return function(t) { + return b(t) + ""; + }; + } + function string_default(a2, b) { + var bi = reA.lastIndex = reB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; + a2 = a2 + "", b = b + ""; + while ((am = reA.exec(a2)) && (bm = reB.exec(b))) { + if ((bs = bm.index) > bi) { + bs = b.slice(bi, bs); + if (s[i]) + s[i] += bs; + else + s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { + if (s[i]) + s[i] += bm; + else + s[++i] = bm; + } else { + s[++i] = null; + q.push({ i, x: number_default(am, bm) }); + } + bi = reB.lastIndex; + } + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) + s[i] += bs; + else + s[++i] = bs; + } + return s.length < 2 ? q[0] ? one(q[0].x) : zero2(b) : (b = q.length, function(t) { + for (var i2 = 0, o; i2 < b; ++i2) + s[(o = q[i2]).i] = o.x(t); + return s.join(""); + }); + } + + // node_modules/d3-interpolate/src/value.js + function value_default(a2, b) { + var t = typeof b, c2; + return b == null || t === "boolean" ? constant_default3(b) : (t === "number" ? number_default : t === "string" ? (c2 = color(b)) ? (b = c2, rgb_default) : string_default : b instanceof color ? rgb_default : b instanceof Date ? date_default : isNumberArray(b) ? numberArray_default : Array.isArray(b) ? genericArray : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object_default : number_default)(a2, b); + } + + // node_modules/d3-interpolate/src/round.js + function round_default(a2, b) { + return a2 = +a2, b = +b, function(t) { + return Math.round(a2 * (1 - t) + b * t); + }; + } + + // node_modules/d3-interpolate/src/transform/decompose.js + var degrees = 180 / Math.PI; + var identity = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1 + }; + function decompose_default(a2, b, c2, d, e, f) { + var scaleX, scaleY, skewX; + if (scaleX = Math.sqrt(a2 * a2 + b * b)) + a2 /= scaleX, b /= scaleX; + if (skewX = a2 * c2 + b * d) + c2 -= a2 * skewX, d -= b * skewX; + if (scaleY = Math.sqrt(c2 * c2 + d * d)) + c2 /= scaleY, d /= scaleY, skewX /= scaleY; + if (a2 * d < b * c2) + a2 = -a2, b = -b, skewX = -skewX, scaleX = -scaleX; + return { + translateX: e, + translateY: f, + rotate: Math.atan2(b, a2) * degrees, + skewX: Math.atan(skewX) * degrees, + scaleX, + scaleY + }; + } + + // node_modules/d3-interpolate/src/transform/parse.js + var svgNode; + function parseCss(value) { + const m2 = new (typeof DOMMatrix === "function" ? DOMMatrix : WebKitCSSMatrix)(value + ""); + return m2.isIdentity ? identity : decompose_default(m2.a, m2.b, m2.c, m2.d, m2.e, m2.f); + } + function parseSvg(value) { + if (value == null) + return identity; + if (!svgNode) + svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svgNode.setAttribute("transform", value); + if (!(value = svgNode.transform.baseVal.consolidate())) + return identity; + value = value.matrix; + return decompose_default(value.a, value.b, value.c, value.d, value.e, value.f); + } + + // node_modules/d3-interpolate/src/transform/index.js + function interpolateTransform(parse, pxComma, pxParen, degParen) { + function pop(s) { + return s.length ? s.pop() + " " : ""; + } + function translate(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push("translate(", null, pxComma, null, pxParen); + q.push({ i: i - 4, x: number_default(xa, xb) }, { i: i - 2, x: number_default(ya, yb) }); + } else if (xb || yb) { + s.push("translate(" + xb + pxComma + yb + pxParen); + } + } + function rotate(a2, b, s, q) { + if (a2 !== b) { + if (a2 - b > 180) + b += 360; + else if (b - a2 > 180) + a2 += 360; + q.push({ i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: number_default(a2, b) }); + } else if (b) { + s.push(pop(s) + "rotate(" + b + degParen); + } + } + function skewX(a2, b, s, q) { + if (a2 !== b) { + q.push({ i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number_default(a2, b) }); + } else if (b) { + s.push(pop(s) + "skewX(" + b + degParen); + } + } + function scale2(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push(pop(s) + "scale(", null, ",", null, ")"); + q.push({ i: i - 4, x: number_default(xa, xb) }, { i: i - 2, x: number_default(ya, yb) }); + } else if (xb !== 1 || yb !== 1) { + s.push(pop(s) + "scale(" + xb + "," + yb + ")"); + } + } + return function(a2, b) { + var s = [], q = []; + a2 = parse(a2), b = parse(b); + translate(a2.translateX, a2.translateY, b.translateX, b.translateY, s, q); + rotate(a2.rotate, b.rotate, s, q); + skewX(a2.skewX, b.skewX, s, q); + scale2(a2.scaleX, a2.scaleY, b.scaleX, b.scaleY, s, q); + a2 = b = null; + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) + s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + }; + } + var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); + var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); + + // node_modules/d3-timer/src/timer.js + var frame = 0; + var timeout = 0; + var interval = 0; + var pokeDelay = 1e3; + var taskHead; + var taskTail; + var clockLast = 0; + var clockNow = 0; + var clockSkew = 0; + var clock = typeof performance === "object" && performance.now ? performance : Date; + var setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { + setTimeout(f, 17); + }; + function now() { + return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); + } + function clearNow() { + clockNow = 0; + } + function Timer() { + this._call = this._time = this._next = null; + } + Timer.prototype = timer.prototype = { + constructor: Timer, + restart: function(callback, delay, time) { + if (typeof callback !== "function") + throw new TypeError("callback is not a function"); + time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); + if (!this._next && taskTail !== this) { + if (taskTail) + taskTail._next = this; + else + taskHead = this; + taskTail = this; + } + this._call = callback; + this._time = time; + sleep(); + }, + stop: function() { + if (this._call) { + this._call = null; + this._time = Infinity; + sleep(); + } + } + }; + function timer(callback, delay, time) { + var t = new Timer(); + t.restart(callback, delay, time); + return t; + } + function timerFlush() { + now(); + ++frame; + var t = taskHead, e; + while (t) { + if ((e = clockNow - t._time) >= 0) + t._call.call(void 0, e); + t = t._next; + } + --frame; + } + function wake() { + clockNow = (clockLast = clock.now()) + clockSkew; + frame = timeout = 0; + try { + timerFlush(); + } finally { + frame = 0; + nap(); + clockNow = 0; + } + } + function poke() { + var now2 = clock.now(), delay = now2 - clockLast; + if (delay > pokeDelay) + clockSkew -= delay, clockLast = now2; + } + function nap() { + var t0, t1 = taskHead, t2, time = Infinity; + while (t1) { + if (t1._call) { + if (time > t1._time) + time = t1._time; + t0 = t1, t1 = t1._next; + } else { + t2 = t1._next, t1._next = null; + t1 = t0 ? t0._next = t2 : taskHead = t2; + } + } + taskTail = t0; + sleep(time); + } + function sleep(time) { + if (frame) + return; + if (timeout) + timeout = clearTimeout(timeout); + var delay = time - clockNow; + if (delay > 24) { + if (time < Infinity) + timeout = setTimeout(wake, time - clock.now() - clockSkew); + if (interval) + interval = clearInterval(interval); + } else { + if (!interval) + clockLast = clock.now(), interval = setInterval(poke, pokeDelay); + frame = 1, setFrame(wake); + } + } + + // node_modules/d3-timer/src/timeout.js + function timeout_default(callback, delay, time) { + var t = new Timer(); + delay = delay == null ? 0 : +delay; + t.restart((elapsed) => { + t.stop(); + callback(elapsed + delay); + }, delay, time); + return t; + } + + // node_modules/d3-transition/src/transition/schedule.js + var emptyOn = dispatch_default("start", "end", "cancel", "interrupt"); + var emptyTween = []; + var CREATED = 0; + var SCHEDULED = 1; + var STARTING = 2; + var STARTED = 3; + var RUNNING = 4; + var ENDING = 5; + var ENDED = 6; + function schedule_default(node, name, id2, index2, group, timing) { + var schedules = node.__transition; + if (!schedules) + node.__transition = {}; + else if (id2 in schedules) + return; + create(node, id2, { + name, + index: index2, + group, + on: emptyOn, + tween: emptyTween, + time: timing.time, + delay: timing.delay, + duration: timing.duration, + ease: timing.ease, + timer: null, + state: CREATED + }); + } + function init(node, id2) { + var schedule = get2(node, id2); + if (schedule.state > CREATED) + throw new Error("too late; already scheduled"); + return schedule; + } + function set2(node, id2) { + var schedule = get2(node, id2); + if (schedule.state > STARTED) + throw new Error("too late; already running"); + return schedule; + } + function get2(node, id2) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id2])) + throw new Error("transition not found"); + return schedule; + } + function create(node, id2, self2) { + var schedules = node.__transition, tween; + schedules[id2] = self2; + self2.timer = timer(schedule, 0, self2.time); + function schedule(elapsed) { + self2.state = SCHEDULED; + self2.timer.restart(start2, self2.delay, self2.time); + if (self2.delay <= elapsed) + start2(elapsed - self2.delay); + } + function start2(elapsed) { + var i, j, n, o; + if (self2.state !== SCHEDULED) + return stop(); + for (i in schedules) { + o = schedules[i]; + if (o.name !== self2.name) + continue; + if (o.state === STARTED) + return timeout_default(start2); + if (o.state === RUNNING) { + o.state = ENDED; + o.timer.stop(); + o.on.call("interrupt", node, node.__data__, o.index, o.group); + delete schedules[i]; + } else if (+i < id2) { + o.state = ENDED; + o.timer.stop(); + o.on.call("cancel", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + } + timeout_default(function() { + if (self2.state === STARTED) { + self2.state = RUNNING; + self2.timer.restart(tick, self2.delay, self2.time); + tick(elapsed); + } + }); + self2.state = STARTING; + self2.on.call("start", node, node.__data__, self2.index, self2.group); + if (self2.state !== STARTING) + return; + self2.state = STARTED; + tween = new Array(n = self2.tween.length); + for (i = 0, j = -1; i < n; ++i) { + if (o = self2.tween[i].value.call(node, node.__data__, self2.index, self2.group)) { + tween[++j] = o; + } + } + tween.length = j + 1; + } + function tick(elapsed) { + var t = elapsed < self2.duration ? self2.ease.call(null, elapsed / self2.duration) : (self2.timer.restart(stop), self2.state = ENDING, 1), i = -1, n = tween.length; + while (++i < n) { + tween[i].call(node, t); + } + if (self2.state === ENDING) { + self2.on.call("end", node, node.__data__, self2.index, self2.group); + stop(); + } + } + function stop() { + self2.state = ENDED; + self2.timer.stop(); + delete schedules[id2]; + for (var i in schedules) + return; + delete node.__transition; + } + } + + // node_modules/d3-transition/src/interrupt.js + function interrupt_default(node, name) { + var schedules = node.__transition, schedule, active, empty2 = true, i; + if (!schedules) + return; + name = name == null ? null : name + ""; + for (i in schedules) { + if ((schedule = schedules[i]).name !== name) { + empty2 = false; + continue; + } + active = schedule.state > STARTING && schedule.state < ENDING; + schedule.state = ENDED; + schedule.timer.stop(); + schedule.on.call(active ? "interrupt" : "cancel", node, node.__data__, schedule.index, schedule.group); + delete schedules[i]; + } + if (empty2) + delete node.__transition; + } + + // node_modules/d3-transition/src/selection/interrupt.js + function interrupt_default2(name) { + return this.each(function() { + interrupt_default(this, name); + }); + } + + // node_modules/d3-transition/src/transition/tween.js + function tweenRemove(id2, name) { + var tween0, tween1; + return function() { + var schedule = set2(this, id2), tween = schedule.tween; + if (tween !== tween0) { + tween1 = tween0 = tween; + for (var i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1 = tween1.slice(); + tween1.splice(i, 1); + break; + } + } + } + schedule.tween = tween1; + }; + } + function tweenFunction(id2, name, value) { + var tween0, tween1; + if (typeof value !== "function") + throw new Error(); + return function() { + var schedule = set2(this, id2), tween = schedule.tween; + if (tween !== tween0) { + tween1 = (tween0 = tween).slice(); + for (var t = { name, value }, i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1[i] = t; + break; + } + } + if (i === n) + tween1.push(t); + } + schedule.tween = tween1; + }; + } + function tween_default(name, value) { + var id2 = this._id; + name += ""; + if (arguments.length < 2) { + var tween = get2(this.node(), id2).tween; + for (var i = 0, n = tween.length, t; i < n; ++i) { + if ((t = tween[i]).name === name) { + return t.value; + } + } + return null; + } + return this.each((value == null ? tweenRemove : tweenFunction)(id2, name, value)); + } + function tweenValue(transition2, name, value) { + var id2 = transition2._id; + transition2.each(function() { + var schedule = set2(this, id2); + (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); + }); + return function(node) { + return get2(node, id2).value[name]; + }; + } + + // node_modules/d3-transition/src/transition/interpolate.js + function interpolate_default(a2, b) { + var c2; + return (typeof b === "number" ? number_default : b instanceof color ? rgb_default : (c2 = color(b)) ? (b = c2, rgb_default) : string_default)(a2, b); + } + + // node_modules/d3-transition/src/transition/attr.js + function attrRemove2(name) { + return function() { + this.removeAttribute(name); + }; + } + function attrRemoveNS2(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; + } + function attrConstant2(name, interpolate, value1) { + var string00, string1 = value1 + "", interpolate0; + return function() { + var string0 = this.getAttribute(name); + return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1); + }; + } + function attrConstantNS2(fullname, interpolate, value1) { + var string00, string1 = value1 + "", interpolate0; + return function() { + var string0 = this.getAttributeNS(fullname.space, fullname.local); + return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1); + }; + } + function attrFunction2(name, interpolate, value) { + var string00, string10, interpolate0; + return function() { + var string0, value1 = value(this), string1; + if (value1 == null) + return void this.removeAttribute(name); + string0 = this.getAttribute(name); + string1 = value1 + ""; + return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + function attrFunctionNS2(fullname, interpolate, value) { + var string00, string10, interpolate0; + return function() { + var string0, value1 = value(this), string1; + if (value1 == null) + return void this.removeAttributeNS(fullname.space, fullname.local); + string0 = this.getAttributeNS(fullname.space, fullname.local); + string1 = value1 + ""; + return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + function attr_default2(name, value) { + var fullname = namespace_default(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate_default; + return this.attrTween(name, typeof value === "function" ? (fullname.local ? attrFunctionNS2 : attrFunction2)(fullname, i, tweenValue(this, "attr." + name, value)) : value == null ? (fullname.local ? attrRemoveNS2 : attrRemove2)(fullname) : (fullname.local ? attrConstantNS2 : attrConstant2)(fullname, i, value)); + } + + // node_modules/d3-transition/src/transition/attrTween.js + function attrInterpolate(name, i) { + return function(t) { + this.setAttribute(name, i.call(this, t)); + }; + } + function attrInterpolateNS(fullname, i) { + return function(t) { + this.setAttributeNS(fullname.space, fullname.local, i.call(this, t)); + }; + } + function attrTweenNS(fullname, value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t0 = (i0 = i) && attrInterpolateNS(fullname, i); + return t0; + } + tween._value = value; + return tween; + } + function attrTween(name, value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t0 = (i0 = i) && attrInterpolate(name, i); + return t0; + } + tween._value = value; + return tween; + } + function attrTween_default(name, value) { + var key = "attr." + name; + if (arguments.length < 2) + return (key = this.tween(key)) && key._value; + if (value == null) + return this.tween(key, null); + if (typeof value !== "function") + throw new Error(); + var fullname = namespace_default(name); + return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); + } + + // node_modules/d3-transition/src/transition/delay.js + function delayFunction(id2, value) { + return function() { + init(this, id2).delay = +value.apply(this, arguments); + }; + } + function delayConstant(id2, value) { + return value = +value, function() { + init(this, id2).delay = value; + }; + } + function delay_default(value) { + var id2 = this._id; + return arguments.length ? this.each((typeof value === "function" ? delayFunction : delayConstant)(id2, value)) : get2(this.node(), id2).delay; + } + + // node_modules/d3-transition/src/transition/duration.js + function durationFunction(id2, value) { + return function() { + set2(this, id2).duration = +value.apply(this, arguments); + }; + } + function durationConstant(id2, value) { + return value = +value, function() { + set2(this, id2).duration = value; + }; + } + function duration_default(value) { + var id2 = this._id; + return arguments.length ? this.each((typeof value === "function" ? durationFunction : durationConstant)(id2, value)) : get2(this.node(), id2).duration; + } + + // node_modules/d3-transition/src/transition/ease.js + function easeConstant(id2, value) { + if (typeof value !== "function") + throw new Error(); + return function() { + set2(this, id2).ease = value; + }; + } + function ease_default(value) { + var id2 = this._id; + return arguments.length ? this.each(easeConstant(id2, value)) : get2(this.node(), id2).ease; + } + + // node_modules/d3-transition/src/transition/easeVarying.js + function easeVarying(id2, value) { + return function() { + var v2 = value.apply(this, arguments); + if (typeof v2 !== "function") + throw new Error(); + set2(this, id2).ease = v2; + }; + } + function easeVarying_default(value) { + if (typeof value !== "function") + throw new Error(); + return this.each(easeVarying(this._id, value)); + } + + // node_modules/d3-transition/src/transition/filter.js + function filter_default2(match) { + if (typeof match !== "function") + match = matcher_default(match); + for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + return new Transition(subgroups, this._parents, this._name, this._id); + } + + // node_modules/d3-transition/src/transition/merge.js + function merge_default2(transition2) { + if (transition2._id !== this._id) + throw new Error(); + for (var groups0 = this._groups, groups1 = transition2._groups, m0 = groups0.length, m1 = groups1.length, m2 = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m2; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + return new Transition(merges, this._parents, this._name, this._id); + } + + // node_modules/d3-transition/src/transition/on.js + function start(name) { + return (name + "").trim().split(/^|\s+/).every(function(t) { + var i = t.indexOf("."); + if (i >= 0) + t = t.slice(0, i); + return !t || t === "start"; + }); + } + function onFunction(id2, name, listener) { + var on0, on1, sit = start(name) ? init : set2; + return function() { + var schedule = sit(this, id2), on = schedule.on; + if (on !== on0) + (on1 = (on0 = on).copy()).on(name, listener); + schedule.on = on1; + }; + } + function on_default2(name, listener) { + var id2 = this._id; + return arguments.length < 2 ? get2(this.node(), id2).on.on(name) : this.each(onFunction(id2, name, listener)); + } + + // node_modules/d3-transition/src/transition/remove.js + function removeFunction(id2) { + return function() { + var parent = this.parentNode; + for (var i in this.__transition) + if (+i !== id2) + return; + if (parent) + parent.removeChild(this); + }; + } + function remove_default2() { + return this.on("end.remove", removeFunction(this._id)); + } + + // node_modules/d3-transition/src/transition/select.js + function select_default3(select) { + var name = this._name, id2 = this._id; + if (typeof select !== "function") + select = selector_default(select); + for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) + subnode.__data__ = node.__data__; + subgroup[i] = subnode; + schedule_default(subgroup[i], name, id2, i, subgroup, get2(node, id2)); + } + } + } + return new Transition(subgroups, this._parents, name, id2); + } + + // node_modules/d3-transition/src/transition/selectAll.js + function selectAll_default2(select) { + var name = this._name, id2 = this._id; + if (typeof select !== "function") + select = selectorAll_default(select); + for (var groups = this._groups, m2 = groups.length, subgroups = [], parents = [], j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + for (var children2 = select.call(node, node.__data__, i, group), child, inherit2 = get2(node, id2), k = 0, l = children2.length; k < l; ++k) { + if (child = children2[k]) { + schedule_default(child, name, id2, k, children2, inherit2); + } + } + subgroups.push(children2); + parents.push(node); + } + } + } + return new Transition(subgroups, parents, name, id2); + } + + // node_modules/d3-transition/src/transition/selection.js + var Selection2 = selection_default.prototype.constructor; + function selection_default2() { + return new Selection2(this._groups, this._parents); + } + + // node_modules/d3-transition/src/transition/style.js + function styleNull(name, interpolate) { + var string00, string10, interpolate0; + return function() { + var string0 = styleValue(this, name), string1 = (this.style.removeProperty(name), styleValue(this, name)); + return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : interpolate0 = interpolate(string00 = string0, string10 = string1); + }; + } + function styleRemove2(name) { + return function() { + this.style.removeProperty(name); + }; + } + function styleConstant2(name, interpolate, value1) { + var string00, string1 = value1 + "", interpolate0; + return function() { + var string0 = styleValue(this, name); + return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1); + }; + } + function styleFunction2(name, interpolate, value) { + var string00, string10, interpolate0; + return function() { + var string0 = styleValue(this, name), value1 = value(this), string1 = value1 + ""; + if (value1 == null) + string1 = value1 = (this.style.removeProperty(name), styleValue(this, name)); + return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + function styleMaybeRemove(id2, name) { + var on0, on1, listener0, key = "style." + name, event = "end." + key, remove2; + return function() { + var schedule = set2(this, id2), on = schedule.on, listener = schedule.value[key] == null ? remove2 || (remove2 = styleRemove2(name)) : void 0; + if (on !== on0 || listener0 !== listener) + (on1 = (on0 = on).copy()).on(event, listener0 = listener); + schedule.on = on1; + }; + } + function style_default2(name, value, priority) { + var i = (name += "") === "transform" ? interpolateTransformCss : interpolate_default; + return value == null ? this.styleTween(name, styleNull(name, i)).on("end.style." + name, styleRemove2(name)) : typeof value === "function" ? this.styleTween(name, styleFunction2(name, i, tweenValue(this, "style." + name, value))).each(styleMaybeRemove(this._id, name)) : this.styleTween(name, styleConstant2(name, i, value), priority).on("end.style." + name, null); + } + + // node_modules/d3-transition/src/transition/styleTween.js + function styleInterpolate(name, i, priority) { + return function(t) { + this.style.setProperty(name, i.call(this, t), priority); + }; + } + function styleTween(name, value, priority) { + var t, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t = (i0 = i) && styleInterpolate(name, i, priority); + return t; + } + tween._value = value; + return tween; + } + function styleTween_default(name, value, priority) { + var key = "style." + (name += ""); + if (arguments.length < 2) + return (key = this.tween(key)) && key._value; + if (value == null) + return this.tween(key, null); + if (typeof value !== "function") + throw new Error(); + return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); + } + + // node_modules/d3-transition/src/transition/text.js + function textConstant2(value) { + return function() { + this.textContent = value; + }; + } + function textFunction2(value) { + return function() { + var value1 = value(this); + this.textContent = value1 == null ? "" : value1; + }; + } + function text_default2(value) { + return this.tween("text", typeof value === "function" ? textFunction2(tweenValue(this, "text", value)) : textConstant2(value == null ? "" : value + "")); + } + + // node_modules/d3-transition/src/transition/textTween.js + function textInterpolate(i) { + return function(t) { + this.textContent = i.call(this, t); + }; + } + function textTween(value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t0 = (i0 = i) && textInterpolate(i); + return t0; + } + tween._value = value; + return tween; + } + function textTween_default(value) { + var key = "text"; + if (arguments.length < 1) + return (key = this.tween(key)) && key._value; + if (value == null) + return this.tween(key, null); + if (typeof value !== "function") + throw new Error(); + return this.tween(key, textTween(value)); + } + + // node_modules/d3-transition/src/transition/transition.js + function transition_default() { + var name = this._name, id0 = this._id, id1 = newId(); + for (var groups = this._groups, m2 = groups.length, j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + var inherit2 = get2(node, id0); + schedule_default(node, name, id1, i, group, { + time: inherit2.time + inherit2.delay + inherit2.duration, + delay: 0, + duration: inherit2.duration, + ease: inherit2.ease + }); + } + } + } + return new Transition(groups, this._parents, name, id1); + } + + // node_modules/d3-transition/src/transition/end.js + function end_default() { + var on0, on1, that = this, id2 = that._id, size = that.size(); + return new Promise(function(resolve, reject) { + var cancel = { value: reject }, end = { value: function() { + if (--size === 0) + resolve(); + } }; + that.each(function() { + var schedule = set2(this, id2), on = schedule.on; + if (on !== on0) { + on1 = (on0 = on).copy(); + on1._.cancel.push(cancel); + on1._.interrupt.push(cancel); + on1._.end.push(end); + } + schedule.on = on1; + }); + if (size === 0) + resolve(); + }); + } + + // node_modules/d3-transition/src/transition/index.js + var id = 0; + function Transition(groups, parents, name, id2) { + this._groups = groups; + this._parents = parents; + this._name = name; + this._id = id2; + } + function transition(name) { + return selection_default().transition(name); + } + function newId() { + return ++id; + } + var selection_prototype = selection_default.prototype; + Transition.prototype = transition.prototype = { + constructor: Transition, + select: select_default3, + selectAll: selectAll_default2, + selectChild: selection_prototype.selectChild, + selectChildren: selection_prototype.selectChildren, + filter: filter_default2, + merge: merge_default2, + selection: selection_default2, + transition: transition_default, + call: selection_prototype.call, + nodes: selection_prototype.nodes, + node: selection_prototype.node, + size: selection_prototype.size, + empty: selection_prototype.empty, + each: selection_prototype.each, + on: on_default2, + attr: attr_default2, + attrTween: attrTween_default, + style: style_default2, + styleTween: styleTween_default, + text: text_default2, + textTween: textTween_default, + remove: remove_default2, + tween: tween_default, + delay: delay_default, + duration: duration_default, + ease: ease_default, + easeVarying: easeVarying_default, + end: end_default, + [Symbol.iterator]: selection_prototype[Symbol.iterator] + }; + + // node_modules/d3-ease/src/cubic.js + function cubicInOut(t) { + return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; + } + + // node_modules/d3-transition/src/selection/transition.js + var defaultTiming = { + time: null, + delay: 0, + duration: 250, + ease: cubicInOut + }; + function inherit(node, id2) { + var timing; + while (!(timing = node.__transition) || !(timing = timing[id2])) { + if (!(node = node.parentNode)) { + throw new Error(`transition ${id2} not found`); + } + } + return timing; + } + function transition_default2(name) { + var id2, timing; + if (name instanceof Transition) { + id2 = name._id, name = name._name; + } else { + id2 = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + ""; + } + for (var groups = this._groups, m2 = groups.length, j = 0; j < m2; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + schedule_default(node, name, id2, i, group, timing || inherit(node, id2)); + } + } + } + return new Transition(groups, this._parents, name, id2); + } + + // node_modules/d3-transition/src/selection/index.js + selection_default.prototype.interrupt = interrupt_default2; + selection_default.prototype.transition = transition_default2; + + // node_modules/d3-brush/src/brush.js + var { abs, max: max2, min: min2 } = Math; + function number1(e) { + return [+e[0], +e[1]]; + } + function number2(e) { + return [number1(e[0]), number1(e[1])]; + } + var X = { + name: "x", + handles: ["w", "e"].map(type), + input: function(x3, e) { + return x3 == null ? null : [[+x3[0], e[0][1]], [+x3[1], e[1][1]]]; + }, + output: function(xy) { + return xy && [xy[0][0], xy[1][0]]; + } + }; + var Y = { + name: "y", + handles: ["n", "s"].map(type), + input: function(y4, e) { + return y4 == null ? null : [[e[0][0], +y4[0]], [e[1][0], +y4[1]]]; + }, + output: function(xy) { + return xy && [xy[0][1], xy[1][1]]; + } + }; + var XY = { + name: "xy", + handles: ["n", "w", "e", "s", "nw", "ne", "sw", "se"].map(type), + input: function(xy) { + return xy == null ? null : number2(xy); + }, + output: function(xy) { + return xy; + } + }; + function type(t) { + return { type: t }; + } + + // node_modules/robust-predicates/esm/util.js + var epsilon = 11102230246251565e-32; + var splitter = 134217729; + var resulterrbound = (3 + 8 * epsilon) * epsilon; + function sum(elen, e, flen, f, h) { + let Q, Qnew, hh, bvirt; + let enow = e[0]; + let fnow = f[0]; + let eindex = 0; + let findex = 0; + if (fnow > enow === fnow > -enow) { + Q = enow; + enow = e[++eindex]; + } else { + Q = fnow; + fnow = f[++findex]; + } + let hindex = 0; + if (eindex < elen && findex < flen) { + if (fnow > enow === fnow > -enow) { + Qnew = enow + Q; + hh = Q - (Qnew - enow); + enow = e[++eindex]; + } else { + Qnew = fnow + Q; + hh = Q - (Qnew - fnow); + fnow = f[++findex]; + } + Q = Qnew; + if (hh !== 0) { + h[hindex++] = hh; + } + while (eindex < elen && findex < flen) { + if (fnow > enow === fnow > -enow) { + Qnew = Q + enow; + bvirt = Qnew - Q; + hh = Q - (Qnew - bvirt) + (enow - bvirt); + enow = e[++eindex]; + } else { + Qnew = Q + fnow; + bvirt = Qnew - Q; + hh = Q - (Qnew - bvirt) + (fnow - bvirt); + fnow = f[++findex]; + } + Q = Qnew; + if (hh !== 0) { + h[hindex++] = hh; + } + } + } + while (eindex < elen) { + Qnew = Q + enow; + bvirt = Qnew - Q; + hh = Q - (Qnew - bvirt) + (enow - bvirt); + enow = e[++eindex]; + Q = Qnew; + if (hh !== 0) { + h[hindex++] = hh; + } + } + while (findex < flen) { + Qnew = Q + fnow; + bvirt = Qnew - Q; + hh = Q - (Qnew - bvirt) + (fnow - bvirt); + fnow = f[++findex]; + Q = Qnew; + if (hh !== 0) { + h[hindex++] = hh; + } + } + if (Q !== 0 || hindex === 0) { + h[hindex++] = Q; + } + return hindex; + } + function estimate(elen, e) { + let Q = e[0]; + for (let i = 1; i < elen; i++) + Q += e[i]; + return Q; + } + function vec(n) { + return new Float64Array(n); + } + + // node_modules/robust-predicates/esm/orient2d.js + var ccwerrboundA = (3 + 16 * epsilon) * epsilon; + var ccwerrboundB = (2 + 12 * epsilon) * epsilon; + var ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon; + var B = vec(4); + var C1 = vec(8); + var C2 = vec(12); + var D = vec(16); + var u = vec(4); + function orient2dadapt(ax, ay, bx, by, cx, cy, detsum) { + let acxtail, acytail, bcxtail, bcytail; + let bvirt, c2, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u32; + const acx = ax - cx; + const bcx = bx - cx; + const acy = ay - cy; + const bcy = by - cy; + s1 = acx * bcy; + c2 = splitter * acx; + ahi = c2 - (c2 - acx); + alo = acx - ahi; + c2 = splitter * bcy; + bhi = c2 - (c2 - bcy); + blo = bcy - bhi; + s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo); + t1 = acy * bcx; + c2 = splitter * acy; + ahi = c2 - (c2 - acy); + alo = acy - ahi; + c2 = splitter * bcx; + bhi = c2 - (c2 - bcx); + blo = bcx - bhi; + t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo); + _i = s0 - t0; + bvirt = s0 - _i; + B[0] = s0 - (_i + bvirt) + (bvirt - t0); + _j = s1 + _i; + bvirt = _j - s1; + _0 = s1 - (_j - bvirt) + (_i - bvirt); + _i = _0 - t1; + bvirt = _0 - _i; + B[1] = _0 - (_i + bvirt) + (bvirt - t1); + u32 = _j + _i; + bvirt = u32 - _j; + B[2] = _j - (u32 - bvirt) + (_i - bvirt); + B[3] = u32; + let det = estimate(4, B); + let errbound = ccwerrboundB * detsum; + if (det >= errbound || -det >= errbound) { + return det; + } + bvirt = ax - acx; + acxtail = ax - (acx + bvirt) + (bvirt - cx); + bvirt = bx - bcx; + bcxtail = bx - (bcx + bvirt) + (bvirt - cx); + bvirt = ay - acy; + acytail = ay - (acy + bvirt) + (bvirt - cy); + bvirt = by - bcy; + bcytail = by - (bcy + bvirt) + (bvirt - cy); + if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) { + return det; + } + errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det); + det += acx * bcytail + bcy * acxtail - (acy * bcxtail + bcx * acytail); + if (det >= errbound || -det >= errbound) + return det; + s1 = acxtail * bcy; + c2 = splitter * acxtail; + ahi = c2 - (c2 - acxtail); + alo = acxtail - ahi; + c2 = splitter * bcy; + bhi = c2 - (c2 - bcy); + blo = bcy - bhi; + s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo); + t1 = acytail * bcx; + c2 = splitter * acytail; + ahi = c2 - (c2 - acytail); + alo = acytail - ahi; + c2 = splitter * bcx; + bhi = c2 - (c2 - bcx); + blo = bcx - bhi; + t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo); + _i = s0 - t0; + bvirt = s0 - _i; + u[0] = s0 - (_i + bvirt) + (bvirt - t0); + _j = s1 + _i; + bvirt = _j - s1; + _0 = s1 - (_j - bvirt) + (_i - bvirt); + _i = _0 - t1; + bvirt = _0 - _i; + u[1] = _0 - (_i + bvirt) + (bvirt - t1); + u32 = _j + _i; + bvirt = u32 - _j; + u[2] = _j - (u32 - bvirt) + (_i - bvirt); + u[3] = u32; + const C1len = sum(4, B, 4, u, C1); + s1 = acx * bcytail; + c2 = splitter * acx; + ahi = c2 - (c2 - acx); + alo = acx - ahi; + c2 = splitter * bcytail; + bhi = c2 - (c2 - bcytail); + blo = bcytail - bhi; + s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo); + t1 = acy * bcxtail; + c2 = splitter * acy; + ahi = c2 - (c2 - acy); + alo = acy - ahi; + c2 = splitter * bcxtail; + bhi = c2 - (c2 - bcxtail); + blo = bcxtail - bhi; + t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo); + _i = s0 - t0; + bvirt = s0 - _i; + u[0] = s0 - (_i + bvirt) + (bvirt - t0); + _j = s1 + _i; + bvirt = _j - s1; + _0 = s1 - (_j - bvirt) + (_i - bvirt); + _i = _0 - t1; + bvirt = _0 - _i; + u[1] = _0 - (_i + bvirt) + (bvirt - t1); + u32 = _j + _i; + bvirt = u32 - _j; + u[2] = _j - (u32 - bvirt) + (_i - bvirt); + u[3] = u32; + const C2len = sum(C1len, C1, 4, u, C2); + s1 = acxtail * bcytail; + c2 = splitter * acxtail; + ahi = c2 - (c2 - acxtail); + alo = acxtail - ahi; + c2 = splitter * bcytail; + bhi = c2 - (c2 - bcytail); + blo = bcytail - bhi; + s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo); + t1 = acytail * bcxtail; + c2 = splitter * acytail; + ahi = c2 - (c2 - acytail); + alo = acytail - ahi; + c2 = splitter * bcxtail; + bhi = c2 - (c2 - bcxtail); + blo = bcxtail - bhi; + t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo); + _i = s0 - t0; + bvirt = s0 - _i; + u[0] = s0 - (_i + bvirt) + (bvirt - t0); + _j = s1 + _i; + bvirt = _j - s1; + _0 = s1 - (_j - bvirt) + (_i - bvirt); + _i = _0 - t1; + bvirt = _0 - _i; + u[1] = _0 - (_i + bvirt) + (bvirt - t1); + u32 = _j + _i; + bvirt = u32 - _j; + u[2] = _j - (u32 - bvirt) + (_i - bvirt); + u[3] = u32; + const Dlen = sum(C2len, C2, 4, u, D); + return D[Dlen - 1]; + } + function orient2d(ax, ay, bx, by, cx, cy) { + const detleft = (ay - cy) * (bx - cx); + const detright = (ax - cx) * (by - cy); + const det = detleft - detright; + if (detleft === 0 || detright === 0 || detleft > 0 !== detright > 0) + return det; + const detsum = Math.abs(detleft + detright); + if (Math.abs(det) >= ccwerrboundA * detsum) + return det; + return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum); + } + + // node_modules/robust-predicates/esm/orient3d.js + var o3derrboundA = (7 + 56 * epsilon) * epsilon; + var o3derrboundB = (3 + 28 * epsilon) * epsilon; + var o3derrboundC = (26 + 288 * epsilon) * epsilon * epsilon; + var bc = vec(4); + var ca = vec(4); + var ab = vec(4); + var at_b = vec(4); + var at_c = vec(4); + var bt_c = vec(4); + var bt_a = vec(4); + var ct_a = vec(4); + var ct_b = vec(4); + var bct = vec(8); + var cat = vec(8); + var abt = vec(8); + var u2 = vec(4); + var _8 = vec(8); + var _8b = vec(8); + var _16 = vec(8); + var _12 = vec(12); + var fin = vec(192); + var fin2 = vec(192); + + // node_modules/robust-predicates/esm/incircle.js + var iccerrboundA = (10 + 96 * epsilon) * epsilon; + var iccerrboundB = (4 + 48 * epsilon) * epsilon; + var iccerrboundC = (44 + 576 * epsilon) * epsilon * epsilon; + var bc2 = vec(4); + var ca2 = vec(4); + var ab2 = vec(4); + var aa = vec(4); + var bb = vec(4); + var cc = vec(4); + var u3 = vec(4); + var v = vec(4); + var axtbc = vec(8); + var aytbc = vec(8); + var bxtca = vec(8); + var bytca = vec(8); + var cxtab = vec(8); + var cytab = vec(8); + var abt2 = vec(8); + var bct2 = vec(8); + var cat2 = vec(8); + var abtt = vec(4); + var bctt = vec(4); + var catt = vec(4); + var _82 = vec(8); + var _162 = vec(16); + var _16b = vec(16); + var _16c = vec(16); + var _32 = vec(32); + var _32b = vec(32); + var _48 = vec(48); + var _64 = vec(64); + var fin3 = vec(1152); + var fin22 = vec(1152); + + // node_modules/robust-predicates/esm/insphere.js + var isperrboundA = (16 + 224 * epsilon) * epsilon; + var isperrboundB = (5 + 72 * epsilon) * epsilon; + var isperrboundC = (71 + 1408 * epsilon) * epsilon * epsilon; + var ab3 = vec(4); + var bc3 = vec(4); + var cd = vec(4); + var de = vec(4); + var ea = vec(4); + var ac = vec(4); + var bd = vec(4); + var ce = vec(4); + var da = vec(4); + var eb = vec(4); + var abc = vec(24); + var bcd = vec(24); + var cde = vec(24); + var dea = vec(24); + var eab = vec(24); + var abd = vec(24); + var bce = vec(24); + var cda = vec(24); + var deb = vec(24); + var eac = vec(24); + var adet = vec(1152); + var bdet = vec(1152); + var cdet = vec(1152); + var ddet = vec(1152); + var edet = vec(1152); + var abdet = vec(2304); + var cddet = vec(2304); + var cdedet = vec(3456); + var deter = vec(5760); + var _83 = vec(8); + var _8b2 = vec(8); + var _8c = vec(8); + var _163 = vec(16); + var _24 = vec(24); + var _482 = vec(48); + var _48b = vec(48); + var _96 = vec(96); + var _192 = vec(192); + var _384x = vec(384); + var _384y = vec(384); + var _384z = vec(384); + var _768 = vec(768); + var xdet = vec(96); + var ydet = vec(96); + var zdet = vec(96); + var fin4 = vec(1152); + + // node_modules/delaunator/index.js + var EPSILON = Math.pow(2, -52); + var EDGE_STACK = new Uint32Array(512); + var Delaunator = class { + static from(points, getX = defaultGetX, getY = defaultGetY) { + const n = points.length; + const coords = new Float64Array(n * 2); + for (let i = 0; i < n; i++) { + const p = points[i]; + coords[2 * i] = getX(p); + coords[2 * i + 1] = getY(p); + } + return new Delaunator(coords); + } + constructor(coords) { + const n = coords.length >> 1; + if (n > 0 && typeof coords[0] !== "number") + throw new Error("Expected coords to contain numbers."); + this.coords = coords; + const maxTriangles = Math.max(2 * n - 5, 0); + this._triangles = new Uint32Array(maxTriangles * 3); + this._halfedges = new Int32Array(maxTriangles * 3); + this._hashSize = Math.ceil(Math.sqrt(n)); + this._hullPrev = new Uint32Array(n); + this._hullNext = new Uint32Array(n); + this._hullTri = new Uint32Array(n); + this._hullHash = new Int32Array(this._hashSize).fill(-1); + this._ids = new Uint32Array(n); + this._dists = new Float64Array(n); + this.update(); + } + update() { + const { coords, _hullPrev: hullPrev, _hullNext: hullNext, _hullTri: hullTri, _hullHash: hullHash } = this; + const n = coords.length >> 1; + let minX = Infinity; + let minY = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + for (let i = 0; i < n; i++) { + const x3 = coords[2 * i]; + const y4 = coords[2 * i + 1]; + if (x3 < minX) + minX = x3; + if (y4 < minY) + minY = y4; + if (x3 > maxX) + maxX = x3; + if (y4 > maxY) + maxY = y4; + this._ids[i] = i; + } + const cx = (minX + maxX) / 2; + const cy = (minY + maxY) / 2; + let minDist = Infinity; + let i0, i1, i2; + for (let i = 0; i < n; i++) { + const d = dist(cx, cy, coords[2 * i], coords[2 * i + 1]); + if (d < minDist) { + i0 = i; + minDist = d; + } + } + const i0x = coords[2 * i0]; + const i0y = coords[2 * i0 + 1]; + minDist = Infinity; + for (let i = 0; i < n; i++) { + if (i === i0) + continue; + const d = dist(i0x, i0y, coords[2 * i], coords[2 * i + 1]); + if (d < minDist && d > 0) { + i1 = i; + minDist = d; + } + } + let i1x = coords[2 * i1]; + let i1y = coords[2 * i1 + 1]; + let minRadius = Infinity; + for (let i = 0; i < n; i++) { + if (i === i0 || i === i1) + continue; + const r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i], coords[2 * i + 1]); + if (r < minRadius) { + i2 = i; + minRadius = r; + } + } + let i2x = coords[2 * i2]; + let i2y = coords[2 * i2 + 1]; + if (minRadius === Infinity) { + for (let i = 0; i < n; i++) { + this._dists[i] = coords[2 * i] - coords[0] || coords[2 * i + 1] - coords[1]; + } + quicksort(this._ids, this._dists, 0, n - 1); + const hull = new Uint32Array(n); + let j = 0; + for (let i = 0, d0 = -Infinity; i < n; i++) { + const id2 = this._ids[i]; + if (this._dists[id2] > d0) { + hull[j++] = id2; + d0 = this._dists[id2]; + } + } + this.hull = hull.subarray(0, j); + this.triangles = new Uint32Array(0); + this.halfedges = new Uint32Array(0); + return; + } + if (orient2d(i0x, i0y, i1x, i1y, i2x, i2y) < 0) { + const i = i1; + const x3 = i1x; + const y4 = i1y; + i1 = i2; + i1x = i2x; + i1y = i2y; + i2 = i; + i2x = x3; + i2y = y4; + } + const center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y); + this._cx = center.x; + this._cy = center.y; + for (let i = 0; i < n; i++) { + this._dists[i] = dist(coords[2 * i], coords[2 * i + 1], center.x, center.y); + } + quicksort(this._ids, this._dists, 0, n - 1); + this._hullStart = i0; + let hullSize = 3; + hullNext[i0] = hullPrev[i2] = i1; + hullNext[i1] = hullPrev[i0] = i2; + hullNext[i2] = hullPrev[i1] = i0; + hullTri[i0] = 0; + hullTri[i1] = 1; + hullTri[i2] = 2; + hullHash.fill(-1); + hullHash[this._hashKey(i0x, i0y)] = i0; + hullHash[this._hashKey(i1x, i1y)] = i1; + hullHash[this._hashKey(i2x, i2y)] = i2; + this.trianglesLen = 0; + this._addTriangle(i0, i1, i2, -1, -1, -1); + for (let k = 0, xp, yp; k < this._ids.length; k++) { + const i = this._ids[k]; + const x3 = coords[2 * i]; + const y4 = coords[2 * i + 1]; + if (k > 0 && Math.abs(x3 - xp) <= EPSILON && Math.abs(y4 - yp) <= EPSILON) + continue; + xp = x3; + yp = y4; + if (i === i0 || i === i1 || i === i2) + continue; + let start2 = 0; + for (let j = 0, key = this._hashKey(x3, y4); j < this._hashSize; j++) { + start2 = hullHash[(key + j) % this._hashSize]; + if (start2 !== -1 && start2 !== hullNext[start2]) + break; + } + start2 = hullPrev[start2]; + let e = start2, q; + while (q = hullNext[e], orient2d(x3, y4, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1]) >= 0) { + e = q; + if (e === start2) { + e = -1; + break; + } + } + if (e === -1) + continue; + let t = this._addTriangle(e, i, hullNext[e], -1, -1, hullTri[e]); + hullTri[i] = this._legalize(t + 2); + hullTri[e] = t; + hullSize++; + let n2 = hullNext[e]; + while (q = hullNext[n2], orient2d(x3, y4, coords[2 * n2], coords[2 * n2 + 1], coords[2 * q], coords[2 * q + 1]) < 0) { + t = this._addTriangle(n2, i, q, hullTri[i], -1, hullTri[n2]); + hullTri[i] = this._legalize(t + 2); + hullNext[n2] = n2; + hullSize--; + n2 = q; + } + if (e === start2) { + while (q = hullPrev[e], orient2d(x3, y4, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1]) < 0) { + t = this._addTriangle(q, i, e, -1, hullTri[e], hullTri[q]); + this._legalize(t + 2); + hullTri[q] = t; + hullNext[e] = e; + hullSize--; + e = q; + } + } + this._hullStart = hullPrev[i] = e; + hullNext[e] = hullPrev[n2] = i; + hullNext[i] = n2; + hullHash[this._hashKey(x3, y4)] = i; + hullHash[this._hashKey(coords[2 * e], coords[2 * e + 1])] = e; + } + this.hull = new Uint32Array(hullSize); + for (let i = 0, e = this._hullStart; i < hullSize; i++) { + this.hull[i] = e; + e = hullNext[e]; + } + this.triangles = this._triangles.subarray(0, this.trianglesLen); + this.halfedges = this._halfedges.subarray(0, this.trianglesLen); + } + _hashKey(x3, y4) { + return Math.floor(pseudoAngle(x3 - this._cx, y4 - this._cy) * this._hashSize) % this._hashSize; + } + _legalize(a2) { + const { _triangles: triangles, _halfedges: halfedges, coords } = this; + let i = 0; + let ar = 0; + while (true) { + const b = halfedges[a2]; + const a0 = a2 - a2 % 3; + ar = a0 + (a2 + 2) % 3; + if (b === -1) { + if (i === 0) + break; + a2 = EDGE_STACK[--i]; + continue; + } + const b0 = b - b % 3; + const al = a0 + (a2 + 1) % 3; + const bl = b0 + (b + 2) % 3; + const p0 = triangles[ar]; + const pr = triangles[a2]; + const pl = triangles[al]; + const p1 = triangles[bl]; + const illegal = inCircle(coords[2 * p0], coords[2 * p0 + 1], coords[2 * pr], coords[2 * pr + 1], coords[2 * pl], coords[2 * pl + 1], coords[2 * p1], coords[2 * p1 + 1]); + if (illegal) { + triangles[a2] = p1; + triangles[b] = p0; + const hbl = halfedges[bl]; + if (hbl === -1) { + let e = this._hullStart; + do { + if (this._hullTri[e] === bl) { + this._hullTri[e] = a2; + break; + } + e = this._hullPrev[e]; + } while (e !== this._hullStart); + } + this._link(a2, hbl); + this._link(b, halfedges[ar]); + this._link(ar, bl); + const br = b0 + (b + 1) % 3; + if (i < EDGE_STACK.length) { + EDGE_STACK[i++] = br; + } + } else { + if (i === 0) + break; + a2 = EDGE_STACK[--i]; + } + } + return ar; + } + _link(a2, b) { + this._halfedges[a2] = b; + if (b !== -1) + this._halfedges[b] = a2; + } + _addTriangle(i0, i1, i2, a2, b, c2) { + const t = this.trianglesLen; + this._triangles[t] = i0; + this._triangles[t + 1] = i1; + this._triangles[t + 2] = i2; + this._link(t, a2); + this._link(t + 1, b); + this._link(t + 2, c2); + this.trianglesLen += 3; + return t; + } + }; + function pseudoAngle(dx, dy) { + const p = dx / (Math.abs(dx) + Math.abs(dy)); + return (dy > 0 ? 3 - p : 1 + p) / 4; + } + function dist(ax, ay, bx, by) { + const dx = ax - bx; + const dy = ay - by; + return dx * dx + dy * dy; + } + function inCircle(ax, ay, bx, by, cx, cy, px, py) { + const dx = ax - px; + const dy = ay - py; + const ex = bx - px; + const ey = by - py; + const fx = cx - px; + const fy = cy - py; + const ap = dx * dx + dy * dy; + const bp = ex * ex + ey * ey; + const cp = fx * fx + fy * fy; + return dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) < 0; + } + function circumradius(ax, ay, bx, by, cx, cy) { + const dx = bx - ax; + const dy = by - ay; + const ex = cx - ax; + const ey = cy - ay; + const bl = dx * dx + dy * dy; + const cl = ex * ex + ey * ey; + const d = 0.5 / (dx * ey - dy * ex); + const x3 = (ey * bl - dy * cl) * d; + const y4 = (dx * cl - ex * bl) * d; + return x3 * x3 + y4 * y4; + } + function circumcenter(ax, ay, bx, by, cx, cy) { + const dx = bx - ax; + const dy = by - ay; + const ex = cx - ax; + const ey = cy - ay; + const bl = dx * dx + dy * dy; + const cl = ex * ex + ey * ey; + const d = 0.5 / (dx * ey - dy * ex); + const x3 = ax + (ey * bl - dy * cl) * d; + const y4 = ay + (dx * cl - ex * bl) * d; + return { x: x3, y: y4 }; + } + function quicksort(ids, dists, left, right) { + if (right - left <= 20) { + for (let i = left + 1; i <= right; i++) { + const temp = ids[i]; + const tempDist = dists[temp]; + let j = i - 1; + while (j >= left && dists[ids[j]] > tempDist) + ids[j + 1] = ids[j--]; + ids[j + 1] = temp; + } + } else { + const median = left + right >> 1; + let i = left + 1; + let j = right; + swap(ids, median, i); + if (dists[ids[left]] > dists[ids[right]]) + swap(ids, left, right); + if (dists[ids[i]] > dists[ids[right]]) + swap(ids, i, right); + if (dists[ids[left]] > dists[ids[i]]) + swap(ids, left, i); + const temp = ids[i]; + const tempDist = dists[temp]; + while (true) { + do + i++; + while (dists[ids[i]] < tempDist); + do + j--; + while (dists[ids[j]] > tempDist); + if (j < i) + break; + swap(ids, i, j); + } + ids[left + 1] = ids[j]; + ids[j] = temp; + if (right - i + 1 >= j - left) { + quicksort(ids, dists, i, right); + quicksort(ids, dists, left, j - 1); + } else { + quicksort(ids, dists, left, j - 1); + quicksort(ids, dists, i, right); + } + } + } + function swap(arr, i, j) { + const tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + function defaultGetX(p) { + return p[0]; + } + function defaultGetY(p) { + return p[1]; + } + + // node_modules/d3-delaunay/src/path.js + var epsilon2 = 1e-6; + var Path = class { + constructor() { + this._x0 = this._y0 = this._x1 = this._y1 = null; + this._ = ""; + } + moveTo(x3, y4) { + this._ += `M${this._x0 = this._x1 = +x3},${this._y0 = this._y1 = +y4}`; + } + closePath() { + if (this._x1 !== null) { + this._x1 = this._x0, this._y1 = this._y0; + this._ += "Z"; + } + } + lineTo(x3, y4) { + this._ += `L${this._x1 = +x3},${this._y1 = +y4}`; + } + arc(x3, y4, r) { + x3 = +x3, y4 = +y4, r = +r; + const x0 = x3 + r; + const y0 = y4; + if (r < 0) + throw new Error("negative radius"); + if (this._x1 === null) + this._ += `M${x0},${y0}`; + else if (Math.abs(this._x1 - x0) > epsilon2 || Math.abs(this._y1 - y0) > epsilon2) + this._ += "L" + x0 + "," + y0; + if (!r) + return; + this._ += `A${r},${r},0,1,1,${x3 - r},${y4}A${r},${r},0,1,1,${this._x1 = x0},${this._y1 = y0}`; + } + rect(x3, y4, w, h) { + this._ += `M${this._x0 = this._x1 = +x3},${this._y0 = this._y1 = +y4}h${+w}v${+h}h${-w}Z`; + } + value() { + return this._ || null; + } + }; + + // node_modules/d3-delaunay/src/polygon.js + var Polygon = class { + constructor() { + this._ = []; + } + moveTo(x3, y4) { + this._.push([x3, y4]); + } + closePath() { + this._.push(this._[0].slice()); + } + lineTo(x3, y4) { + this._.push([x3, y4]); + } + value() { + return this._.length ? this._ : null; + } + }; + + // node_modules/d3-delaunay/src/voronoi.js + var Voronoi = class { + constructor(delaunay, [xmin, ymin, xmax, ymax] = [0, 0, 960, 500]) { + if (!((xmax = +xmax) >= (xmin = +xmin)) || !((ymax = +ymax) >= (ymin = +ymin))) + throw new Error("invalid bounds"); + this.delaunay = delaunay; + this._circumcenters = new Float64Array(delaunay.points.length * 2); + this.vectors = new Float64Array(delaunay.points.length * 2); + this.xmax = xmax, this.xmin = xmin; + this.ymax = ymax, this.ymin = ymin; + this._init(); + } + update() { + this.delaunay.update(); + this._init(); + return this; + } + _init() { + const { delaunay: { points, hull, triangles }, vectors } = this; + const circumcenters = this.circumcenters = this._circumcenters.subarray(0, triangles.length / 3 * 2); + for (let i = 0, j = 0, n = triangles.length, x3, y4; i < n; i += 3, j += 2) { + const t1 = triangles[i] * 2; + const t2 = triangles[i + 1] * 2; + const t3 = triangles[i + 2] * 2; + const x12 = points[t1]; + const y12 = points[t1 + 1]; + const x22 = points[t2]; + const y22 = points[t2 + 1]; + const x32 = points[t3]; + const y32 = points[t3 + 1]; + const dx = x22 - x12; + const dy = y22 - y12; + const ex = x32 - x12; + const ey = y32 - y12; + const ab4 = (dx * ey - dy * ex) * 2; + if (Math.abs(ab4) < 1e-9) { + let a2 = 1e9; + const r = triangles[0] * 2; + a2 *= Math.sign((points[r] - x12) * ey - (points[r + 1] - y12) * ex); + x3 = (x12 + x32) / 2 - a2 * ey; + y4 = (y12 + y32) / 2 + a2 * ex; + } else { + const d = 1 / ab4; + const bl = dx * dx + dy * dy; + const cl = ex * ex + ey * ey; + x3 = x12 + (ey * bl - dy * cl) * d; + y4 = y12 + (dx * cl - ex * bl) * d; + } + circumcenters[j] = x3; + circumcenters[j + 1] = y4; + } + let h = hull[hull.length - 1]; + let p0, p1 = h * 4; + let x0, x1 = points[2 * h]; + let y0, y1 = points[2 * h + 1]; + vectors.fill(0); + for (let i = 0; i < hull.length; ++i) { + h = hull[i]; + p0 = p1, x0 = x1, y0 = y1; + p1 = h * 4, x1 = points[2 * h], y1 = points[2 * h + 1]; + vectors[p0 + 2] = vectors[p1] = y0 - y1; + vectors[p0 + 3] = vectors[p1 + 1] = x1 - x0; + } + } + render(context) { + const buffer = context == null ? context = new Path() : void 0; + const { delaunay: { halfedges, inedges, hull }, circumcenters, vectors } = this; + if (hull.length <= 1) + return null; + for (let i = 0, n = halfedges.length; i < n; ++i) { + const j = halfedges[i]; + if (j < i) + continue; + const ti = Math.floor(i / 3) * 2; + const tj = Math.floor(j / 3) * 2; + const xi = circumcenters[ti]; + const yi = circumcenters[ti + 1]; + const xj = circumcenters[tj]; + const yj = circumcenters[tj + 1]; + this._renderSegment(xi, yi, xj, yj, context); + } + let h0, h1 = hull[hull.length - 1]; + for (let i = 0; i < hull.length; ++i) { + h0 = h1, h1 = hull[i]; + const t = Math.floor(inedges[h1] / 3) * 2; + const x3 = circumcenters[t]; + const y4 = circumcenters[t + 1]; + const v2 = h0 * 4; + const p = this._project(x3, y4, vectors[v2 + 2], vectors[v2 + 3]); + if (p) + this._renderSegment(x3, y4, p[0], p[1], context); + } + return buffer && buffer.value(); + } + renderBounds(context) { + const buffer = context == null ? context = new Path() : void 0; + context.rect(this.xmin, this.ymin, this.xmax - this.xmin, this.ymax - this.ymin); + return buffer && buffer.value(); + } + renderCell(i, context) { + const buffer = context == null ? context = new Path() : void 0; + const points = this._clip(i); + if (points === null || !points.length) + return; + context.moveTo(points[0], points[1]); + let n = points.length; + while (points[0] === points[n - 2] && points[1] === points[n - 1] && n > 1) + n -= 2; + for (let i2 = 2; i2 < n; i2 += 2) { + if (points[i2] !== points[i2 - 2] || points[i2 + 1] !== points[i2 - 1]) + context.lineTo(points[i2], points[i2 + 1]); + } + context.closePath(); + return buffer && buffer.value(); + } + *cellPolygons() { + const { delaunay: { points } } = this; + for (let i = 0, n = points.length / 2; i < n; ++i) { + const cell = this.cellPolygon(i); + if (cell) + cell.index = i, yield cell; + } + } + cellPolygon(i) { + const polygon = new Polygon(); + this.renderCell(i, polygon); + return polygon.value(); + } + _renderSegment(x0, y0, x1, y1, context) { + let S; + const c0 = this._regioncode(x0, y0); + const c1 = this._regioncode(x1, y1); + if (c0 === 0 && c1 === 0) { + context.moveTo(x0, y0); + context.lineTo(x1, y1); + } else if (S = this._clipSegment(x0, y0, x1, y1, c0, c1)) { + context.moveTo(S[0], S[1]); + context.lineTo(S[2], S[3]); + } + } + contains(i, x3, y4) { + if ((x3 = +x3, x3 !== x3) || (y4 = +y4, y4 !== y4)) + return false; + return this.delaunay._step(i, x3, y4) === i; + } + *neighbors(i) { + const ci = this._clip(i); + if (ci) + for (const j of this.delaunay.neighbors(i)) { + const cj = this._clip(j); + if (cj) + loop: + for (let ai = 0, li = ci.length; ai < li; ai += 2) { + for (let aj = 0, lj = cj.length; aj < lj; aj += 2) { + if (ci[ai] == cj[aj] && ci[ai + 1] == cj[aj + 1] && ci[(ai + 2) % li] == cj[(aj + lj - 2) % lj] && ci[(ai + 3) % li] == cj[(aj + lj - 1) % lj]) { + yield j; + break loop; + } + } + } + } + } + _cell(i) { + const { circumcenters, delaunay: { inedges, halfedges, triangles } } = this; + const e0 = inedges[i]; + if (e0 === -1) + return null; + const points = []; + let e = e0; + do { + const t = Math.floor(e / 3); + points.push(circumcenters[t * 2], circumcenters[t * 2 + 1]); + e = e % 3 === 2 ? e - 2 : e + 1; + if (triangles[e] !== i) + break; + e = halfedges[e]; + } while (e !== e0 && e !== -1); + return points; + } + _clip(i) { + if (i === 0 && this.delaunay.hull.length === 1) { + return [this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax, this.xmin, this.ymin]; + } + const points = this._cell(i); + if (points === null) + return null; + const { vectors: V } = this; + const v2 = i * 4; + return V[v2] || V[v2 + 1] ? this._clipInfinite(i, points, V[v2], V[v2 + 1], V[v2 + 2], V[v2 + 3]) : this._clipFinite(i, points); + } + _clipFinite(i, points) { + const n = points.length; + let P = null; + let x0, y0, x1 = points[n - 2], y1 = points[n - 1]; + let c0, c1 = this._regioncode(x1, y1); + let e0, e1 = 0; + for (let j = 0; j < n; j += 2) { + x0 = x1, y0 = y1, x1 = points[j], y1 = points[j + 1]; + c0 = c1, c1 = this._regioncode(x1, y1); + if (c0 === 0 && c1 === 0) { + e0 = e1, e1 = 0; + if (P) + P.push(x1, y1); + else + P = [x1, y1]; + } else { + let S, sx0, sy0, sx1, sy1; + if (c0 === 0) { + if ((S = this._clipSegment(x0, y0, x1, y1, c0, c1)) === null) + continue; + [sx0, sy0, sx1, sy1] = S; + } else { + if ((S = this._clipSegment(x1, y1, x0, y0, c1, c0)) === null) + continue; + [sx1, sy1, sx0, sy0] = S; + e0 = e1, e1 = this._edgecode(sx0, sy0); + if (e0 && e1) + this._edge(i, e0, e1, P, P.length); + if (P) + P.push(sx0, sy0); + else + P = [sx0, sy0]; + } + e0 = e1, e1 = this._edgecode(sx1, sy1); + if (e0 && e1) + this._edge(i, e0, e1, P, P.length); + if (P) + P.push(sx1, sy1); + else + P = [sx1, sy1]; + } + } + if (P) { + e0 = e1, e1 = this._edgecode(P[0], P[1]); + if (e0 && e1) + this._edge(i, e0, e1, P, P.length); + } else if (this.contains(i, (this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2)) { + return [this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax, this.xmin, this.ymin]; + } + return P; + } + _clipSegment(x0, y0, x1, y1, c0, c1) { + while (true) { + if (c0 === 0 && c1 === 0) + return [x0, y0, x1, y1]; + if (c0 & c1) + return null; + let x3, y4, c2 = c0 || c1; + if (c2 & 8) + x3 = x0 + (x1 - x0) * (this.ymax - y0) / (y1 - y0), y4 = this.ymax; + else if (c2 & 4) + x3 = x0 + (x1 - x0) * (this.ymin - y0) / (y1 - y0), y4 = this.ymin; + else if (c2 & 2) + y4 = y0 + (y1 - y0) * (this.xmax - x0) / (x1 - x0), x3 = this.xmax; + else + y4 = y0 + (y1 - y0) * (this.xmin - x0) / (x1 - x0), x3 = this.xmin; + if (c0) + x0 = x3, y0 = y4, c0 = this._regioncode(x0, y0); + else + x1 = x3, y1 = y4, c1 = this._regioncode(x1, y1); + } + } + _clipInfinite(i, points, vx0, vy0, vxn, vyn) { + let P = Array.from(points), p; + if (p = this._project(P[0], P[1], vx0, vy0)) + P.unshift(p[0], p[1]); + if (p = this._project(P[P.length - 2], P[P.length - 1], vxn, vyn)) + P.push(p[0], p[1]); + if (P = this._clipFinite(i, P)) { + for (let j = 0, n = P.length, c0, c1 = this._edgecode(P[n - 2], P[n - 1]); j < n; j += 2) { + c0 = c1, c1 = this._edgecode(P[j], P[j + 1]); + if (c0 && c1) + j = this._edge(i, c0, c1, P, j), n = P.length; + } + } else if (this.contains(i, (this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2)) { + P = [this.xmin, this.ymin, this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax]; + } + return P; + } + _edge(i, e0, e1, P, j) { + while (e0 !== e1) { + let x3, y4; + switch (e0) { + case 5: + e0 = 4; + continue; + case 4: + e0 = 6, x3 = this.xmax, y4 = this.ymin; + break; + case 6: + e0 = 2; + continue; + case 2: + e0 = 10, x3 = this.xmax, y4 = this.ymax; + break; + case 10: + e0 = 8; + continue; + case 8: + e0 = 9, x3 = this.xmin, y4 = this.ymax; + break; + case 9: + e0 = 1; + continue; + case 1: + e0 = 5, x3 = this.xmin, y4 = this.ymin; + break; + } + if ((P[j] !== x3 || P[j + 1] !== y4) && this.contains(i, x3, y4)) { + P.splice(j, 0, x3, y4), j += 2; + } + } + if (P.length > 4) { + for (let i2 = 0; i2 < P.length; i2 += 2) { + const j2 = (i2 + 2) % P.length, k = (i2 + 4) % P.length; + if (P[i2] === P[j2] && P[j2] === P[k] || P[i2 + 1] === P[j2 + 1] && P[j2 + 1] === P[k + 1]) + P.splice(j2, 2), i2 -= 2; + } + } + return j; + } + _project(x0, y0, vx, vy) { + let t = Infinity, c2, x3, y4; + if (vy < 0) { + if (y0 <= this.ymin) + return null; + if ((c2 = (this.ymin - y0) / vy) < t) + y4 = this.ymin, x3 = x0 + (t = c2) * vx; + } else if (vy > 0) { + if (y0 >= this.ymax) + return null; + if ((c2 = (this.ymax - y0) / vy) < t) + y4 = this.ymax, x3 = x0 + (t = c2) * vx; + } + if (vx > 0) { + if (x0 >= this.xmax) + return null; + if ((c2 = (this.xmax - x0) / vx) < t) + x3 = this.xmax, y4 = y0 + (t = c2) * vy; + } else if (vx < 0) { + if (x0 <= this.xmin) + return null; + if ((c2 = (this.xmin - x0) / vx) < t) + x3 = this.xmin, y4 = y0 + (t = c2) * vy; + } + return [x3, y4]; + } + _edgecode(x3, y4) { + return (x3 === this.xmin ? 1 : x3 === this.xmax ? 2 : 0) | (y4 === this.ymin ? 4 : y4 === this.ymax ? 8 : 0); + } + _regioncode(x3, y4) { + return (x3 < this.xmin ? 1 : x3 > this.xmax ? 2 : 0) | (y4 < this.ymin ? 4 : y4 > this.ymax ? 8 : 0); + } + }; + + // node_modules/d3-delaunay/src/delaunay.js + var tau = 2 * Math.PI; + var pow = Math.pow; + function pointX(p) { + return p[0]; + } + function pointY(p) { + return p[1]; + } + function collinear(d) { + const { triangles, coords } = d; + for (let i = 0; i < triangles.length; i += 3) { + const a2 = 2 * triangles[i], b = 2 * triangles[i + 1], c2 = 2 * triangles[i + 2], cross = (coords[c2] - coords[a2]) * (coords[b + 1] - coords[a2 + 1]) - (coords[b] - coords[a2]) * (coords[c2 + 1] - coords[a2 + 1]); + if (cross > 1e-10) + return false; + } + return true; + } + function jitter(x3, y4, r) { + return [x3 + Math.sin(x3 + y4) * r, y4 + Math.cos(x3 - y4) * r]; + } + var Delaunay = class { + static from(points, fx = pointX, fy = pointY, that) { + return new Delaunay("length" in points ? flatArray(points, fx, fy, that) : Float64Array.from(flatIterable(points, fx, fy, that))); + } + constructor(points) { + this._delaunator = new Delaunator(points); + this.inedges = new Int32Array(points.length / 2); + this._hullIndex = new Int32Array(points.length / 2); + this.points = this._delaunator.coords; + this._init(); + } + update() { + this._delaunator.update(); + this._init(); + return this; + } + _init() { + const d = this._delaunator, points = this.points; + if (d.hull && d.hull.length > 2 && collinear(d)) { + this.collinear = Int32Array.from({ length: points.length / 2 }, (_, i) => i).sort((i, j) => points[2 * i] - points[2 * j] || points[2 * i + 1] - points[2 * j + 1]); + const e = this.collinear[0], f = this.collinear[this.collinear.length - 1], bounds = [points[2 * e], points[2 * e + 1], points[2 * f], points[2 * f + 1]], r = 1e-8 * Math.hypot(bounds[3] - bounds[1], bounds[2] - bounds[0]); + for (let i = 0, n = points.length / 2; i < n; ++i) { + const p = jitter(points[2 * i], points[2 * i + 1], r); + points[2 * i] = p[0]; + points[2 * i + 1] = p[1]; + } + this._delaunator = new Delaunator(points); + } else { + delete this.collinear; + } + const halfedges = this.halfedges = this._delaunator.halfedges; + const hull = this.hull = this._delaunator.hull; + const triangles = this.triangles = this._delaunator.triangles; + const inedges = this.inedges.fill(-1); + const hullIndex = this._hullIndex.fill(-1); + for (let e = 0, n = halfedges.length; e < n; ++e) { + const p = triangles[e % 3 === 2 ? e - 2 : e + 1]; + if (halfedges[e] === -1 || inedges[p] === -1) + inedges[p] = e; + } + for (let i = 0, n = hull.length; i < n; ++i) { + hullIndex[hull[i]] = i; + } + if (hull.length <= 2 && hull.length > 0) { + this.triangles = new Int32Array(3).fill(-1); + this.halfedges = new Int32Array(3).fill(-1); + this.triangles[0] = hull[0]; + inedges[hull[0]] = 1; + if (hull.length === 2) { + inedges[hull[1]] = 0; + this.triangles[1] = hull[1]; + this.triangles[2] = hull[1]; + } + } + } + voronoi(bounds) { + return new Voronoi(this, bounds); + } + *neighbors(i) { + const { inedges, hull, _hullIndex, halfedges, triangles, collinear: collinear2 } = this; + if (collinear2) { + const l = collinear2.indexOf(i); + if (l > 0) + yield collinear2[l - 1]; + if (l < collinear2.length - 1) + yield collinear2[l + 1]; + return; + } + const e0 = inedges[i]; + if (e0 === -1) + return; + let e = e0, p0 = -1; + do { + yield p0 = triangles[e]; + e = e % 3 === 2 ? e - 2 : e + 1; + if (triangles[e] !== i) + return; + e = halfedges[e]; + if (e === -1) { + const p = hull[(_hullIndex[i] + 1) % hull.length]; + if (p !== p0) + yield p; + return; + } + } while (e !== e0); + } + find(x3, y4, i = 0) { + if ((x3 = +x3, x3 !== x3) || (y4 = +y4, y4 !== y4)) + return -1; + const i0 = i; + let c2; + while ((c2 = this._step(i, x3, y4)) >= 0 && c2 !== i && c2 !== i0) + i = c2; + return c2; + } + _step(i, x3, y4) { + const { inedges, hull, _hullIndex, halfedges, triangles, points } = this; + if (inedges[i] === -1 || !points.length) + return (i + 1) % (points.length >> 1); + let c2 = i; + let dc = pow(x3 - points[i * 2], 2) + pow(y4 - points[i * 2 + 1], 2); + const e0 = inedges[i]; + let e = e0; + do { + let t = triangles[e]; + const dt = pow(x3 - points[t * 2], 2) + pow(y4 - points[t * 2 + 1], 2); + if (dt < dc) + dc = dt, c2 = t; + e = e % 3 === 2 ? e - 2 : e + 1; + if (triangles[e] !== i) + break; + e = halfedges[e]; + if (e === -1) { + e = hull[(_hullIndex[i] + 1) % hull.length]; + if (e !== t) { + if (pow(x3 - points[e * 2], 2) + pow(y4 - points[e * 2 + 1], 2) < dc) + return e; + } + break; + } + } while (e !== e0); + return c2; + } + render(context) { + const buffer = context == null ? context = new Path() : void 0; + const { points, halfedges, triangles } = this; + for (let i = 0, n = halfedges.length; i < n; ++i) { + const j = halfedges[i]; + if (j < i) + continue; + const ti = triangles[i] * 2; + const tj = triangles[j] * 2; + context.moveTo(points[ti], points[ti + 1]); + context.lineTo(points[tj], points[tj + 1]); + } + this.renderHull(context); + return buffer && buffer.value(); + } + renderPoints(context, r) { + if (r === void 0 && (!context || typeof context.moveTo !== "function")) + r = context, context = null; + r = r == void 0 ? 2 : +r; + const buffer = context == null ? context = new Path() : void 0; + const { points } = this; + for (let i = 0, n = points.length; i < n; i += 2) { + const x3 = points[i], y4 = points[i + 1]; + context.moveTo(x3 + r, y4); + context.arc(x3, y4, r, 0, tau); + } + return buffer && buffer.value(); + } + renderHull(context) { + const buffer = context == null ? context = new Path() : void 0; + const { hull, points } = this; + const h = hull[0] * 2, n = hull.length; + context.moveTo(points[h], points[h + 1]); + for (let i = 1; i < n; ++i) { + const h2 = 2 * hull[i]; + context.lineTo(points[h2], points[h2 + 1]); + } + context.closePath(); + return buffer && buffer.value(); + } + hullPolygon() { + const polygon = new Polygon(); + this.renderHull(polygon); + return polygon.value(); + } + renderTriangle(i, context) { + const buffer = context == null ? context = new Path() : void 0; + const { points, triangles } = this; + const t0 = triangles[i *= 3] * 2; + const t1 = triangles[i + 1] * 2; + const t2 = triangles[i + 2] * 2; + context.moveTo(points[t0], points[t0 + 1]); + context.lineTo(points[t1], points[t1 + 1]); + context.lineTo(points[t2], points[t2 + 1]); + context.closePath(); + return buffer && buffer.value(); + } + *trianglePolygons() { + const { triangles } = this; + for (let i = 0, n = triangles.length / 3; i < n; ++i) { + yield this.trianglePolygon(i); + } + } + trianglePolygon(i) { + const polygon = new Polygon(); + this.renderTriangle(i, polygon); + return polygon.value(); + } + }; + function flatArray(points, fx, fy, that) { + const n = points.length; + const array2 = new Float64Array(n * 2); + for (let i = 0; i < n; ++i) { + const p = points[i]; + array2[i * 2] = fx.call(that, p, i, points); + array2[i * 2 + 1] = fy.call(that, p, i, points); + } + return array2; + } + function* flatIterable(points, fx, fy, that) { + let i = 0; + for (const p of points) { + yield fx.call(that, p, i, points); + yield fy.call(that, p, i, points); + ++i; + } + } + + // node_modules/d3-dsv/src/dsv.js + var EOL = {}; + var EOF = {}; + var QUOTE = 34; + var NEWLINE = 10; + var RETURN = 13; + function objectConverter(columns) { + return new Function("d", "return {" + columns.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + '] || ""'; + }).join(",") + "}"); + } + function customConverter(columns, f) { + var object = objectConverter(columns); + return function(row, i) { + return f(object(row), i, columns); + }; + } + function inferColumns(rows) { + var columnSet = /* @__PURE__ */ Object.create(null), columns = []; + rows.forEach(function(row) { + for (var column in row) { + if (!(column in columnSet)) { + columns.push(columnSet[column] = column); + } + } + }); + return columns; + } + function pad(value, width) { + var s = value + "", length = s.length; + return length < width ? new Array(width - length + 1).join(0) + s : s; + } + function formatYear(year) { + return year < 0 ? "-" + pad(-year, 6) : year > 9999 ? "+" + pad(year, 6) : pad(year, 4); + } + function formatDate(date) { + var hours = date.getUTCHours(), minutes = date.getUTCMinutes(), seconds = date.getUTCSeconds(), milliseconds = date.getUTCMilliseconds(); + return isNaN(date) ? "Invalid Date" : formatYear(date.getUTCFullYear(), 4) + "-" + pad(date.getUTCMonth() + 1, 2) + "-" + pad(date.getUTCDate(), 2) + (milliseconds ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + "." + pad(milliseconds, 3) + "Z" : seconds ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + "Z" : minutes || hours ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + "Z" : ""); + } + function dsv_default(delimiter) { + var reFormat = new RegExp('["' + delimiter + "\n\r]"), DELIMITER = delimiter.charCodeAt(0); + function parse(text, f) { + var convert, columns, rows = parseRows(text, function(row, i) { + if (convert) + return convert(row, i - 1); + columns = row, convert = f ? customConverter(row, f) : objectConverter(row); + }); + rows.columns = columns || []; + return rows; + } + function parseRows(text, f) { + var rows = [], N = text.length, I = 0, n = 0, t, eof = N <= 0, eol = false; + if (text.charCodeAt(N - 1) === NEWLINE) + --N; + if (text.charCodeAt(N - 1) === RETURN) + --N; + function token() { + if (eof) + return EOF; + if (eol) + return eol = false, EOL; + var i, j = I, c2; + if (text.charCodeAt(j) === QUOTE) { + while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE) + ; + if ((i = I) >= N) + eof = true; + else if ((c2 = text.charCodeAt(I++)) === NEWLINE) + eol = true; + else if (c2 === RETURN) { + eol = true; + if (text.charCodeAt(I) === NEWLINE) + ++I; + } + return text.slice(j + 1, i - 1).replace(/""/g, '"'); + } + while (I < N) { + if ((c2 = text.charCodeAt(i = I++)) === NEWLINE) + eol = true; + else if (c2 === RETURN) { + eol = true; + if (text.charCodeAt(I) === NEWLINE) + ++I; + } else if (c2 !== DELIMITER) + continue; + return text.slice(j, i); + } + return eof = true, text.slice(j, N); + } + while ((t = token()) !== EOF) { + var row = []; + while (t !== EOL && t !== EOF) + row.push(t), t = token(); + if (f && (row = f(row, n++)) == null) + continue; + rows.push(row); + } + return rows; + } + function preformatBody(rows, columns) { + return rows.map(function(row) { + return columns.map(function(column) { + return formatValue(row[column]); + }).join(delimiter); + }); + } + function format2(rows, columns) { + if (columns == null) + columns = inferColumns(rows); + return [columns.map(formatValue).join(delimiter)].concat(preformatBody(rows, columns)).join("\n"); + } + function formatBody(rows, columns) { + if (columns == null) + columns = inferColumns(rows); + return preformatBody(rows, columns).join("\n"); + } + function formatRows(rows) { + return rows.map(formatRow).join("\n"); + } + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + function formatValue(value) { + return value == null ? "" : value instanceof Date ? formatDate(value) : reFormat.test(value += "") ? '"' + value.replace(/"/g, '""') + '"' : value; + } + return { + parse, + parseRows, + format: format2, + formatBody, + formatRows, + formatRow, + formatValue + }; + } + + // node_modules/d3-dsv/src/csv.js + var csv = dsv_default(","); + var csvParse = csv.parse; + var csvParseRows = csv.parseRows; + var csvFormat = csv.format; + var csvFormatBody = csv.formatBody; + var csvFormatRows = csv.formatRows; + var csvFormatRow = csv.formatRow; + var csvFormatValue = csv.formatValue; + + // node_modules/d3-dsv/src/tsv.js + var tsv = dsv_default(" "); + var tsvParse = tsv.parse; + var tsvParseRows = tsv.parseRows; + var tsvFormat = tsv.format; + var tsvFormatBody = tsv.formatBody; + var tsvFormatRows = tsv.formatRows; + var tsvFormatRow = tsv.formatRow; + var tsvFormatValue = tsv.formatValue; + + // node_modules/d3-fetch/src/text.js + function responseText(response) { + if (!response.ok) + throw new Error(response.status + " " + response.statusText); + return response.text(); + } + function text_default3(input, init2) { + return fetch(input, init2).then(responseText); + } + + // node_modules/d3-fetch/src/dsv.js + function dsvParse(parse) { + return function(input, init2, row) { + if (arguments.length === 2 && typeof init2 === "function") + row = init2, init2 = void 0; + return text_default3(input, init2).then(function(response) { + return parse(response, row); + }); + }; + } + var csv2 = dsvParse(csvParse); + var tsv2 = dsvParse(tsvParse); + + // node_modules/d3-force/src/center.js + function center_default(x3, y4) { + var nodes, strength = 1; + if (x3 == null) + x3 = 0; + if (y4 == null) + y4 = 0; + function force() { + var i, n = nodes.length, node, sx = 0, sy = 0; + for (i = 0; i < n; ++i) { + node = nodes[i], sx += node.x, sy += node.y; + } + for (sx = (sx / n - x3) * strength, sy = (sy / n - y4) * strength, i = 0; i < n; ++i) { + node = nodes[i], node.x -= sx, node.y -= sy; + } + } + force.initialize = function(_) { + nodes = _; + }; + force.x = function(_) { + return arguments.length ? (x3 = +_, force) : x3; + }; + force.y = function(_) { + return arguments.length ? (y4 = +_, force) : y4; + }; + force.strength = function(_) { + return arguments.length ? (strength = +_, force) : strength; + }; + return force; + } + + // node_modules/d3-quadtree/src/add.js + function add_default(d) { + const x3 = +this._x.call(null, d), y4 = +this._y.call(null, d); + return add(this.cover(x3, y4), x3, y4, d); + } + function add(tree, x3, y4, d) { + if (isNaN(x3) || isNaN(y4)) + return tree; + var parent, node = tree._root, leaf = { data: d }, x0 = tree._x0, y0 = tree._y0, x1 = tree._x1, y1 = tree._y1, xm, ym, xp, yp, right, bottom, i, j; + if (!node) + return tree._root = leaf, tree; + while (node.length) { + if (right = x3 >= (xm = (x0 + x1) / 2)) + x0 = xm; + else + x1 = xm; + if (bottom = y4 >= (ym = (y0 + y1) / 2)) + y0 = ym; + else + y1 = ym; + if (parent = node, !(node = node[i = bottom << 1 | right])) + return parent[i] = leaf, tree; + } + xp = +tree._x.call(null, node.data); + yp = +tree._y.call(null, node.data); + if (x3 === xp && y4 === yp) + return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; + do { + parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); + if (right = x3 >= (xm = (x0 + x1) / 2)) + x0 = xm; + else + x1 = xm; + if (bottom = y4 >= (ym = (y0 + y1) / 2)) + y0 = ym; + else + y1 = ym; + } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | xp >= xm)); + return parent[j] = node, parent[i] = leaf, tree; + } + function addAll(data) { + var d, i, n = data.length, x3, y4, xz = new Array(n), yz = new Array(n), x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity; + for (i = 0; i < n; ++i) { + if (isNaN(x3 = +this._x.call(null, d = data[i])) || isNaN(y4 = +this._y.call(null, d))) + continue; + xz[i] = x3; + yz[i] = y4; + if (x3 < x0) + x0 = x3; + if (x3 > x1) + x1 = x3; + if (y4 < y0) + y0 = y4; + if (y4 > y1) + y1 = y4; + } + if (x0 > x1 || y0 > y1) + return this; + this.cover(x0, y0).cover(x1, y1); + for (i = 0; i < n; ++i) { + add(this, xz[i], yz[i], data[i]); + } + return this; + } + + // node_modules/d3-quadtree/src/cover.js + function cover_default(x3, y4) { + if (isNaN(x3 = +x3) || isNaN(y4 = +y4)) + return this; + var x0 = this._x0, y0 = this._y0, x1 = this._x1, y1 = this._y1; + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x3)) + 1; + y1 = (y0 = Math.floor(y4)) + 1; + } else { + var z = x1 - x0 || 1, node = this._root, parent, i; + while (x0 > x3 || x3 >= x1 || y0 > y4 || y4 >= y1) { + i = (y4 < y0) << 1 | x3 < x0; + parent = new Array(4), parent[i] = node, node = parent, z *= 2; + switch (i) { + case 0: + x1 = x0 + z, y1 = y0 + z; + break; + case 1: + x0 = x1 - z, y1 = y0 + z; + break; + case 2: + x1 = x0 + z, y0 = y1 - z; + break; + case 3: + x0 = x1 - z, y0 = y1 - z; + break; + } + } + if (this._root && this._root.length) + this._root = node; + } + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + return this; + } + + // node_modules/d3-quadtree/src/data.js + function data_default2() { + var data = []; + this.visit(function(node) { + if (!node.length) + do + data.push(node.data); + while (node = node.next); + }); + return data; + } + + // node_modules/d3-quadtree/src/extent.js + function extent_default(_) { + return arguments.length ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) : isNaN(this._x0) ? void 0 : [[this._x0, this._y0], [this._x1, this._y1]]; + } + + // node_modules/d3-quadtree/src/quad.js + function quad_default(node, x0, y0, x1, y1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.x1 = x1; + this.y1 = y1; + } + + // node_modules/d3-quadtree/src/find.js + function find_default(x3, y4, radius) { + var data, x0 = this._x0, y0 = this._y0, x1, y1, x22, y22, x32 = this._x1, y32 = this._y1, quads = [], node = this._root, q, i; + if (node) + quads.push(new quad_default(node, x0, y0, x32, y32)); + if (radius == null) + radius = Infinity; + else { + x0 = x3 - radius, y0 = y4 - radius; + x32 = x3 + radius, y32 = y4 + radius; + radius *= radius; + } + while (q = quads.pop()) { + if (!(node = q.node) || (x1 = q.x0) > x32 || (y1 = q.y0) > y32 || (x22 = q.x1) < x0 || (y22 = q.y1) < y0) + continue; + if (node.length) { + var xm = (x1 + x22) / 2, ym = (y1 + y22) / 2; + quads.push(new quad_default(node[3], xm, ym, x22, y22), new quad_default(node[2], x1, ym, xm, y22), new quad_default(node[1], xm, y1, x22, ym), new quad_default(node[0], x1, y1, xm, ym)); + if (i = (y4 >= ym) << 1 | x3 >= xm) { + q = quads[quads.length - 1]; + quads[quads.length - 1] = quads[quads.length - 1 - i]; + quads[quads.length - 1 - i] = q; + } + } else { + var dx = x3 - +this._x.call(null, node.data), dy = y4 - +this._y.call(null, node.data), d2 = dx * dx + dy * dy; + if (d2 < radius) { + var d = Math.sqrt(radius = d2); + x0 = x3 - d, y0 = y4 - d; + x32 = x3 + d, y32 = y4 + d; + data = node.data; + } + } + } + return data; + } + + // node_modules/d3-quadtree/src/remove.js + function remove_default3(d) { + if (isNaN(x3 = +this._x.call(null, d)) || isNaN(y4 = +this._y.call(null, d))) + return this; + var parent, node = this._root, retainer, previous, next, x0 = this._x0, y0 = this._y0, x1 = this._x1, y1 = this._y1, x3, y4, xm, ym, right, bottom, i, j; + if (!node) + return this; + if (node.length) + while (true) { + if (right = x3 >= (xm = (x0 + x1) / 2)) + x0 = xm; + else + x1 = xm; + if (bottom = y4 >= (ym = (y0 + y1) / 2)) + y0 = ym; + else + y1 = ym; + if (!(parent = node, node = node[i = bottom << 1 | right])) + return this; + if (!node.length) + break; + if (parent[i + 1 & 3] || parent[i + 2 & 3] || parent[i + 3 & 3]) + retainer = parent, j = i; + } + while (node.data !== d) + if (!(previous = node, node = node.next)) + return this; + if (next = node.next) + delete node.next; + if (previous) + return next ? previous.next = next : delete previous.next, this; + if (!parent) + return this._root = next, this; + next ? parent[i] = next : delete parent[i]; + if ((node = parent[0] || parent[1] || parent[2] || parent[3]) && node === (parent[3] || parent[2] || parent[1] || parent[0]) && !node.length) { + if (retainer) + retainer[j] = node; + else + this._root = node; + } + return this; + } + function removeAll(data) { + for (var i = 0, n = data.length; i < n; ++i) + this.remove(data[i]); + return this; + } + + // node_modules/d3-quadtree/src/root.js + function root_default() { + return this._root; + } + + // node_modules/d3-quadtree/src/size.js + function size_default2() { + var size = 0; + this.visit(function(node) { + if (!node.length) + do + ++size; + while (node = node.next); + }); + return size; + } + + // node_modules/d3-quadtree/src/visit.js + function visit_default(callback) { + var quads = [], q, node = this._root, child, x0, y0, x1, y1; + if (node) + quads.push(new quad_default(node, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { + var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[3]) + quads.push(new quad_default(child, xm, ym, x1, y1)); + if (child = node[2]) + quads.push(new quad_default(child, x0, ym, xm, y1)); + if (child = node[1]) + quads.push(new quad_default(child, xm, y0, x1, ym)); + if (child = node[0]) + quads.push(new quad_default(child, x0, y0, xm, ym)); + } + } + return this; + } + + // node_modules/d3-quadtree/src/visitAfter.js + function visitAfter_default(callback) { + var quads = [], next = [], q; + if (this._root) + quads.push(new quad_default(this._root, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[0]) + quads.push(new quad_default(child, x0, y0, xm, ym)); + if (child = node[1]) + quads.push(new quad_default(child, xm, y0, x1, ym)); + if (child = node[2]) + quads.push(new quad_default(child, x0, ym, xm, y1)); + if (child = node[3]) + quads.push(new quad_default(child, xm, ym, x1, y1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.y0, q.x1, q.y1); + } + return this; + } + + // node_modules/d3-quadtree/src/x.js + function defaultX(d) { + return d[0]; + } + function x_default(_) { + return arguments.length ? (this._x = _, this) : this._x; + } + + // node_modules/d3-quadtree/src/y.js + function defaultY(d) { + return d[1]; + } + function y_default(_) { + return arguments.length ? (this._y = _, this) : this._y; + } + + // node_modules/d3-quadtree/src/quadtree.js + function quadtree(nodes, x3, y4) { + var tree = new Quadtree(x3 == null ? defaultX : x3, y4 == null ? defaultY : y4, NaN, NaN, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); + } + function Quadtree(x3, y4, x0, y0, x1, y1) { + this._x = x3; + this._y = y4; + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + this._root = void 0; + } + function leaf_copy(leaf) { + var copy2 = { data: leaf.data }, next = copy2; + while (leaf = leaf.next) + next = next.next = { data: leaf.data }; + return copy2; + } + var treeProto = quadtree.prototype = Quadtree.prototype; + treeProto.copy = function() { + var copy2 = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), node = this._root, nodes, child; + if (!node) + return copy2; + if (!node.length) + return copy2._root = leaf_copy(node), copy2; + nodes = [{ source: node, target: copy2._root = new Array(4) }]; + while (node = nodes.pop()) { + for (var i = 0; i < 4; ++i) { + if (child = node.source[i]) { + if (child.length) + nodes.push({ source: child, target: node.target[i] = new Array(4) }); + else + node.target[i] = leaf_copy(child); + } + } + } + return copy2; + }; + treeProto.add = add_default; + treeProto.addAll = addAll; + treeProto.cover = cover_default; + treeProto.data = data_default2; + treeProto.extent = extent_default; + treeProto.find = find_default; + treeProto.remove = remove_default3; + treeProto.removeAll = removeAll; + treeProto.root = root_default; + treeProto.size = size_default2; + treeProto.visit = visit_default; + treeProto.visitAfter = visitAfter_default; + treeProto.x = x_default; + treeProto.y = y_default; + + // node_modules/d3-force/src/constant.js + function constant_default5(x3) { + return function() { + return x3; + }; + } + + // node_modules/d3-force/src/jiggle.js + function jiggle_default(random) { + return (random() - 0.5) * 1e-6; + } + + // node_modules/d3-force/src/collide.js + function x(d) { + return d.x + d.vx; + } + function y2(d) { + return d.y + d.vy; + } + function collide_default(radius) { + var nodes, radii, random, strength = 1, iterations = 1; + if (typeof radius !== "function") + radius = constant_default5(radius == null ? 1 : +radius); + function force() { + var i, n = nodes.length, tree, node, xi, yi, ri, ri2; + for (var k = 0; k < iterations; ++k) { + tree = quadtree(nodes, x, y2).visitAfter(prepare); + for (i = 0; i < n; ++i) { + node = nodes[i]; + ri = radii[node.index], ri2 = ri * ri; + xi = node.x + node.vx; + yi = node.y + node.vy; + tree.visit(apply); + } + } + function apply(quad, x0, y0, x1, y1) { + var data = quad.data, rj = quad.r, r = ri + rj; + if (data) { + if (data.index > node.index) { + var x3 = xi - data.x - data.vx, y4 = yi - data.y - data.vy, l = x3 * x3 + y4 * y4; + if (l < r * r) { + if (x3 === 0) + x3 = jiggle_default(random), l += x3 * x3; + if (y4 === 0) + y4 = jiggle_default(random), l += y4 * y4; + l = (r - (l = Math.sqrt(l))) / l * strength; + node.vx += (x3 *= l) * (r = (rj *= rj) / (ri2 + rj)); + node.vy += (y4 *= l) * r; + data.vx -= x3 * (r = 1 - r); + data.vy -= y4 * r; + } + } + return; + } + return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; + } + } + function prepare(quad) { + if (quad.data) + return quad.r = radii[quad.data.index]; + for (var i = quad.r = 0; i < 4; ++i) { + if (quad[i] && quad[i].r > quad.r) { + quad.r = quad[i].r; + } + } + } + function initialize() { + if (!nodes) + return; + var i, n = nodes.length, node; + radii = new Array(n); + for (i = 0; i < n; ++i) + node = nodes[i], radii[node.index] = +radius(node, i, nodes); + } + force.initialize = function(_nodes, _random) { + nodes = _nodes; + random = _random; + initialize(); + }; + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + force.strength = function(_) { + return arguments.length ? (strength = +_, force) : strength; + }; + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant_default5(+_), initialize(), force) : radius; + }; + return force; + } + + // node_modules/d3-force/src/link.js + function index(d) { + return d.index; + } + function find2(nodeById, nodeId) { + var node = nodeById.get(nodeId); + if (!node) + throw new Error("node not found: " + nodeId); + return node; + } + function link_default(links) { + var id2 = index, strength = defaultStrength, strengths, distance = constant_default5(30), distances, nodes, count, bias, random, iterations = 1; + if (links == null) + links = []; + function defaultStrength(link) { + return 1 / Math.min(count[link.source.index], count[link.target.index]); + } + function force(alpha) { + for (var k = 0, n = links.length; k < iterations; ++k) { + for (var i = 0, link, source, target, x3, y4, l, b; i < n; ++i) { + link = links[i], source = link.source, target = link.target; + x3 = target.x + target.vx - source.x - source.vx || jiggle_default(random); + y4 = target.y + target.vy - source.y - source.vy || jiggle_default(random); + l = Math.sqrt(x3 * x3 + y4 * y4); + l = (l - distances[i]) / l * alpha * strengths[i]; + x3 *= l, y4 *= l; + target.vx -= x3 * (b = bias[i]); + target.vy -= y4 * b; + source.vx += x3 * (b = 1 - b); + source.vy += y4 * b; + } + } + } + function initialize() { + if (!nodes) + return; + var i, n = nodes.length, m2 = links.length, nodeById = new Map(nodes.map((d, i2) => [id2(d, i2, nodes), d])), link; + for (i = 0, count = new Array(n); i < m2; ++i) { + link = links[i], link.index = i; + if (typeof link.source !== "object") + link.source = find2(nodeById, link.source); + if (typeof link.target !== "object") + link.target = find2(nodeById, link.target); + count[link.source.index] = (count[link.source.index] || 0) + 1; + count[link.target.index] = (count[link.target.index] || 0) + 1; + } + for (i = 0, bias = new Array(m2); i < m2; ++i) { + link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + } + strengths = new Array(m2), initializeStrength(); + distances = new Array(m2), initializeDistance(); + } + function initializeStrength() { + if (!nodes) + return; + for (var i = 0, n = links.length; i < n; ++i) { + strengths[i] = +strength(links[i], i, links); + } + } + function initializeDistance() { + if (!nodes) + return; + for (var i = 0, n = links.length; i < n; ++i) { + distances[i] = +distance(links[i], i, links); + } + } + force.initialize = function(_nodes, _random) { + nodes = _nodes; + random = _random; + initialize(); + }; + force.links = function(_) { + return arguments.length ? (links = _, initialize(), force) : links; + }; + force.id = function(_) { + return arguments.length ? (id2 = _, force) : id2; + }; + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant_default5(+_), initializeStrength(), force) : strength; + }; + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant_default5(+_), initializeDistance(), force) : distance; + }; + return force; + } + + // node_modules/d3-force/src/lcg.js + var a = 1664525; + var c = 1013904223; + var m = 4294967296; + function lcg_default() { + let s = 1; + return () => (s = (a * s + c) % m) / m; + } + + // node_modules/d3-force/src/simulation.js + function x2(d) { + return d.x; + } + function y3(d) { + return d.y; + } + var initialRadius = 10; + var initialAngle = Math.PI * (3 - Math.sqrt(5)); + function simulation_default(nodes) { + var simulation, alpha = 1, alphaMin = 1e-3, alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), alphaTarget = 0, velocityDecay = 0.6, forces = /* @__PURE__ */ new Map(), stepper = timer(step), event = dispatch_default("tick", "end"), random = lcg_default(); + if (nodes == null) + nodes = []; + function step() { + tick(); + event.call("tick", simulation); + if (alpha < alphaMin) { + stepper.stop(); + event.call("end", simulation); + } + } + function tick(iterations) { + var i, n = nodes.length, node; + if (iterations === void 0) + iterations = 1; + for (var k = 0; k < iterations; ++k) { + alpha += (alphaTarget - alpha) * alphaDecay; + forces.forEach(function(force) { + force(alpha); + }); + for (i = 0; i < n; ++i) { + node = nodes[i]; + if (node.fx == null) + node.x += node.vx *= velocityDecay; + else + node.x = node.fx, node.vx = 0; + if (node.fy == null) + node.y += node.vy *= velocityDecay; + else + node.y = node.fy, node.vy = 0; + } + } + return simulation; + } + function initializeNodes() { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.index = i; + if (node.fx != null) + node.x = node.fx; + if (node.fy != null) + node.y = node.fy; + if (isNaN(node.x) || isNaN(node.y)) { + var radius = initialRadius * Math.sqrt(0.5 + i), angle = i * initialAngle; + node.x = radius * Math.cos(angle); + node.y = radius * Math.sin(angle); + } + if (isNaN(node.vx) || isNaN(node.vy)) { + node.vx = node.vy = 0; + } + } + } + function initializeForce(force) { + if (force.initialize) + force.initialize(nodes, random); + return force; + } + initializeNodes(); + return simulation = { + tick, + restart: function() { + return stepper.restart(step), simulation; + }, + stop: function() { + return stepper.stop(), simulation; + }, + nodes: function(_) { + return arguments.length ? (nodes = _, initializeNodes(), forces.forEach(initializeForce), simulation) : nodes; + }, + alpha: function(_) { + return arguments.length ? (alpha = +_, simulation) : alpha; + }, + alphaMin: function(_) { + return arguments.length ? (alphaMin = +_, simulation) : alphaMin; + }, + alphaDecay: function(_) { + return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; + }, + alphaTarget: function(_) { + return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; + }, + velocityDecay: function(_) { + return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; + }, + randomSource: function(_) { + return arguments.length ? (random = _, forces.forEach(initializeForce), simulation) : random; + }, + force: function(name, _) { + return arguments.length > 1 ? (_ == null ? forces.delete(name) : forces.set(name, initializeForce(_)), simulation) : forces.get(name); + }, + find: function(x3, y4, radius) { + var i = 0, n = nodes.length, dx, dy, d2, node, closest; + if (radius == null) + radius = Infinity; + else + radius *= radius; + for (i = 0; i < n; ++i) { + node = nodes[i]; + dx = x3 - node.x; + dy = y4 - node.y; + d2 = dx * dx + dy * dy; + if (d2 < radius) + closest = node, radius = d2; + } + return closest; + }, + on: function(name, _) { + return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); + } + }; + } + + // node_modules/d3-force/src/manyBody.js + function manyBody_default() { + var nodes, node, random, alpha, strength = constant_default5(-30), strengths, distanceMin2 = 1, distanceMax2 = Infinity, theta2 = 0.81; + function force(_) { + var i, n = nodes.length, tree = quadtree(nodes, x2, y3).visitAfter(accumulate); + for (alpha = _, i = 0; i < n; ++i) + node = nodes[i], tree.visit(apply); + } + function initialize() { + if (!nodes) + return; + var i, n = nodes.length, node2; + strengths = new Array(n); + for (i = 0; i < n; ++i) + node2 = nodes[i], strengths[node2.index] = +strength(node2, i, nodes); + } + function accumulate(quad) { + var strength2 = 0, q, c2, weight = 0, x3, y4, i; + if (quad.length) { + for (x3 = y4 = i = 0; i < 4; ++i) { + if ((q = quad[i]) && (c2 = Math.abs(q.value))) { + strength2 += q.value, weight += c2, x3 += c2 * q.x, y4 += c2 * q.y; + } + } + quad.x = x3 / weight; + quad.y = y4 / weight; + } else { + q = quad; + q.x = q.data.x; + q.y = q.data.y; + do + strength2 += strengths[q.data.index]; + while (q = q.next); + } + quad.value = strength2; + } + function apply(quad, x1, _, x22) { + if (!quad.value) + return true; + var x3 = quad.x - node.x, y4 = quad.y - node.y, w = x22 - x1, l = x3 * x3 + y4 * y4; + if (w * w / theta2 < l) { + if (l < distanceMax2) { + if (x3 === 0) + x3 = jiggle_default(random), l += x3 * x3; + if (y4 === 0) + y4 = jiggle_default(random), l += y4 * y4; + if (l < distanceMin2) + l = Math.sqrt(distanceMin2 * l); + node.vx += x3 * quad.value * alpha / l; + node.vy += y4 * quad.value * alpha / l; + } + return true; + } else if (quad.length || l >= distanceMax2) + return; + if (quad.data !== node || quad.next) { + if (x3 === 0) + x3 = jiggle_default(random), l += x3 * x3; + if (y4 === 0) + y4 = jiggle_default(random), l += y4 * y4; + if (l < distanceMin2) + l = Math.sqrt(distanceMin2 * l); + } + do + if (quad.data !== node) { + w = strengths[quad.data.index] * alpha / l; + node.vx += x3 * w; + node.vy += y4 * w; + } + while (quad = quad.next); + } + force.initialize = function(_nodes, _random) { + nodes = _nodes; + random = _random; + initialize(); + }; + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant_default5(+_), initialize(), force) : strength; + }; + force.distanceMin = function(_) { + return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); + }; + force.distanceMax = function(_) { + return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); + }; + force.theta = function(_) { + return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); + }; + return force; + } + + // node_modules/d3-force/src/radial.js + function radial_default(radius, x3, y4) { + var nodes, strength = constant_default5(0.1), strengths, radiuses; + if (typeof radius !== "function") + radius = constant_default5(+radius); + if (x3 == null) + x3 = 0; + if (y4 == null) + y4 = 0; + function force(alpha) { + for (var i = 0, n = nodes.length; i < n; ++i) { + var node = nodes[i], dx = node.x - x3 || 1e-6, dy = node.y - y4 || 1e-6, r = Math.sqrt(dx * dx + dy * dy), k = (radiuses[i] - r) * strengths[i] * alpha / r; + node.vx += dx * k; + node.vy += dy * k; + } + } + function initialize() { + if (!nodes) + return; + var i, n = nodes.length; + strengths = new Array(n); + radiuses = new Array(n); + for (i = 0; i < n; ++i) { + radiuses[i] = +radius(nodes[i], i, nodes); + strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes); + } + } + force.initialize = function(_) { + nodes = _, initialize(); + }; + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant_default5(+_), initialize(), force) : strength; + }; + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant_default5(+_), initialize(), force) : radius; + }; + force.x = function(_) { + return arguments.length ? (x3 = +_, force) : x3; + }; + force.y = function(_) { + return arguments.length ? (y4 = +_, force) : y4; + }; + return force; + } + + // node_modules/d3-format/src/formatDecimal.js + function formatDecimal_default(x3) { + return Math.abs(x3 = Math.round(x3)) >= 1e21 ? x3.toLocaleString("en").replace(/,/g, "") : x3.toString(10); + } + function formatDecimalParts(x3, p) { + if ((i = (x3 = p ? x3.toExponential(p - 1) : x3.toExponential()).indexOf("e")) < 0) + return null; + var i, coefficient = x3.slice(0, i); + return [ + coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, + +x3.slice(i + 1) + ]; + } + + // node_modules/d3-format/src/exponent.js + function exponent_default(x3) { + return x3 = formatDecimalParts(Math.abs(x3)), x3 ? x3[1] : NaN; + } + + // node_modules/d3-format/src/formatGroup.js + function formatGroup_default(grouping, thousands) { + return function(value, width) { + var i = value.length, t = [], j = 0, g = grouping[0], length = 0; + while (i > 0 && g > 0) { + if (length + g + 1 > width) + g = Math.max(1, width - length); + t.push(value.substring(i -= g, i + g)); + if ((length += g + 1) > width) + break; + g = grouping[j = (j + 1) % grouping.length]; + } + return t.reverse().join(thousands); + }; + } + + // node_modules/d3-format/src/formatNumerals.js + function formatNumerals_default(numerals) { + return function(value) { + return value.replace(/[0-9]/g, function(i) { + return numerals[+i]; + }); + }; + } + + // node_modules/d3-format/src/formatSpecifier.js + var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i; + function formatSpecifier(specifier) { + if (!(match = re.exec(specifier))) + throw new Error("invalid format: " + specifier); + var match; + return new FormatSpecifier({ + fill: match[1], + align: match[2], + sign: match[3], + symbol: match[4], + zero: match[5], + width: match[6], + comma: match[7], + precision: match[8] && match[8].slice(1), + trim: match[9], + type: match[10] + }); + } + formatSpecifier.prototype = FormatSpecifier.prototype; + function FormatSpecifier(specifier) { + this.fill = specifier.fill === void 0 ? " " : specifier.fill + ""; + this.align = specifier.align === void 0 ? ">" : specifier.align + ""; + this.sign = specifier.sign === void 0 ? "-" : specifier.sign + ""; + this.symbol = specifier.symbol === void 0 ? "" : specifier.symbol + ""; + this.zero = !!specifier.zero; + this.width = specifier.width === void 0 ? void 0 : +specifier.width; + this.comma = !!specifier.comma; + this.precision = specifier.precision === void 0 ? void 0 : +specifier.precision; + this.trim = !!specifier.trim; + this.type = specifier.type === void 0 ? "" : specifier.type + ""; + } + FormatSpecifier.prototype.toString = function() { + return this.fill + this.align + this.sign + this.symbol + (this.zero ? "0" : "") + (this.width === void 0 ? "" : Math.max(1, this.width | 0)) + (this.comma ? "," : "") + (this.precision === void 0 ? "" : "." + Math.max(0, this.precision | 0)) + (this.trim ? "~" : "") + this.type; + }; + + // node_modules/d3-format/src/formatTrim.js + function formatTrim_default(s) { + out: + for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) { + switch (s[i]) { + case ".": + i0 = i1 = i; + break; + case "0": + if (i0 === 0) + i0 = i; + i1 = i; + break; + default: + if (!+s[i]) + break out; + if (i0 > 0) + i0 = 0; + break; + } + } + return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s; + } + + // node_modules/d3-format/src/formatPrefixAuto.js + var prefixExponent; + function formatPrefixAuto_default(x3, p) { + var d = formatDecimalParts(x3, p); + if (!d) + return x3 + ""; + var coefficient = d[0], exponent = d[1], i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, n = coefficient.length; + return i === n ? coefficient : i > n ? coefficient + new Array(i - n + 1).join("0") : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) : "0." + new Array(1 - i).join("0") + formatDecimalParts(x3, Math.max(0, p + i - 1))[0]; + } + + // node_modules/d3-format/src/formatRounded.js + function formatRounded_default(x3, p) { + var d = formatDecimalParts(x3, p); + if (!d) + return x3 + ""; + var coefficient = d[0], exponent = d[1]; + return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) : coefficient + new Array(exponent - coefficient.length + 2).join("0"); + } + + // node_modules/d3-format/src/formatTypes.js + var formatTypes_default = { + "%": (x3, p) => (x3 * 100).toFixed(p), + "b": (x3) => Math.round(x3).toString(2), + "c": (x3) => x3 + "", + "d": formatDecimal_default, + "e": (x3, p) => x3.toExponential(p), + "f": (x3, p) => x3.toFixed(p), + "g": (x3, p) => x3.toPrecision(p), + "o": (x3) => Math.round(x3).toString(8), + "p": (x3, p) => formatRounded_default(x3 * 100, p), + "r": formatRounded_default, + "s": formatPrefixAuto_default, + "X": (x3) => Math.round(x3).toString(16).toUpperCase(), + "x": (x3) => Math.round(x3).toString(16) + }; + + // node_modules/d3-format/src/identity.js + function identity_default(x3) { + return x3; + } + + // node_modules/d3-format/src/locale.js + var map = Array.prototype.map; + var prefixes = ["y", "z", "a", "f", "p", "n", "\xB5", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"]; + function locale_default(locale2) { + var group = locale2.grouping === void 0 || locale2.thousands === void 0 ? identity_default : formatGroup_default(map.call(locale2.grouping, Number), locale2.thousands + ""), currencyPrefix = locale2.currency === void 0 ? "" : locale2.currency[0] + "", currencySuffix = locale2.currency === void 0 ? "" : locale2.currency[1] + "", decimal = locale2.decimal === void 0 ? "." : locale2.decimal + "", numerals = locale2.numerals === void 0 ? identity_default : formatNumerals_default(map.call(locale2.numerals, String)), percent = locale2.percent === void 0 ? "%" : locale2.percent + "", minus = locale2.minus === void 0 ? "\u2212" : locale2.minus + "", nan = locale2.nan === void 0 ? "NaN" : locale2.nan + ""; + function newFormat(specifier) { + specifier = formatSpecifier(specifier); + var fill = specifier.fill, align = specifier.align, sign = specifier.sign, symbol = specifier.symbol, zero3 = specifier.zero, width = specifier.width, comma = specifier.comma, precision = specifier.precision, trim = specifier.trim, type2 = specifier.type; + if (type2 === "n") + comma = true, type2 = "g"; + else if (!formatTypes_default[type2]) + precision === void 0 && (precision = 12), trim = true, type2 = "g"; + if (zero3 || fill === "0" && align === "=") + zero3 = true, fill = "0", align = "="; + var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type2) ? "0" + type2.toLowerCase() : "", suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type2) ? percent : ""; + var formatType = formatTypes_default[type2], maybeSuffix = /[defgprs%]/.test(type2); + precision = precision === void 0 ? 6 : /[gprs]/.test(type2) ? Math.max(1, Math.min(21, precision)) : Math.max(0, Math.min(20, precision)); + function format2(value) { + var valuePrefix = prefix, valueSuffix = suffix, i, n, c2; + if (type2 === "c") { + valueSuffix = formatType(value) + valueSuffix; + value = ""; + } else { + value = +value; + var valueNegative = value < 0 || 1 / value < 0; + value = isNaN(value) ? nan : formatType(Math.abs(value), precision); + if (trim) + value = formatTrim_default(value); + if (valueNegative && +value === 0 && sign !== "+") + valueNegative = false; + valuePrefix = (valueNegative ? sign === "(" ? sign : minus : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; + valueSuffix = (type2 === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); + if (maybeSuffix) { + i = -1, n = value.length; + while (++i < n) { + if (c2 = value.charCodeAt(i), 48 > c2 || c2 > 57) { + valueSuffix = (c2 === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; + value = value.slice(0, i); + break; + } + } + } + } + if (comma && !zero3) + value = group(value, Infinity); + var length = valuePrefix.length + value.length + valueSuffix.length, padding = length < width ? new Array(width - length + 1).join(fill) : ""; + if (comma && zero3) + value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; + switch (align) { + case "<": + value = valuePrefix + value + valueSuffix + padding; + break; + case "=": + value = valuePrefix + padding + value + valueSuffix; + break; + case "^": + value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); + break; + default: + value = padding + valuePrefix + value + valueSuffix; + break; + } + return numerals(value); + } + format2.toString = function() { + return specifier + ""; + }; + return format2; + } + function formatPrefix2(specifier, value) { + var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), e = Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3, k = Math.pow(10, -e), prefix = prefixes[8 + e / 3]; + return function(value2) { + return f(k * value2) + prefix; + }; + } + return { + format: newFormat, + formatPrefix: formatPrefix2 + }; + } + + // node_modules/d3-format/src/defaultLocale.js + var locale; + var format; + var formatPrefix; + defaultLocale({ + thousands: ",", + grouping: [3], + currency: ["$", ""] + }); + function defaultLocale(definition) { + locale = locale_default(definition); + format = locale.format; + formatPrefix = locale.formatPrefix; + return locale; + } + + // node_modules/d3-format/src/precisionFixed.js + function precisionFixed_default(step) { + return Math.max(0, -exponent_default(Math.abs(step))); + } + + // node_modules/d3-format/src/precisionPrefix.js + function precisionPrefix_default(step, value) { + return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3 - exponent_default(Math.abs(step))); + } + + // node_modules/d3-format/src/precisionRound.js + function precisionRound_default(step, max3) { + step = Math.abs(step), max3 = Math.abs(max3) - step; + return Math.max(0, exponent_default(max3) - exponent_default(step)) + 1; + } + + // node_modules/d3-polygon/src/centroid.js + function centroid_default(polygon) { + var i = -1, n = polygon.length, x3 = 0, y4 = 0, a2, b = polygon[n - 1], c2, k = 0; + while (++i < n) { + a2 = b; + b = polygon[i]; + k += c2 = a2[0] * b[1] - b[0] * a2[1]; + x3 += (a2[0] + b[0]) * c2; + y4 += (a2[1] + b[1]) * c2; + } + return k *= 3, [x3 / k, y4 / k]; + } + + // node_modules/d3-polygon/src/contains.js + function contains_default(polygon, point) { + var n = polygon.length, p = polygon[n - 1], x3 = point[0], y4 = point[1], x0 = p[0], y0 = p[1], x1, y1, inside = false; + for (var i = 0; i < n; ++i) { + p = polygon[i], x1 = p[0], y1 = p[1]; + if (y1 > y4 !== y0 > y4 && x3 < (x0 - x1) * (y4 - y1) / (y0 - y1) + x1) + inside = !inside; + x0 = x1, y0 = y1; + } + return inside; + } + + // node_modules/d3-scale/src/init.js + function initRange(domain, range2) { + switch (arguments.length) { + case 0: + break; + case 1: + this.range(domain); + break; + default: + this.range(range2).domain(domain); + break; + } + return this; + } + + // node_modules/d3-scale/src/constant.js + function constants(x3) { + return function() { + return x3; + }; + } + + // node_modules/d3-scale/src/number.js + function number3(x3) { + return +x3; + } + + // node_modules/d3-scale/src/continuous.js + var unit = [0, 1]; + function identity2(x3) { + return x3; + } + function normalize(a2, b) { + return (b -= a2 = +a2) ? function(x3) { + return (x3 - a2) / b; + } : constants(isNaN(b) ? NaN : 0.5); + } + function clamper(a2, b) { + var t; + if (a2 > b) + t = a2, a2 = b, b = t; + return function(x3) { + return Math.max(a2, Math.min(b, x3)); + }; + } + function bimap(domain, range2, interpolate) { + var d0 = domain[0], d1 = domain[1], r0 = range2[0], r1 = range2[1]; + if (d1 < d0) + d0 = normalize(d1, d0), r0 = interpolate(r1, r0); + else + d0 = normalize(d0, d1), r0 = interpolate(r0, r1); + return function(x3) { + return r0(d0(x3)); + }; + } + function polymap(domain, range2, interpolate) { + var j = Math.min(domain.length, range2.length) - 1, d = new Array(j), r = new Array(j), i = -1; + if (domain[j] < domain[0]) { + domain = domain.slice().reverse(); + range2 = range2.slice().reverse(); + } + while (++i < j) { + d[i] = normalize(domain[i], domain[i + 1]); + r[i] = interpolate(range2[i], range2[i + 1]); + } + return function(x3) { + var i2 = bisect_default(domain, x3, 1, j) - 1; + return r[i2](d[i2](x3)); + }; + } + function copy(source, target) { + return target.domain(source.domain()).range(source.range()).interpolate(source.interpolate()).clamp(source.clamp()).unknown(source.unknown()); + } + function transformer() { + var domain = unit, range2 = unit, interpolate = value_default, transform2, untransform, unknown, clamp = identity2, piecewise, output, input; + function rescale() { + var n = Math.min(domain.length, range2.length); + if (clamp !== identity2) + clamp = clamper(domain[0], domain[n - 1]); + piecewise = n > 2 ? polymap : bimap; + output = input = null; + return scale2; + } + function scale2(x3) { + return x3 == null || isNaN(x3 = +x3) ? unknown : (output || (output = piecewise(domain.map(transform2), range2, interpolate)))(transform2(clamp(x3))); + } + scale2.invert = function(y4) { + return clamp(untransform((input || (input = piecewise(range2, domain.map(transform2), number_default)))(y4))); + }; + scale2.domain = function(_) { + return arguments.length ? (domain = Array.from(_, number3), rescale()) : domain.slice(); + }; + scale2.range = function(_) { + return arguments.length ? (range2 = Array.from(_), rescale()) : range2.slice(); + }; + scale2.rangeRound = function(_) { + return range2 = Array.from(_), interpolate = round_default, rescale(); + }; + scale2.clamp = function(_) { + return arguments.length ? (clamp = _ ? true : identity2, rescale()) : clamp !== identity2; + }; + scale2.interpolate = function(_) { + return arguments.length ? (interpolate = _, rescale()) : interpolate; + }; + scale2.unknown = function(_) { + return arguments.length ? (unknown = _, scale2) : unknown; + }; + return function(t, u4) { + transform2 = t, untransform = u4; + return rescale(); + }; + } + function continuous() { + return transformer()(identity2, identity2); + } + + // node_modules/d3-scale/src/tickFormat.js + function tickFormat(start2, stop, count, specifier) { + var step = tickStep(start2, stop, count), precision; + specifier = formatSpecifier(specifier == null ? ",f" : specifier); + switch (specifier.type) { + case "s": { + var value = Math.max(Math.abs(start2), Math.abs(stop)); + if (specifier.precision == null && !isNaN(precision = precisionPrefix_default(step, value))) + specifier.precision = precision; + return formatPrefix(specifier, value); + } + case "": + case "e": + case "g": + case "p": + case "r": { + if (specifier.precision == null && !isNaN(precision = precisionRound_default(step, Math.max(Math.abs(start2), Math.abs(stop))))) + specifier.precision = precision - (specifier.type === "e"); + break; + } + case "f": + case "%": { + if (specifier.precision == null && !isNaN(precision = precisionFixed_default(step))) + specifier.precision = precision - (specifier.type === "%") * 2; + break; + } + } + return format(specifier); + } + + // node_modules/d3-scale/src/linear.js + function linearish(scale2) { + var domain = scale2.domain; + scale2.ticks = function(count) { + var d = domain(); + return ticks(d[0], d[d.length - 1], count == null ? 10 : count); + }; + scale2.tickFormat = function(count, specifier) { + var d = domain(); + return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier); + }; + scale2.nice = function(count) { + if (count == null) + count = 10; + var d = domain(); + var i0 = 0; + var i1 = d.length - 1; + var start2 = d[i0]; + var stop = d[i1]; + var prestep; + var step; + var maxIter = 10; + if (stop < start2) { + step = start2, start2 = stop, stop = step; + step = i0, i0 = i1, i1 = step; + } + while (maxIter-- > 0) { + step = tickIncrement(start2, stop, count); + if (step === prestep) { + d[i0] = start2; + d[i1] = stop; + return domain(d); + } else if (step > 0) { + start2 = Math.floor(start2 / step) * step; + stop = Math.ceil(stop / step) * step; + } else if (step < 0) { + start2 = Math.ceil(start2 * step) / step; + stop = Math.floor(stop * step) / step; + } else { + break; + } + prestep = step; + } + return scale2; + }; + return scale2; + } + function linear2() { + var scale2 = continuous(); + scale2.copy = function() { + return copy(scale2, linear2()); + }; + initRange.apply(scale2, arguments); + return linearish(scale2); + } + + // node_modules/d3-scale-chromatic/src/colors.js + function colors_default(specifier) { + var n = specifier.length / 6 | 0, colors = new Array(n), i = 0; + while (i < n) + colors[i] = "#" + specifier.slice(i * 6, ++i * 6); + return colors; + } + + // node_modules/d3-scale-chromatic/src/categorical/Tableau10.js + var Tableau10_default = colors_default("4e79a7f28e2ce1575976b7b259a14fedc949af7aa1ff9da79c755fbab0ab"); + + // node_modules/d3-zoom/src/transform.js + function Transform(k, x3, y4) { + this.k = k; + this.x = x3; + this.y = y4; + } + Transform.prototype = { + constructor: Transform, + scale: function(k) { + return k === 1 ? this : new Transform(this.k * k, this.x, this.y); + }, + translate: function(x3, y4) { + return x3 === 0 & y4 === 0 ? this : new Transform(this.k, this.x + this.k * x3, this.y + this.k * y4); + }, + apply: function(point) { + return [point[0] * this.k + this.x, point[1] * this.k + this.y]; + }, + applyX: function(x3) { + return x3 * this.k + this.x; + }, + applyY: function(y4) { + return y4 * this.k + this.y; + }, + invert: function(location) { + return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; + }, + invertX: function(x3) { + return (x3 - this.x) / this.k; + }, + invertY: function(y4) { + return (y4 - this.y) / this.k; + }, + rescaleX: function(x3) { + return x3.copy().domain(x3.range().map(this.invertX, this).map(x3.invert, x3)); + }, + rescaleY: function(y4) { + return y4.copy().domain(y4.range().map(this.invertY, this).map(y4.invert, y4)); + }, + toString: function() { + return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + } + }; + var identity3 = new Transform(1, 0, 0); + transform.prototype = Transform.prototype; + function transform(node) { + while (!node.__zoom) + if (!(node = node.parentNode)) + return identity3; + return node.__zoom; + } + + // test/config.js + var imgNamesFilePath = "https://assets.zilliz.com/voc_names_4cee9440b1.csv"; + var getRowId2name = () => __async(void 0, null, function* () { + const data = yield csv2(imgNamesFilePath); + const rowId2name = (rowId) => data[rowId].name; + return rowId2name; + }); + var name2imgUrl = (name) => `https://assets.zilliz.com/voc2012/JPEGImages/${name}`; + var getRowId2imgUrl = () => __async(void 0, null, function* () { + const rowId2name = yield getRowId2name(); + const rowId2imgUrl = (rowId) => name2imgUrl(rowId2name(rowId)); + return rowId2imgUrl; + }); + + // federjs/Types.js + var SOURCE_TYPE = { + hnswlib: "hnswlib", + faiss: "faiss" + }; + var INDEX_TYPE = { + hnsw: "hnsw", + ivf_flat: "ivf_flat", + flat: "flat" + }; + var PROJECT_METHOD = { + umap: "umap", + tsne: "tsne" + }; + var MetricType = { + METRIC_INNER_PRODUCT: 0, + METRIC_L2: 1, + METRIC_L1: 2, + METRIC_Linf: 3, + METRIC_Lp: 4, + METRIC_Canberra: 20, + METRIC_BrayCurtis: 21, + METRIC_JensenShannon: 22 + }; + var DirectMapType = { + NoMap: 0, + Array: 1, + Hashtable: 2 + }; + var IndexHeader = { + IVFFlat: "IwFl", + FlatL2: "IxF2", + FlatIR: "IxFI" + }; + var HNSW_NODE_TYPE = { + Coarse: 1, + Candidate: 2, + Fine: 3, + Target: 4 + }; + var HNSW_LINK_TYPE = { + None: 0, + Visited: 1, + Extended: 2, + Searched: 3, + Fine: 4 + }; + var VIEW_TYPE = { + overview: "overview", + search: "search" + }; + var SEARCH_VIEW_TYPE = { + voronoi: "voronoi", + polar: "polar", + project: "project" + }; + var ANIMATION_TYPE = { + exit: "exit", + enter: "enter" + }; + var FEDER_CORE_REQUEST = { + get_index_type: "get_index_type", + get_index_meta: "get_index_meta", + get_test_id_and_vector: "get_test_id_and_vector", + get_vector_by_id: "get_vector_by_id", + search: "search", + set_search_params: "set_search_params" + }; + + // federjs/Utils/index.js + var getDisL2 = (vec1, vec2) => { + return Math.sqrt(vec1.map((num, i) => num - vec2[i]).map((num) => num * num).reduce((a2, c2) => a2 + c2, 0)); + }; + var getDisIR = (vec1, vec2) => { + return vec1.map((num, i) => num * vec2[i]).reduce((acc, cur) => acc + cur, 0); + }; + var getDisFunc = (metricType) => { + if (metricType === MetricType.METRIC_L2) { + return getDisL2; + } else if (metricType === MetricType.METRIC_INNER_PRODUCT) { + return getDisIR; + } + console.warn("[getDisFunc] wrong metric_type, use L2 (default).", metricType); + return getDisL2; + }; + var getIvfListId = (listId) => `list-${listId}`; + var uint8toChars = (data) => { + return String.fromCharCode(...data); + }; + var generateArray = (num) => { + return Array.from(new Array(Math.floor(num)).keys()); + }; + var polyPoints2path = (points, withZ = true) => { + return `M${points.join("L")}${withZ ? "Z" : ""}`; + }; + var calAngle = (x3, y4) => { + let angle = Math.atan(x3 / y4) / Math.PI * 180; + if (angle < 0) { + if (x3 < 0) { + angle += 360; + } else { + angle += 180; + } + } else { + if (x3 < 0) { + angle += 180; + } + } + return angle; + }; + var vecSort = (vecs, layoutKey, returnKey) => { + const center = { + x: vecs.reduce((acc, c2) => acc + c2[layoutKey][0], 0) / vecs.length, + y: vecs.reduce((acc, c2) => acc + c2[layoutKey][1], 0) / vecs.length + }; + const angles = vecs.map((vec2) => ({ + _vecSortAngle: calAngle(vec2[layoutKey][0] - center.x, vec2[layoutKey][1] - center.y), + _key: vec2[returnKey] + })); + angles.sort((a2, b) => a2._vecSortAngle - b._vecSortAngle); + const res = angles.map((vec2) => vec2._key); + return res; + }; + var dist2 = (vec1, vec2) => vec1.map((num, i) => num - vec2[i]).reduce((acc, cur) => acc + cur * cur, 0); + var dist3 = (vec1, vec2) => Math.sqrt(dist2(vec1, vec2)); + var deDupLink = (links, source = "source", target = "target") => { + const linkStringSet = /* @__PURE__ */ new Set(); + return links.filter((link) => { + const linkString = `${link[source]}---${link[target]}`; + const linkStringReverse = `${link[target]}---${link[source]}`; + if (linkStringSet.has(linkString) || linkStringSet.has(linkStringReverse)) { + return false; + } else { + linkStringSet.add(linkString); + return true; + } + }); + }; + var connection = "---"; + var getLinkId = (sourceId, targetId) => `${sourceId}${connection}${targetId}`; + var parseLinkId = (linkId) => linkId.split(connection).map((d) => +d); + var getLinkIdWithLevel = (sourceId, targetId, level) => `link-${level}-${sourceId}-${targetId}`; + var getNodeIdWithLevel = (nodeId, level) => `node-${level}-${nodeId}`; + var getEntryLinkIdWithLevel = (nodeId, level) => `inter-level-${level}-${nodeId}`; + var shortenLine = (point_0, point_1, d = 20) => { + const length = dist3(point_0, point_1); + const t = Math.min(d / length, 0.4); + return [ + getInprocessPos(point_0, point_1, t), + getInprocessPos(point_0, point_1, 1 - t) + ]; + }; + var getInprocessPos = (point_0, point_1, t) => { + const x3 = point_0[0] * (1 - t) + point_1[0] * t; + const y4 = point_0[1] * (1 - t) + point_1[1] * t; + return [x3, y4]; + }; + var showVectors = (vec2, precision = 6, maxLength = 20) => { + return vec2.slice(0, maxLength).map((num) => num.toFixed(precision)).join(", ") + ", ..."; + }; + var randomSelect = (arr, k) => { + const res = /* @__PURE__ */ new Set(); + k = Math.min(arr.length, k); + while (k > 0) { + const itemIndex = Math.floor(Math.random() * arr.length); + if (!res.has(itemIndex)) { + res.add(itemIndex); + k -= 1; + } + } + return Array.from(res).map((i) => arr[i]); + }; + + // federjs/FederCore/parser/FileReader.js + var FileReader = class { + constructor(arrayBuffer) { + this.data = arrayBuffer; + this.dataview = new DataView(arrayBuffer); + this.p = 0; + } + get isEmpty() { + return this.p >= this.data.byteLength; + } + readInt8() { + const int8 = this.dataview.getInt8(this.p, true); + this.p += 1; + return int8; + } + readUint8() { + const uint8 = this.dataview.getUint8(this.p, true); + this.p += 1; + return uint8; + } + readBool() { + const int8 = this.readInt8(); + return Boolean(int8); + } + readUint16() { + const uint16 = this.dataview.getUint16(this.p, true); + this.p += 2; + return uint16; + } + readInt32() { + const int32 = this.dataview.getInt32(this.p, true); + this.p += 4; + return int32; + } + readUint32() { + const uint32 = this.dataview.getUint32(this.p, true); + this.p += 4; + return uint32; + } + readUint64() { + const left = this.readUint32(); + const right = this.readUint32(); + const int64 = left + Math.pow(2, 32) * right; + if (!Number.isSafeInteger(int64)) + console.warn(int64, "Exceeds MAX_SAFE_INTEGER. Precision may be lost"); + return int64; + } + readFloat64() { + const float64 = this.dataview.getFloat64(this.p, true); + this.p += 8; + return float64; + } + readDouble() { + return this.readFloat64(); + } + readUint32Array(n) { + const res = generateArray(n).map((_) => this.readUint32()); + return res; + } + readFloat32Array(n) { + const res = new Float32Array(this.data.slice(this.p, this.p + n * 4)); + this.p += n * 4; + return res; + } + readUint64Array(n) { + const res = generateArray(n).map((_) => this.readUint64()); + return res; + } + }; + + // federjs/FederCore/parser/hnswlibIndexParser/HNSWlibFileReader.js + var HNSWlibFileReader = class extends FileReader { + constructor(arrayBuffer) { + super(arrayBuffer); + } + readIsDeleted() { + return this.readUint8(); + } + readIsReused() { + return this.readUint8(); + } + readLevelOCount() { + return this.readUint16(); + } + }; + + // federjs/FederCore/parser/hnswlibIndexParser/index.js + var hnswlibIndexParser = (arrayBuffer) => { + const reader = new HNSWlibFileReader(arrayBuffer); + const index2 = {}; + index2.offsetLevel0_ = reader.readUint64(); + index2.max_elements_ = reader.readUint64(); + index2.cur_element_count = reader.readUint64(); + index2.size_data_per_element_ = reader.readUint64(); + index2.label_offset_ = reader.readUint64(); + index2.offsetData_ = reader.readUint64(); + index2.dim = (index2.size_data_per_element_ - index2.offsetData_ - 8) / 4; + index2.maxlevel_ = reader.readUint32(); + index2.enterpoint_node_ = reader.readUint32(); + index2.maxM_ = reader.readUint64(); + index2.maxM0_ = reader.readUint64(); + index2.M = reader.readUint64(); + index2.mult_ = reader.readFloat64(); + index2.ef_construction_ = reader.readUint64(); + index2.size_links_per_element_ = index2.maxM_ * 4 + 4; + index2.size_links_level0_ = index2.maxM0_ * 4 + 4; + index2.revSize_ = 1 / index2.mult_; + index2.ef_ = 10; + read_data_level0_memory_(reader, index2); + const linkListSizes = []; + const linkLists_ = []; + for (let i = 0; i < index2.cur_element_count; i++) { + const linkListSize = reader.readUint32(); + linkListSizes.push(linkListSize); + if (linkListSize === 0) { + linkLists_[i] = []; + } else { + const levelCount = linkListSize / 4 / (index2.maxM_ + 1); + linkLists_[i] = generateArray(levelCount).map((_) => reader.readUint32Array(index2.maxM_ + 1)).map((linkLists) => linkLists.slice(1, linkLists[0] + 1)); + } + } + index2.linkListSizes = linkListSizes; + index2.linkLists_ = linkLists_; + console.assert(reader.isEmpty, "HNSWlib Parser Failed. Not empty when the parser completes."); + return { + indexType: INDEX_TYPE.hnsw, + ntotal: index2.cur_element_count, + vectors: index2.vectors, + maxLevel: index2.maxlevel_, + linkLists_level0_count: index2.linkLists_level0_count, + linkLists_level_0: index2.linkLists_level0, + linkLists_levels: index2.linkLists_, + enterPoint: index2.enterpoint_node_, + labels: index2.externalLabel, + isDeleted: index2.isDeleted, + numDeleted: index2.num_deleted_, + M: index2.M, + ef_construction: index2.ef_construction_ + }; + }; + var read_data_level0_memory_ = (reader, index2) => { + const isDeleted = []; + const linkLists_level0_count = []; + const linkLists_level0 = []; + const vectors = []; + const externalLabel = []; + for (let i = 0; i < index2.cur_element_count; i++) { + linkLists_level0_count.push(reader.readLevelOCount()); + isDeleted.push(reader.readIsDeleted()); + reader.readIsReused(); + linkLists_level0.push(reader.readUint32Array(index2.maxM0_)); + vectors.push(reader.readFloat32Array(index2.dim)); + externalLabel.push(reader.readUint64()); + } + index2.isDeleted = isDeleted; + index2.num_deleted_ = isDeleted.reduce((acc, cur) => acc + cur, 0); + index2.linkLists_level0_count = linkLists_level0_count; + index2.linkLists_level0 = linkLists_level0; + index2.vectors = vectors; + index2.externalLabel = externalLabel; + }; + var hnswlibIndexParser_default = hnswlibIndexParser; + + // federjs/FederCore/parser/faissIndexParser/FaissFileReader.js + var FaissFileReader = class extends FileReader { + constructor(arrayBuffer) { + super(arrayBuffer); + } + readH() { + const uint8Array = generateArray(4).map((_) => this.readUint8()); + const h = uint8toChars(uint8Array); + return h; + } + readDummy() { + const dummy = this.readUint64(); + return dummy; + } + }; + + // federjs/FederCore/parser/faissIndexParser/readInvertedLists.js + var checkInvH = (h) => { + if (h !== "ilar") { + console.warn("[invlists h] not ilar.", h); + } + }; + var checkInvListType = (listType) => { + if (listType !== "full") { + console.warn("[inverted_lists list_type] only support full.", listType); + } + }; + var readArrayInvLists = (reader, invlists) => { + invlists.listType = reader.readH(); + checkInvListType(invlists.listType); + invlists.listSizesSize = reader.readUint64(); + invlists.listSizes = generateArray(invlists.listSizesSize).map((_) => reader.readUint64()); + const data = []; + generateArray(invlists.listSizesSize).forEach((_, i) => { + const vectors = generateArray(invlists.listSizes[i]).map((_2) => reader.readFloat32Array(invlists.codeSize / 4)); + const ids = reader.readUint64Array(invlists.listSizes[i]); + data.push({ ids, vectors }); + }); + invlists.data = data; + }; + var readInvertedLists = (reader, index2) => { + const invlists = {}; + invlists.h = reader.readH(); + checkInvH(invlists.h); + invlists.nlist = reader.readUint64(); + invlists.codeSize = reader.readUint64(); + readArrayInvLists(reader, invlists); + index2.invlists = invlists; + }; + var readInvertedLists_default = readInvertedLists; + + // federjs/FederCore/parser/faissIndexParser/readDirectMap.js + var checkDmType = (dmType) => { + if (dmType !== DirectMapType.NoMap) { + console.warn("[directmap_type] only support NoMap."); + } + }; + var checkDmSize = (dmSize) => { + if (dmSize !== 0) { + console.warn("[directmap_size] should be 0."); + } + }; + var readDirectMap = (reader, index2) => { + const directMap = {}; + directMap.dmType = reader.readUint8(); + checkDmType(directMap.dmType); + directMap.size = reader.readUint64(); + checkDmSize(directMap.size); + index2.directMap = directMap; + }; + var readDirectMap_default = readDirectMap; + + // federjs/FederCore/parser/faissIndexParser/readIndexHeader.js + var checkMetricType = (metricType) => { + if (metricType !== MetricType.METRIC_L2 && metricType !== MetricType.METRIC_INNER_PRODUCT) { + console.warn("[metric_type] only support l2 and inner_product."); + } + }; + var checkDummy = (dummy_1, dummy_2) => { + if (dummy_1 !== dummy_2) { + console.warn("[dummy] not equal.", dummy_1, dummy_2); + } + }; + var checkIsTrained = (isTrained) => { + if (!isTrained) { + console.warn("[is_trained] should be trained.", isTrained); + } + }; + var readIndexHeader = (reader, index2) => { + index2.d = reader.readUint32(); + index2.ntotal = reader.readUint64(); + const dummy_1 = reader.readDummy(); + const dummy_2 = reader.readDummy(); + checkDummy(dummy_1, dummy_2); + index2.isTrained = reader.readBool(); + checkIsTrained(index2.isTrained); + index2.metricType = reader.readUint32(); + checkMetricType(index2.metricType); + }; + var readIndexHeader_default = readIndexHeader; + + // federjs/FederCore/parser/faissIndexParser/index.js + var readIvfHeader = (reader, index2) => { + readIndexHeader_default(reader, index2); + index2.nlist = reader.readUint64(); + index2.nprobe = reader.readUint64(); + index2.childIndex = readIndex(reader); + readDirectMap_default(reader, index2); + }; + var readXbVectors = (reader, index2) => { + index2.codeSize = reader.readUint64(); + index2.vectors = generateArray(index2.ntotal).map((_) => reader.readFloat32Array(index2.d)); + }; + var readIndex = (reader) => { + const index2 = {}; + index2.h = reader.readH(); + if (index2.h === IndexHeader.IVFFlat) { + index2.indexType = INDEX_TYPE.ivf_flat; + readIvfHeader(reader, index2); + readInvertedLists_default(reader, index2); + } else if (index2.h === IndexHeader.FlatIR || index2.h === IndexHeader.FlatL2) { + index2.indexType = INDEX_TYPE.flat; + readIndexHeader_default(reader, index2); + readXbVectors(reader, index2); + } else { + console.warn("[index type] not supported -", index2.h); + } + return index2; + }; + var faissIndexParser = (arraybuffer) => { + const faissFileReader = new FaissFileReader(arraybuffer); + const index2 = readIndex(faissFileReader); + return index2; + }; + var faissIndexParser_default = faissIndexParser; + + // federjs/FederCore/parser/index.js + var indexParserMap = { + [SOURCE_TYPE.hnswlib]: hnswlibIndexParser_default, + [SOURCE_TYPE.faiss]: faissIndexParser_default + }; + var getIndexParser = (sourceType) => { + if (sourceType in indexParserMap) { + return indexParserMap[sourceType]; + } else + throw `No index parser for [${sourceType}]`; + }; + var parser_default = getIndexParser; + + // federjs/FederCore/metaHandler/hnswMeta/hnswOverviewData.js + var getHnswlibHNSWOverviewData = ({ index: index2, overviewLevelCount = 3 }) => { + const { maxLevel, linkLists_levels, labels, enterPoint } = index2; + const highlevel = Math.min(maxLevel, overviewLevelCount); + const lowlevel = maxLevel - highlevel; + const highLevelNodes = linkLists_levels.map((linkLists_levels_item, internalId) => linkLists_levels_item.length > lowlevel ? { + internalId, + id: labels[internalId], + linksLevels: linkLists_levels_item.slice(lowlevel, linkLists_levels_item.length), + path: [] + } : null).filter((d) => d); + const internalId2node = {}; + highLevelNodes.forEach((node) => { + internalId2node[node.internalId] = node; + }); + let queue = [enterPoint]; + let start2 = 0; + internalId2node[enterPoint].path = []; + for (let level = highlevel - 1; level >= 0; level--) { + while (start2 < queue.length) { + const curNodeId = queue[start2]; + const curNode = internalId2node[curNodeId]; + const candidateNodes = curNode.linksLevels[level]; + candidateNodes.forEach((candidateNodeId) => { + const candidateNode = internalId2node[candidateNodeId]; + if (candidateNode.path.length === 0 && candidateNodeId !== enterPoint) { + candidateNode.path = [...curNode.path, curNodeId]; + queue.push(candidateNodeId); + } + }); + start2 += 1; + } + queue = highLevelNodes.filter((node) => node.linksLevels.length > level).map((node) => node.internalId); + start2 = 0; + } + return highLevelNodes; + }; + var hnswOverviewData_default = getHnswlibHNSWOverviewData; + + // federjs/FederCore/metaHandler/hnswMeta/index.js + var getHnswMeta = (index2, { overviewLevelCount = 3 }) => { + const { labels, vectors } = index2; + const id2vector = {}; + labels.forEach((id2, i) => { + id2vector[id2] = vectors[i]; + }); + const overviewNodes = hnswOverviewData_default({ + index: index2, + overviewLevelCount + }); + const indexMeta = { + ntotal: index2.ntotal, + M: index2.M, + ef_construction: index2.ef_construction, + overviewLevelCount, + levelCount: index2.maxLevel + 1, + overviewNodes + }; + return { id2vector, indexMeta }; + }; + var hnswMeta_default = getHnswMeta; + + // federjs/FederCore/projector/umap.js + var import_umap_js = __toESM(require_dist(), 1); + var fixedParams = { + nComponents: 2 + }; + var umapProject = (projectParams = {}) => { + const params = Object.assign({}, projectParams, fixedParams); + return (vectors) => { + const umap = new import_umap_js.UMAP(params); + return umap.fit(vectors); + }; + }; + var umap_default = umapProject; + + // federjs/FederCore/projector/index.js + var projectorMap = { + [PROJECT_METHOD.umap]: umap_default + }; + var getProjector = ({ method, params = {} }) => { + if (method in projectorMap) { + return projectorMap[method](params); + } else { + console.error(`No projector for [${method}]`); + } + }; + var projector_default = getProjector; + + // federjs/FederCore/metaHandler/ivfflatMeta/index.js + var import_seedrandom = __toESM(require_seedrandom2(), 1); + var getIvfflatMeta = (index2, params) => { + const id2vector = {}; + const inv = index2.invlists; + for (let list_no = 0; list_no < inv.nlist; list_no++) { + inv.data[list_no].ids.forEach((id2, ofs) => { + id2vector[id2] = inv.data[list_no].vectors[ofs]; + }); + } + index2.childIndex.vectors.forEach((vector, i) => id2vector[getIvfListId(i)] = vector); + const indexMeta = {}; + indexMeta.ntotal = index2.ntotal; + indexMeta.nlist = index2.nlist; + indexMeta.listIds = index2.invlists.data.map((d) => d.ids); + indexMeta.listSizes = index2.invlists.data.map((d) => d.ids.length); + const { + coarseSearchWithProjection = true, + projectMethod = "umap", + projectSeed = null, + projectParams = {} + } = params; + if (coarseSearchWithProjection) { + const params2 = Object.assign({}, projectParams); + if (!!projectSeed) { + params2.random = (0, import_seedrandom.default)(projectSeed); + } + const project = projector_default({ method: projectMethod, params: params2 }); + const vectors = index2.childIndex.vectors; + indexMeta.listCentroidProjections = project(vectors); + } + return { id2vector, indexMeta }; + }; + var ivfflatMeta_default = getIvfflatMeta; + + // federjs/FederCore/metaHandler/index.js + var metaHandlerMap = { + [INDEX_TYPE.hnsw]: hnswMeta_default, + [INDEX_TYPE.ivf_flat]: ivfflatMeta_default + }; + var getMetaHandler = (indexType) => { + if (indexType in metaHandlerMap) { + return metaHandlerMap[indexType]; + } else + throw `No meta handler for [${indexType}]`; + }; + var metaHandler_default = getMetaHandler; + + // federjs/Utils/PriorityQueue.js + var PriorityQueue = class { + constructor(arr = [], key = null) { + if (typeof key == "string") { + this._key = (item) => item[key]; + } else + this._key = key; + this._tree = []; + arr.forEach((d) => this.add(d)); + } + add(item) { + this._tree.push(item); + let id2 = this._tree.length - 1; + while (id2) { + const fatherId = Math.floor((id2 - 1) / 2); + if (this._getValue(id2) >= this._getValue(fatherId)) + break; + else { + this._swap(fatherId, id2); + id2 = fatherId; + } + } + } + get top() { + return this._tree[0]; + } + pop() { + if (this.isEmpty) { + return "empty"; + } + const item = this.top; + if (this._tree.length > 1) { + const lastItem = this._tree.pop(); + let id2 = 0; + this._tree[id2] = lastItem; + while (!this._isLeaf(id2)) { + const curValue = this._getValue(id2); + const leftId = id2 * 2 + 1; + const leftValue = this._getValue(leftId); + const rightId = leftId >= this._tree.length - 1 ? leftId : id2 * 2 + 2; + const rightValue = this._getValue(rightId); + const minValue = Math.min(leftValue, rightValue); + if (curValue <= minValue) + break; + else { + const minId = leftValue < rightValue ? leftId : rightId; + this._swap(minId, id2); + id2 = minId; + } + } + } else { + this._tree = []; + } + return item; + } + get isEmpty() { + return this._tree.length === 0; + } + get size() { + return this._tree.length; + } + get _firstLeaf() { + return Math.floor(this._tree.length / 2); + } + _isLeaf(id2) { + return id2 >= this._firstLeaf; + } + _getValue(id2) { + if (this._key) { + return this._key(this._tree[id2]); + } else { + return this._tree[id2]; + } + } + _swap(id0, id1) { + const tree = this._tree; + [tree[id0], tree[id1]] = [tree[id1], tree[id0]]; + } + }; + var PriorityQueue_default = PriorityQueue; + + // federjs/FederCore/searchHandler/hnswSearch/searchLevel0.js + var searchLevelO = ({ + ep_id, + target, + vectors, + ef, + isDeleted, + hasDeleted, + linkLists_level_0, + disfunc, + labels + }) => { + const top_candidates = new PriorityQueue_default([], (d) => d[0]); + const candidates = new PriorityQueue_default([], (d) => d[0]); + const vis_records_level_0 = []; + const visited = /* @__PURE__ */ new Set(); + let lowerBound; + if (!hasDeleted || !isDeleted[ep_id]) { + const dist4 = disfunc(vectors[ep_id], target); + lowerBound = dist4; + top_candidates.add([-dist4, ep_id]); + candidates.add([dist4, ep_id]); + } else { + lowerBound = 9999999; + candidates.add([lowerBound, ep_id]); + } + visited.add(ep_id); + vis_records_level_0.push([labels[ep_id], labels[ep_id], lowerBound]); + while (!candidates.isEmpty) { + const curNodePair = candidates.top; + if (curNodePair[0] > lowerBound && (top_candidates.size === ef || !hasDeleted)) { + break; + } + candidates.pop(); + const curNodeId = curNodePair[1]; + const curLinks = linkLists_level_0[curNodeId]; + curLinks.forEach((candidateId) => { + if (!visited.has(candidateId)) { + visited.add(candidateId); + const dist4 = disfunc(vectors[candidateId], target); + vis_records_level_0.push([ + labels[curNodeId], + labels[candidateId], + dist4 + ]); + if (top_candidates.size < ef || lowerBound > dist4) { + candidates.add([dist4, candidateId]); + if (!hasDeleted || !isDeleted(candidateId)) { + top_candidates.add([-dist4, candidateId]); + } + if (top_candidates.size > ef) { + top_candidates.pop(); + } + if (!top_candidates.isEmpty) { + lowerBound = -top_candidates.top[0]; + } + } + } else { + vis_records_level_0.push([labels[curNodeId], labels[candidateId], -1]); + } + }); + } + return { top_candidates, vis_records_level_0 }; + }; + var searchLevel0_default = searchLevelO; + + // federjs/FederCore/searchHandler/hnswSearch/index.js + var hnswlibHNSWSearch = ({ index: index2, target, params = {} }) => { + const { ef = 10, k = 8, metricType = MetricType.METRIC_L2 } = params; + const disfunc = getDisFunc(metricType); + let topkResults = []; + const vis_records_all = []; + const { + enterPoint, + vectors, + maxLevel, + linkLists_levels, + linkLists_level_0, + numDeleted, + labels + } = index2; + let curNodeId = enterPoint; + let curDist = disfunc(vectors[curNodeId], target); + for (let level = maxLevel; level > 0; level--) { + const vis_records = []; + vis_records.push([labels[curNodeId], labels[curNodeId], curDist]); + let changed = true; + while (changed) { + changed = false; + const curlinks = linkLists_levels[curNodeId][level - 1]; + curlinks.forEach((candidateId) => { + const dist4 = disfunc(vectors[candidateId], target); + vis_records.push([labels[curNodeId], labels[candidateId], dist4]); + if (dist4 < curDist) { + curDist = dist4; + curNodeId = candidateId; + changed = true; + } + }); + } + vis_records_all.push(vis_records); + } + const hasDeleted = numDeleted > 0; + const { top_candidates, vis_records_level_0 } = searchLevel0_default({ + ep_id: curNodeId, + target, + vectors, + ef: Math.max(ef, k), + hasDeleted, + linkLists_level_0, + disfunc, + labels + }); + vis_records_all.push(vis_records_level_0); + while (top_candidates.size > k) { + top_candidates.pop(); + } + while (top_candidates.size > 0) { + const res = top_candidates.pop(); + topkResults.push({ + id: labels[res[1]], + internalId: res[1], + dis: -res[0] + }); + } + topkResults = topkResults.reverse(); + return { vis_records: vis_records_all, topkResults, searchParams: { k, ef } }; + }; + var hnswSearch_default = hnswlibHNSWSearch; + + // federjs/FederCore/searchHandler/ivfflatSearch/faissFlatSearch.js + var faissFlatSearch = ({ index: index2, target }) => { + const disFunc = getDisFunc(index2.metricType); + const distances = index2.vectors.map((vec2, id2) => ({ + id: id2, + dis: disFunc(vec2, target) + })); + distances.sort((a2, b) => a2.dis - b.dis); + return distances; + }; + var faissFlatSearch_default = faissFlatSearch; + + // federjs/FederCore/searchHandler/ivfflatSearch/faissIVFSearch.js + var faissIVFSearch = ({ index: index2, csListIds, target }) => { + const disFunc = getDisFunc(index2.metricType); + const distances = index2.invlists.data.reduce((acc, cur, listId) => acc.concat(csListIds.includes(listId) ? cur.ids.map((id2, ofs) => ({ + id: id2, + listId, + dis: disFunc(cur.vectors[ofs], target) + })) : []), []); + distances.sort((a2, b) => a2.dis - b.dis); + return distances; + }; + var faissIVFSearch_default = faissIVFSearch; + + // federjs/FederCore/searchHandler/ivfflatSearch/index.js + var faissIVFFlatSearch = ({ index: index2, target, params = {} }) => { + const { nprobe = 8, k = 10 } = params; + const csAllListIdsAndDistances = faissFlatSearch_default({ + index: index2.childIndex, + target + }); + const csRes = csAllListIdsAndDistances.slice(0, Math.min(index2.nlist, nprobe)); + const csListIds = csRes.map((res2) => res2.id); + const fsAllIdsAndDistances = faissIVFSearch_default({ + index: index2, + csListIds, + target + }); + const fsRes = fsAllIdsAndDistances.slice(0, Math.min(index2.ntotal, k)); + const coarse = csAllListIdsAndDistances; + const fine = fsAllIdsAndDistances; + const res = { + coarse, + fine, + csResIds: csListIds, + fsResIds: fsRes.map((d) => d.id) + }; + return res; + }; + var ivfflatSearch_default = faissIVFFlatSearch; + + // federjs/FederCore/searchHandler/index.js + var indexSearchHandlerMap = { + [INDEX_TYPE.hnsw]: hnswSearch_default, + [INDEX_TYPE.ivf_flat]: ivfflatSearch_default + }; + var getIndexSearchHandler = (indexType) => { + if (indexType in indexSearchHandlerMap) { + return indexSearchHandlerMap[indexType]; + } else + throw `No search handler for [${indexType}]`; + }; + var searchHandler_default = getIndexSearchHandler; + + // federjs/FederCore/index.js + var import_seedrandom2 = __toESM(require_seedrandom2(), 1); + var FederCore = class { + constructor({ + data, + source, + viewParams + }) { + try { + this.viewParams = viewParams; + const index2 = this.parserIndex(data, source); + this.index = index2; + this.indexType = index2.indexType; + const { indexMeta, id2vector } = this.extractMeta(index2, viewParams); + this.indexMeta = indexMeta; + this.id2vector = id2vector; + this.indexSearchHandler = searchHandler_default(index2.indexType); + } catch (e) { + console.log(e); + } + } + parserIndex(data, source) { + const indexParser = parser_default(source); + const index2 = indexParser(data); + return index2; + } + extractMeta(index2, viewParams = {}) { + const metaHandler = metaHandler_default(index2.indexType); + const meta = metaHandler(index2, viewParams); + return meta; + } + getTestIdAndVec() { + const ids = Object.keys(this.id2vector); + const r = Math.floor(Math.random() * ids.length); + const testId = ids[r]; + const testVec = this.id2vector[testId]; + return [testId, testVec]; + } + setSearchParams(params) { + const newSearchParams = Object.assign({}, this.searchParams, params); + this.searchParams = newSearchParams; + } + search(target) { + const searchRes = this.indexSearchHandler({ + index: this.index, + params: this.searchParams, + target + }); + if (this.index.indexType === INDEX_TYPE.ivf_flat) { + const { + fineSearchWithProjection = true, + projectMethod = "umap", + projectSeed = null, + projectParams = {} + } = this.viewParams; + if (fineSearchWithProjection) { + const ids = searchRes.fine.map((item) => item.id); + const params = projectParams; + if (!!projectSeed) { + params.random = (0, import_seedrandom2.default)(projectSeed); + } + this.initProjector({ + method: projectMethod, + params + }); + const projections = this.projectByIds(ids); + searchRes.fine.map((item, i) => item.projection = projections[i]); + } + } + return searchRes; + } + initProjector({ method, params = {} }) { + this.project = projector_default({ method, params }); + } + projectByIds(ids) { + const vectors = ids.map((id2) => this.id2vector[id2]); + return this.project(vectors); + } + }; + + // federjs/FederView/loading.js + var loadingSvgId2 = "feder-loading"; + var loadingWidth2 = 30; + var loadingStrokeWidth = 6; + var initLoadingStyle = () => { + const style = document.createElement("style"); + style.type = "text/css"; + style.innerHTML = ` + @keyframes rotation { + from { + transform: translate(${loadingWidth2 / 2}px,${loadingWidth2 / 2}px) rotate(0deg); + } + to { + transform: translate(${loadingWidth2 / 2}px,${loadingWidth2 / 2}px) rotate(359deg); + } + } + .rotate { + animation: rotation 2s infinite linear; + } + `; + document.getElementsByTagName("head").item(0).appendChild(style); + }; + var renderLoading = (domNode, width, height) => { + const dom = select_default2(domNode); + if (!dom.select(`#${loadingSvgId2}`).empty()) + return; + const svg = dom.append("svg").attr("id", loadingSvgId2).attr("width", loadingWidth2).attr("height", loadingWidth2).style("position", "absolute").style("left", width / 2 - loadingWidth2 / 2).style("bottom", height / 2 - loadingWidth2 / 2).style("overflow", "visible"); + const defsG = svg.append("defs"); + const linearGradientId = `feder-loading-gradient`; + const linearGradient = defsG.append("linearGradient").attr("id", linearGradientId).attr("x1", 0).attr("y1", 0).attr("x2", 0).attr("y2", 1); + linearGradient.append("stop").attr("offset", "0%").style("stop-color", "#1E64FF"); + linearGradient.append("stop").attr("offset", "100%").style("stop-color", "#061982"); + const loadingCircle = svg.append("circle").attr("cx", loadingWidth2 / 2).attr("cy", loadingWidth2 / 2).attr("fill", "none").attr("r", loadingWidth2 / 2).attr("stroke", "#1E64FF").attr("stroke-width", loadingStrokeWidth); + const semiCircle = svg.append("path").attr("d", `M0,${-loadingWidth2 / 2} a ${loadingWidth2 / 2} ${loadingWidth2 / 2} 0 1 1 ${0} ${loadingWidth2}`).attr("fill", "none").attr("stroke", `url(#${linearGradientId})`).attr("stroke-width", loadingStrokeWidth).classed("rotate", true); + }; + var finishLoading = (domNode) => { + const dom = select_default2(domNode); + dom.selectAll(`#${loadingSvgId2}`).remove(); + }; + + // federjs/FederView/BaseView.js + var BaseView = class { + constructor({ viewParams, getVectorById }) { + this.viewParams = viewParams; + const { width, height, canvasScale, mediaType, mediaCallback } = viewParams; + this.clientWidth = width; + this.width = width * canvasScale; + this.clientHeight = height; + this.height = height * canvasScale; + this.getVectorById = getVectorById; + this.canvasScale = canvasScale; + this.mediaType = mediaType; + this.mediaCallback = mediaCallback; + } + initInfoPanel() { + } + renderOverview() { + } + renderSearchView() { + } + searchViewHandler() { + } + getOverviewEventHandler() { + } + getSearchViewEventHandler() { + } + overview(dom) { + return __async(this, null, function* () { + const canvas = initCanvas(dom, this.clientWidth, this.clientHeight, this.canvasScale); + const ctx = canvas.getContext("2d"); + const infoPanel = this.initInfoPanel(dom); + this.overviewLayoutPromise && (yield this.overviewLayoutPromise); + finishLoading(dom); + this.renderOverview(ctx, infoPanel); + const eventHandlers = this.getOverviewEventHandler(ctx, infoPanel); + addMouseListener(canvas, this.canvasScale, eventHandlers); + }); + } + search(_0, _1) { + return __async(this, arguments, function* (dom, { searchRes, targetMediaUrl }) { + const canvas = initCanvas(dom, this.clientWidth, this.clientHeight, this.canvasScale); + const ctx = canvas.getContext("2d"); + const infoPanel = this.initInfoPanel(dom); + const searchViewLayoutData = yield this.searchViewHandler(searchRes); + finishLoading(dom); + this.renderSearchView(ctx, infoPanel, searchViewLayoutData, targetMediaUrl, dom); + const eventHandlers = this.getSearchViewEventHandler(ctx, searchViewLayoutData, infoPanel); + addMouseListener(canvas, this.canvasScale, eventHandlers); + }); + } + }; + var addMouseListener = (element, canvasScale, { mouseMoveHandler, mouseClickHandler, mouseLeaveHandler } = {}) => { + element.addEventListener("mousemove", (e) => { + const { offsetX, offsetY } = e; + const x3 = offsetX * canvasScale; + const y4 = offsetY * canvasScale; + mouseMoveHandler && mouseMoveHandler({ x: x3, y: y4 }); + }); + element.addEventListener("click", (e) => { + const { offsetX, offsetY } = e; + const x3 = offsetX * canvasScale; + const y4 = offsetY * canvasScale; + mouseClickHandler && mouseClickHandler({ x: x3, y: y4 }); + }); + element.addEventListener("mouseleave", () => { + mouseLeaveHandler && mouseLeaveHandler(); + }); + }; + var initCanvas = (dom, clientWidth, clientHeight, canvasScale) => { + renderLoading(dom, clientWidth, clientHeight); + const domD3 = select_default2(dom); + domD3.selectAll("canvas").remove(); + const canvas = domD3.append("canvas").attr("width", clientWidth).attr("height", clientHeight); + const ctx = canvas.node().getContext("2d"); + ctx.scale(1 / canvasScale, 1 / canvasScale); + return canvas.node(); + }; + + // federjs/FederView/HnswView/layout/transformHandler.js + var transformHandler = (nodes, { levelCount, width, height, padding, xBias = 0.65, yBias = 0.4, yOver = 0.1 }) => { + const layerWidth = width - padding[1] - padding[3]; + const layerHeight = (height - padding[0] - padding[2]) / (levelCount - (levelCount - 1) * yOver); + const xRange = extent(nodes, (node) => node.x); + const yRange = extent(nodes, (node) => node.y); + const xOffset = padding[3] + layerWidth * xBias; + const transformFunc = (x3, y4, level) => { + const _x = (x3 - xRange[0]) / (xRange[1] - xRange[0]); + const _y = (y4 - yRange[0]) / (yRange[1] - yRange[0]); + const newX = xOffset + _x * layerWidth * (1 - xBias) - _y * layerWidth * xBias; + const newY = padding[0] + layerHeight * (1 - yOver) * (levelCount - 1 - level) + _x * layerHeight * (1 - yBias) + _y * layerHeight * yBias; + return [newX, newY]; + }; + const layerPos = [ + [layerWidth * xBias, 0], + [layerWidth, layerHeight * (1 - yBias)], + [layerWidth * (1 - xBias), layerHeight], + [0, layerHeight * yBias] + ]; + const layerPosLevels = generateArray(levelCount).map((_, level) => layerPos.map((coord) => [ + coord[0] + padding[3], + coord[1] + padding[0] + layerHeight * (1 - yOver) * (levelCount - 1 - level) + ])); + return { layerPosLevels, transformFunc }; + }; + var transformHandler_default = transformHandler; + + // federjs/FederView/HnswView/layout/overviewLayout.js + var overviewLayoutHandler = ({ + overviewNodes, + overviewLevelCount, + width, + height, + padding, + forceIterations, + M + }) => { + return new Promise((resolve) => __async(void 0, null, function* () { + const overviewNodesLevels = []; + const overviewLinksLevels = []; + for (let level = overviewLevelCount - 1; level >= 0; level--) { + const nodes = overviewNodes.filter((node) => node.linksLevels.length > level); + const links = nodes.reduce((acc, curNode) => acc.concat(curNode.linksLevels[level].map((targetNodeInternalId) => ({ + source: curNode.internalId, + target: targetNodeInternalId + }))), []); + yield forceLevel({ nodes, links, forceIterations }); + level > 0 && scaleNodes({ nodes, M }); + level > 0 && fixedCurLevel({ nodes }); + overviewNodesLevels[level] = nodes; + overviewLinksLevels[level] = links; + } + const { layerPosLevels: overviewLayerPosLevels, transformFunc } = transformHandler_default(overviewNodes, { + levelCount: overviewLevelCount, + width, + height, + padding + }); + overviewNodes.forEach((node) => { + node.overviewPosLevels = node.linksLevels.map((_, level) => transformFunc(node.x, node.y, level)); + node.r = node.linksLevels.length * 0.8 + 1; + }); + resolve({ + overviewLayerPosLevels, + overviewNodesLevels, + overviewLinksLevels + }); + })); + }; + var overviewLayout_default = overviewLayoutHandler; + var forceLevel = ({ nodes, links, forceIterations }) => { + return new Promise((resolve) => { + const simulation = simulation_default(nodes).alphaDecay(1 - Math.pow(1e-3, 1 / forceIterations * 2)).force("link", link_default(links).id((d) => d.internalId).strength(1)).force("center", center_default(0, 0)).force("charge", manyBody_default().strength(-500)).on("end", () => { + resolve(); + }); + }); + }; + var scaleNodes = ({ nodes, M }) => { + const xRange = extent(nodes, (node) => node.x); + const yRange = extent(nodes, (node) => node.y); + const isXLonger = xRange[1] - xRange[0] > yRange[1] - yRange[0]; + if (!isXLonger) { + nodes.forEach((node) => [node.x, node.y] = [node.y, node.x]); + } + const t = Math.sqrt(M) * 0.85; + nodes.forEach((node) => { + node.x = node.x * t; + node.y = node.y * t; + }); + }; + var fixedCurLevel = ({ nodes }) => { + nodes.forEach((node) => { + node.fx = node.x; + node.fy = node.y; + }); + }; + + // federjs/FederView/HnswView/layout/mouse2node.js + function mouse2node({ mouse, layerPosLevels, nodesLevels, posAttr }, { mouse2nodeBias, canvasScale }) { + const mouseLevel = layerPosLevels.findIndex((points) => contains_default(points, mouse)); + let mouseNode; + if (mouseLevel >= 0) { + const allDis = nodesLevels[mouseLevel].map((node) => dist2(node[posAttr][mouseLevel], mouse)); + const minDistIndex = minIndex(allDis); + const minDist = allDis[minDistIndex]; + const clearestNode = nodesLevels[mouseLevel][minDistIndex]; + mouseNode = minDist < Math.pow((clearestNode.r + mouse2nodeBias) * canvasScale, 2) ? clearestNode : null; + } else { + mouseNode = null; + } + return { mouseLevel, mouseNode }; + } + + // federjs/Utils/renderUtils.js + var colorScheme = Tableau10_default; + var ZBlue = "#175FFF"; + var ZLightBlue = "#91FDFF"; + var ZYellow = "#FFFC85"; + var ZOrange = "#F36E4B"; + var ZLayerBorder = "#D9EAFF"; + var whiteColor = "#ffffff"; + var blackColor = "#000000"; + var highLightColor = ZYellow; + var hexWithOpacity = (color2, opacity) => { + let opacityString = Math.round(opacity * 255).toString(16); + if (opacityString.length < 2) { + opacityString = "0" + opacityString; + } + return color2 + opacityString; + }; + var highLightGradientStopColors = [ + [0, hexWithOpacity(whiteColor, 0.2)], + [1, hexWithOpacity(ZYellow, 1)] + ]; + var neighbourGradientStopColors = [ + [0, hexWithOpacity(whiteColor, 0)], + [1, hexWithOpacity(whiteColor, 0.8)] + ]; + var targetLevelGradientStopColors = neighbourGradientStopColors; + var normalGradientStopColors = [ + [0, hexWithOpacity("#061982", 0.3)], + [1, hexWithOpacity("#1E64FF", 0.4)] + ]; + var layerGradientStopColors = [ + [0.1, hexWithOpacity("#1E64FF", 0.4)], + [0.9, hexWithOpacity("#00234D", 0)] + ]; + var draw = ({ + ctx, + drawFunc = () => { + }, + fillStyle = "", + strokeStyle = "", + lineWidth = 0, + lineCap = "butt", + shadowColor = "", + shadowBlur = 0, + shadowOffsetX = 0, + shadowOffsetY = 0, + isFillLinearGradient = false, + isStrokeLinearGradient = false, + gradientPos = [0, 0, 100, 100], + gradientStopColors = [] + }) => { + ctx.save(); + let gradient = null; + if (isFillLinearGradient || isStrokeLinearGradient) { + gradient = ctx.createLinearGradient(...gradientPos); + gradientStopColors.forEach((stopColor) => gradient.addColorStop(...stopColor)); + } + ctx.fillStyle = isFillLinearGradient ? gradient : fillStyle; + ctx.strokeStyle = isStrokeLinearGradient ? gradient : strokeStyle; + ctx.lineWidth = lineWidth; + ctx.lineCap = lineCap; + ctx.shadowColor = shadowColor; + ctx.shadowBlur = shadowBlur; + ctx.shadowOffsetX = shadowOffsetX; + ctx.shadowOffsetY = shadowOffsetY; + drawFunc(); + ctx.restore(); + }; + var drawVoronoi = (_a) => { + var _b = _a, { + ctx, + pointsList, + hasFill = false, + hasStroke = false + } = _b, styles = __objRest(_b, [ + "ctx", + "pointsList", + "hasFill", + "hasStroke" + ]); + const drawFunc = () => { + pointsList.forEach((points) => { + const path2 = new Path2D(polyPoints2path(points)); + hasFill && ctx.fill(path2); + hasStroke && ctx.stroke(path2); + }); + }; + draw(__spreadValues({ ctx, drawFunc }, styles)); + }; + var drawCircle = (_a) => { + var _b = _a, { + ctx, + circles, + hasFill = false, + hasStroke = false + } = _b, styles = __objRest(_b, [ + "ctx", + "circles", + "hasFill", + "hasStroke" + ]); + const drawFunc = () => { + circles.forEach(([x3, y4, r]) => { + ctx.beginPath(); + ctx.arc(x3, y4, r, 0, 2 * Math.PI); + hasFill && ctx.fill(); + hasStroke && ctx.stroke(); + }); + }; + draw(__spreadValues({ ctx, drawFunc }, styles)); + }; + var drawEllipse = (_a) => { + var _b = _a, { + ctx, + circles, + hasFill = false, + hasStroke = false + } = _b, styles = __objRest(_b, [ + "ctx", + "circles", + "hasFill", + "hasStroke" + ]); + const drawFunc = () => { + circles.forEach(([x3, y4, rx, ry]) => { + ctx.beginPath(); + ctx.ellipse(x3, y4, rx, ry, 0, 0, 2 * Math.PI); + hasFill && ctx.fill(); + hasStroke && ctx.stroke(); + }); + }; + draw(__spreadValues({ ctx, drawFunc }, styles)); + }; + var drawRect = (_a) => { + var _b = _a, { + ctx, + x: x3 = 0, + y: y4 = 0, + width, + height, + hasFill = false, + hasStroke = false + } = _b, styles = __objRest(_b, [ + "ctx", + "x", + "y", + "width", + "height", + "hasFill", + "hasStroke" + ]); + const drawFunc = () => { + hasFill && ctx.fillRect(0, 0, width, height); + hasStroke && ctx.strokeRect(0, 0, width, height); + }; + draw(__spreadValues({ ctx, drawFunc }, styles)); + }; + var drawPath = (_a) => { + var _b = _a, { + ctx, + points, + hasFill = false, + hasStroke = false, + withZ = true + } = _b, styles = __objRest(_b, [ + "ctx", + "points", + "hasFill", + "hasStroke", + "withZ" + ]); + const drawFunc = () => { + const path2 = new Path2D(polyPoints2path(points, withZ)); + hasFill && ctx.fill(path2); + hasStroke && ctx.stroke(path2); + }; + draw(__spreadValues({ ctx, drawFunc }, styles)); + }; + var drawLinesWithLinearGradient = (_a) => { + var _b = _a, { + ctx, + pointsList, + hasFill = false, + hasStroke = false, + isStrokeLinearGradient = true + } = _b, styles = __objRest(_b, [ + "ctx", + "pointsList", + "hasFill", + "hasStroke", + "isStrokeLinearGradient" + ]); + pointsList.forEach((points) => { + const path2 = new Path2D(`M${points[0]}L${points[1]}`); + const gradientPos = [...points[0], ...points[1]]; + const drawFunc = () => { + hasFill && ctx.fill(path2); + hasStroke && ctx.stroke(path2); + }; + draw(__spreadValues({ ctx, drawFunc, isStrokeLinearGradient, gradientPos }, styles)); + }); + }; + + // federjs/FederView/HnswView/render/renderBackground.js + function renderBackground(ctx, { width, height }) { + drawRect({ + ctx, + width, + height, + hasFill: true, + fillStyle: blackColor + }); + } + + // federjs/FederView/HnswView/render/renderlevelLayer.js + function renderlevelLayer(ctx, points, { canvasScale, layerDotNum }) { + drawPath({ + ctx, + points, + hasStroke: true, + isStrokeLinearGradient: false, + strokeStyle: hexWithOpacity(ZLayerBorder, 0.6), + lineWidth: 0.5 * canvasScale, + hasFill: true, + isFillLinearGradient: true, + gradientStopColors: layerGradientStopColors, + gradientPos: [points[1][0], points[0][1], points[3][0], points[2][1]] + }); + const rightTopLength = dist3(points[0], points[1]); + const leftTopLength = dist3(points[0], points[3]); + const rightTopDotNum = layerDotNum; + const leftTopDotNum = layerDotNum; + const rightTopVec = [ + points[1][0] - points[0][0], + points[1][1] - points[0][1] + ]; + const leftTopVec = [points[3][0] - points[0][0], points[3][1] - points[0][1]]; + const dots = []; + for (let i = 0; i < layerDotNum; i++) { + const rightTopT = i / layerDotNum + 1 / (2 * layerDotNum); + for (let j = 0; j < layerDotNum; j++) { + const leftTopT = j / layerDotNum + 1 / (2 * layerDotNum); + dots.push([ + points[0][0] + rightTopVec[0] * rightTopT + leftTopVec[0] * leftTopT, + points[0][1] + rightTopVec[1] * rightTopT + leftTopVec[1] * leftTopT, + 0.8 * canvasScale + ]); + } + } + drawCircle({ + ctx, + circles: dots, + hasFill: true, + fillStyle: hexWithOpacity(whiteColor, 0.4) + }); + } + + // federjs/FederView/HnswView/render/renderLinks.js + function renderLinks(ctx, links, level, { shortenLineD, overviewLinkLineWidth, canvasScale }) { + const pointsList = links.map((link) => shortenLine(link.source.overviewPosLevels[level], link.target.overviewPosLevels[level], shortenLineD * canvasScale)); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: normalGradientStopColors, + lineWidth: overviewLinkLineWidth * canvasScale, + lineCap: "round" + }); + } + + // federjs/FederView/HnswView/render/renderNodes.js + function renderNodes(ctx, nodes, level, { canvasScale, ellipseRation, shadowBlur }) { + drawEllipse({ + ctx, + circles: nodes.map((node) => [ + ...node.overviewPosLevels[level], + node.r * ellipseRation * canvasScale, + node.r * canvasScale + ]), + hasFill: true, + fillStyle: hexWithOpacity(ZBlue, 0.75), + shadowColor: ZBlue, + shadowBlur: shadowBlur * canvasScale + }); + } + + // federjs/FederView/HnswView/render/renderReachable.js + function renderReachableData(ctx, level, { reachableLevel, reachableNodes, reachableLinks }, { + shortenLineD, + canvasScale, + reachableLineWidth, + ellipseRation, + shadowBlur, + highlightRadiusExt, + posAttr = "overviewPosLevels" + }) { + if (level != reachableLevel) + return; + const pointsList = reachableLinks.map((link) => [link.source[posAttr][level], link.target[posAttr][level]]).map((points) => shortenLine(...points, shortenLineD * canvasScale)); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: neighbourGradientStopColors, + lineWidth: reachableLineWidth * canvasScale, + lineCap: "round" + }); + drawEllipse({ + ctx, + circles: reachableNodes.map((node) => [ + ...node[posAttr][level], + (node.r + highlightRadiusExt) * ellipseRation * canvasScale, + (node.r + highlightRadiusExt) * canvasScale + ]), + hasFill: true, + fillStyle: hexWithOpacity(whiteColor, 1), + shadowColor: whiteColor, + shadowBlur: shadowBlur * canvasScale + }); + } + + // federjs/FederView/HnswView/render/renderShortestPath.js + function renderShortestPath(ctx, level, { SPLinksLevels, SPNodesLevels }, { + shortenLineD, + canvasScale, + shortestPathLineWidth, + highlightRadiusExt, + shadowBlur, + ellipseRation, + posAttr = "overviewPosLevels" + }) { + const pointsList = (SPLinksLevels ? SPLinksLevels[level] : []).map((link) => link.source === link.target ? !!link.source[posAttr][level + 1] ? [link.source[posAttr][level + 1], link.target[posAttr][level]] : null : [link.source[posAttr][level], link.target[posAttr][level]]).filter((a2) => a2).map((points) => shortenLine(...points, shortenLineD * canvasScale)); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: shortestPathLineWidth * canvasScale, + lineCap: "round" + }); + drawEllipse({ + ctx, + circles: (SPNodesLevels ? SPNodesLevels[level] : []).filter((node) => !!node[posAttr][level]).map((node) => [ + ...node[posAttr][level], + (node.r + highlightRadiusExt) * ellipseRation * canvasScale, + (node.r + highlightRadiusExt) * canvasScale + ]), + hasFill: true, + fillStyle: hexWithOpacity(highLightColor, 1), + shadowColor: highLightColor, + shadowBlur: shadowBlur * canvasScale + }); + } + + // federjs/FederView/HnswView/render/renderOverview.js + function renderOverview(ctx, federView, overviewHighlightData) { + const { + overviewLevelCount, + overviewNodesLevels, + overviewLinksLevels, + overviewLayerPosLevels + } = federView; + renderBackground(ctx, federView); + for (let level = 0; level < overviewLevelCount; level++) { + renderlevelLayer(ctx, overviewLayerPosLevels[level], federView); + const nodes = overviewNodesLevels[level]; + const links = overviewLinksLevels[level]; + level > 0 && renderLinks(ctx, links, level, federView); + renderNodes(ctx, nodes, level, federView); + if (overviewHighlightData) { + renderReachableData(ctx, level, overviewHighlightData, federView); + renderShortestPath(ctx, level, overviewHighlightData, federView); + } + } + } + + // federjs/FederView/HnswView/layout/overviewShortestPath.js + function getOverviewShortestPathData(keyNode, keyLevel, { overviewNodesLevels, internalId2overviewNode, overviewLevelCount }) { + let SPLinksLevels = overviewNodesLevels.map((_) => []); + let SPNodesLevels = overviewNodesLevels.map((_) => []); + let reachableNodes = []; + let reachableLinks = []; + let reachableLevel = null; + if (keyNode) { + const path2 = [...keyNode.path, keyNode.internalId]; + if (path2.length === 0) { + SPNodesLevels = [keyNode.overviewPosLevels[keyLevel]]; + } else { + let preNodeId = path2[0]; + let preNode = internalId2overviewNode[preNodeId]; + let preLevel = overviewLevelCount - 1; + SPNodesLevels[preLevel].push(preNode); + for (let i = 1; i < path2.length; i++) { + let curNodeId = path2[i]; + let curNode = internalId2overviewNode[curNodeId]; + while (curNode.overviewPosLevels.length <= preLevel) { + preLevel -= 1; + SPLinksLevels[preLevel].push({ + source: preNode, + target: preNode + }); + SPNodesLevels[preLevel].push(preNode); + } + SPNodesLevels[preLevel].push(curNode); + SPLinksLevels[preLevel].push({ + source: preNode, + target: curNode + }); + preNode = curNode; + } + while (preLevel > keyLevel) { + preLevel -= 1; + SPLinksLevels[preLevel].push({ + source: preNode, + target: preNode + }); + SPNodesLevels[preLevel].push(preNode); + } + } + const preNodeInternalId = keyNode.path.length > 0 ? keyNode.path[keyNode.path.length - 1] : null; + reachableLevel = keyLevel; + reachableNodes = keyNode.linksLevels[keyLevel].filter((internalId) => internalId != preNodeInternalId).map((internalId) => internalId2overviewNode[internalId]); + reachableLinks = reachableNodes.map((target) => ({ + source: keyNode, + target + })); + } + return { + SPLinksLevels, + SPNodesLevels, + reachableLevel, + reachableNodes, + reachableLinks + }; + } + + // federjs/FederView/HnswView/layout/parseVisRecords.js + var parseVisRecords = ({ topkResults, vis_records }) => { + const visData = []; + const numLevels = vis_records.length; + let fineIds = topkResults.map((d) => d.id); + let entryId = -1; + for (let i = numLevels - 1; i >= 0; i--) { + const level = numLevels - 1 - i; + if (level > 0) { + fineIds = [entryId]; + } + const visRecordsLevel = vis_records[i]; + const id2nodeType = {}; + const linkId2linkType = {}; + const updateNodeType = (nodeId, type2) => { + if (id2nodeType[nodeId]) { + id2nodeType[nodeId] = Math.max(id2nodeType[nodeId], type2); + } else { + id2nodeType[nodeId] = type2; + } + }; + const updateLinkType = (sourceId, targetId, type2) => { + const linkId = getLinkId(sourceId, targetId, type2); + if (linkId2linkType[linkId]) { + linkId2linkType[linkId] = Math.max(linkId2linkType[linkId], type2); + } else { + linkId2linkType[linkId] = type2; + } + }; + const id2dist = {}; + const sourceMap = {}; + visRecordsLevel.forEach((record) => { + const [sourceId, targetId, dist4] = record; + if (sourceId === targetId) { + entryId = targetId; + id2dist[targetId] = dist4; + } else { + updateNodeType(sourceId, HNSW_NODE_TYPE.Candidate); + updateNodeType(targetId, HNSW_NODE_TYPE.Coarse); + if (id2dist[targetId] >= 0) { + updateLinkType(sourceId, targetId, HNSW_LINK_TYPE.Visited); + } else { + id2dist[targetId] = dist4; + updateLinkType(sourceId, targetId, HNSW_LINK_TYPE.Extended); + sourceMap[targetId] = sourceId; + if (level === 0) { + const preSourceId = sourceMap[sourceId]; + if (preSourceId >= 0) { + updateLinkType(preSourceId, sourceId, HNSW_LINK_TYPE.Searched); + } + } + } + } + }); + fineIds.forEach((fineId) => { + updateNodeType(fineId, HNSW_NODE_TYPE.Fine); + let t = fineId; + while (t in sourceMap) { + let s = sourceMap[t]; + updateLinkType(s, t, HNSW_LINK_TYPE.Fine); + t = s; + } + }); + const nodes = Object.keys(id2nodeType).map((id2) => ({ + id: `${id2}`, + type: id2nodeType[id2], + dist: id2dist[id2] + })); + const links = Object.keys(linkId2linkType).map((linkId) => { + const [source, target] = parseLinkId(linkId); + return { + source: `${source}`, + target: `${target}`, + type: linkId2linkType[linkId] + }; + }); + const visDataLevel = { + entryIds: [`${entryId}`], + fineIds: fineIds.map((id2) => `${id2}`), + links, + nodes + }; + visData.push(visDataLevel); + } + return visData; + }; + var parseVisRecords_default = parseVisRecords; + + // federjs/FederView/HnswView/layout/forceSearchView.js + var forceSearchView = (visData, targetOrigin = [0, 0], forceIterations = 100) => { + return new Promise((resolve) => { + const nodeId2dist = {}; + visData.forEach((levelData) => levelData.nodes.forEach((node) => nodeId2dist[node.id] = node.dist || 0)); + const nodeIds = Object.keys(nodeId2dist); + const nodes = nodeIds.map((nodeId) => ({ + nodeId, + dist: nodeId2dist[nodeId] + })); + const linksAll = visData.reduce((acc, cur) => acc.concat(cur.links), []); + const links = deDupLink(linksAll); + const targetNode = { + nodeId: "target", + dist: 0, + fx: targetOrigin[0], + fy: targetOrigin[1] + }; + nodes.push(targetNode); + const targetLinks = visData[0].fineIds.map((fineId) => ({ + source: `${fineId}`, + target: "target", + type: HNSW_LINK_TYPE.None + })); + links.push(...targetLinks); + const rScale = linear2().domain(extent(nodes.filter((node) => node.dist > 0), (node) => node.dist)).range([10, 1e3]).clamp(true); + const simulation = simulation_default(nodes).alphaDecay(1 - Math.pow(1e-3, 1 / forceIterations)).force("link", link_default(links).id((d) => `${d.nodeId}`).strength((d) => d.type === HNSW_LINK_TYPE.None ? 2 : 0.4)).force("r", radial_default((node) => rScale(node.dist), targetOrigin[0], targetOrigin[1]).strength(1)).force("charge", manyBody_default().strength(-1e4)).on("end", () => { + const id2forcePos = {}; + nodes.forEach((node) => id2forcePos[node.nodeId] = [node.x, node.y]); + resolve(id2forcePos); + }); + }); + }; + var forceSearchView_default = forceSearchView; + + // federjs/FederView/HnswView/layout/computeSearchViewTransition.js + var computeSearchViewTransition = ({ + linksLevels, + entryNodesLevels, + interLevelGap = 1e3, + intraLevelGap = 300 + }) => { + let currentTime = 0; + const targetShowTime = []; + const nodeShowTime = {}; + const linkShowTime = {}; + let isPreLinkImportant = true; + let isSourceChanged = true; + let preSourceIdWithLevel = ""; + for (let level = linksLevels.length - 1; level >= 0; level--) { + const links = linksLevels[level]; + if (links.length === 0) { + const sourceId = entryNodesLevels[level].id; + const sourceIdWithLevel = getNodeIdWithLevel(sourceId, level); + nodeShowTime[sourceIdWithLevel] = currentTime; + } else { + links.forEach((link) => { + const sourceId = link.source.id; + const targetId = link.target.id; + const sourceIdWithLevel = getNodeIdWithLevel(sourceId, level); + const targetIdWithLevel = getNodeIdWithLevel(targetId, level); + const linkIdWithLevel = getLinkIdWithLevel(sourceId, targetId, level); + const isCurrentLinkImportant = link.type === HNSW_LINK_TYPE.Searched || link.type === HNSW_LINK_TYPE.Fine; + isSourceChanged = preSourceIdWithLevel !== sourceIdWithLevel; + const isSourceEntry = !(sourceIdWithLevel in nodeShowTime); + if (isSourceEntry) { + if (level < linksLevels.length - 1) { + const entryLinkIdWithLevel = getEntryLinkIdWithLevel(sourceId, level); + linkShowTime[entryLinkIdWithLevel] = currentTime; + const targetLinkIdWithLevel = getEntryLinkIdWithLevel("target", level); + linkShowTime[targetLinkIdWithLevel] = currentTime; + currentTime += interLevelGap; + isPreLinkImportant = true; + } + targetShowTime[level] = currentTime; + nodeShowTime[sourceIdWithLevel] = currentTime; + } + if (isPreLinkImportant || isCurrentLinkImportant || isSourceChanged) { + currentTime += intraLevelGap; + } else { + currentTime += intraLevelGap * 0.5; + } + linkShowTime[linkIdWithLevel] = currentTime; + if (!(targetIdWithLevel in nodeShowTime)) { + nodeShowTime[targetIdWithLevel] = currentTime += intraLevelGap; + } + isPreLinkImportant = isCurrentLinkImportant; + preSourceIdWithLevel = sourceIdWithLevel; + }); + } + currentTime += intraLevelGap; + isPreLinkImportant = true; + isSourceChanged = true; + } + return { targetShowTime, nodeShowTime, linkShowTime, duration: currentTime }; + }; + var computeSearchViewTransition_default = computeSearchViewTransition; + + // federjs/FederView/HnswView/layout/searchViewLayout.js + function searchViewLayoutHandler(searchRes, federView) { + return __async(this, null, function* () { + const { + targetR, + canvasScale, + targetOrigin, + searchViewNodeBasicR, + searchInterLevelTime, + searchIntraLevelTime, + forceIterations + } = federView; + const visData = parseVisRecords_default(searchRes); + const id2forcePos = yield forceSearchView_default(visData, targetOrigin, forceIterations); + const searchNodesLevels = visData.map((levelData) => levelData.nodes); + searchNodesLevels.forEach((levelData) => levelData.forEach((node) => { + node.forcePos = id2forcePos[node.id]; + node.x = node.forcePos[0]; + node.y = node.forcePos[1]; + })); + const { layerPosLevels, transformFunc } = transformHandler_default(searchNodesLevels.reduce((acc, node) => acc.concat(node), []), federView); + const searchTarget = { + id: "target", + r: targetR * canvasScale, + searchViewPosLevels: range(visData.length).map((i) => transformFunc(...targetOrigin, i)) + }; + searchNodesLevels.forEach((nodes, level) => { + nodes.forEach((node) => { + node.searchViewPosLevels = range(level + 1).map((i) => transformFunc(...node.forcePos, i)); + node.r = (searchViewNodeBasicR + node.type * 0.5) * canvasScale; + }); + }); + const id2searchNode = {}; + searchNodesLevels.forEach((levelData) => levelData.forEach((node) => id2searchNode[node.id] = node)); + const searchLinksLevels = parseVisRecords_default(searchRes).map((levelData) => levelData.links.filter((link) => link.type !== HNSW_LINK_TYPE.None)); + searchLinksLevels.forEach((levelData) => levelData.forEach((link) => { + const sourceId = link.source; + const targetId = link.target; + const sourceNode = id2searchNode[sourceId]; + const targetNode = id2searchNode[targetId]; + link.source = sourceNode; + link.target = targetNode; + })); + const entryNodesLevels = visData.map((levelData) => levelData.entryIds.map((id2) => id2searchNode[id2])); + const { targetShowTime, nodeShowTime, linkShowTime, duration } = computeSearchViewTransition_default({ + linksLevels: searchLinksLevels, + entryNodesLevels, + interLevelGap: searchInterLevelTime, + intraLevelGap: searchIntraLevelTime + }); + return { + visData, + id2forcePos, + searchTarget, + entryNodesLevels, + searchNodesLevels, + searchLinksLevels, + searchLayerPosLevels: layerPosLevels, + searchTargetShowTime: targetShowTime, + searchNodeShowTime: nodeShowTime, + searchLinkShowTime: linkShowTime, + searchTransitionDuration: duration, + searchParams: searchRes.searchParams + }; + }); + } + + // federjs/FederView/HnswView/render/TimeControllerView.js + var iconGap = 10; + var rectW = 36; + var sliderBackGroundWidth = 200; + var sliderWidth = sliderBackGroundWidth * 0.8; + var sliderHeight = rectW * 0.15; + var sliderBarWidth = 10; + var sliderBarHeight = rectW * 0.6; + var resetW = 16; + var resetIconD = `M12.3579 13.0447C11.1482 14.0929 9.60059 14.6689 7.99992 14.6667C4.31792 14.6667 1.33325 11.682 1.33325 8.00004C1.33325 4.31804 4.31792 1.33337 7.99992 1.33337C11.6819 1.33337 14.6666 4.31804 14.6666 8.00004C14.6666 9.42404 14.2199 10.744 13.4599 11.8267L11.3333 8.00004H13.3333C13.3332 6.77085 12.9085 5.57942 12.131 4.6273C11.3536 3.67519 10.2712 3.02084 9.06681 2.77495C7.86246 2.52906 6.61014 2.70672 5.5217 3.27788C4.43327 3.84905 3.57553 4.77865 3.0936 5.90943C2.61167 7.04021 2.53512 8.30275 2.87691 9.48347C3.2187 10.6642 3.95785 11.6906 4.96931 12.3891C5.98077 13.0876 7.20245 13.4152 8.42768 13.3166C9.65292 13.218 10.8065 12.6993 11.6933 11.848L12.3579 13.0447Z`; + var pauseIconHeight = rectW * 0.4; + var pauseIconWidth = rectW * 0.08; + var pauseIconGap = rectW * 0.15; + var pauseIconX = (rectW - pauseIconWidth * 2 - pauseIconGap) / 2; + var TimeControllerView = class { + constructor(domSelector2) { + this.render(domSelector2); + this.moveSilderBar = () => { + }; + } + play() { + this.renderPauseIcon(); + } + pause() { + this.renderPlayIcon(); + } + renderPlayIcon() { + const playPauseIconG = this.playPauseIconG; + playPauseIconG.selectAll("*").remove(); + playPauseIconG.append("path").attr("d", `M${rectW * 0.36},${rectW * 0.3}L${rectW * 0.64},${rectW * 0.5}L${rectW * 0.36},${rectW * 0.7}Z`).attr("fill", "#000"); + } + renderPauseIcon() { + const playPauseIconG = this.playPauseIconG; + playPauseIconG.selectAll("*").remove(); + playPauseIconG.selectAll("rect").data([, ,]).join("rect").attr("x", (_, i) => pauseIconX + i * (pauseIconGap + pauseIconWidth)).attr("y", (rectW - pauseIconHeight) / 2).attr("rx", pauseIconWidth / 2).attr("ry", pauseIconWidth / 2).attr("width", pauseIconWidth).attr("height", pauseIconHeight).attr("fill", "#000"); + } + render(domSelector2) { + const _dom = select_default2(domSelector2); + _dom.selectAll("svg#feder-timer").remove(); + const svg = _dom.append("svg").attr("id", "feder-timer").attr("width", 300).attr("height", rectW).style("position", "absolute").style("left", "20px").style("bottom", "32px"); + const playPauseG = svg.append("g"); + playPauseG.append("rect").attr("x", 0).attr("y", 0).attr("width", rectW).attr("height", rectW).attr("fill", "#fff"); + const playPauseIconG = playPauseG.append("g"); + this.playPauseIconG = playPauseIconG; + this.renderPlayIcon(); + const sliderG = svg.append("g").attr("transform", `translate(${rectW + iconGap}, 0)`); + sliderG.append("rect").attr("x", 0).attr("y", 0).attr("width", sliderBackGroundWidth).attr("height", rectW).attr("fill", "#1D2939"); + sliderG.append("rect").attr("x", sliderBackGroundWidth / 2 - sliderWidth / 2).attr("y", rectW / 2 - sliderHeight / 2).attr("width", sliderWidth).attr("height", sliderHeight).attr("fill", "#fff"); + const sliderBar = sliderG.append("g").append("rect").datum({ x: 0, y: 0 }).attr("transform", `translate(${sliderBackGroundWidth / 2 - sliderWidth / 2 - sliderBarWidth / 2},0)`).attr("x", 0).attr("y", rectW / 2 - sliderBarHeight / 2).attr("width", sliderBarWidth).attr("height", sliderBarHeight).attr("fill", "#fff"); + const resetG = svg.append("g").attr("transform", `translate(${rectW + iconGap + sliderBackGroundWidth + iconGap}, 0)`); + resetG.append("rect").attr("x", 0).attr("y", 0).attr("width", rectW).attr("height", rectW).attr("fill", "#fff"); + resetG.append("path").attr("d", resetIconD).attr("fill", "#000").attr("transform", `translate(${rectW / 2 - resetW / 2},${rectW / 2 - resetW / 2})`); + this.playPauseG = playPauseG; + this.sliderBar = sliderBar; + this.resetG = resetG; + } + setTimer(timer2) { + this.playPauseG.on("click", () => timer2.playPause()); + this.resetG.on("click", () => timer2.restart()); + const drag = drag_default().on("start", () => timer2.stop()).on("drag", (e, d) => { + const x3 = Math.max(0, Math.min(e.x, sliderWidth)); + sliderBar.attr("x", d.x = x3); + timer2.setTimeP(x3 / sliderWidth); + }); + const sliderBar = this.sliderBar; + sliderBar.call(drag); + this.moveSilderBar = (p) => { + const x3 = p * sliderWidth; + sliderBar.datum().x = x3; + sliderBar.attr("x", x3); + }; + } + }; + var TimeControllerView_default = TimeControllerView; + + // federjs/FederView/HnswView/render/TimerController.js + var TimerController = class { + constructor({ duration, speed = 1, callback, playCallback, pauseCallback }) { + this.callback = callback; + this.speed = speed; + this.duration = duration; + this.playCallback = playCallback; + this.pauseCallback = pauseCallback; + this.tAlready = 0; + this.t = 0; + this.timer = null; + this.isPlaying = false; + } + get currentT() { + return this.t; + } + start() { + const speed = this.speed; + this.isPlaying || this.playCallback(); + this.isPlaying = true; + this.timer = timer((elapsed) => { + const t = elapsed * speed + this.tAlready; + const p = t / this.duration; + this.t = t; + this.callback({ + t, + p + }); + if (p >= 1) { + this.stop(); + } + }); + } + restart() { + this.timer.stop(); + this.tAlready = 0; + this.start(); + } + stop() { + this.timer.stop(); + this.tAlready = this.t; + this.isPlaying && this.pauseCallback(); + this.isPlaying = false; + } + playPause() { + if (this.isPlaying) + this.stop(); + else + this.start(); + } + continue() { + this.start(); + } + setSpeed(speed) { + this.stop(); + this.speed = speed; + this.continue(); + } + setTimeT(t) { + this.stop(); + const p = t / this.duration; + this.tAlready = t; + this.t = t; + this.callback({ + t, + p + }); + } + setTimeP(p) { + this.stop(); + const t = this.duration * p; + this.tAlready = t; + this.t = t; + this.callback({ + t, + p + }); + } + }; + + // federjs/FederView/HnswView/render/renderHoverLine.js + var renderHoverLine = (ctx, { hoveredNode, hoveredLevel, clickedNode, clickedLevel }, { + width, + padding, + hoveredPanelLineWidth, + HoveredPanelLine_1_x, + HoveredPanelLine_1_y, + HoveredPanelLine_2_x, + canvasScale + }) => { + let isLeft = true; + let endX = 0; + let endY = 0; + if (!!hoveredNode) { + const [x3, y4] = hoveredNode.overviewPosLevels[hoveredLevel]; + const originX = (width - padding[1] - padding[3]) / 2 + padding[3]; + isLeft = !clickedNode ? originX > x3 : clickedNode.overviewPosLevels[clickedLevel][0] > x3; + const k = isLeft ? -1 : 1; + endX = x3 + HoveredPanelLine_1_x * canvasScale * k + HoveredPanelLine_2_x * canvasScale * k; + endY = y4 + HoveredPanelLine_1_y * canvasScale * k; + const points = [ + [x3, y4], + [ + x3 + HoveredPanelLine_1_x * canvasScale * k, + y4 + HoveredPanelLine_1_y * canvasScale * k + ], + [ + x3 + HoveredPanelLine_1_x * canvasScale * k + HoveredPanelLine_2_x * canvasScale * k, + y4 + HoveredPanelLine_1_y * canvasScale * k + ] + ]; + drawPath({ + ctx, + points, + withZ: false, + hasStroke: true, + strokeStyle: hexWithOpacity(ZYellow, 1), + lineWidth: hoveredPanelLineWidth * canvasScale + }); + } + return { isLeft, endX, endY }; + }; + var renderHoverLine_default = renderHoverLine; + + // federjs/FederView/HnswView/render/renderSearchViewLinks.js + function renderSearchViewLinks(ctx, { links, inProcessLinks, level }, { shortenLineD, canvasScale }) { + let pointsList = []; + let inprocessPointsList = []; + pointsList = links.filter((link) => link.type === HNSW_LINK_TYPE.Visited).map((link) => shortenLine(link.source.searchViewPosLevels[level], link.target.searchViewPosLevels[level], shortenLineD * canvasScale)); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: normalGradientStopColors, + lineWidth: 4, + lineCap: "round" + }); + inprocessPointsList = inProcessLinks.filter(({ link }) => link.type === HNSW_LINK_TYPE.Visited).map(({ t, link }) => shortenLine(link.source.searchViewPosLevels[level], getInprocessPos(link.source.searchViewPosLevels[level], link.target.searchViewPosLevels[level], t), shortenLineD)); + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: normalGradientStopColors, + lineWidth: 4, + lineCap: "round" + }); + pointsList = links.filter((link) => link.type === HNSW_LINK_TYPE.Extended).map((link) => shortenLine(link.source.searchViewPosLevels[level], link.target.searchViewPosLevels[level], shortenLineD)); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: normalGradientStopColors, + lineWidth: 4, + lineCap: "round" + }); + inprocessPointsList = inProcessLinks.filter(({ link }) => link.type === HNSW_LINK_TYPE.Extended).map(({ t, link }) => shortenLine(link.source.searchViewPosLevels[level], getInprocessPos(link.source.searchViewPosLevels[level], link.target.searchViewPosLevels[level], t), shortenLineD)); + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: normalGradientStopColors, + lineWidth: 4, + lineCap: "round" + }); + pointsList = links.filter((link) => link.type === HNSW_LINK_TYPE.Searched).map((link) => shortenLine(link.source.searchViewPosLevels[level], link.target.searchViewPosLevels[level], shortenLineD)); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: "round" + }); + inprocessPointsList = inProcessLinks.filter(({ link }) => link.type === HNSW_LINK_TYPE.Searched).map(({ t, link }) => shortenLine(link.source.searchViewPosLevels[level], getInprocessPos(link.source.searchViewPosLevels[level], link.target.searchViewPosLevels[level], t), shortenLineD)); + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: "round" + }); + pointsList = links.filter((link) => link.type === HNSW_LINK_TYPE.Fine).map((link) => shortenLine(link.source.searchViewPosLevels[level], link.target.searchViewPosLevels[level], shortenLineD)); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: "round" + }); + inprocessPointsList = inProcessLinks.filter(({ link }) => link.type === HNSW_LINK_TYPE.Fine).map(({ t, link }) => shortenLine(link.source.searchViewPosLevels[level], getInprocessPos(link.source.searchViewPosLevels[level], link.target.searchViewPosLevels[level], t), shortenLineD)); + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: "round" + }); + } + + // federjs/FederView/HnswView/render/renderSearchViewInterLevelLinks.js + function renderSearchViewInterLevelLinks(ctx, { entryNodes, inprocessEntryNodes, searchTarget, level }, { shortenLineD, canvasScale }) { + const pointsList = entryNodes.map((node) => shortenLine(node.searchViewPosLevels[level + 1], node.searchViewPosLevels[level], shortenLineD * canvasScale)); + drawLinesWithLinearGradient({ + ctx, + pointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: "round" + }); + const targetPointsList = pointsList.length === 0 ? [] : [ + shortenLine(searchTarget.searchViewPosLevels[level + 1], searchTarget.searchViewPosLevels[level], shortenLineD) + ]; + drawLinesWithLinearGradient({ + ctx, + pointsList: targetPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: targetLevelGradientStopColors, + lineWidth: 6, + lineCap: "round" + }); + const inprocessPointsList = inprocessEntryNodes.map(({ node, t }) => shortenLine(node.searchViewPosLevels[level + 1], getInprocessPos(node.searchViewPosLevels[level + 1], node.searchViewPosLevels[level], t), shortenLineD)); + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: highLightGradientStopColors, + lineWidth: 6, + lineCap: "round" + }); + const inprocessTargetPointsList = inprocessPointsList.length === 0 ? [] : [ + shortenLine(searchTarget.searchViewPosLevels[level + 1], getInprocessPos(searchTarget.searchViewPosLevels[level + 1], searchTarget.searchViewPosLevels[level], inprocessEntryNodes[0].t), shortenLineD) + ]; + drawLinesWithLinearGradient({ + ctx, + pointsList: inprocessTargetPointsList, + hasStroke: true, + isStrokeLinearGradient: true, + gradientStopColors: targetLevelGradientStopColors, + lineWidth: 6, + lineCap: "round" + }); + } + + // federjs/FederView/HnswView/render/renderSearchViewNodes.js + function renderSearchViewNodes(ctx, { nodes, level }, { ellipseRation, shadowBlur }) { + let _nodes = []; + _nodes = nodes.filter((node) => node.type === HNSW_NODE_TYPE.Coarse); + drawEllipse({ + ctx, + circles: _nodes.map((node) => [ + ...node.searchViewPosLevels[level], + node.r * ellipseRation, + node.r + ]), + hasFill: true, + fillStyle: hexWithOpacity(ZBlue, 0.7), + shadowColor: ZBlue, + shadowBlur + }); + _nodes = nodes.filter((node) => node.type === HNSW_NODE_TYPE.Candidate); + drawEllipse({ + ctx, + circles: _nodes.map((node) => [ + ...node.searchViewPosLevels[level], + node.r * ellipseRation, + node.r + ]), + hasFill: true, + fillStyle: hexWithOpacity(ZYellow, 0.8), + shadowColor: ZYellow, + shadowBlur + }); + _nodes = nodes.filter((node) => node.type === HNSW_NODE_TYPE.Fine); + drawEllipse({ + ctx, + circles: _nodes.map((node) => [ + ...node.searchViewPosLevels[level], + node.r * ellipseRation, + node.r + ]), + hasFill: true, + fillStyle: hexWithOpacity(colorScheme[2], 1), + hasStroke: true, + lineWidth: 1, + strokeStyle: hexWithOpacity(ZOrange, 0.8), + shadowColor: ZOrange, + shadowBlur + }); + } + + // federjs/FederView/HnswView/render/renderSearchViewTarget.js + function renderSearchViewTarget(ctx, { node, level }, { ellipseRation }) { + drawEllipse({ + ctx, + circles: [ + [...node.searchViewPosLevels[level], node.r * ellipseRation, node.r] + ], + hasFill: true, + fillStyle: hexWithOpacity(whiteColor, 1), + shadowColor: whiteColor, + shadowBlur: 6 + }); + } + + // federjs/FederView/HnswView/render/renderSelectedNode.js + function renderSelectedNode(ctx, { pos, r }, { ellipseRation }) { + drawEllipse({ + ctx, + circles: [[...pos, r * ellipseRation, r]], + hasStroke: true, + strokeStyle: hexWithOpacity(ZYellow, 0.8), + lineWidth: 4 + }); + } + + // federjs/FederView/HnswView/render/renderHoveredPanelLine.js + function renderHoveredPanelLine(ctx, { x: x3, y: y4, isLeft }, { + hoveredPanelLineWidth, + HoveredPanelLine_1_x, + HoveredPanelLine_1_y, + HoveredPanelLine_2_x, + canvasScale + }) { + const k = isLeft ? -1 : 1; + const points = [ + [x3, y4], + [ + x3 + HoveredPanelLine_1_x * canvasScale * k, + y4 + HoveredPanelLine_1_y * canvasScale * k + ], + [ + x3 + HoveredPanelLine_1_x * canvasScale * k + HoveredPanelLine_2_x * canvasScale * k, + y4 + HoveredPanelLine_1_y * canvasScale * k + ] + ]; + drawPath({ + ctx, + points, + withZ: false, + hasStroke: true, + strokeStyle: hexWithOpacity(ZYellow, 1), + lineWidth: hoveredPanelLineWidth * canvasScale + }); + } + + // federjs/FederView/HnswView/render/renderSearchViewTransition.js + function renderSearchViewTransition(ctx, { + searchNodesLevels, + searchLinksLevels, + searchLayerPosLevels, + searchNodeShowTime, + searchLinkShowTime, + searchTarget, + searchTargetShowTime, + entryNodesLevels, + clickedLevel, + clickedNode, + hoveredLevel, + hoveredNode + }, federView, { t, p }) { + const { + searchIntraLevelTime, + searchInterLevelTime, + width, + padding, + canvasScale + } = federView; + renderBackground(ctx, federView); + for (let level = 0; level < searchNodesLevels.length; level++) { + renderlevelLayer(ctx, searchLayerPosLevels[level], federView); + const nodes = searchNodesLevels[level].filter((node) => searchNodeShowTime[getNodeIdWithLevel(node.id, level)] < t); + const links = searchLinksLevels[level].filter((link) => searchLinkShowTime[getLinkIdWithLevel(link.source.id, link.target.id, level)] + searchIntraLevelTime < t); + const inProcessLinks = searchLinksLevels[level].filter((link) => searchLinkShowTime[getLinkIdWithLevel(link.source.id, link.target.id, level)] < t && searchLinkShowTime[getLinkIdWithLevel(link.source.id, link.target.id, level)] + searchIntraLevelTime >= t).map((link) => ({ + t: (t - searchLinkShowTime[getLinkIdWithLevel(link.source.id, link.target.id, level)]) / searchIntraLevelTime, + link + })); + const entryNodes = level === entryNodesLevels.length - 1 ? [] : entryNodesLevels[level].filter((entryNode) => searchLinkShowTime[getEntryLinkIdWithLevel(entryNode.id, level)] + searchInterLevelTime < t); + const inprocessEntryNodes = level === entryNodesLevels.length - 1 ? [] : entryNodesLevels[level].filter((entryNode) => searchLinkShowTime[getEntryLinkIdWithLevel(entryNode.id, level)] < t && searchLinkShowTime[getEntryLinkIdWithLevel(entryNode.id, level)] + searchInterLevelTime >= t).map((node) => ({ + node, + t: (t - searchLinkShowTime[getEntryLinkIdWithLevel(node.id, level)]) / searchInterLevelTime + })); + renderSearchViewLinks(ctx, { links, inProcessLinks, level }, federView); + renderSearchViewInterLevelLinks(ctx, { + entryNodes, + inprocessEntryNodes, + searchTarget, + level + }, federView); + renderSearchViewNodes(ctx, { nodes, level }, federView); + searchTargetShowTime[level] < t && renderSearchViewTarget(ctx, { node: searchTarget, level }, federView); + if (!!hoveredNode) { + const [x3, y4] = hoveredNode.searchViewPosLevels[hoveredLevel]; + const originX = (width - padding[1] - padding[3]) / 2 + padding[3]; + const isLeft = originX > x3; + renderHoveredPanelLine(ctx, { x: x3, y: y4, isLeft }, federView); + } + if (!!clickedNode) { + renderSelectedNode(ctx, { + pos: clickedNode.searchViewPosLevels[clickedLevel], + r: clickedNode.r + 2 * canvasScale + }, federView); + } + } + } + + // federjs/FederView/HnswView/InfoPanel/index.js + var overviewPanelId = "feder-info-overview-panel"; + var selectedPanelId = "feder-info-selected-panel"; + var hoveredPanelId = "feder-info-hovered-panel"; + var panelBackgroundColor = hexWithOpacity(blackColor, 0.6); + var InfoPanel = class { + constructor({ dom, width, height }) { + this.dom = dom; + this.width = width; + this.height = height; + const overviewPanel = document.createElement("div"); + overviewPanel.setAttribute("id", overviewPanelId); + overviewPanel.className = overviewPanel.className + " panel-border panel hide"; + const overviewPanelStyle = { + position: "absolute", + left: "16px", + top: "10px", + width: "280px", + "max-height": `${height - 20}px`, + overflow: "auto", + borderColor: whiteColor, + backgroundColor: panelBackgroundColor + }; + Object.assign(overviewPanel.style, overviewPanelStyle); + dom.appendChild(overviewPanel); + const selectedPanel = document.createElement("div"); + selectedPanel.setAttribute("id", selectedPanelId); + selectedPanel.className = selectedPanel.className + " panel-border panel hide"; + const selectedPanelStyle = { + position: "absolute", + right: "16px", + top: "10px", + "max-width": "180px", + "max-height": `${height - 20}px`, + overflow: "auto", + borderColor: ZYellow, + backgroundColor: panelBackgroundColor + }; + Object.assign(selectedPanel.style, selectedPanelStyle); + dom.appendChild(selectedPanel); + const hoveredPanel = document.createElement("div"); + hoveredPanel.setAttribute("id", hoveredPanelId); + hoveredPanel.className = hoveredPanel.className + " hide"; + const hoveredPanelStyle = { + position: "absolute", + left: 0, + top: 0, + width: "240px", + display: "flex", + pointerEvents: "none" + }; + Object.assign(hoveredPanel.style, hoveredPanelStyle); + dom.appendChild(hoveredPanel); + this.initStyle(); + } + initStyle() { + const style = document.createElement("style"); + style.type = "text/css"; + style.innerHTML = ` + .panel-border { + border-style: dashed; + border-width: 1px; + } + .panel { + padding: 6px 8px; + font-size: 12px; + } + .hide { + opacity: 0; + } + .panel-item { + margin-bottom: 6px; + } + .panel-img { + width: 150px; + height: 100px; + background-size: cover; + margin-bottom: 12px; + border-radius: 4px; + border: 1px solid ${ZYellow}; + } + .panel-item-display-flex { + display: flex; + } + .panel-item-title { + font-weight: 600; + margin-bottom: 3px; + } + .panel-item-text { + font-weight: 400; + font-size: 10px; + word-break: break-all; + } + .panel-item-text-flex { + margin-left: 8px; + } + .panel-item-text-margin { + margin: 0 6px; + } + .text-no-wrap { + white-space: nowrap; + } + `; + document.getElementsByTagName("head").item(0).appendChild(style); + } + renderSelectedPanel(itemList = [], color2 = "#000") { + const panel = select_default2(this.dom).select(`#${selectedPanelId}`); + panel.style("color", color2); + if (itemList.length === 0) + panel.classed("hide", true); + else { + this.renderPanel(panel, itemList); + } + } + renderHoveredPanel({ + itemList = [], + canvasScale = 1, + color: color2 = "#000", + x: x3 = 0, + y: y4 = 0, + isLeft = false + } = {}) { + const panel = select_default2(this.dom).select(`#${hoveredPanelId}`); + if (itemList.length === 0) + panel.classed("hide", true); + else { + panel.style("color", color2); + if (isLeft) { + panel.style("left", null); + panel.style("right", this.width - x3 / canvasScale + "px"); + panel.style("flex-direction", "row-reverse"); + } else { + panel.style("left", x3 / canvasScale + "px"); + panel.style("flex-direction", "row"); + } + panel.style("transform", `translateY(-6px)`); + panel.style("top", y4 / canvasScale + "px"); + this.renderPanel(panel, itemList); + } + } + renderOverviewPanel(itemList = [], color2) { + const panel = select_default2(this.dom).select(`#${overviewPanelId}`); + panel.style("color", color2); + if (itemList.length === 0) + panel.classed("hide", true); + else { + this.renderPanel(panel, itemList); + } + } + renderPanel(panel, itemList) { + panel.classed("hide", false); + panel.selectAll("*").remove(); + itemList.forEach((item) => { + const div = panel.append("div"); + div.classed("panel-item", true); + item.isFlex && div.classed("panel-item-display-flex", true); + if (item.isImg && item.imgUrl) { + div.classed("panel-img", true); + div.style("background-image", `url(${item.imgUrl})`); + } + if (item.title) { + const title = div.append("div"); + title.classed("panel-item-title", true); + title.text(item.title); + } + if (item.text) { + const title = div.append("div"); + title.classed("panel-item-text", true); + item.isFlex && title.classed("panel-item-text-flex", true); + item.textWithMargin && title.classed("panel-item-text-margin", true); + item.noWrap && title.classed("text-no-wrap", true); + title.text(item.text); + } + }); + } + updateOverviewOverviewInfo({ indexMeta, nodesCount, linksCount }) { + const overviewInfo = [ + { + title: "HNSW" + }, + { + title: `M = ${indexMeta.M}, ef_construction = ${indexMeta.ef_construction}` + }, + { + title: `${indexMeta.ntotal} vectors, including ${indexMeta.levelCount} levels (only show the top 3 levels).` + } + ]; + for (let level = indexMeta.overviewLevelCount - 1; level >= 0; level--) { + overviewInfo.push({ + isFlex: true, + title: `Level ${level + indexMeta.levelCount - indexMeta.overviewLevelCount}`, + text: `${nodesCount[level]} vectors, ${linksCount[level]} links` + }); + } + this.renderOverviewPanel(overviewInfo, whiteColor); + } + updateOverviewClickedInfo(_0, _1, _2) { + return __async(this, arguments, function* (node, level, { indexMeta, mediaType, mediaCallback, getVectorById }) { + const itemList = []; + if (node) { + itemList.push({ + title: `Level ${level + indexMeta.levelCount - indexMeta.overviewLevelCount}` + }); + itemList.push({ + title: `Row No. ${node.id}` + }); + mediaType === "img" && itemList.push({ + isImg: true, + imgUrl: mediaCallback(node.id) + }); + itemList.push({ + title: `Shortest path from the entry:`, + text: `${[...node.path, node.id].join(" => ")}` + }); + itemList.push({ + title: `Linked vectors:`, + text: `${node.linksLevels[level].join(", ")}` + }); + itemList.push({ + title: `Vectors:`, + text: `${showVectors(yield getVectorById(node.id))}` + }); + } + this.renderSelectedPanel(itemList, ZYellow); + }); + } + updateOverviewHoveredInfo(hoveredNode, { isLeft, endX, endY }, { mediaType, mediaCallback, canvasScale }) { + if (!!hoveredNode) { + const itemList = []; + itemList.push({ + text: `No. ${hoveredNode.id}`, + textWithMargin: true, + noWrap: true + }); + mediaType === "img" && itemList.push({ + isImg: true, + imgUrl: mediaCallback(hoveredNode.id) + }); + this.renderHoveredPanel({ + itemList, + color: ZYellow, + x: endX, + y: endY, + isLeft, + canvasScale + }); + } else { + this.renderHoveredPanel(); + } + } + updateSearchViewOverviewInfo({ + targetMediaUrl, + id2forcePos, + searchNodesLevels, + searchLinksLevels, + searchParams + }, { indexMeta }) { + const overviewInfo = [ + { + title: "HNSW - Search" + }, + { + isImg: true, + imgUrl: targetMediaUrl + }, + { + title: `M = ${indexMeta.M}, ef_construction = ${indexMeta.ef_construction}.` + }, + { + title: `k = ${searchParams.k}, ef_search = ${searchParams.ef}.` + }, + { + title: `${indexMeta.ntotal} vectors, including ${indexMeta.levelCount} levels.` + }, + { + title: `During the search, a total of ${Object.keys(id2forcePos).length - 1} of these vectors were visited.` + } + ]; + for (let level = indexMeta.levelCount - 1; level >= 0; level--) { + const nodes = searchNodesLevels[level]; + const links = searchLinksLevels[level]; + const minDist = level > 0 ? nodes.find((node) => node.type === HNSW_NODE_TYPE.Fine).dist.toFixed(3) : min(nodes.filter((node) => node.type === HNSW_NODE_TYPE.Fine), (node) => node.dist.toFixed(3)); + overviewInfo.push({ + isFlex: true, + title: `Level ${level}`, + text: `${nodes.length} vectors, ${links.length} links, min-dist: ${minDist}` + }); + } + this.renderOverviewPanel(overviewInfo, whiteColor); + } + updateSearchViewHoveredInfo({ hoveredNode, hoveredLevel }, { + mediaType, + mediaCallback, + width, + padding, + HoveredPanelLine_1_x, + HoveredPanelLine_1_y, + HoveredPanelLine_2_x, + canvasScale + }) { + if (!hoveredNode) { + this.renderHoveredPanel(); + } else { + const [x3, y4] = hoveredNode.searchViewPosLevels[hoveredLevel]; + const originX = (width - padding[1] - padding[3]) / 2 + padding[3]; + const isLeft = originX > x3; + const k = isLeft ? -1 : 1; + const endX = x3 + HoveredPanelLine_1_x * canvasScale * k + HoveredPanelLine_2_x * canvasScale * k; + const endY = y4 + HoveredPanelLine_1_y * canvasScale * k; + const itemList = []; + itemList.push({ + text: `No. ${hoveredNode.id}`, + textWithMargin: true, + noWrap: true + }); + mediaType === "img" && itemList.push({ + isImg: true, + imgUrl: mediaCallback(hoveredNode.id) + }); + this.renderHoveredPanel({ + itemList, + color: ZYellow, + x: endX, + y: endY, + isLeft, + canvasScale + }); + } + } + updateSearchViewClickedInfo(_0, _1) { + return __async(this, arguments, function* ({ clickedNode, clickedLevel }, { mediaType, mediaCallback, getVectorById }) { + const itemList = []; + if (!clickedNode) { + this.renderSelectedPanel([], ZYellow); + } else { + itemList.push({ + title: `Level ${clickedLevel}` + }); + itemList.push({ + title: `Row No. ${clickedNode.id}` + }); + itemList.push({ + title: `Distance to the target: ${clickedNode.dist.toFixed(3)}` + }); + mediaType === "img" && itemList.push({ + isImg: true, + imgUrl: mediaCallback(clickedNode.id) + }); + itemList.push({ + title: `Vector:`, + text: `${showVectors(yield getVectorById(clickedNode.id))}` + }); + } + this.renderSelectedPanel(itemList, ZYellow); + }); + } + }; + + // federjs/FederView/HnswView/index.js + var defaultHnswViewParams = { + padding: [80, 200, 60, 220], + forceTime: 3e3, + layerDotNum: 20, + shortenLineD: 8, + overviewLinkLineWidth: 2, + reachableLineWidth: 3, + shortestPathLineWidth: 4, + ellipseRation: 1.4, + shadowBlur: 4, + mouse2nodeBias: 3, + highlightRadiusExt: 0.5, + targetR: 3, + searchViewNodeBasicR: 1.5, + searchInterLevelTime: 300, + searchIntraLevelTime: 100, + HoveredPanelLine_1_x: 15, + HoveredPanelLine_1_y: -25, + HoveredPanelLine_2_x: 30, + hoveredPanelLineWidth: 2, + forceIterations: 100, + targetOrigin: [0, 0] + }; + var HnswView = class extends BaseView { + constructor({ indexMeta, viewParams, getVectorById }) { + super({ + indexMeta, + viewParams, + getVectorById + }); + for (let key in defaultHnswViewParams) { + this[key] = key in viewParams ? viewParams[key] : defaultHnswViewParams[key]; + } + this.padding = this.padding.map((num) => num * this.canvasScale); + this.overviewHandler(indexMeta); + } + initInfoPanel(dom) { + const infoPanel = new InfoPanel({ + dom, + width: this.viewParams.width, + height: this.viewParams.height + }); + return infoPanel; + } + overviewHandler(indexMeta) { + console.log(indexMeta); + this.indexMeta = indexMeta; + Object.assign(this, indexMeta); + const internalId2overviewNode = {}; + this.overviewNodes.forEach((node) => internalId2overviewNode[node.internalId] = node); + this.internalId2overviewNode = internalId2overviewNode; + this.overviewLayoutPromise = overviewLayout_default(this).then(({ + overviewLayerPosLevels, + overviewNodesLevels, + overviewLinksLevels + }) => { + this.overviewLayerPosLevels = overviewLayerPosLevels; + this.overviewNodesLevels = overviewNodesLevels; + this.overviewLinksLevels = overviewLinksLevels; + }); + } + renderOverview(ctx, infoPanel) { + const indexMeta = this.indexMeta; + const nodesCount = this.overviewNodesLevels.map((nodesLevel) => nodesLevel.length); + const linksCount = this.overviewLinksLevels.map((linksLevel) => linksLevel.length); + const overviewInfo = { indexMeta, nodesCount, linksCount }; + infoPanel.updateOverviewOverviewInfo(overviewInfo); + renderOverview(ctx, this); + } + getOverviewEventHandler(ctx, infoPanel) { + let clickedNode = null; + let clickedLevel = null; + let hoveredNode = null; + let hoveredLevel = null; + let overviewHighlightData = null; + const mouseMoveHandler = ({ x: x3, y: y4 }) => { + const mouse = [x3, y4]; + const { mouseLevel, mouseNode } = mouse2node({ + mouse, + layerPosLevels: this.overviewLayerPosLevels, + nodesLevels: this.overviewNodesLevels, + posAttr: "overviewPosLevels" + }, this); + const hoveredNodeChanged = hoveredLevel !== mouseLevel || hoveredNode !== mouseNode; + hoveredNode = mouseNode; + hoveredLevel = mouseLevel; + if (hoveredNodeChanged) { + if (!clickedNode) { + overviewHighlightData = getOverviewShortestPathData(mouseNode, mouseLevel, this); + } + renderOverview(ctx, this, overviewHighlightData); + const hoveredPanelPos = renderHoverLine_default(ctx, { + hoveredNode, + hoveredLevel, + clickedNode, + clickedLevel + }, this); + infoPanel.updateOverviewHoveredInfo(mouseNode, hoveredPanelPos, this); + } + }; + const mouseClickHandler = ({ x: x3, y: y4 }) => { + const mouse = [x3, y4]; + const { mouseLevel, mouseNode } = mouse2node({ + mouse, + layerPosLevels: this.overviewLayerPosLevels, + nodesLevels: this.overviewNodesLevels, + posAttr: "overviewPosLevels" + }, this); + const clickedNodeChanged = clickedLevel !== mouseLevel || clickedNode !== mouseNode; + clickedNode = mouseNode; + clickedLevel = mouseLevel; + if (clickedNodeChanged) { + overviewHighlightData = getOverviewShortestPathData(mouseNode, mouseLevel, this); + renderOverview(ctx, this, overviewHighlightData); + infoPanel.updateOverviewClickedInfo(mouseNode, mouseLevel, this); + } + }; + return { mouseMoveHandler, mouseClickHandler }; + } + searchViewHandler(searchRes) { + return searchViewLayoutHandler(searchRes, this); + } + renderSearchView(ctx, infoPanel, searchViewLayoutData, targetMediaUrl, dom) { + searchViewLayoutData.targetMediaUrl = targetMediaUrl; + infoPanel.updateSearchViewOverviewInfo(searchViewLayoutData, this); + const timeControllerView = new TimeControllerView_default(dom); + const callback = ({ t, p }) => { + renderSearchViewTransition(ctx, searchViewLayoutData, this, { + t, + p + }); + timeControllerView.moveSilderBar(p); + }; + const timer2 = new TimerController({ + duration: searchViewLayoutData.searchTransitionDuration, + callback, + playCallback: () => timeControllerView.play(), + pauseCallback: () => timeControllerView.pause() + }); + timeControllerView.setTimer(timer2); + timer2.start(); + searchViewLayoutData.searchTransitionTimer = timer2; + } + getSearchViewEventHandler(ctx, searchViewLayoutData, infoPanel) { + searchViewLayoutData.clickedLevel = null; + searchViewLayoutData.clickedNode = null; + searchViewLayoutData.hoveredLevel = null; + searchViewLayoutData.hoveredNode = null; + const mouseMoveHandler = ({ x: x3, y: y4 }) => { + const mouse = [x3, y4]; + const { mouseLevel, mouseNode } = mouse2node({ + mouse, + layerPosLevels: searchViewLayoutData.searchLayerPosLevels, + nodesLevels: searchViewLayoutData.searchNodesLevels, + posAttr: "searchViewPosLevels" + }, this); + const hoveredNodeChanged = searchViewLayoutData.hoveredLevel !== mouseLevel || searchViewLayoutData.hoveredNode !== mouseNode; + searchViewLayoutData.hoveredNode = mouseNode; + searchViewLayoutData.hoveredLevel = mouseLevel; + if (hoveredNodeChanged) { + infoPanel.updateSearchViewHoveredInfo(searchViewLayoutData, this); + if (!searchViewLayoutData.searchTransitionTimer.isPlaying) { + renderSearchViewTransition(ctx, searchViewLayoutData, this, { + t: searchViewLayoutData.searchTransitionTimer.tAlready + }); + } + } + }; + const mouseClickHandler = ({ x: x3, y: y4 }) => { + const mouse = [x3, y4]; + const { mouseLevel, mouseNode } = mouse2node({ + mouse, + layerPosLevels: searchViewLayoutData.searchLayerPosLevels, + nodesLevels: searchViewLayoutData.searchNodesLevels, + posAttr: "searchViewPosLevels" + }, this); + const clickedNodeChanged = searchViewLayoutData.clickedLevel !== mouseLevel || searchViewLayoutData.clickedNode !== mouseNode; + searchViewLayoutData.clickedNode = mouseNode; + searchViewLayoutData.clickedLevel = mouseLevel; + if (clickedNodeChanged) { + infoPanel.updateSearchViewClickedInfo(searchViewLayoutData, this); + if (!searchViewLayoutData.searchTransitionTimer.isPlaying) { + renderSearchViewTransition(ctx, searchViewLayoutData, this, { + t: searchViewLayoutData.searchTransitionTimer.tAlready + }); + } + } + }; + return { mouseMoveHandler, mouseClickHandler }; + } + }; + + // federjs/FederView/IvfflatView/layout/getVoronoi.js + function getVoronoi(clusters, width, height) { + const delaunay = Delaunay.from(clusters.map((cluster) => [cluster.x, cluster.y])); + const voronoi = delaunay.voronoi([0, 0, width, height]); + return voronoi; + } + + // federjs/FederView/IvfflatView/layout/overviewLayout.js + function overviewLayoutHandler2({ + indexMeta, + width, + height, + canvasScale, + minVoronoiRadius, + forceIterations + }) { + return new Promise((resolve) => { + const allArea = width * height; + const { ntotal, listCentroidProjections = null, listSizes } = indexMeta; + const clusters = listSizes.map((listSize, i) => ({ + clusterId: i, + oriProjection: listCentroidProjections ? listCentroidProjections[i] : [Math.random(), Math.random()], + count: listSize, + countP: listSize / ntotal, + countArea: allArea * (listSize / ntotal) + })); + const x3 = linear2().domain(extent(clusters, (cluster) => cluster.oriProjection[0])).range([0, width]); + const y4 = linear2().domain(extent(clusters, (cluster) => cluster.oriProjection[1])).range([0, height]); + clusters.forEach((cluster) => { + cluster.x = x3(cluster.oriProjection[0]); + cluster.y = y4(cluster.oriProjection[1]); + cluster.r = Math.max(minVoronoiRadius * canvasScale, Math.sqrt(cluster.countArea / Math.PI)); + }); + const simulation = simulation_default(clusters).alphaDecay(1 - Math.pow(1e-3, 1 / forceIterations)).force("collision", collide_default().radius((cluster) => cluster.r)).force("center", center_default(width / 2, height / 2)).on("tick", () => { + clusters.forEach((cluster) => { + cluster.x = Math.max(cluster.r, Math.min(width - cluster.r, cluster.x)); + cluster.y = Math.max(cluster.r, Math.min(height - cluster.r, cluster.y)); + }); + }).on("end", () => { + clusters.forEach((cluster) => { + cluster.forceProjection = [cluster.x, cluster.y]; + }); + const voronoi = getVoronoi(clusters, width, height); + clusters.forEach((cluster, i) => { + const points = voronoi.cellPolygon(i); + points.pop(); + cluster.OVPolyPoints = points; + cluster.OVPolyCentroid = centroid_default(points); + }); + resolve({ clusters, voronoi }); + }); + }); + } + + // federjs/FederView/IvfflatView/render/renderBackground.js + function renderBackground2(ctx, { + width, + height + }) { + drawRect({ + ctx, + width, + height, + hasFill: true, + fillStyle: blackColor + }); + } + + // federjs/FederView/IvfflatView/render/renderNormalVoronoi.js + function renderNormalVoronoi(ctx, viewType, { clusters, nonNprobeClusters }, { voronoiStrokeWidth, canvasScale }) { + const pointsList = viewType === VIEW_TYPE.overview ? clusters.map((cluster) => cluster.OVPolyPoints) : nonNprobeClusters.map((cluster) => cluster.SVPolyPoints); + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZBlue, 1) + }); + } + + // federjs/FederView/IvfflatView/render/renderHighlightVoronoi.js + function renderHighlightVoronoi(ctx, { nprobeClusters }, { voronoiStrokeWidth, canvasScale }) { + const pointsList = nprobeClusters.map((cluster) => cluster.SVPolyPoints); + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZLightBlue, 1) + }); + } + + // federjs/FederView/IvfflatView/render/renderSelectedVoronoi.js + function renderNormalVoronoi2(ctx, viewType, hoveredCluster, { + voronoiStrokeWidth, + canvasScale + }) { + const pointsList = viewType === VIEW_TYPE.overview ? [hoveredCluster.OVPolyPoints] : [hoveredCluster.SVPolyPoints]; + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZYellow, 0.8) + }); + } + + // federjs/FederView/IvfflatView/render/renderTarget.js + function renderTarget(ctx, searchViewType, { targetNode }, { targetNodeR, canvasScale, targetNodeStrokeWidth }) { + if (searchViewType === SEARCH_VIEW_TYPE.project) + return; + const circle = searchViewType === SEARCH_VIEW_TYPE.voronoi ? [...targetNode.SVPos, targetNodeR * canvasScale] : [...targetNode.polarPos, targetNodeR * canvasScale]; + drawCircle({ + ctx, + circles: [circle], + hasStroke: true, + strokeStyle: whiteColor, + lineWidth: targetNodeStrokeWidth * canvasScale + }); + } + + // federjs/FederView/IvfflatView/render/renderVoronoiView.js + function renderVoronoiView(ctx, viewType, layoutData, federView, hoveredCluster = null) { + renderBackground2(ctx, federView); + renderNormalVoronoi(ctx, viewType, layoutData, federView); + viewType === VIEW_TYPE.search && renderHighlightVoronoi(ctx, layoutData, federView); + !!hoveredCluster && renderNormalVoronoi2(ctx, viewType, hoveredCluster, federView); + viewType === VIEW_TYPE.search && renderTarget(ctx, SEARCH_VIEW_TYPE.voronoi, layoutData, federView); + } + + // federjs/FederView/IvfflatView/render/renderPolarAxis.js + function renderPolarAxis(ctx, { polarOrigin, polarMaxR }, { axisTickCount, polarAxisStrokeWidth, canvasScale, polarAxisOpacity }) { + const circles = range(axisTickCount).map((i) => [...polarOrigin, (i + 0.7) / axisTickCount * polarMaxR]); + drawCircle({ + ctx, + circles, + hasStroke: true, + lineWidth: polarAxisStrokeWidth * canvasScale, + strokeStyle: hexWithOpacity(ZBlue, polarAxisOpacity) + }); + } + + // federjs/FederView/IvfflatView/render/renderNormalNodes.js + function renderNormalNodes(ctx, { colorScheme: colorScheme2, nonTopKNodes, nprobe }, { nonTopKNodeR, canvasScale, nonTopKNodeOpacity }, searchViewType) { + const allCircles = searchViewType === SEARCH_VIEW_TYPE.polar ? nonTopKNodes.map((node) => [ + ...node.polarPos, + nonTopKNodeR * canvasScale, + node.polarOrder + ]) : nonTopKNodes.map((node) => [ + ...node.projectPos, + nonTopKNodeR * canvasScale, + node.polarOrder + ]); + for (let i = 0; i < nprobe; i++) { + let circles = allCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme2[i], nonTopKNodeOpacity) + }); + } + } + + // federjs/FederView/IvfflatView/render/renderHighLightNodes.js + function renderHighLightNodes(ctx, { colorScheme: colorScheme2, topKNodes, nprobe }, { topKNodeR, canvasScale, topKNodeOpacity, topKNodeStrokeWidth }, searchViewType) { + const allCircles = searchViewType === SEARCH_VIEW_TYPE.polar ? topKNodes.map((node) => [ + ...node.polarPos, + topKNodeR * canvasScale, + node.polarOrder + ]) : topKNodes.map((node) => [ + ...node.projectPos, + topKNodeR * canvasScale, + node.polarOrder + ]); + for (let i = 0; i < nprobe; i++) { + let circles = allCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme2[i], topKNodeOpacity), + hasStroke: true, + strokeStyle: hexWithOpacity(whiteColor, topKNodeOpacity), + lineWidth: topKNodeStrokeWidth * canvasScale + }); + } + } + + // federjs/FederView/IvfflatView/render/renderSelectedNode.js + function renderSelectedNode2(ctx, { colorScheme: colorScheme2 }, { hoveredNodeR, canvasScale, hoveredNodeOpacity, hoveredNodeStrokeWidth }, searchViewType, hoveredNode) { + const circle = searchViewType === SEARCH_VIEW_TYPE.polar ? [ + ...hoveredNode.polarPos, + hoveredNodeR * canvasScale, + hoveredNode.polarOrder + ] : [ + ...hoveredNode.projectPos, + hoveredNodeR * canvasScale, + hoveredNode.polarOrder + ]; + drawCircle({ + ctx, + circles: [circle], + hasFill: true, + fillStyle: hexWithOpacity(colorScheme2[circle[3]], hoveredNodeOpacity), + hasStroke: true, + lineWidth: hoveredNodeStrokeWidth * canvasScale, + strokeStyle: hexWithOpacity(whiteColor, 1) + }); + } + + // federjs/FederView/IvfflatView/render/renderNodeView.js + function renderNodeView(ctx, searchViewLayoutData, federView, searchViewType = SEARCH_VIEW_TYPE.polar, hoveredNode = null) { + renderBackground2(ctx, federView); + searchViewType === SEARCH_VIEW_TYPE.polar && renderPolarAxis(ctx, searchViewLayoutData, federView); + renderNormalNodes(ctx, searchViewLayoutData, federView, searchViewType); + renderHighLightNodes(ctx, searchViewLayoutData, federView, searchViewType); + !!hoveredNode && renderSelectedNode2(ctx, searchViewLayoutData, federView, searchViewType, hoveredNode); + renderTarget(ctx, searchViewType, searchViewLayoutData, federView); + } + + // federjs/FederView/IvfflatView/layout/mouse2voronoi.js + function mouse2node2({ voronoi, x: x3, y: y4 }) { + return voronoi.delaunay.find(x3, y4); + } + + // federjs/FederView/IvfflatView/layout/mouse2node.js + function mouse2node3({ nodesPos, x: x3, y: y4, bias }) { + const minIndex2 = minIndex(nodesPos, (nodePos) => dist2(nodePos, [x3, y4])); + return dist2(nodesPos[minIndex2], [x3, y4]) > Math.pow(bias, 2) ? -1 : minIndex2; + } + + // federjs/FederView/IvfflatView/layout/SVCoarseVoronoiHandler.js + function SVCoarseVoronoiHandler(searchRes, searchViewLayoutData, federView) { + return new Promise((resolve) => { + const { clusters, nprobeClusters, nprobe } = searchViewLayoutData; + const { width, height, forceIterations, polarOriginBias } = federView; + const fineClusterOrder = vecSort(nprobeClusters, "OVPolyCentroid", "clusterId"); + const targetClusterId = searchRes.coarse[0].id; + const targetCluster = clusters.find((cluster) => cluster.clusterId === targetClusterId); + const otherFineClustersId = fineClusterOrder.filter((clusterId) => clusterId !== targetClusterId); + const links = otherFineClustersId.map((clusterId) => ({ + source: clusterId, + target: targetClusterId + })); + clusters.forEach((cluster) => { + cluster.x = cluster.forceProjection[0]; + cluster.y = cluster.forceProjection[1]; + }); + const targetClusterX = nprobeClusters.reduce((acc, cluster) => acc + cluster.x, 0) / nprobe; + const targetClusterY = nprobeClusters.reduce((acc, cluster) => acc + cluster.y, 0) / nprobe; + targetCluster.x = targetClusterX; + targetCluster.y = targetClusterY; + const otherFineCluster = otherFineClustersId.map((clusterId) => nprobeClusters.find((cluster) => cluster.clusterId === clusterId)); + const angleStep = 2 * Math.PI / (nprobe - 1); + const biasR = targetCluster.r * 0.5; + otherFineCluster.forEach((cluster, i) => { + cluster.x = targetClusterX + biasR * Math.sin(angleStep * i); + cluster.y = targetClusterY + biasR * Math.cos(angleStep * i); + }); + const simulation = simulation_default(clusters).alphaDecay(1 - Math.pow(1e-3, 1 / forceIterations)).force("links", link_default(links).id((cluster) => cluster.clusterId).strength((_) => 0.25)).force("collision", collide_default().radius((cluster) => cluster.r).strength(0.1)).force("center", center_default(width / 2, height / 2)).on("tick", () => { + clusters.forEach((cluster) => { + cluster.x = Math.max(cluster.r, Math.min(width - cluster.r, cluster.x)); + cluster.y = Math.max(cluster.r, Math.min(height - cluster.r, cluster.y)); + }); + }).on("end", () => { + clusters.forEach((cluster) => { + cluster.SVPos = [cluster.x, cluster.y]; + }); + const voronoi = getVoronoi(clusters, width, height); + clusters.forEach((cluster, i) => { + const points = voronoi.cellPolygon(i); + points.pop(); + cluster.SVPolyPoints = points; + cluster.SVPolyCentroid = centroid_default(points); + }); + searchViewLayoutData.SVVoronoi = voronoi; + const targetCluster2 = clusters.find((cluster) => cluster.clusterId === targetClusterId); + const centoid_fineClusters_x = nprobeClusters.reduce((acc, cluster) => acc + cluster.SVPolyCentroid[0], 0) / nprobe; + const centroid_fineClusters_y = nprobeClusters.reduce((acc, cluster) => acc + cluster.SVPolyCentroid[1], 0) / nprobe; + const _x = centoid_fineClusters_x - targetCluster2.SVPos[0]; + const _y = centroid_fineClusters_y - targetCluster2.SVPos[1]; + const biasR2 = Math.sqrt(_x * _x + _y * _y); + const targetNode = { + SVPos: [ + targetCluster2.SVPos[0] + targetCluster2.r * 0.4 * (_x / biasR2), + targetCluster2.SVPos[1] + targetCluster2.r * 0.4 * (_y / biasR2) + ] + }; + targetNode.isLeft_coarseLevel = targetNode.SVPos[0] < width / 2; + searchViewLayoutData.targetNode = targetNode; + const polarOrigin = [ + width / 2 + (targetNode.isLeft_coarseLevel ? -1 : 1) * polarOriginBias * width, + height / 2 + ]; + searchViewLayoutData.polarOrigin = polarOrigin; + targetNode.polarPos = polarOrigin; + const polarMaxR = Math.min(width, height) * 0.5 - 5; + searchViewLayoutData.polarMaxR = polarMaxR; + const angleStep2 = Math.PI * 2 / fineClusterOrder.length; + nprobeClusters.forEach((cluster) => { + const order = fineClusterOrder.indexOf(cluster.clusterId); + cluster.polarOrder = order; + cluster.SVNextLevelPos = [ + polarOrigin[0] + polarMaxR / 2 * Math.sin(angleStep2 * order), + polarOrigin[1] + polarMaxR / 2 * Math.cos(angleStep2 * order) + ]; + cluster.SVNextLevelTran = [ + cluster.SVNextLevelPos[0] - cluster.SVPolyCentroid[0], + cluster.SVNextLevelPos[1] - cluster.SVPolyCentroid[1] + ]; + }); + const clusterId2cluster = {}; + nprobeClusters.forEach((cluster) => { + clusterId2cluster[cluster.clusterId] = cluster; + }); + searchViewLayoutData.clusterId2cluster = clusterId2cluster; + resolve(); + }); + }); + } + + // federjs/FederView/IvfflatView/layout/SVFinePolarHandler.js + function SVFinePolarHandler(searchRes, searchViewLayoutData, federView) { + return new Promise((resolve) => { + const { polarMaxR, polarOrigin, clusterId2cluster } = searchViewLayoutData; + const { forceIterations, nonTopKNodeR, canvasScale } = federView; + const nodes = searchRes.fine; + const distances = nodes.map((node) => node.dis).filter((a2) => a2 > 0).sort(); + const minDis = distances.length > 0 ? distances[0] : 0; + const maxDis = distances.length > 0 ? distances[Math.round((distances.length - 1) * 0.98)] : 0; + const r = linear2().domain([minDis, maxDis]).range([polarMaxR * 0.2, polarMaxR]).clamp(true); + nodes.forEach((node) => { + const cluster = clusterId2cluster[node.listId]; + const { polarOrder, SVNextLevelPos } = cluster; + node.polarOrder = polarOrder; + const randAngle = Math.random() * Math.PI * 2; + const randBias = [Math.sin, Math.cos].map((f) => cluster.r * Math.random() * 0.7 * f(randAngle)); + node.voronoiPos = SVNextLevelPos.map((d, i) => d + randBias[i]); + node.x = node.voronoiPos[0]; + node.y = node.voronoiPos[1]; + node.r = r(node.dis); + }); + const simulation = simulation_default(nodes).alphaDecay(1 - Math.pow(1e-3, 1 / forceIterations * 2)).force("collide", collide_default().radius((_) => nonTopKNodeR * canvasScale).strength(0.4)).force("r", radial_default((node) => node.r, ...polarOrigin).strength(1)).on("end", () => { + nodes.forEach((node) => { + node.polarPos = [node.x, node.y]; + }); + searchViewLayoutData.nodes = nodes; + searchViewLayoutData.topKNodes = nodes.filter((node) => searchRes.fsResIds.find((id2) => id2 == node.id)); + searchViewLayoutData.nonTopKNodes = nodes.filter((node) => !searchRes.fsResIds.find((id2) => id2 == node.id)); + resolve(); + }); + }); + } + + // federjs/FederView/IvfflatView/layout/SVFineProjectHandler.js + function SVFineProjectHandler(searchRes, searchViewLayoutData, federView) { + const { nodes, targetNode } = searchViewLayoutData; + const { projectPadding, width, height } = federView; + if (!nodes[0].projection) { + console.log('No Projection Data. Should use "fineWithProjection".'); + nodes.forEach((node) => { + node.projection = [Math.random(), Math.random()]; + }); + } + const xRange = targetNode.isLeft_coarseLevel ? [projectPadding[1], width - projectPadding[3]] : [projectPadding[3], width - projectPadding[1]]; + const x3 = linear2().domain(extent(nodes, (node) => node.projection[0])).range(xRange); + const y4 = linear2().domain(extent(nodes, (node) => node.projection[1])).range([projectPadding[0], height - projectPadding[2]]); + nodes.forEach((node) => { + node.projectPos = [x3(node.projection[0]), y4(node.projection[1])]; + }); + } + + // federjs/FederView/IvfflatView/layout/searchViewLayout.js + function searchViewLayoutHandler2(searchRes, searchViewLayoutData, federView) { + return new Promise((resolve) => __async(this, null, function* () { + searchRes.coarse.forEach(({ id: id2, dis }) => searchViewLayoutData.clusters[id2].dis = dis); + yield SVCoarseVoronoiHandler(searchRes, searchViewLayoutData, federView); + yield SVFinePolarHandler(searchRes, searchViewLayoutData, federView); + SVFineProjectHandler(searchRes, searchViewLayoutData, federView); + resolve(); + })); + } + + // federjs/FederView/IvfflatView/render/animateNonNprobeClusters.js + function animateNonNprobeClusters({ + ctx, + elapsed, + duration, + delay, + animationType, + searchViewLayoutData, + federView + }) { + const { ease, voronoiStrokeWidth, canvasScale } = federView; + const { nonNprobeClusters } = searchViewLayoutData; + let t = ease((elapsed - delay) / duration); + if (t > 1 || t < 0) + return; + const opacity = animationType === ANIMATION_TYPE.enter ? t : 1 - t; + const pointsList = nonNprobeClusters.map((cluster) => cluster.SVPolyPoints); + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZBlue, opacity) + }); + } + + // federjs/FederView/IvfflatView/render/animateNprobeClustersTrans.js + function animateNprobeClustersTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration, + delay, + animationType + }) { + const { nprobeClusters } = searchViewLayoutData; + const { ease, voronoiStrokeWidth, canvasScale } = federView; + let t = ease((elapsed - delay) / duration); + if (t > 1 || t < 0) + return; + t = animationType === ANIMATION_TYPE.enter ? 1 - t : t; + const pointsList = nprobeClusters.map((cluster) => cluster.SVPolyPoints.map((point) => [ + point[0] + t * cluster.SVNextLevelTran[0], + point[1] + t * cluster.SVNextLevelTran[1] + ])); + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZLightBlue, 1) + }); + } + + // federjs/FederView/IvfflatView/render/animateTargetNode.js + function animateTargetNode({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration, + delay, + animationType, + newSearchViewType + }) { + const { targetNode } = searchViewLayoutData; + const { ease, targetNodeR, canvasScale, targetNodeStrokeWidth } = federView; + let t = ease((elapsed - delay) / duration); + if (newSearchViewType === SEARCH_VIEW_TYPE.project) { + if (t < 0 || t > 1) + return; + } + if (t > 1) + t = 1; + if (t < 0) + t = 0; + t = animationType === ANIMATION_TYPE.enter ? t : 1 - t; + const x3 = targetNode.SVPos[0] * t + targetNode.polarPos[0] * (1 - t); + const y4 = targetNode.SVPos[1] * t + targetNode.polarPos[1] * (1 - t); + drawCircle({ + ctx, + circles: [[x3, y4, targetNodeR * canvasScale]], + hasStroke: true, + strokeStyle: whiteColor, + lineWidth: targetNodeStrokeWidth * canvasScale + }); + } + + // federjs/FederView/IvfflatView/render/animateNprobeClustersOpacity.js + function animateNonNprobeClusters2({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration, + delay, + animationType + }) { + const { nprobeClusters } = searchViewLayoutData; + const { ease, voronoiStrokeWidth, canvasScale } = federView; + let t = ease((elapsed - delay) / duration); + if (t > 1 || t < 0) + return; + t = animationType === ANIMATION_TYPE.enter ? t : 1 - t; + const opacity = t; + const pointsList = nprobeClusters.map((cluster) => cluster.SVPolyPoints.map((point) => [ + point[0] + cluster.SVNextLevelTran[0], + point[1] + cluster.SVNextLevelTran[1] + ])); + drawVoronoi({ + ctx, + pointsList, + hasStroke: true, + strokeStyle: blackColor, + lineWidth: voronoiStrokeWidth * canvasScale, + hasFill: true, + fillStyle: hexWithOpacity(ZLightBlue, opacity) + }); + } + + // federjs/FederView/IvfflatView/render/animateNodesOpacityAndTrans.js + function animateNodesOpacityAndTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration, + delay, + animationType, + newSearchViewType, + oldSearchViewType + }) { + const { colorScheme: colorScheme2, nprobe, topKNodes, nonTopKNodes } = searchViewLayoutData; + const { + ease, + topKNodeR, + topKNodeOpacity, + topKNodeStrokeWidth, + nonTopKNodeR, + nonTopKNodeOpacity, + canvasScale + } = federView; + let t = ease((elapsed - delay) / duration); + if (t > 1 || t < 0) + return; + t = animationType === ANIMATION_TYPE.enter ? 1 - t : t; + const nonTopKCircles = newSearchViewType === SEARCH_VIEW_TYPE.polar && animationType === ANIMATION_TYPE.enter || oldSearchViewType === SEARCH_VIEW_TYPE.polar && animationType === ANIMATION_TYPE.exit ? nonTopKNodes.map((node) => [ + t * node.voronoiPos[0] + (1 - t) * node.polarPos[0], + t * node.voronoiPos[1] + (1 - t) * node.polarPos[1], + nonTopKNodeR * canvasScale, + node.polarOrder + ]) : nonTopKNodes.map((node) => [ + t * node.voronoiPos[0] + (1 - t) * node.projectPos[0], + t * node.voronoiPos[1] + (1 - t) * node.projectPos[1], + nonTopKNodeR * canvasScale, + node.polarOrder + ]); + const topKCircles = newSearchViewType === SEARCH_VIEW_TYPE.polar && animationType === ANIMATION_TYPE.enter || oldSearchViewType === SEARCH_VIEW_TYPE.polar && animationType === ANIMATION_TYPE.exit ? topKNodes.map((node) => [ + t * node.voronoiPos[0] + (1 - t) * node.polarPos[0], + t * node.voronoiPos[1] + (1 - t) * node.polarPos[1], + topKNodeR * canvasScale, + node.polarOrder + ]) : topKNodes.map((node) => [ + t * node.voronoiPos[0] + (1 - t) * node.projectPos[0], + t * node.voronoiPos[1] + (1 - t) * node.projectPos[1], + topKNodeR * canvasScale, + node.polarOrder + ]); + for (let i = 0; i < nprobe; i++) { + let circles = nonTopKCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme2[i], nonTopKNodeOpacity) + }); + } + const opacity = t * 0.5 + (1 - t) * topKNodeOpacity; + for (let i = 0; i < nprobe; i++) { + let circles = topKCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme2[i], opacity), + hasStroke: true, + strokeStyle: hexWithOpacity(whiteColor, opacity), + lineWidth: topKNodeStrokeWidth * canvasScale + }); + } + } + + // federjs/FederView/IvfflatView/render/animateCoarse2Fine.js + function animateCoarse2Fine(oldSearchViewType, newSearchViewType, ctx, searchViewLayoutData, federView, endCallback = () => { + }) { + const { animateExitTime, animateEnterTime } = federView; + const stepAllTime = animateExitTime + animateEnterTime; + const timer2 = timer((elapsed) => { + renderBackground2(ctx, federView); + animateNonNprobeClusters({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: 0, + duration: animateExitTime, + animationType: ANIMATION_TYPE.exit + }); + animateNprobeClustersTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: 0, + duration: animateExitTime, + animationType: ANIMATION_TYPE.exit + }); + animateTargetNode({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: 0, + duration: animateExitTime, + animationType: ANIMATION_TYPE.exit, + newSearchViewType + }); + animateNonNprobeClusters2({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: animateExitTime, + duration: animateEnterTime, + animationType: ANIMATION_TYPE.exit + }); + animateNodesOpacityAndTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: animateExitTime, + duration: animateEnterTime, + animationType: ANIMATION_TYPE.enter, + oldSearchViewType, + newSearchViewType + }); + if (elapsed >= stepAllTime) { + console.log("Coarse => Fine [OK]"); + timer2.stop(); + endCallback(); + } + }); + } + + // federjs/FederView/IvfflatView/render/animateFine2Coarse.js + function animateFine2Coarse(oldSearchViewType, newSearchViewType, ctx, searchViewLayoutData, federView, endCallback = () => { + }) { + const { animateExitTime, animateEnterTime } = federView; + const stepAllTime = animateExitTime + animateEnterTime; + const timer2 = timer((elapsed) => { + renderBackground2(ctx, federView); + animateNodesOpacityAndTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: 0, + duration: animateExitTime, + animationType: ANIMATION_TYPE.exit, + oldSearchViewType, + newSearchViewType + }); + animateNonNprobeClusters2({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: 0, + duration: animateExitTime, + animationType: ANIMATION_TYPE.enter + }); + animateNonNprobeClusters({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: animateExitTime, + duration: animateEnterTime, + animationType: ANIMATION_TYPE.enter + }); + animateNprobeClustersTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: animateExitTime, + duration: animateEnterTime, + animationType: ANIMATION_TYPE.enter + }); + animateTargetNode({ + ctx, + searchViewLayoutData, + federView, + elapsed, + delay: animateExitTime, + duration: animateEnterTime, + animationType: ANIMATION_TYPE.enter, + newSearchViewType + }); + if (elapsed >= stepAllTime) { + console.log("Fine => Coarse [OK]"); + timer2.stop(); + endCallback(); + } + }); + } + + // federjs/FederView/IvfflatView/render/animateNodesTrans.js + function animateNodesTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration, + delay, + newSearchViewType + }) { + const { colorScheme: colorScheme2, nonTopKNodes, topKNodes, nprobe } = searchViewLayoutData; + const { + ease, + nonTopKNodeR, + canvasScale, + topKNodeR, + topKNodeStrokeWidth, + nonTopKNodeOpacity, + topKNodeOpacity + } = federView; + let t = ease((elapsed - delay) / duration); + if (t > 1 || t < 0) + return; + t = newSearchViewType === SEARCH_VIEW_TYPE.polar ? 1 - t : t; + const nonTopKCircles = nonTopKNodes.map((node) => [ + t * node.projectPos[0] + (1 - t) * node.polarPos[0], + t * node.projectPos[1] + (1 - t) * node.polarPos[1], + nonTopKNodeR * canvasScale, + node.polarOrder + ]); + const topKCircles = topKNodes.map((node) => [ + t * node.projectPos[0] + (1 - t) * node.polarPos[0], + t * node.projectPos[1] + (1 - t) * node.polarPos[1], + topKNodeR * canvasScale, + node.polarOrder + ]); + for (let i = 0; i < nprobe; i++) { + let circles = nonTopKCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme2[i], nonTopKNodeOpacity) + }); + } + for (let i = 0; i < nprobe; i++) { + let circles = topKCircles.filter((circle) => circle[3] == i); + drawCircle({ + ctx, + circles, + hasFill: true, + fillStyle: hexWithOpacity(colorScheme2[i], topKNodeOpacity), + hasStroke: true, + strokeStyle: hexWithOpacity(whiteColor, topKNodeOpacity), + lineWidth: topKNodeStrokeWidth * canvasScale + }); + } + } + + // federjs/FederView/IvfflatView/render/animateFine2Fine.js + function animateFine2Fine(oldSearchViewType, newSearchViewType, ctx, searchViewLayoutData, federView, endCallback) { + const { fineSearchNodeTransTime } = federView; + const timer2 = timer((elapsed) => { + renderBackground2(ctx, federView); + animateNodesTrans({ + ctx, + searchViewLayoutData, + federView, + elapsed, + duration: fineSearchNodeTransTime, + delay: 0, + newSearchViewType + }); + if (elapsed >= fineSearchNodeTransTime) { + console.log(`${oldSearchViewType} To ${newSearchViewType} OK!`); + timer2.stop(); + endCallback(); + } + }); + } + + // federjs/FederView/IvfflatView/InfoPanel/index.js + var overviewPanelId2 = "feder-info-overview-panel"; + var hoveredPanelId2 = "feder-info-hovered-panel"; + var panelBackgroundColor2 = hexWithOpacity(blackColor, 0.6); + var InfoPanel2 = class { + constructor({ dom, width, height }) { + this.dom = dom; + this.width = width; + this.height = height; + this.initOverviewPanel(); + this.initHoveredPanel(); + this.initStyle(); + } + initOverviewPanel() { + const dom = this.dom; + const overviewPanel = document.createElement("div"); + overviewPanel.setAttribute("id", overviewPanelId2); + overviewPanel.className = overviewPanel.className + " panel-border panel hide"; + const overviewPanelStyle = { + position: "absolute", + left: "16px", + top: "10px", + width: "240px", + "max-height": `${this.height - 40}px`, + overflow: "auto", + borderColor: whiteColor, + backgroundColor: panelBackgroundColor2 + }; + Object.assign(overviewPanel.style, overviewPanelStyle); + dom.appendChild(overviewPanel); + this.overviewPanel = overviewPanel; + } + setOverviewPanelPos(isPanelLeft) { + const overviewPanel = this.overviewPanel; + const overviewPanelStyle = isPanelLeft ? { + left: "16px" + } : { + left: null, + right: "16px" + }; + Object.assign(overviewPanel.style, overviewPanelStyle); + } + updateOverviewOverviewInfo({ indexMeta }) { + const { ntotal, nlist, listSizes } = indexMeta; + const items = [ + { + title: "IVF_Flat" + }, + { + text: `${ntotal} vectors, divided into ${nlist} clusters.` + }, + { + text: `The largest cluster has ${max(listSizes)} vectors and the smallest cluster has only ${min(listSizes)} vectors.` + } + ]; + this.renderOverviewPanel(items, whiteColor); + } + updateSearchViewCoarseOverviewInfo(searchViewLayoutData, federView) { + const { + nprobe, + clusters, + targetMediaUrl, + nprobeClusters, + switchSearchViewHandlers + } = searchViewLayoutData; + const { indexMeta } = federView; + const { ntotal, nlist, listSizes } = indexMeta; + const { switchVoronoi, switchPolar, switchProject } = switchSearchViewHandlers; + const items = [ + { + title: "IVF_Flat - Search" + }, + { + isImg: true, + imgUrl: targetMediaUrl + }, + { + isOption: true, + isActive: true, + label: "Coarse Search", + callback: switchVoronoi + }, + { + isOption: true, + isActive: false, + label: "Fine Search (Distance)", + callback: switchPolar + }, + { + isOption: true, + isActive: false, + label: "Fine Search (Project)", + callback: switchProject + }, + { + text: `${ntotal} vectors, divided into ${nlist} clusters.` + }, + { + title: `Find the ${nprobe} (nprobe=${nprobe}) closest clusters.` + }, + ...nprobeClusters.map(({ clusterId }) => ({ + text: `cluster-${clusterId} (${listSizes[clusterId]} vectors) dist: ${clusters[clusterId].dis.toFixed(3)}.` + })) + ]; + this.renderOverviewPanel(items, whiteColor); + } + updateSearchViewFinePolarOverviewInfo(searchViewLayoutData, federView) { + const { + k, + nprobe, + nodes, + topKNodes, + switchSearchViewHandlers, + targetMediaUrl + } = searchViewLayoutData; + const { switchVoronoi, switchPolar, switchProject } = switchSearchViewHandlers; + const { mediaCallback } = federView; + const fineAllVectorsCount = nodes.length; + const showImages = topKNodes.map(({ id: id2 }) => mediaCallback(id2)).filter((a2) => a2); + const items = [ + { + title: "IVF_Flat - Search" + }, + { + isImg: true, + imgUrl: targetMediaUrl + }, + { + isOption: true, + isActive: false, + label: "Coarse Search", + callback: switchVoronoi + }, + { + isOption: true, + isActive: true, + label: "Fine Search (Distance)", + callback: switchPolar + }, + { + isOption: true, + isActive: false, + label: "Fine Search (Project)", + callback: switchProject + }, + { + text: `Find the ${k} (k=${k}) vectors closest to the target from these ${nprobe} (nprobe=${nprobe}) clusters, ${fineAllVectorsCount} vectors in total.` + }, + { + images: showImages + } + ]; + this.renderOverviewPanel(items, whiteColor); + } + updateSearchViewFineProjectOverviewInfo(searchViewLayoutData, federView) { + const { + nprobe, + nodes, + topKNodes, + targetMediaUrl, + switchSearchViewHandlers + } = searchViewLayoutData; + const { switchVoronoi, switchPolar, switchProject } = switchSearchViewHandlers; + const { mediaCallback, viewParams } = federView; + const fineAllVectorsCount = nodes.length; + const showImages = topKNodes.map(({ id: id2 }) => mediaCallback(id2)).filter((a2) => a2); + const items = [ + { + title: "IVF_Flat - Search" + }, + { + isImg: true, + imgUrl: targetMediaUrl + }, + { + isOption: true, + isActive: false, + label: "Coarse Search", + callback: switchVoronoi + }, + { + isOption: true, + isActive: false, + label: "Fine Search (Distance)", + callback: switchPolar + }, + { + isOption: true, + isActive: true, + label: "Fine Search (Project)", + callback: switchProject + }, + { + text: `Projection of all ${fineAllVectorsCount} vectors in the ${nprobe} (nprobe=${nprobe}) clusters using ${viewParams.projectMethod || "random"}.` + }, + { + images: showImages + } + ]; + this.renderOverviewPanel(items, whiteColor); + } + initHoveredPanel() { + const dom = this.dom; + const hoveredPanel = document.createElement("div"); + hoveredPanel.setAttribute("id", hoveredPanelId2); + hoveredPanel.className = hoveredPanel.className + "panel-border panel hide"; + const hoveredPanelStyle = { + position: "absolute", + left: 0, + top: 0, + width: "200px", + pointerEvents: "none", + backgroundColor: panelBackgroundColor2 + }; + Object.assign(hoveredPanel.style, hoveredPanelStyle); + dom.appendChild(hoveredPanel); + } + updateOverviewHoveredInfo({ + hoveredCluster = null, + listIds = [], + images = [], + x: x3 = 0, + y: y4 = 0 + } = {}) { + const showImages = randomSelect(images, 9).filter((a2) => a2); + const items = hoveredCluster ? [ + { + title: `cluster-${hoveredCluster.clusterId}` + }, + { + text: `including ${listIds.length} vectors` + }, + { + images: showImages + } + ] : []; + this.renderHoveredPanel(items, ZYellow, x3, y4); + } + updateSearchViewHoveredInfo({ + hoveredCluster = null, + listIds = [], + images = [], + x: x3 = 0, + y: y4 = 0 + } = {}) { + if (!hoveredCluster) { + this.renderHoveredPanel(); + } else { + const showImages = randomSelect(images.filter((a2) => a2), 9); + const items = hoveredCluster ? [ + { + title: `cluster-${hoveredCluster.clusterId}` + }, + { + text: `including ${listIds.length} vectors` + }, + { + text: `distance from center: ${hoveredCluster.dis.toFixed(3)}` + }, + { + images: showImages + } + ] : []; + this.renderHoveredPanel(items, ZYellow, x3, y4); + } + } + updateSearchViewHoveredNodeInfo({ + hoveredNode = null, + img = "", + x: x3 = 0, + y: y4 = 0 + } = {}) { + if (!hoveredNode) { + this.renderHoveredPanel(); + } else { + const items = hoveredNode ? [ + { + title: `Row No. ${hoveredNode.id}` + }, + { + text: `belong to cluster-${hoveredNode.listId}` + }, + { + text: `distance the target: ${hoveredNode.dis.toFixed(3)}` + }, + { + isImg: true, + imgUrl: img + } + ] : []; + this.renderHoveredPanel(items, ZYellow, x3, y4); + } + } + initStyle() { + const style = document.createElement("style"); + style.type = "text/css"; + style.innerHTML = ` + .panel-border { + border-style: dashed; + border-width: 1px; + } + .panel { + padding: 6px 8px; + font-size: 12px; + } + .hide { + opacity: 0; + } + .panel-item { + margin-bottom: 6px; + } + .panel-img { + width: 150px; + height: 100px; + background-size: cover; + margin-bottom: 12px; + border-radius: 4px; + border: 1px solid ${ZYellow}; + } + .panel-item-display-flex { + display: flex; + } + .panel-item-title { + font-weight: 600; + margin-bottom: 3px; + } + .panel-item-text { + font-weight: 400; + font-size: 10px; + word-break: break-all; + } + .panel-item-text-flex { + margin-left: 8px; + } + .panel-item-text-margin { + margin: 0 6px; + } + .text-no-wrap { + white-space: nowrap; + } + .panel-img-gallery { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-row-gap: 8px; + grid-column-gap: 8px; + // flex-wrap: wrap; + } + .panel-img-gallery-item { + width: 100%; + height: 44px; + background-size: cover; + border-radius: 2px; + // border: 1px solid ${ZYellow}; + } + .panel-item-option { + display: flex; + align-items: center; + cursor: pointer; + // pointer-events: auto; + } + .panel-item-option-icon { + width: 6px; + height: 6px; + border-radius: 7px; + border: 2px solid ${ZYellow}; + margin-left: 2px; + } + .panel-item-option-icon-active { + background-color: ${ZYellow}; + } + .panel-item-option-label { + margin-left: 6px; + } + `; + document.getElementsByTagName("head").item(0).appendChild(style); + } + renderHoveredPanel(itemList = [], color2 = "#000", x3 = 0, y4 = 0) { + const panel = select_default2(this.dom).select(`#${hoveredPanelId2}`); + if (itemList.length === 0) + panel.classed("hide", true); + else { + panel.style("color", color2); + const isLeft = x3 > this.width * 0.7; + if (isLeft) { + panel.style("left", null); + panel.style("right", this.width - x3 - 10 + "px"); + } else { + panel.style("left", x3 + 10 + "px"); + panel.style("right", null); + } + const isTop = y4 > this.height * 0.7; + if (isTop) { + panel.style("top", null); + panel.style("bottom", this.height - y4 - 6 + "px"); + } else { + panel.style("top", y4 + 6 + "px"); + panel.style("bottom", null); + } + this.renderPanel(panel, itemList); + } + } + renderOverviewPanel(itemList = [], color2) { + const panel = select_default2(this.dom).select(`#${overviewPanelId2}`); + panel.style("color", color2); + if (itemList.length === 0) + panel.classed("hide", true); + else { + this.renderPanel(panel, itemList); + } + } + renderPanel(panel, itemList) { + panel.classed("hide", false); + panel.selectAll("*").remove(); + itemList.forEach((item) => { + const div = panel.append("div"); + div.classed("panel-item", true); + item.isFlex && div.classed("panel-item-display-flex", true); + if (item.isImg && item.imgUrl) { + div.classed("panel-img", true); + div.style("background-image", `url(${item.imgUrl})`); + } + if (item.title) { + const title = div.append("div"); + title.classed("panel-item-title", true); + title.text(item.title); + } + if (item.text) { + const title = div.append("div"); + title.classed("panel-item-text", true); + item.isFlex && title.classed("panel-item-text-flex", true); + item.textWithMargin && title.classed("panel-item-text-margin", true); + item.noWrap && title.classed("text-no-wrap", true); + title.text(item.text); + } + if (item.images) { + const imagesDiv = div.append("div"); + imagesDiv.classed("panel-img-gallery", true); + item.images.forEach((url2) => { + const imgItem = imagesDiv.append("div"); + imgItem.classed("panel-img-gallery-item", true); + imgItem.style("background-image", `url(${url2})`); + }); + } + if (item.isOption) { + const optionDiv = div.append("div"); + optionDiv.classed("panel-item-option", true); + const optionIcon = optionDiv.append("div"); + optionIcon.classed("panel-item-option-icon", true); + if (item.isActive) + optionIcon.classed("panel-item-option-icon-active", true); + else + optionIcon.classed("panel-item-option-icon-active", false); + const optionLabel = optionDiv.append("div"); + optionLabel.classed("panel-item-option-label", true); + optionLabel.text(item.label); + item.callback && optionDiv.on("click", item.callback); + } + }); + } + }; + + // federjs/FederView/IvfflatView/index.js + var defaultIvfflatViewParams = { + minVoronoiRadius: 4, + backgroundColor: "red", + voronoiStrokeWidth: 2, + targetNodeStrokeWidth: 5, + targetNodeR: 7, + topKNodeR: 5, + hoveredNodeR: 6, + hoveredNodeStrokeWidth: 1, + hoveredNodeOpacity: 1, + topKNodeOpacity: 0.7, + topKNodeStrokeWidth: 1, + nonTopKNodeR: 3, + nonTopKNodeOpacity: 0.4, + projectPadding: [20, 20, 20, 260], + axisTickCount: 5, + polarAxisStrokeWidth: 1, + polarAxisOpacity: 0.4, + polarOriginBias: 0.15, + ease: cubicInOut, + animateExitTime: 1500, + animateEnterTime: 1e3, + fineSearchNodeTransTime: 1200, + forceIterations: 100 + }; + var IvfflatView = class extends BaseView { + constructor({ indexMeta, viewParams, getVectorById }) { + super({ + viewParams, + getVectorById + }); + for (let key in defaultIvfflatViewParams) { + this[key] = key in viewParams ? viewParams[key] : defaultIvfflatViewParams[key]; + } + this.projectPadding = this.projectPadding.map((num) => num * this.canvasScale); + this.indexMeta = indexMeta; + this.overviewLayoutHandler(); + } + initInfoPanel(dom) { + const infoPanel = new InfoPanel2({ + dom, + width: this.clientWidth, + height: this.clientHeight + }); + return infoPanel; + } + overviewLayoutHandler() { + this.overviewLayoutPromise = overviewLayoutHandler2(this).then(({ clusters, voronoi }) => { + this.overviewLayoutData = { clusters, OVVoronoi: voronoi }; + }); + } + renderOverview(ctx, infoPanel) { + infoPanel.updateOverviewOverviewInfo(this); + renderVoronoiView(ctx, VIEW_TYPE.overview, this.overviewLayoutData, this); + } + getOverviewEventHandler(ctx, infoPanel) { + let hoveredClusterId = null; + const mouseLeaveHandler = () => { + hoveredClusterId = null; + renderVoronoiView(ctx, VIEW_TYPE.overview, this.overviewLayoutData, this); + infoPanel.updateOverviewHoveredInfo(); + }; + const mouseMoveHandler = ({ x: x3, y: y4 }) => { + const currentHoveredClusterId = mouse2node2({ + voronoi: this.overviewLayoutData.OVVoronoi, + x: x3, + y: y4 + }); + if (hoveredClusterId !== currentHoveredClusterId) { + hoveredClusterId = currentHoveredClusterId; + const hoveredCluster = this.overviewLayoutData.clusters.find((cluster) => cluster.clusterId == hoveredClusterId); + if (!!hoveredCluster) { + renderVoronoiView(ctx, VIEW_TYPE.overview, this.overviewLayoutData, this, hoveredCluster); + infoPanel.updateOverviewHoveredInfo({ + hoveredCluster, + listIds: this.indexMeta.listIds[hoveredClusterId], + images: this.mediaCallback ? this.indexMeta.listIds[hoveredClusterId].map((listId) => this.mediaCallback(listId)) : [], + x: hoveredCluster.OVPolyCentroid[0] / this.canvasScale, + y: hoveredCluster.OVPolyCentroid[1] / this.canvasScale + }); + } + } + }; + return { mouseLeaveHandler, mouseMoveHandler }; + } + searchViewHandler(searchRes) { + return __async(this, null, function* () { + this.overviewLayoutPromise && (yield this.overviewLayoutPromise); + const searchViewLayoutData = { + nprobe: searchRes.csResIds.length, + k: searchRes.fsResIds.length, + clusters: JSON.parse(JSON.stringify(this.overviewLayoutData.clusters)) + }; + searchViewLayoutData.nprobeClusters = searchViewLayoutData.clusters.filter((cluster) => searchRes.csResIds.indexOf(cluster.clusterId) >= 0); + searchViewLayoutData.nonNprobeClusters = searchViewLayoutData.clusters.filter((cluster) => searchRes.csResIds.indexOf(cluster.clusterId) < 0); + searchViewLayoutData.colorScheme = range(searchViewLayoutData.nprobe).map((i) => hsl(360 * i / searchViewLayoutData.nprobe, 1, 0.5).formatHex()); + yield searchViewLayoutHandler2(searchRes, searchViewLayoutData, this); + return searchViewLayoutData; + }); + } + renderSearchView(ctx, infoPanel, searchViewLayoutData, targetMediaUrl) { + searchViewLayoutData.targetMediaUrl = targetMediaUrl; + searchViewLayoutData.switchSearchViewHandlers = { + switchVoronoi: () => this.switchSearchView(SEARCH_VIEW_TYPE.voronoi, ctx, infoPanel, searchViewLayoutData), + switchPolar: () => this.switchSearchView(SEARCH_VIEW_TYPE.polar, ctx, infoPanel, searchViewLayoutData), + switchProject: () => this.switchSearchView(SEARCH_VIEW_TYPE.project, ctx, infoPanel, searchViewLayoutData) + }; + searchViewLayoutData.searchViewType = SEARCH_VIEW_TYPE.voronoi; + this.updateCoarseSearchInfoPanel(infoPanel, searchViewLayoutData); + this.renderCoarseSearch(ctx, searchViewLayoutData); + } + renderCoarseSearch(ctx, searchViewLayoutData) { + renderVoronoiView(ctx, VIEW_TYPE.search, searchViewLayoutData, this); + } + updateCoarseSearchInfoPanel(infoPanel, searchViewLayoutData) { + infoPanel.setOverviewPanelPos(!searchViewLayoutData.targetNode.isLeft_coarseLevel); + infoPanel.updateSearchViewCoarseOverviewInfo(searchViewLayoutData, this); + } + renderFineSearch(ctx, searchViewLayoutData, searchViewType = SEARCH_VIEW_TYPE.polar, hoveredNode) { + renderNodeView(ctx, searchViewLayoutData, this, searchViewType, hoveredNode); + } + updateFineSearchInfoPanel(infoPanel, searchViewLayoutData, searchViewType = SEARCH_VIEW_TYPE.polar) { + searchViewType === SEARCH_VIEW_TYPE.polar && infoPanel.updateSearchViewFinePolarOverviewInfo(searchViewLayoutData, this); + searchViewType === SEARCH_VIEW_TYPE.project && infoPanel.updateSearchViewFineProjectOverviewInfo(searchViewLayoutData, this); + } + switchSearchView(searchViewType, ctx, infoPanel, searchViewLayoutData) { + if (searchViewType == searchViewLayoutData.searchViewType) + return; + const oldSearchViewType = searchViewLayoutData.searchViewType; + const newSearchViewType = searchViewType; + if (oldSearchViewType === SEARCH_VIEW_TYPE.voronoi) { + this.updateFineSearchInfoPanel(infoPanel, searchViewLayoutData, newSearchViewType); + const endCallback = () => { + searchViewLayoutData.searchViewType = newSearchViewType; + this.renderFineSearch(ctx, searchViewLayoutData, newSearchViewType); + }; + animateCoarse2Fine(oldSearchViewType, newSearchViewType, ctx, searchViewLayoutData, this, endCallback); + } + if (newSearchViewType === SEARCH_VIEW_TYPE.voronoi) { + this.updateCoarseSearchInfoPanel(infoPanel, searchViewLayoutData); + const endCallback = () => { + searchViewLayoutData.searchViewType = newSearchViewType; + this.renderCoarseSearch(ctx, searchViewLayoutData); + }; + animateFine2Coarse(oldSearchViewType, newSearchViewType, ctx, searchViewLayoutData, this, endCallback); + } + if (newSearchViewType !== SEARCH_VIEW_TYPE.voronoi && oldSearchViewType !== SEARCH_VIEW_TYPE.voronoi) { + this.updateFineSearchInfoPanel(infoPanel, searchViewLayoutData, newSearchViewType); + const endCallback = () => { + searchViewLayoutData.searchViewType = newSearchViewType; + this.renderFineSearch(ctx, searchViewLayoutData, newSearchViewType); + }; + animateFine2Fine(oldSearchViewType, newSearchViewType, ctx, searchViewLayoutData, this, endCallback); + } + } + getSearchViewEventHandler(ctx, searchViewLayoutData, infoPanel) { + let hoveredClusterId = null; + let hoveredNode = null; + const mouseLeaveHandler = () => { + hoveredClusterId = null; + hoveredNode = null; + const { searchViewType } = searchViewLayoutData; + if (searchViewType === SEARCH_VIEW_TYPE.voronoi) { + renderVoronoiView(ctx, VIEW_TYPE.search, searchViewLayoutData, this); + infoPanel.updateSearchViewHoveredInfo(); + } else { + infoPanel.updateSearchViewHoveredNodeInfo(); + } + }; + const mouseMoveHandler = ({ x: x3, y: y4 }) => { + const { searchViewType, clusters, nodes } = searchViewLayoutData; + if (searchViewType === SEARCH_VIEW_TYPE.voronoi) { + const currentHoveredClusterId = mouse2node2({ + voronoi: searchViewLayoutData.SVVoronoi, + x: x3, + y: y4 + }); + if (hoveredClusterId !== currentHoveredClusterId) { + hoveredClusterId = currentHoveredClusterId; + const hoveredCluster = clusters.find((cluster) => cluster.clusterId == hoveredClusterId); + renderVoronoiView(ctx, VIEW_TYPE.search, searchViewLayoutData, this, hoveredCluster); + if (!!hoveredCluster) { + infoPanel.updateSearchViewHoveredInfo({ + hoveredCluster, + listIds: this.indexMeta.listIds[hoveredClusterId], + images: this.mediaCallback ? this.indexMeta.listIds[hoveredClusterId].map((listId) => this.mediaCallback(listId)) : [], + x: hoveredCluster.SVPolyCentroid[0] / this.canvasScale, + y: hoveredCluster.SVPolyCentroid[1] / this.canvasScale + }); + } + } + } else { + if (!nodes) + return; + const nodesPos = searchViewType === SEARCH_VIEW_TYPE.polar ? nodes.map((node) => node.polarPos) : nodes.map((node) => node.projectPos); + const hoveredNodeIndex = mouse2node3({ + nodesPos, + x: x3, + y: y4, + bias: (this.hoveredNodeR + 2) * this.canvasScale + }); + const currentHoveredNode = hoveredNodeIndex >= 0 ? nodes[hoveredNodeIndex] : null; + if (hoveredNode !== currentHoveredNode) { + hoveredNode = currentHoveredNode; + this.renderFineSearch(ctx, searchViewLayoutData, searchViewType, hoveredNode); + } + const img = hoveredNode && this.mediaCallback ? this.mediaCallback(hoveredNode.id) : ""; + infoPanel.updateSearchViewHoveredNodeInfo({ + hoveredNode, + img, + x: x3 / this.canvasScale, + y: y4 / this.canvasScale + }); + } + }; + return { mouseLeaveHandler, mouseMoveHandler }; + } + }; + + // federjs/FederView/index.js + var viewHandlerMap = { + [INDEX_TYPE.hnsw]: HnswView, + [INDEX_TYPE.ivf_flat]: IvfflatView + }; + var defaultViewParams = { + width: 1e3, + height: 600, + canvasScale: 3 + }; + var FederView = class { + constructor({ domSelector: domSelector2, viewParams }) { + this.domSelector = domSelector2; + this.viewParams = Object.assign({}, defaultViewParams, viewParams); + this.viewHandler = null; + initLoadingStyle(); + } + initDom() { + const dom = document.createElement("div"); + dom.id = `feder-dom-${Math.floor(Math.random() * 1e5)}`; + const { width, height } = this.viewParams; + const domStyle = { + position: "relative", + width: `${width}px`, + height: `${height}px` + }; + Object.assign(dom.style, domStyle); + renderLoading(dom, width, height); + if (this.domSelector) { + const domContainer = document.querySelector(this.domSelector); + domContainer.innerHTML = ""; + domContainer.appendChild(dom); + } + return dom; + } + initView({ indexType, indexMeta, getVectorById }) { + if (indexType in viewHandlerMap) { + this.view = new viewHandlerMap[indexType]({ + indexMeta, + viewParams: this.viewParams, + getVectorById + }); + } else + throw `No view handler for ${indexType}`; + } + overview(initCoreAndViewPromise) { + const dom = this.initDom(); + initCoreAndViewPromise.then(() => { + this.view.overview(dom); + }); + return dom; + } + search({ + searchRes = null, + targetMediaUrl = null, + searchResPromise = null + } = {}) { + const dom = this.initDom(); + if (searchResPromise) { + searchResPromise.then(({ searchRes: searchRes2, targetMediaUrl: targetMediaUrl2 }) => { + this.view.search(dom, { + searchRes: searchRes2, + targetMediaUrl: targetMediaUrl2 + }); + }); + } else { + this.view.search(dom, { + searchRes, + targetMediaUrl + }); + } + return dom; + } + switchSearchView(searchViewType) { + try { + this.view.switchSearchView(searchViewType); + } catch (e) { + console.log("Not Support", e); + } + } + }; + + // federjs/Feder.js + var Feder = class { + constructor({ + coreUrl: coreUrl2 = null, + filePath = "", + source = "", + domSelector: domSelector2 = null, + viewParams = {} + }) { + this.federView = new FederView({ domSelector: domSelector2, viewParams }); + this.viewParams = viewParams; + if (!coreUrl2) { + this.initCoreAndViewPromise = fetch(filePath, { mode: "cors" }).then((res) => res.arrayBuffer()).then((data) => { + const core = new FederCore({ data, source, viewParams }); + this.core = core; + const indexType = core.indexType; + const indexMeta = core.indexMeta; + const getVectorById = (id2) => id2 in core.id2vector ? core.id2vector[id2] : null; + this.core.getVectorById = getVectorById; + this.federView.initView({ + indexType, + indexMeta, + getVectorById + }); + }); + } else { + const getUrl = (path2) => `${coreUrl2}/${path2}?`; + const requestData = (path2, params = {}) => fetch(getUrl(path2) + new URLSearchParams(params), { + mode: "cors" + }).then((res) => res.json()).then((res) => { + if (res.message === "succeed") + return res.data; + else + throw new Error(res); + }); + this.initCoreAndViewPromise = new Promise((resolve) => __async(this, null, function* () { + const indexType = yield requestData(FEDER_CORE_REQUEST.get_index_type); + const indexMeta = yield requestData(FEDER_CORE_REQUEST.get_index_meta); + const getVectorById = (id2) => requestData(FEDER_CORE_REQUEST.get_vector_by_id, { id: id2 }); + this.core = { + indexType, + indexMeta, + getVectorById, + getTestIdAndVec: () => requestData(FEDER_CORE_REQUEST.get_test_id_and_vector), + search: (target) => requestData(FEDER_CORE_REQUEST.search, { target }), + setSearchParams: (params) => requestData(FEDER_CORE_REQUEST.set_search_params, params) + }; + this.federView.initView({ indexType, indexMeta, getVectorById }); + resolve(); + })); + } + this.setSearchParamsPromise = null; + } + overview() { + return this.federView.overview(this.initCoreAndViewPromise); + } + search(target = null, targetMediaUrl = null) { + if (target) { + const searchResPromise = Promise.all([ + this.initCoreAndViewPromise, + this.setSearchParamsPromise + ]).then(() => __async(this, null, function* () { + const searchRes = yield this.core.search(target); + console.log(searchRes); + this.searchRes = searchRes; + this.targetMediaUrl = targetMediaUrl; + return { searchRes, targetMediaUrl }; + })); + return this.federView.search({ searchResPromise }); + } else { + if (!this.searchRes) { + console.error("No target"); + return; + } + const searchRes = this.searchRes; + const targetMediaUrl2 = this.targetMediaUrl; + return this.federView.search({ searchRes, targetMediaUrl: targetMediaUrl2 }); + } + } + searchById(testId) { + const searchResPromise = this.initCoreAndViewPromise.then(() => __async(this, null, function* () { + const testVec = yield this.core.getVectorById(testId); + const targetMediaUrl = this.viewParams && this.viewParams.mediaCallback ? this.viewParams.mediaCallback(testId) : null; + const searchRes = yield this.core.search(testVec); + console.log(searchRes); + this.searchRes = searchRes; + return { searchRes, targetMediaUrl }; + })); + return this.federView.search({ searchResPromise }); + } + searchRandTestVec() { + const searchResPromise = new Promise((resolve) => __async(this, null, function* () { + this.initCoreAndViewPromise && (yield this.initCoreAndViewPromise); + let { testId, testVec } = yield this.core.getTestIdAndVec(); + while (isNaN(testId)) { + [testId, testVec] = yield this.core.getTestIdAndVec(); + } + console.log("random test vector:", testId, testVec); + const targetMediaUrl = this.viewParams && this.viewParams.mediaCallback ? this.viewParams.mediaCallback(testId) : null; + const searchRes = yield this.core.search(testVec); + console.log(searchRes); + this.searchRes = searchRes; + resolve({ searchRes, targetMediaUrl }); + })); + return this.federView.search({ searchResPromise }); + } + setSearchParams(params) { + this.setSearchParamsPromise = new Promise((resolve) => __async(this, null, function* () { + this.initCoreAndViewPromise && (yield this.initCoreAndViewPromise); + if (!this.core) { + console.error("No feder-core"); + } else { + yield this.core.setSearchParams(params); + } + resolve(); + })); + return this; + } + }; + + // test/test_core_node.js + var url = "http://localhost"; + var port = 1332; + var coreUrl = `${url}:${port}`; + var domSelector = "#container"; + window.addEventListener("DOMContentLoaded", () => __async(void 0, null, function* () { + const rowId2imgUrl = yield getRowId2imgUrl(); + const feder = new Feder({ + coreUrl, + viewParams: { + mediaType: "img", + mediaCallback: rowId2imgUrl + } + }); + document.querySelector(domSelector).appendChild(feder.overview()); + document.querySelector(domSelector).appendChild(feder.setSearchParams({ k: 9, nprobe: 8, ef: 6 }).searchById(14383)); + document.querySelector(domSelector).appendChild(feder.setSearchParams({ k: 12, nprobe: 10, ef: 8 }).searchRandTestVec()); + })); +})(); diff --git a/test_old/config.js b/test_old/config.js new file mode 100644 index 0000000..23d3d96 --- /dev/null +++ b/test_old/config.js @@ -0,0 +1,31 @@ +import * as d3 from 'd3'; +export const hnswSource = 'hnswlib'; + +const local = false; + +export const hnswIndexFilePath = local + ? 'data/hnswlib_hnsw_voc_17k.index' + : 'https://assets.zilliz.com/hnswlib_hnsw_voc_17k_1f1dfd63a9.index'; + +export const ivfflatSource = 'faiss'; +export const ivfflatIndexFilePath = local + ? 'data/faiss_ivf_flat_voc_17k.index' + : 'https://assets.zilliz.com/faiss_ivf_flat_voc_17k_ab112eec72.index'; + +export const imgNamesFilePath = + 'https://assets.zilliz.com/voc_names_4cee9440b1.csv'; + +export const getRowId2name = async () => { + const data = await d3.csv(imgNamesFilePath); + const rowId2name = (rowId) => data[rowId].name; + return rowId2name; +}; +export const name2imgUrl = (name) => + `https://assets.zilliz.com/voc2012/JPEGImages/${name}`; +// export const name2imgUrl = (name) => `http://[::]:6000/${name}`; + +export const getRowId2imgUrl = async () => { + const rowId2name = await getRowId2name(); + const rowId2imgUrl = (rowId) => name2imgUrl(rowId2name(rowId)); + return rowId2imgUrl; +}; diff --git a/test_old/data/gen_faiss_index_random.py b/test_old/data/gen_faiss_index_random.py new file mode 100644 index 0000000..9b7042d --- /dev/null +++ b/test_old/data/gen_faiss_index_random.py @@ -0,0 +1,26 @@ +# 2021-1-7 + +import faiss +import numpy as np +d = 60 # dimension +nb = 100000 # database size +nq = 10 # nb of queries +np.random.seed(1234) # make reproducible +xb = np.random.random((nb, d)).astype('float32') +xb[:, 0] += np.arange(nb) / 1000. +xq = np.random.random((nq, d)).astype('float32') +xq[:, 0] += np.arange(nq) / 1000. + + +nlist = 510 +index = faiss.index_factory(d, 'IVF%s,Flat' % nlist) +index.train(xb) +index.add(xb) +index.nprobe = 15 + +D, I = index.search(xq, 5) +print(I) + +faiss.write_index(index, 'faiss_ivf_flat.index') + +# index = faiss.read_index('faiss_ivf_flat.index') \ No newline at end of file diff --git a/test_old/data/gen_faiss_index_voc.py b/test_old/data/gen_faiss_index_voc.py new file mode 100644 index 0000000..4c79892 --- /dev/null +++ b/test_old/data/gen_faiss_index_voc.py @@ -0,0 +1,25 @@ +import csv +import json +import numpy as np +import faiss + +with open("voc_vectors.csv") as f: + _data = csv.DictReader(f) + data = [row for row in _data] + vectors = [np.array(json.loads(d['vector']), dtype='float32') + for d in data] + num_elements = len(vectors) + dim = len(vectors[0]) + print(num_elements, dim) + + nlist = 200 + index = faiss.index_factory(dim, 'IVF%s,Flat' % nlist) + vectors = np.array(vectors) + index.train(vectors[:num_elements // 3]) + index.add(vectors) + + D, I = index.search(vectors[5:6], 5) + print(D) + print(I) + + faiss.write_index(index, 'faiss_ivf_flat_voc_17k_train_33%.index') diff --git a/test_old/data/gen_hnswlib_index_random.py b/test_old/data/gen_hnswlib_index_random.py new file mode 100644 index 0000000..4489a11 --- /dev/null +++ b/test_old/data/gen_hnswlib_index_random.py @@ -0,0 +1,28 @@ +import hnswlib +import numpy as np + +dim = 8 +num_elements = int(1e6) + +data = np.float32(np.random.random((num_elements, dim))) +labels = np.int32(np.random.randint( + num_elements, num_elements * 2, size=(num_elements))) + +index = hnswlib.Index(space='l2', dim=dim) + +index.init_index(max_elements=num_elements + 20000, ef_construction=32, M=8) +# index.init_index(max_elements=num_elements + 20000, ef_construction=100, M=32) + +index.set_ef(10) + +index.set_num_threads(4) + +# index.add_items(data, labels) +index.add_items(data) + +# index.mark_deleted(1) +# index.mark_deleted(3567) + +index_path = 'hnswlib_hnsw_random_1M.index' + +index.save_index(index_path) diff --git a/test_old/data/gen_hnswlib_index_voc.py b/test_old/data/gen_hnswlib_index_voc.py new file mode 100644 index 0000000..1e56491 --- /dev/null +++ b/test_old/data/gen_hnswlib_index_voc.py @@ -0,0 +1,32 @@ +import csv +import json +import numpy as np +import hnswlib + +with open("voc_vectors.csv") as f: + _data = csv.DictReader(f) + data = [row for row in _data] + vectors = [np.array(json.loads(d['vector']), dtype='float32') + for d in data] + num_elements = len(vectors) + dim = len(vectors[0]) + print(num_elements, dim) + + index = hnswlib.Index(space='l2', dim=dim) + + # index.init_index(max_elements=num_elements + 20000, ef_construction=32, M=8) + index.init_index(max_elements=num_elements + 20000, ef_construction=100, M=8) + + index.set_ef(10) + + index.set_num_threads(4) + + index.add_items(vectors) + + index_path = 'hnswlib_hnsw_voc_17k.index' + + index.save_index(index_path) + + labels, distances = index.knn_query(vectors[0], 5) + print(labels) + print(distances) diff --git a/test_old/index.html b/test_old/index.html new file mode 100644 index 0000000..9ff1989 --- /dev/null +++ b/test_old/index.html @@ -0,0 +1,17 @@ + + + + + + + + Feder view test + + + + +
+
+ + + \ No newline at end of file diff --git a/test_old/nodeServer/index.js b/test_old/nodeServer/index.js new file mode 100644 index 0000000..4ec509f --- /dev/null +++ b/test_old/nodeServer/index.js @@ -0,0 +1,52 @@ +import express from 'express'; +import cors from 'cors'; +import getFederCore from './initFederCore.js.js'; + +import { coreNodePort } from '../config.js.js'; + +const app = express(); +app.use(cors()); + +const core = await getFederCore(); + +const successData = (data) => ({ code: 200, data }); + +app.get('/', (req, res) => { + console.log(req.query); + res.send(successData('get it~')); +}); + +app.get('/get_index_type', (_, res) => { + res.json(successData(core.indexType)); +}); + +app.get('/get_index_meta', (_, res) => { + res.json(successData(core.indexMeta)); +}); + +app.get('/get_test_id_and_vector', (_, res) => { + let [testId, testVec] = core.getTestIdAndVec(); + while (isNaN(testId)) { + [testId, testVec] = core.getTestIdAndVec(); + } + res.json(successData({ testId, testVec: Array.from(testVec) })); +}); + +app.get('/get_vector_by_id', (req, res) => { + const { id } = req.query; + res.json(successData(Array.from(core.id2vector[id] || []))); +}); + +app.get('/search', (req, res) => { + const { target } = req.query; + res.json(successData(core.search(target))); +}); + +app.get('/set_search_params', (req, res) => { + core.setSearchParams(req.query); + res.json(successData('ok')); +}); + +app.listen(coreNodePort, () => { + console.log('listening on port', coreNodePort); +}); diff --git a/test_old/testHnsw.js b/test_old/testHnsw.js new file mode 100644 index 0000000..9391689 --- /dev/null +++ b/test_old/testHnsw.js @@ -0,0 +1,27 @@ +import { Feder } from ''; +import { hnswSource, hnswIndexFilePath, getRowId2imgUrl } from './config'; + +export const getFederHnswLite = () => { + const feder = new Feder({ + source: hnswSource, + filePath: hnswIndexFilePath, + }); + + return feder; +}; + +// Show the corresponding images +export const getFederHnsw = async () => { + const rowId2imgUrl = await getRowId2imgUrl(); + + const feder = new Feder({ + source: hnswSource, + filePath: hnswIndexFilePath, + viewParams: { + mediaType: 'img', + mediaCallback: rowId2imgUrl, + }, + }); + + return feder; +}; diff --git a/test_old/testIvfflat.js b/test_old/testIvfflat.js new file mode 100644 index 0000000..7c90c32 --- /dev/null +++ b/test_old/testIvfflat.js @@ -0,0 +1,27 @@ +import { Feder } from ''; +import { ivfflatSource, ivfflatIndexFilePath, getRowId2imgUrl } from './config'; + +export const getFederIvfflatLite = () => { + const feder = new Feder({ + source: ivfflatSource, + filePath: ivfflatIndexFilePath, + }); + + return feder; +}; + +// Show the corresponding images +export const getFederIvfflat = async () => { + const rowId2imgUrl = await getRowId2imgUrl(); + + const feder = new Feder({ + source: ivfflatSource, + filePath: ivfflatIndexFilePath, + viewParams: { + mediaType: 'img', + mediaCallback: rowId2imgUrl, + }, + }); + + return feder; +}; diff --git a/test_old/test_core_browser.js b/test_old/test_core_browser.js new file mode 100644 index 0000000..277685f --- /dev/null +++ b/test_old/test_core_browser.js @@ -0,0 +1,31 @@ +import { getFederHnswLite, getFederHnsw } from './testHnsw'; +import { getFederIvfflatLite, getFederIvfflat } from './testIvfflat'; +import * as d3 from 'd3'; + +const domSelector = '#container'; +window.addEventListener('DOMContentLoaded', async () => { + // const hnsw_feder = getFederHnswLite(); // without images mapping. + const hnsw_feder = await getFederHnsw(); + + document.querySelector(domSelector).appendChild(hnsw_feder.overview()); + + // randomly select an internal vector as the target + document + .querySelector(domSelector) + .appendChild( + hnsw_feder.setSearchParams({ k: 6, nprobe: 8, ef: 9 }).searchRandTestVec() + ); + + // const ivfflat_feder = getFederIvfflatLite(); // without images mapping. + const ivfflat_feder = await getFederIvfflat(); + + document.querySelector(domSelector).appendChild(ivfflat_feder.overview()); + // select the specified vector as the target + document + .querySelector(domSelector) + .appendChild( + ivfflat_feder + .setSearchParams({ k: 9, nprobe: 8, ef: 6 }) + .searchById(14383) + ); +}); diff --git a/test_old/test_core_node.js b/test_old/test_core_node.js new file mode 100644 index 0000000..f499b95 --- /dev/null +++ b/test_old/test_core_node.js @@ -0,0 +1,34 @@ +import { getRowId2imgUrl } from './config.js'; +import { Feder } from ''; + +const url = 'http://localhost'; +const port = 1332; +const coreUrl = `${url}:${port}`; + +const domSelector = '#container'; + +window.addEventListener('DOMContentLoaded', async () => { + const rowId2imgUrl = await getRowId2imgUrl(); + + const feder = new Feder({ + coreUrl, + viewParams: { + mediaType: 'img', + mediaCallback: rowId2imgUrl, + }, + }); + + document.querySelector(domSelector).appendChild(feder.overview()); + // select the specified vector as the target + document + .querySelector(domSelector) + .appendChild( + feder.setSearchParams({ k: 9, nprobe: 8, ef: 6 }).searchById(14383) + ); + // random select + document + .querySelector(domSelector) + .appendChild( + feder.setSearchParams({ k: 12, nprobe: 10, ef: 8 }).searchRandTestVec() + ); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..0e8f435 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es6", + "baseUrl": "federjs", + "moduleResolution": "node" + }, + "include": ["federjs"] +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..8f106c9 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1389 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/parser@^7.12.5": + version "7.18.3" + resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.18.3.tgz#39e99c7b0c4c56cef4d1eed8de9f506411c2ebc2" + integrity sha512-rL50YcEuHbbauAFAysNsJA4/f89fGTOBRNs9P81sniKnKAr4xULe5AecolcsKbi88xu0ByWYDj/S1AJ3FSFuSQ== + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.npmmirror.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jridgewell/resolve-uri@^3.0.3": + version "3.0.7" + resolved "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" + integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.13" + resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" + integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== + +"@jridgewell/trace-mapping@^0.3.7": + version "0.3.13" + resolved "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" + integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@types/animejs@^3.1.5": + version "3.1.5" + resolved "https://registry.npmmirror.com/@types/animejs/-/animejs-3.1.5.tgz#3cb6c7b90069c6e2969a392eb65ec6311e92c1ab" + integrity sha512-4i3i1YuNaNEPoHBJY78uzYu8qKIwyx96G04tnVtNhRMQC9I1Xhg6fY9GeWmZAzudaesKKrPkQgTCthT1zSGYyg== + +"@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.npmmirror.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/three@^0.143.2": + version "0.143.2" + resolved "https://registry.npmmirror.com/@types/three/-/three-0.143.2.tgz#e3c3d121cbe6b868e226d91ea24896b7cdc5d4eb" + integrity sha512-HjsRWvd6rsXViFeOdU97/pHNDQknzJbFI0/5MrQ0joOlK0uixQH40sDJs/LwkNHhFYUvVENXAUQdKDeiQChHDw== + dependencies: + "@types/webxr" "*" + +"@types/webxr@*": + version "0.5.0" + resolved "https://registry.npmmirror.com/@types/webxr/-/webxr-0.5.0.tgz#aae1cef3210d88fd4204f8c33385a0bbc4da07c9" + integrity sha512-IUMDPSXnYIbEO2IereEFcgcqfDREOgmbGqtrMpVPpACTU6pltYLwHgVkrnYv0XhWEcjio9sYEfIEzgn3c7nDqA== + +"@zilliz/feder@^0.2.4": + version "0.2.4" + resolved "https://registry.npmmirror.com/@zilliz/feder/-/feder-0.2.4.tgz#c4d72d952dca67e3000f126b1850838f31336e03" + integrity sha512-p2ccl4/ZAEEwhbMRJejpNFEp3x1guZKLg/2IUVUBAvSQzDGUPHmZC9tqUURybdymxQAhySOtkcKSlO+4ptZhHA== + dependencies: + d3 "^7.4.4" + d3-fetch "^3.0.1" + seedrandom "^3.0.5" + tsne-js "^1.0.3" + umap-js "^1.3.3" + +acorn@^7.1.1: + version "7.4.1" + resolved "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.npmmirror.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + integrity sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg== + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.npmmirror.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== + +animejs@^3.2.1: + version "3.2.1" + resolved "https://registry.npmmirror.com/animejs/-/animejs-3.2.1.tgz#de9fe2e792f44a777a7fdf6ae160e26604b0cdda" + integrity sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ascjs@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/ascjs/-/ascjs-5.0.1.tgz#c32fc91945e5d816ffbe63c7f787d6516ad40a12" + integrity sha512-1d/QdICzpywXiP53/Zz3fMdaC0/BB1ybLf+fK+QrqY8iyXNnWUHUrpmrowueXeswo+O+meJWm43TJSg2ClP3Sg== + dependencies: + "@babel/parser" "^7.12.5" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +c8@^7.11.2: + version "7.11.3" + resolved "https://registry.npmmirror.com/c8/-/c8-7.11.3.tgz#88c8459c1952ed4f701b619493c9ae732b057163" + integrity sha512-6YBmsaNmqRm9OS3ZbIiL2EZgi1+Xc4O24jL3vMYGE6idixYuGdy76rIfIdltSKDj9DpLNrcXSonUTR1miBD0wA== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@istanbuljs/schema" "^0.1.3" + find-up "^5.0.0" + foreground-child "^2.0.0" + istanbul-lib-coverage "^3.2.0" + istanbul-lib-report "^3.0.0" + istanbul-reports "^3.1.4" + rimraf "^3.0.2" + test-exclude "^6.0.0" + v8-to-istanbul "^9.0.0" + yargs "^16.2.0" + yargs-parser "^20.2.9" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.npmmirror.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + integrity sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g== + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.npmmirror.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + integrity sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ== + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + integrity sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA== + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commander@7: + version "7.2.0" + resolved "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@~1.6.0: + version "1.6.2" + resolved "https://registry.npmmirror.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +convert-source-map@^1.6.0: + version "1.8.0" + resolved "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cross-spawn@^7.0.0: + version "7.0.3" + resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cwise-compiler@^1.0.0, cwise-compiler@^1.1.1, cwise-compiler@^1.1.2: + version "1.1.3" + resolved "https://registry.npmmirror.com/cwise-compiler/-/cwise-compiler-1.1.3.tgz#f4d667410e850d3a313a7d2db7b1e505bb034cc5" + integrity sha512-WXlK/m+Di8DMMcCjcWr4i+XzcQra9eCdXIJrgh4TUgh0pIS/yJduLxS9JgefsHJ/YVLdgPtXm9r62W92MvanEQ== + dependencies: + uniq "^1.0.0" + +cwise-parser@^1.0.0: + version "1.0.3" + resolved "https://registry.npmmirror.com/cwise-parser/-/cwise-parser-1.0.3.tgz#8e493c17d54f97cb030a9e9854bc86c9dfb354fe" + integrity sha512-nAe238ctwjt9l5exq9CQkHS1Tj6YRGAQxqfL4VaN1B2oqG1Ss0VVqIrBG/vyOgN301PI22wL6ZIhe/zA+BO56Q== + dependencies: + esprima "^1.0.3" + uniq "^1.0.0" + +cwise@^1.0.1, cwise@^1.0.9: + version "1.0.10" + resolved "https://registry.npmmirror.com/cwise/-/cwise-1.0.10.tgz#24eee6072ebdfd6b8c6f5dadb17090b649b12bef" + integrity sha512-4OQ6FXVTRO2bk/OkIEt0rNqDk63aOv3Siny6ZD2/WN9CH7k8X6XyQdcip4zKg1WG+L8GP5t2zicXbDb+H7Y77Q== + dependencies: + cwise-compiler "^1.1.1" + cwise-parser "^1.0.0" + static-module "^1.0.0" + uglify-js "^2.6.0" + +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3: + version "3.1.6" + resolved "https://registry.npmmirror.com/d3-array/-/d3-array-3.1.6.tgz#0342c835925826f49b4d16eb7027aec334ffc97d" + integrity sha512-DCbBBNuKOeiR9h04ySRBMW52TFVc91O9wJziuyXw6Ztmy8D3oZbmCkOO3UHKC7ceNJsN2Mavo9+vwV8EAEUXzA== + dependencies: + internmap "1 - 2" + +d3-axis@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" + integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== + +d3-brush@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" + integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "3" + d3-transition "3" + +d3-chord@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" + integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== + dependencies: + d3-path "1 - 3" + +"d3-color@1 - 3", d3-color@3: + version "3.1.0" + resolved "https://registry.npmmirror.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +d3-contour@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-contour/-/d3-contour-3.0.1.tgz#2c64255d43059599cd0dba8fe4cc3d51ccdd9bbd" + integrity sha512-0Oc4D0KyhwhM7ZL0RMnfGycLN7hxHB8CMmwZ3+H26PWAG0ozNuYG5hXSDNgmP1SgJkQMrlG6cP20HoaSbvcJTQ== + dependencies: + d3-array "2 - 3" + +d3-delaunay@6: + version "6.0.2" + resolved "https://registry.npmmirror.com/d3-delaunay/-/d3-delaunay-6.0.2.tgz#7fd3717ad0eade2fc9939f4260acfb503f984e92" + integrity sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ== + dependencies: + delaunator "5" + +"d3-dispatch@1 - 3", d3-dispatch@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" + integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== + +"d3-drag@2 - 3", d3-drag@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" + integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + +"d3-dsv@1 - 3", d3-dsv@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" + integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== + dependencies: + commander "7" + iconv-lite "0.6" + rw "1" + +"d3-ease@1 - 3", d3-ease@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +d3-fetch@3, d3-fetch@^3.0.1: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" + integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== + dependencies: + d3-dsv "1 - 3" + +d3-force@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" + integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== + dependencies: + d3-dispatch "1 - 3" + d3-quadtree "1 - 3" + d3-timer "1 - 3" + +"d3-format@1 - 3", d3-format@3: + version "3.1.0" + resolved "https://registry.npmmirror.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + +d3-geo@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-geo/-/d3-geo-3.0.1.tgz#4f92362fd8685d93e3b1fae0fd97dc8980b1ed7e" + integrity sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA== + dependencies: + d3-array "2.5.0 - 3" + +d3-hierarchy@3: + version "3.1.2" + resolved "https://registry.npmmirror.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6" + integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA== + +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +"d3-path@1 - 3", d3-path@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e" + integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w== + +d3-polygon@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" + integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== + +"d3-quadtree@1 - 3", d3-quadtree@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" + integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== + +d3-random@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" + integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== + +d3-scale-chromatic@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a" + integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + +d3-scale@4: + version "4.0.2" + resolved "https://registry.npmmirror.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +"d3-selection@2 - 3", d3-selection@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + +d3-shape@3: + version "3.1.0" + resolved "https://registry.npmmirror.com/d3-shape/-/d3-shape-3.1.0.tgz#c8a495652d83ea6f524e482fca57aa3f8bc32556" + integrity sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ== + dependencies: + d3-path "1 - 3" + +"d3-time-format@2 - 4", d3-time-format@4: + version "4.1.0" + resolved "https://registry.npmmirror.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975" + integrity sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ== + dependencies: + d3-array "2 - 3" + +"d3-timer@1 - 3", d3-timer@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + +"d3-transition@2 - 3", d3-transition@3: + version "3.0.1" + resolved "https://registry.npmmirror.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" + integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== + dependencies: + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + +d3-zoom@3: + version "3.0.0" + resolved "https://registry.npmmirror.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + +d3@^7.4.4: + version "7.4.4" + resolved "https://registry.npmmirror.com/d3/-/d3-7.4.4.tgz#bfbf87487c37d3196efebd5a63e3a0ed8299d8ff" + integrity sha512-97FE+MYdAlV3R9P74+R3Uar7wUKkIFu89UWMjEaDhiJ9VxKvqaMxauImy8PC2DdBkdM2BxJOIoLxPrcZUyrKoQ== + dependencies: + d3-array "3" + d3-axis "3" + d3-brush "3" + d3-chord "3" + d3-color "3" + d3-contour "3" + d3-delaunay "6" + d3-dispatch "3" + d3-drag "3" + d3-dsv "3" + d3-ease "3" + d3-fetch "3" + d3-force "3" + d3-format "3" + d3-geo "3" + d3-hierarchy "3" + d3-interpolate "3" + d3-path "3" + d3-polygon "3" + d3-quadtree "3" + d3-random "3" + d3-scale "4" + d3-scale-chromatic "3" + d3-selection "3" + d3-shape "3" + d3-time "3" + d3-time-format "4" + d3-timer "3" + d3-transition "3" + d3-zoom "3" + +decamelize@^1.0.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +delaunator@5: + version "5.0.0" + resolved "https://registry.npmmirror.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b" + integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw== + dependencies: + robust-predicates "^3.0.0" + +dup@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/dup/-/dup-1.0.0.tgz#51fc5ac685f8196469df0b905e934b20af5b4029" + integrity sha512-Bz5jxMMC0wgp23Zm15ip1x8IhYRqJvF3nFC0UInJUDkN1z4uNPk9jTnfCUJXbOGiQ1JbXLQsiV41Fb+HXcj5BA== + +duplexer2@~0.0.2: + version "0.0.2" + resolved "https://registry.npmmirror.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + integrity sha512-+AWBwjGadtksxjOQSFDhPNQbed7icNXApT4+2BNpsXzcCBiInq2H9XW0O8sfHFaPmnQRs7cg/P0fAr2IWQSW0g== + dependencies: + readable-stream "~1.1.9" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +esbuild-android-64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.42.tgz#d7ab3d44d3671218d22bce52f65642b12908d954" + integrity sha512-P4Y36VUtRhK/zivqGVMqhptSrFILAGlYp0Z8r9UQqHJ3iWztRCNWnlBzD9HRx0DbueXikzOiwyOri+ojAFfW6A== + +esbuild-android-arm64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.42.tgz#45336d8bec49abddb3a022996a23373f45a57c27" + integrity sha512-0cOqCubq+RWScPqvtQdjXG3Czb3AWI2CaKw3HeXry2eoA2rrPr85HF7IpdU26UWdBXgPYtlTN1LUiuXbboROhg== + +esbuild-darwin-64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.42.tgz#6dff5e44cd70a88c33323e2f5fb598e40c68a9e0" + integrity sha512-ipiBdCA3ZjYgRfRLdQwP82rTiv/YVMtW36hTvAN5ZKAIfxBOyPXY7Cejp3bMXWgzKD8B6O+zoMzh01GZsCuEIA== + +esbuild-darwin-arm64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.42.tgz#2c7313e1b12d2fa5b889c03213d682fb92ca8c4f" + integrity sha512-bU2tHRqTPOaoH/4m0zYHbFWpiYDmaA0gt90/3BMEFaM0PqVK/a6MA2V/ypV5PO0v8QxN6gH5hBPY4YJ2lopXgA== + +esbuild-freebsd-64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.42.tgz#ad1c5a564a7e473b8ce95ee7f76618d05d6daffc" + integrity sha512-75h1+22Ivy07+QvxHyhVqOdekupiTZVLN1PMwCDonAqyXd8TVNJfIRFrdL8QmSJrOJJ5h8H1I9ETyl2L8LQDaw== + +esbuild-freebsd-arm64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.42.tgz#4bdb480234144f944f1930829bace7561135ddc7" + integrity sha512-W6Jebeu5TTDQMJUJVarEzRU9LlKpNkPBbjqSu+GUPTHDCly5zZEQq9uHkmHHl7OKm+mQ2zFySN83nmfCeZCyNA== + +esbuild-linux-32@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-linux-32/-/esbuild-linux-32-0.14.42.tgz#ef18fd19f067e9d2b5f677d6b82fa81519f5a8c2" + integrity sha512-Ooy/Bj+mJ1z4jlWcK5Dl6SlPlCgQB9zg1UrTCeY8XagvuWZ4qGPyYEWGkT94HUsRi2hKsXvcs6ThTOjBaJSMfg== + +esbuild-linux-64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-linux-64/-/esbuild-linux-64-0.14.42.tgz#d84e7333b1c1b22cf8b5b9dbb5dd9b2ecb34b79f" + integrity sha512-2L0HbzQfbTuemUWfVqNIjOfaTRt9zsvjnme6lnr7/MO9toz/MJ5tZhjqrG6uDWDxhsaHI2/nsDgrv8uEEN2eoA== + +esbuild-linux-arm64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.42.tgz#dc19e282f8c4ffbaa470c02a4d171e4ae0180cca" + integrity sha512-c3Ug3e9JpVr8jAcfbhirtpBauLxzYPpycjWulD71CF6ZSY26tvzmXMJYooQ2YKqDY4e/fPu5K8bm7MiXMnyxuA== + +esbuild-linux-arm@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.42.tgz#d49870e63e2242b8156bf473f2ee5154226be328" + integrity sha512-STq69yzCMhdRaWnh29UYrLSr/qaWMm/KqwaRF1pMEK7kDiagaXhSL1zQGXbYv94GuGY/zAwzK98+6idCMUOOCg== + +esbuild-linux-mips64le@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.42.tgz#f4e6ff9bf8a6f175470498826f48d093b054fc22" + integrity sha512-QuvpHGbYlkyXWf2cGm51LBCHx6eUakjaSrRpUqhPwjh/uvNUYvLmz2LgPTTPwCqaKt0iwL+OGVL0tXA5aDbAbg== + +esbuild-linux-ppc64le@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.42.tgz#ac9c66fc80ba9f8fda15a4cc08f4e55f6c0aed63" + integrity sha512-8ohIVIWDbDT+i7lCx44YCyIRrOW1MYlks9fxTo0ME2LS/fxxdoJBwHWzaDYhjvf8kNpA+MInZvyOEAGoVDrMHg== + +esbuild-linux-riscv64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.42.tgz#21e0ae492a3a9bf4eecbfc916339a66e204256d0" + integrity sha512-DzDqK3TuoXktPyG1Lwx7vhaF49Onv3eR61KwQyxYo4y5UKTpL3NmuarHSIaSVlTFDDpcIajCDwz5/uwKLLgKiQ== + +esbuild-linux-s390x@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.42.tgz#06d40b957250ffd9a2183bfdfc9a03d6fd21b3e8" + integrity sha512-YFRhPCxl8nb//Wn6SiS5pmtplBi4z9yC2gLrYoYI/tvwuB1jldir9r7JwAGy1Ck4D7sE7wBN9GFtUUX/DLdcEQ== + +esbuild-netbsd-64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.42.tgz#185664f05f10914f14ed43bd9e22b7de584267f7" + integrity sha512-QYSD2k+oT9dqB/4eEM9c+7KyNYsIPgzYOSrmfNGDIyJrbT1d+CFVKvnKahDKNJLfOYj8N4MgyFaU9/Ytc6w5Vw== + +esbuild-openbsd-64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.42.tgz#c29006f659eb4e55283044bbbd4eb4054fae8839" + integrity sha512-M2meNVIKWsm2HMY7+TU9AxM7ZVwI9havdsw6m/6EzdXysyCFFSoaTQ/Jg03izjCsK17FsVRHqRe26Llj6x0MNA== + +esbuild-sunos-64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.42.tgz#aa9eec112cd1e7105e7bb37000eca7d460083f8f" + integrity sha512-uXV8TAZEw36DkgW8Ak3MpSJs1ofBb3Smkc/6pZ29sCAN1KzCAQzsje4sUwugf+FVicrHvlamCOlFZIXgct+iqQ== + +esbuild-windows-32@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-windows-32/-/esbuild-windows-32-0.14.42.tgz#c3fc450853c61a74dacc5679de301db23b73e61e" + integrity sha512-4iw/8qWmRICWi9ZOnJJf9sYt6wmtp3hsN4TdI5NqgjfOkBVMxNdM9Vt3626G1Rda9ya2Q0hjQRD9W1o+m6Lz6g== + +esbuild-windows-64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-windows-64/-/esbuild-windows-64-0.14.42.tgz#b877aa37ff47d9fcf0ccb1ca6a24b31475a5e555" + integrity sha512-j3cdK+Y3+a5H0wHKmLGTJcq0+/2mMBHPWkItR3vytp/aUGD/ua/t2BLdfBIzbNN9nLCRL9sywCRpOpFMx3CxzA== + +esbuild-windows-arm64@0.14.42: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.42.tgz#79da8744626f24bc016dc40d016950b5a4a2bac5" + integrity sha512-+lRAARnF+hf8J0mN27ujO+VbhPbDqJ8rCcJKye4y7YZLV6C4n3pTRThAb388k/zqF5uM0lS5O201u0OqoWSicw== + +esbuild@^0.14.38: + version "0.14.42" + resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.42.tgz#98587df0b024d5f6341b12a1d735a2bff55e1836" + integrity sha512-V0uPZotCEHokJdNqyozH6qsaQXqmZEOiZWrXnds/zaH/0SyrIayRXWRB98CENO73MIZ9T3HBIOsmds5twWtmgw== + optionalDependencies: + esbuild-android-64 "0.14.42" + esbuild-android-arm64 "0.14.42" + esbuild-darwin-64 "0.14.42" + esbuild-darwin-arm64 "0.14.42" + esbuild-freebsd-64 "0.14.42" + esbuild-freebsd-arm64 "0.14.42" + esbuild-linux-32 "0.14.42" + esbuild-linux-64 "0.14.42" + esbuild-linux-arm "0.14.42" + esbuild-linux-arm64 "0.14.42" + esbuild-linux-mips64le "0.14.42" + esbuild-linux-ppc64le "0.14.42" + esbuild-linux-riscv64 "0.14.42" + esbuild-linux-s390x "0.14.42" + esbuild-netbsd-64 "0.14.42" + esbuild-openbsd-64 "0.14.42" + esbuild-sunos-64 "0.14.42" + esbuild-windows-32 "0.14.42" + esbuild-windows-64 "0.14.42" + esbuild-windows-arm64 "0.14.42" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escodegen@~0.0.24: + version "0.0.28" + resolved "https://registry.npmmirror.com/escodegen/-/escodegen-0.0.28.tgz#0e4ff1715f328775d6cab51ac44a406cd7abffd3" + integrity sha512-6ioQhg16lFs5c7XJlJFXIDxBjO4yRvXC9yK6dLNNGuhI3a/fJukHanPF6qtpjGDgAFzI8Wuq3PSIarWmaOq/5A== + dependencies: + esprima "~1.0.2" + estraverse "~1.3.0" + optionalDependencies: + source-map ">= 0.1.2" + +escodegen@~1.3.2: + version "1.3.3" + resolved "https://registry.npmmirror.com/escodegen/-/escodegen-1.3.3.tgz#f024016f5a88e046fd12005055e939802e6c5f23" + integrity sha512-z9FWgKc48wjMlpzF5ymKS1AF8OIgnKLp9VyN7KbdtyrP/9lndwUFqCtMm+TAJmJf7KJFFYc4cFJfVTTGkKEwsA== + dependencies: + esprima "~1.1.1" + estraverse "~1.5.0" + esutils "~1.0.0" + optionalDependencies: + source-map "~0.1.33" + +esprima@^1.0.3: + version "1.2.5" + resolved "https://registry.npmmirror.com/esprima/-/esprima-1.2.5.tgz#0993502feaf668138325756f30f9a51feeec11e9" + integrity sha512-S9VbPDU0adFErpDai3qDkjq8+G05ONtKzcyNrPKg/ZKa+tf879nX2KexNU95b31UoTJjRLInNBHHHjFPoCd7lQ== + +esprima@~1.0.2: + version "1.0.4" + resolved "https://registry.npmmirror.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" + integrity sha512-rp5dMKN8zEs9dfi9g0X1ClLmV//WRyk/R15mppFNICIFRG5P92VP7Z04p8pk++gABo9W2tY+kHyu6P1mEHgmTA== + +esprima@~1.1.1: + version "1.1.1" + resolved "https://registry.npmmirror.com/esprima/-/esprima-1.1.1.tgz#5b6f1547f4d102e670e140c509be6771d6aeb549" + integrity sha512-qxxB994/7NtERxgXdFgLHIs9M6bhLXc6qtUmWZ3L8+gTQ9qaoyki2887P2IqAYsoENyr8SUbTutStDniOHSDHg== + +estraverse@~1.3.0: + version "1.3.2" + resolved "https://registry.npmmirror.com/estraverse/-/estraverse-1.3.2.tgz#37c2b893ef13d723f276d878d60d8535152a6c42" + integrity sha512-OkbCPVUu8D9tbsLcUR+CKFRBbhZlogmkbWaP3BPERlkqzWL5Q6IdTz6eUk+b5cid2MTaCqJb2nNRGoJ8TpfPrg== + +estraverse@~1.5.0: + version "1.5.1" + resolved "https://registry.npmmirror.com/estraverse/-/estraverse-1.5.1.tgz#867a3e8e58a9f84618afb6c2ddbcd916b7cbaf71" + integrity sha512-FpCjJDfmo3vsc/1zKSeqR5k42tcIhxFIlvq+h9j0fO2q/h2uLKyweq7rYJ+0CoVvrGQOxIS5wyBrW/+vF58BUQ== + +esutils@~1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" + integrity sha512-x/iYH53X3quDwfHRz4y8rn4XcEwwCJeWsul9pF1zldMbGtgOtMNBEOuYWwB1EQlK2LRa1fev3YAgym/RElp5Cg== + +falafel@^2.1.0: + version "2.2.5" + resolved "https://registry.npmmirror.com/falafel/-/falafel-2.2.5.tgz#3ccb4970a09b094e9e54fead2deee64b4a589d56" + integrity sha512-HuC1qF9iTnHDnML9YZAdCDQwT0yKl/U55K4XSUXqGAA2GLoafFgWRqdAbhWJxXaYD4pyoVxAJ8wH670jMpI9DQ== + dependencies: + acorn "^7.1.1" + isarray "^2.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^3.0.2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has@^1.0.0: + version "1.0.3" + resolved "https://registry.npmmirror.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.npmmirror.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +iconv-lite@0.6: + version "0.6.3" + resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.npmmirror.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + +iota-array@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/iota-array/-/iota-array-1.0.0.tgz#81ef57fe5d05814cd58c2483632a99c30a0e8087" + integrity sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA== + +is-any-array@^0.1.0: + version "0.1.1" + resolved "https://registry.npmmirror.com/is-any-array/-/is-any-array-0.1.1.tgz#519776164315fcad0fd96a913e02409b18346fef" + integrity sha512-qTiELO+kpTKqPgxPYbshMERlzaFu29JDnpB8s3bjg+JkxBpw29/qqSaOdKv2pCdaG92rLGeG/zG2GauX58hfoA== + +is-any-array@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/is-any-array/-/is-any-array-2.0.0.tgz#e71bc13741537c06afac03c07885967ef56d8742" + integrity sha512-WdPV58rT3aOWXvvyuBydnCq4S2BM1Yz8shKxlEpk/6x+GX202XRvXOycEFtNgnHVLoc46hpexPFx8Pz1/sMS0w== + +is-buffer@^1.0.2, is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.npmmirror.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.npmmirror.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@^2.0.1: + version "2.0.5" + resolved "https://registry.npmmirror.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.npmmirror.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-reports@^3.1.4: + version "3.1.4" + resolved "https://registry.npmmirror.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" + integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.npmmirror.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.npmmirror.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + integrity sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ== + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + integrity sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg== + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.npmmirror.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.npmmirror.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q== + +ml-array-max@^1.2.4: + version "1.2.4" + resolved "https://registry.npmmirror.com/ml-array-max/-/ml-array-max-1.2.4.tgz#2373e2b7e51c8807e456cc0ef364c5863713623b" + integrity sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ== + dependencies: + is-any-array "^2.0.0" + +ml-array-min@^1.2.3: + version "1.2.3" + resolved "https://registry.npmmirror.com/ml-array-min/-/ml-array-min-1.2.3.tgz#662f027c400105816b849cc3cd786915d0801495" + integrity sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q== + dependencies: + is-any-array "^2.0.0" + +ml-array-rescale@^1.3.7: + version "1.3.7" + resolved "https://registry.npmmirror.com/ml-array-rescale/-/ml-array-rescale-1.3.7.tgz#c4d129320d113a732e62dd963dc1695bba9a5340" + integrity sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ== + dependencies: + is-any-array "^2.0.0" + ml-array-max "^1.2.4" + ml-array-min "^1.2.3" + +ml-levenberg-marquardt@^2.0.0: + version "2.1.1" + resolved "https://registry.npmmirror.com/ml-levenberg-marquardt/-/ml-levenberg-marquardt-2.1.1.tgz#6a26751657adb340ed5ae4daadf5bfd2f757bdd4" + integrity sha512-2+HwUqew4qFFFYujYlQtmFUrxCB4iJAPqnUYro3P831wj70eJZcANwcRaIMGUVaH9NDKzfYuA4N5u67KExmaRA== + dependencies: + is-any-array "^0.1.0" + ml-matrix "^6.4.1" + +ml-matrix@^6.4.1: + version "6.10.0" + resolved "https://registry.npmmirror.com/ml-matrix/-/ml-matrix-6.10.0.tgz#daeaaa8e6a57bcebf6ea19a55f588578712a9bae" + integrity sha512-wU+jacx1dcP1QArV1/Kv49Ah6y2fq+BiQl2BnNVBC+hoCW7KgBZ4YZrowPopeoY164TB6Kes5wMeDjY8ODHYDg== + dependencies: + is-any-array "^2.0.0" + ml-array-rescale "^1.3.7" + +ndarray-ops@^1.2.2: + version "1.2.2" + resolved "https://registry.npmmirror.com/ndarray-ops/-/ndarray-ops-1.2.2.tgz#59e88d2c32a7eebcb1bc690fae141579557a614e" + integrity sha512-BppWAFRjMYF7N/r6Ie51q6D4fs0iiGmeXIACKY66fLpnwIui3Wc3CXiD/30mgLbDjPpSLrsqcp3Z62+IcHZsDw== + dependencies: + cwise-compiler "^1.0.0" + +ndarray-pack@^1.2.0: + version "1.2.1" + resolved "https://registry.npmmirror.com/ndarray-pack/-/ndarray-pack-1.2.1.tgz#8caebeaaa24d5ecf70ff86020637977da8ee585a" + integrity sha512-51cECUJMT0rUZNQa09EoKsnFeDL4x2dHRT0VR5U2H5ZgEcm95ZDWcMA5JShroXjHOejmAD/fg8+H+OvUnVXz2g== + dependencies: + cwise-compiler "^1.1.2" + ndarray "^1.0.13" + +ndarray-unpack@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/ndarray-unpack/-/ndarray-unpack-1.0.0.tgz#4b53c767300a5e3909b8b5225ab55c6e886d91dc" + integrity sha512-BH6Ytr5/K0ckdhblKSAiwtkcLr0BnbSUMfYbilr9dkySj9QqdIZv2HyAoZnk9htNmsZrozYqNT01wjcWy/+6/Q== + dependencies: + cwise "^1.0.1" + dup "^1.0.0" + +ndarray@^1.0.13, ndarray@^1.0.18: + version "1.0.19" + resolved "https://registry.npmmirror.com/ndarray/-/ndarray-1.0.19.tgz#6785b5f5dfa58b83e31ae5b2a058cfd1ab3f694e" + integrity sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ== + dependencies: + iota-array "^1.0.0" + is-buffer "^1.0.2" + +object-inspect@~0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/object-inspect/-/object-inspect-0.4.0.tgz#f5157c116c1455b243b06ee97703392c5ad89fec" + integrity sha512-8WvkvUZiKAjjsy/63rJjA7jw9uyF0CLVLjBKEfnPHE3Jxvs1LgwqL2OmJN+LliIX1vrzKW+AAu02Cc+xv27ncQ== + +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +quote-stream@~0.0.0: + version "0.0.0" + resolved "https://registry.npmmirror.com/quote-stream/-/quote-stream-0.0.0.tgz#cde29e94c409b16e19dc7098b89b6658f9721d3b" + integrity sha512-m4VtvjAMx00wgAS6eOy50ZDat1EBQeFKBIrtF/oxUt0MenEI33y7runJcRiOihc+JBBIt2aFFJhILIh4e9shJA== + dependencies: + minimist "0.0.8" + through2 "~0.4.1" + +readable-stream@^2.2.2: + version "2.3.7" + resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@~1.0.17, readable-stream@~1.0.27-1: + version "1.0.34" + resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.npmmirror.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.npmmirror.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + integrity sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg== + dependencies: + align-text "^0.1.1" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +robust-predicates@^3.0.0: + version "3.0.1" + resolved "https://registry.npmmirror.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a" + integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g== + +rw@1: + version "1.3.3" + resolved "https://registry.npmmirror.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +seedrandom@^3.0.5: + version "3.0.5" + resolved "https://registry.npmmirror.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" + integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== + +semver@^6.0.0: + version "6.3.0" + resolved "https://registry.npmmirror.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +shallow-copy@~0.0.1: + version "0.0.1" + resolved "https://registry.npmmirror.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" + integrity sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +"source-map@>= 0.1.2": + version "0.7.3" + resolved "https://registry.npmmirror.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + +source-map@~0.1.33: + version "0.1.43" + resolved "https://registry.npmmirror.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + integrity sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ== + dependencies: + amdefine ">=0.0.4" + +source-map@~0.5.1: + version "0.5.7" + resolved "https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +static-eval@~0.2.0: + version "0.2.4" + resolved "https://registry.npmmirror.com/static-eval/-/static-eval-0.2.4.tgz#b7d34d838937b969f9641ca07d48f8ede263ea7b" + integrity sha512-6dWWPfa/0+1zULdQi7ssT5EQZHsGK8LygBzhE/HdafNCo4e/Ibt7vLPfxBw9VcdVV+t0ARtN4ZAJKtApVc0A5Q== + dependencies: + escodegen "~0.0.24" + +static-module@^1.0.0: + version "1.5.0" + resolved "https://registry.npmmirror.com/static-module/-/static-module-1.5.0.tgz#27da9883c41a8cd09236f842f0c1ebc6edf63d86" + integrity sha512-XTj7pQOHT33l77lK/Pu8UXqzI44C6LYAqwAc9hLTTESHRqJAFudBpReuopFPpoRr5CtOoSmGfFQC6FPlbDnyCw== + dependencies: + concat-stream "~1.6.0" + duplexer2 "~0.0.2" + escodegen "~1.3.2" + falafel "^2.1.0" + has "^1.0.0" + object-inspect "~0.4.0" + quote-stream "~0.0.0" + readable-stream "~1.0.27-1" + shallow-copy "~0.0.1" + static-eval "~0.2.0" + through2 "~0.4.1" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.npmmirror.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +three.meshline@^1.4.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/three.meshline/-/three.meshline-1.4.0.tgz#2a483cbd99cd5f74cf6ee5c253a9a4b4a8169178" + integrity sha512-A8IsiMrWP8zmHisGDAJ76ZD7t/dOF/oCe/FUKNE6Bu01ZYEx8N6IlU/1Plb2aOZtAuWM2A8s8qS3hvY0OFuvOw== + +three@^0.143.0: + version "0.143.0" + resolved "https://registry.npmmirror.com/three/-/three-0.143.0.tgz#1455bca132cc2b20beb7f41d313e10c29e5ed9df" + integrity sha512-oKcAGYHhJ46TGEuHjodo2n6TY2R6lbvrkp+feKZxqsUL/WkH7GKKaeu6RHeyb2Xjfk2dPLRKLsOP0KM2VgT8Zg== + +through2@~0.4.1: + version "0.4.2" + resolved "https://registry.npmmirror.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" + integrity sha512-45Llu+EwHKtAZYTPPVn3XZHBgakWMN3rokhEv5hu596XP+cNgplMg+Gj+1nmAvj+L0K7+N49zBKx5rah5u0QIQ== + dependencies: + readable-stream "~1.0.17" + xtend "~2.1.1" + +tsne-js@^1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/tsne-js/-/tsne-js-1.0.3.tgz#9dca61a6edabf0d0b62ea8490890c31fc7a735f7" + integrity sha512-qFHOgQaOR3/OaE1Gvs5KLj3N8ppWt7U/nvEJohzRAtrOxWeTKEK2wMh1fhIoRRiY/WGrN+BSrzgYhVOsIE38vg== + dependencies: + cwise "^1.0.9" + ndarray "^1.0.18" + ndarray-ops "^1.2.2" + ndarray-pack "^1.2.0" + ndarray-unpack "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.npmmirror.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + +uglify-js@^2.6.0: + version "2.8.29" + resolved "https://registry.npmmirror.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" + integrity sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w== + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.npmmirror.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + integrity sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q== + +umap-js@^1.3.3: + version "1.3.3" + resolved "https://registry.npmmirror.com/umap-js/-/umap-js-1.3.3.tgz#4f04e4986549cad620dd84ff324bf7f124498e0e" + integrity sha512-roaP4i1fXtCGOrgqYbmJPJ6rVOhhyzU4XPEM9rXAlqGQQLrslMWKQ9+fcGoN//WjrIRqsa6gBN0cW/2FV2PvPw== + dependencies: + ml-levenberg-marquardt "^2.0.0" + +uniq@^1.0.0: + version "1.0.1" + resolved "https://registry.npmmirror.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA== + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +v8-to-istanbul@^9.0.0: + version "9.0.0" + resolved "https://registry.npmmirror.com/v8-to-istanbul/-/v8-to-istanbul-9.0.0.tgz#be0dae58719fc53cb97e5c7ac1d7e6d4f5b19511" + integrity sha512-HcvgY/xaRm7isYmyx+lFKA4uQmfUbN0J4M0nNItvzTvH/iQ9kW5j/t4YSR+Ge323/lrgDAWJoF46tzGQHwBHFw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.7" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmmirror.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.npmmirror.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + integrity sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg== + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.npmmirror.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + integrity sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.npmmirror.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ== + dependencies: + object-keys "~0.4.0" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^20.2.2, yargs-parser@^20.2.9: + version "20.2.9" + resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.npmmirror.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + integrity sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A== + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==